项目总览:从代码看 asset-light
技术栈与依赖(以当前代码为准)
- UI:Dioxus Desktop(Rust 声明式 UI)
- 本地数据库:SQLite(
rusqlite,嵌入式,无需服务端) - 序列化:
serde - 时间:
chrono - ID:
uuid - 金额/比例:
rust_decimal(避免浮点误差)
依赖定义见:Cargo.toml
运行入口
- 应用入口:
src/main.rs- 初始化数据库:
db::init_database() - 启动 UI:
dioxus::launch(app::App)
- 初始化数据库:
- 根组件:
src/app.rs- 提供全局状态:
provide_app_state() - 路由渲染:
Router::<Route> {}
- 提供全局状态:
目录结构(核心)
src/main.rs:进程入口,初始化依赖(数据库)后启动 UIsrc/app.rs:根组件,注入全局状态并挂载路由src/router.rs:路由枚举(页面入口 + layout 包裹)src/error.rs:统一错误类型AppError与AppResult<T>src/pages/*:页面(Home / Assets / History / Plans / Analysis)src/components/*:页面内部 UI 组件(按业务域拆分)src/models/*:领域模型(资产分类体系、资产/快照/方案等)src/db/*:数据库访问层(连接、迁移、Repository,返回AppResult<T>)src/state/*:全局状态(Dioxus Signal Context)src/services/*:业务计算/服务(例如分析计算)src/utils/*:格式化等工具函数
分层与职责(建议的理解方式)
- UI 层(components/pages/router/app)
负责渲染与交互,不直接拼 SQL;从 Repository 拉取数据或触发写入;在需要时更新AppState。 - 数据访问层(db/ + repositories)*
负责 SQL、类型转换与持久化规则(例如字符串到Decimal/Uuid/chrono的解析)。 - 领域模型(models/*)
负责“数据结构 + 稳定编码”,例如资产大类Category、口径AssetScope、工具类型VehicleType、子资产类别编码等。 - 业务服务层(services/*,可选)
负责跨模块的计算逻辑,避免把复杂计算堆进 UI。
数据库位置与环境变量
数据库文件路径由 dirs::data_local_dir() 决定(macOS 通常在用户目录下的 Application Support)。
项目支持通过环境变量指定 DB 路径(便于测试/调试):
ASSET_LIGHT_DB_PATH:指向一个 sqlite 文件路径
对应实现见:src/db/connection.rs 的 Database::db_path()
迁移策略(重要)
当前迁移逻辑内置于 src/db/connection.rs 的 Database::run_migrations():
会维护 schema_meta 表中的 schema_version,并在版本升级时进行表结构处理。
注意:当 schema_version < 2 时,迁移会执行 DROP TABLE(会清空历史数据)。
这适用于早期迭代阶段“允许破坏性升级”的策略,若要进入长期使用阶段,需要改为真正的“非破坏性迁移”。
扩展一个新功能的建议切入点
以“新增一个页面/功能”为例,推荐按顺序改动:
- models:先定义稳定的数据结构与编码(必要时为 DB 做准备)
- db:增加/扩展 Repository 方法(读写与类型转换)
- pages/components:增加 UI 与交互
- state/services:补全全局状态同步或业务计算(需要时)