# 开源简账 **Repository Path**: run_wind/OpenSourceSimpleAccount ## Basic Information - **Project Name**: 开源简账 - **Description**: 基于 Flutter 的跨平台个人记账应用。支持多账本、归属人管理、类型分类、账单记录与统计报表,含加密备份恢复与 WebDAV 同步。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2025-12-31 - **Last Updated**: 2026-09-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 开源简账 — 个人记账 App 基于 Flutter 的跨平台个人记账应用,支持多账本、归属管理、收支归类配置、定额储备(独立储蓄模块)、资产概览、账单记录、统计看板、CSV 导入导出、数据加密备份、WebDAV 远程备份与恢复、数据库清除。应用启动时自动检测新版本,左侧抽屉提示下载。 ### 截图效果
## 功能特性 ### 账单管理(核心) | 功能 | 说明 | |------|------| | **账单列表** | 按月分组展示,每月头部显示支出/收入汇总。按月 SQL 分批加载(6 个月/批),滚动到底自动加载更多,长年使用不卡顿 | | **账单表单** | 七行布局:所属账本 / 归属人+金额 / 日期+时间 / 类型+分类(级联) / 计入统计开关 / 固定支出+必要支出(仅支出) / 描述。红(支出) 绿(收入) 颜色区分 | | **账单筛选** | 右侧抽屉式筛选面板,支持账本多选、归属人多选、类型(支出/收入)多选、分类多选、时间范围选择、描述关键词模糊搜索。筛选激活时右上角图标显示红色圆点 | | **账单复制** | 列表项长按菜单 → 复制为未保存的草稿表单,改个金额即可提交(适合水电费、房租等重复账单) | | **账单删除** | 软删除,列表项长按菜单 → 确认弹窗 → 逻辑删除 | ### 配置管理 | 功能 | 说明 | |------|------| | **账本目录** | 创建 / 编辑 / 封账(停用后不在账单表单出现) / 删除 / 排序。支持多账本(日常、旅行、投资等) | | **归属管理** | 创建 / 编辑 / 停用 / 删除 / 排序。可用于家庭成员或合伙人分摊 | | **收支归类** | 两层结构:支出 / 收入。每个类型下可自定义分类,支持排序。分类可禁用(隐藏,不在表单中出现) | ### 资产概览 | 功能 | 说明 | |------|------| | **资产概览** | 独立页面集中展示全生命周期累计资产状态:累计收入 / 累计支出 / 在管储蓄 / 流动资金 | | **全量累计口径** | 数据为全部账单与储蓄汇总,不随统计看板的日期/筛选变化,代表"当前资产状态" | | **流动资金** | 流动资金 = 累计收入 - 累计支出 - 在管储蓄 | | **明细入口** | 资产页内置"定额储备""统计看板"跳转入口,串联储备与分析功能 | ### 定额储备 | 功能 | 说明 | |------|------| | **定额储备** | 独立于收支账本的储蓄模块,记录定期存单、现金封装等长期储蓄 | | **储蓄归类** | 自定义储蓄类型名称,在定额储备表单中选择使用 | ### 小金库 | 功能 | 说明 | |------|------| | **小金库** | 完全独立于主流水账本的私密资金模块,不参与收支统计、不支持 Excel 导入导出 | | **隐藏入口** | 左侧抽屉长按 Logo 进入,日常使用不暴露入口 | | **独立统计** | 模块顶部显示总金额和笔数,支持按日期记录和备注 | ### 统计看板 **年度统计(选定年份,8 区块):** | 区块 | 内容 | |------|------| | 年度概览 | 年收入 / 年支出 / 支出比 / 月均收入 / 月均支出 | | 每月收支双柱图 | X 轴固定 1-12 月,每轴点并列收入(绿)+支出(红)双柱,触摸显示数值 | | 历年对比 | 以选定年为最右,向前 5 年,每轴点 2 柱(收入/支出),不足 5 年左侧留空 | | 支出分类分析 | 横向条形图,各分类支出降序排列 | | 归属人分析 | 横向条形图,各归属人支出降序排列 | | 堆叠进度条(固定支出) | 仅固定支出(品牌色) + 灵活支出(红色) 斜切分割线,按比例占满 100% | | 堆叠进度条(刚性支出) | 固定+必要支出(品牌色) + 灵活支出(红色) 斜切分割线,按比例占满 100% | | 大额支出 Top3 | 排名圆圈 + 分类名 + 归属人 + 金额 + 日期 | | 月报列表 | 顶部汇总行(月均收入/支出)+ 倒序 12 个月每行明细 | **月度统计(选定年月,7 区块):** | 区块 | 内容 | |------|------| | 月度概览 | 月收入 / 月支出 / 支出比 / 日均收入 / 日均支出 | | 支出分类分析 | 横向条形图 | | 归属人分析 | 横向条形图 | | 堆叠进度条(固定支出) | 仅固定支出 vs 灵活支出斜切分割 | | 堆叠进度条(刚性支出) | 固定+必要支出 vs 灵活支出斜切分割 | | 大额支出 Top3 | 排名列表 | | 日历日报 | 周一~周日网格日历,每格显示日期 + 收/支 两行数字,格子背景按当天最高值颜色半透明 | **筛选:** 账本多选 + 归属人多选,右侧抽屉式面板 + 完成批量应用 ### 数据迁移 | 功能 | 说明 | |------|------| | **CSV 导入** | 两遍扫描:收集缺失配置 → 确认创建 → 逐行校验 → 去重 → 批量插入。自动识别 UTF-8 / GBK 编码,自动识别逗号/分号分隔符。⚠️ 增量导入,不会覆盖已有数据;小金库数据不支持导入;导入前建议先加密备份当前数据 | | **CSV 导出** | UTF-8 BOM + 逗号分隔(Excel/WPS 双击直接打开)。有数据按真实账单导出,无数据自动生成 7 条示例模板。弹出目录选择器保存到指定位置。⚠️ 仅导出「账单流水」和「储蓄记录」,不含小金库、备注等明细;建议仅用于数据迁移或账本合并等特殊场景 | ### 远程备份 | 功能 | 说明 | |------|------| | **WebDAV 配置** | 配置服务器地址、用户名、密码与远端路径,支持测试连接 | | **上传到远端** | 将本地加密备份上传到远程服务器 | | **从远端恢复** | 从远程服务器下载最新备份并恢复数据库 | | **自动同步** | 可配置检测间隔(每次打开 / 10 分钟 ~ 72 小时),打开应用后在后台检测远端是否有更新备份,发现新版本时询问是否恢复;已恢复的远端备份会去重避免重复提示 | ### 数据管理 | 功能 | 说明 | |------|------| | **加密备份** | SQLite 数据库加密打包为 ZIP(支持自定义密码)→ 弹出目录选择器保存到指定位置 | | **加密恢复** | 从 ZIP 文件恢复数据库(覆盖当前数据,重启应用) | | **数据库清除** | 一键清除所有数据(账本、归属人、分类、账单等),操作前弹出确认弹框,不可撤销 | ### 其他 | 功能 | 说明 | |------|------| | **主题切换** | 跟随系统 / 亮色 / 深色 三选一,持久化到本地存储,下次启动自动恢复 | | **左侧导航抽屉** | 统一入口:账单管理(账单流水/账本目录/归属管理/收支归类)、储备管理(资产概览/定额储备/储蓄归类)、财务分析(统计看板),分组展示 | | **自动更新检测** | 启动时检测 Gitee 新版本,根据当前平台自动匹配安装包(Windows → .exe,Android → .apk,macOS → .dmg,Linux → .AppImage),左侧抽屉提示下载,点击跳转浏览器 | ## 截图 | 账单列表 | 统计报表 | 设置 | |---------|---------|------| | (待添加) | (待添加) | (待添加) | ## 技术栈 | 层面 | 技术 | 用途 | |------|------|------| | 框架 | Flutter 3.10+ | 跨平台(Windows / Android / iOS / macOS / Linux) | | 状态管理 | GetX 4.7 | 响应式状态 + 依赖注入 + 路由 | | 本地数据库 | sqflite 2.3 | SQLite 数据库 | | 轻量持久化 | GetStorage 2.1 | 主题模式、当前账本 ID、备份密码等偏好 | | 数据模型 | Freezed 3.2 + JsonSerializable | 不可变数据类生成 | | 图表 | fl_chart 1.2 | 统计图:柱状图、双柱图、横向条形图、触摸 tooltip | | CSV | csv 8.0 | CSV 编解码(逗号分隔) | | GBK | gbk_codec 0.4 | GBK 编码解码(兼容 WPS/Excel 导出的 CSV) | | 备份 | archive 4.0 | ZIP 压缩/解压 + 加密支持 | | 文件选择 | file_picker 11.0 | 选择 CSV 导入文件、备份文件、选择保存目录 | | 国际化 | flutter_localizations (intl) | 日期/时间选择器中文 | | 版本信息 | package_info_plus 9.0 | 运行时获取应用版本号 | | HTTP 请求 | dio 5.9 | 检测新版本(Gitee API) | | 打开外部链接 | url_launcher 6.3 | 打开浏览器下载安装包 | ## 项目结构 ``` lib/ ├── main.dart # 应用入口 — 路由、主题、本地化 ├── app/ │ ├── routes/app_routes.dart # 路由名称常量(集中维护) │ ├── themes/app_theme.dart # 亮/暗主题 + 字体/间距/圆角常量 │ └── bindings/app_binding.dart # GetX 依赖注入 ├── core/ │ ├── database/database_helper.dart # SQLite 单例 + 建表 + 通用 CRUD + 迁移 │ ├── services/ │ │ ├── backup_service.dart # 加密 ZIP 备份与恢复 │ │ ├── excel_service.dart # CSV 导入导出(校验/去重/自动创建配置) │ │ └── update_service.dart # 版本更新检测(Gitee API) │ ├── utils/ │ │ ├── toast_utils.dart # 吐司提示(成功/错误/信息) │ │ └── validators.dart # 表单校验 │ └── widgets/ │ ├── app_drawer.dart # 左侧导航抽屉(统一入口 + 更新提示) │ ├── confirm_dialog.dart # 确认弹窗 │ ├── update_dialog.dart # 版本更新弹窗 │ ├── empty_state.dart # 空状态占位 │ ├── list_item_card.dart # 通用列表项卡片(标题+副标题+状态+操作) │ ├── edit_delete_menu.dart # 编辑/删除三点菜单 │ ├── loading_indicator.dart # 加载指示器 │ └── selection_picker.dart # 底部弹窗选择器(账本/归属人/类型/分类) ├── modules/ # 业务模块(按功能拆分) │ ├── assets/ # 资产概览模块(全量累计资产状态) │ │ ├── controllers/ # 加载累计收支 + 储蓄总额 │ │ └── views/ # 资产页面 + 概览主卡片 │ ├── bill/ # 账单模块(核心) │ │ ├── models/bill.dart # Freezed 数据模型 │ │ ├── controllers/ # GetX 控制器(SQL 分批加载 + 筛选) │ │ ├── views/ # 列表页 + 表单页 │ │ └── widgets/ # 列表项、筛选抽屉等 │ ├── ledger/ # 账本目录模块(CRUD + 排序 + 封账) │ ├── person/ # 归属管理模块(CRUD + 停用 + 排序) │ ├── category/ # 收支归类模块(CRUD + 停用 + 排序) │ ├── savings/ # 定额储备模块(独立储蓄管理) │ │ ├── models/savings.dart # Freezed 数据模型 │ │ ├── controllers/ # CRUD + CSV 导入导出 │ │ └── views/ # 列表页 + 表单页 │ ├── savings_type/ # 储蓄归类模块(CRUD + 停用 + 排序) │ │ ├── models/savings_type.dart # Freezed 数据模型 │ │ ├── controllers/ # CRUD + 默认初始化 │ │ └── views/ # 列表页 + 表单页 │ ├── settings/ # 设置模块(主题/备份/WebDAV/CSV/关于/更新) │ │ ├── controllers/ │ │ │ ├── update_controller.dart # 版本更新检测控制器(启动时自动检测) │ │ └── services/ │ └── statistics/ # 统计模块(年度/月度图表 + 日历日报) └── shared/ ├── constants/enums.dart # 业务枚举(账本状态/类型/默认分类) ├── controllers/theme_controller.dart # 主题控制器(持久化到 GetStorage) ├── extensions/ # Dart 扩展方法 └── helpers/type_helpers.dart # 类型颜色映射(红/绿) ``` ## 数据表 所有表之间不设物理外键约束,关联通过应用层维护,便于备份恢复和跨设备数据迁移。软删除标记 `is_deleted` 统一控制逻辑删除。 表名在 `DatabaseHelper` 中以 `static const String` 常量的形式定义(如 `tableBill`、`tableLedger`),业务代码中统一引用这些常量,避免硬编码字符串。 ### 核心表:`bill`(账单) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | `id` | INTEGER | PK AUTOINCREMENT | 自增主键 | | `amount` | REAL | NOT NULL | 金额(正数) | | `bill_time` | INTEGER | NOT NULL | 账单时间(毫秒时间戳) | | `ledger_id` | INTEGER | NOT NULL | 账本 ID | | `person_id` | INTEGER | NOT NULL | 归属人 ID | | `type_category_id` | INTEGER | NOT NULL | 分类 ID(关联 bill_type_category) | | `include_in_stats` | INTEGER | NOT NULL DEFAULT 1 | 是否计入统计 | | `is_fixed_expense` | INTEGER | NOT NULL DEFAULT 0 | 是否固定支出 | | `is_necessary` | INTEGER | NOT NULL DEFAULT 0 | 是否必要支出 | | `description` | TEXT | | 描述/备注 | | `create_time` | INTEGER | NOT NULL | 创建时间 | | `update_time` | INTEGER | NOT NULL | 更新时间 | | `is_deleted` | INTEGER | DEFAULT 0 | 软删除标记 | ### 配置表:`ledger`(账本) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | `id` | INTEGER | PK AUTOINCREMENT | 自增主键 | | `name` | TEXT | NOT NULL | 账本名称 | | `description` | TEXT | | 账本描述 | | `status` | TEXT | NOT NULL DEFAULT '启用' | 状态:启用 / 封账 | | `sort_order` | INTEGER | DEFAULT 0 | 排序权重 | | `create_time` | INTEGER | NOT NULL | 创建时间 | | `update_time` | INTEGER | NOT NULL | 更新时间 | | `is_deleted` | INTEGER | DEFAULT 0 | 软删除标记 | ### 配置表:`person`(归属人) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | `id` | INTEGER | PK AUTOINCREMENT | 自增主键 | | `name` | TEXT | NOT NULL UNIQUE | 归属人姓名 | | `remark` | TEXT | | 备注 | | `sort_order` | INTEGER | DEFAULT 0 | 排序权重 | | `is_disabled` | INTEGER | DEFAULT 0 | 是否停用 | | `create_time` | INTEGER | NOT NULL | 创建时间 | | `update_time` | INTEGER | NOT NULL | 更新时间 | | `is_deleted` | INTEGER | DEFAULT 0 | 软删除标记 | ### 配置表:`bill_type_category`(类型分类) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | `id` | INTEGER | PK AUTOINCREMENT | 自增主键 | | `type` | TEXT | NOT NULL | 类型:支出 / 收入 | | `category` | TEXT | NOT NULL | 分类名称 | | `sort_order` | INTEGER | DEFAULT 0 | 排序权重 | | `description` | TEXT | | 分类描述 | | `is_disabled` | INTEGER | DEFAULT 0 | 是否停用 | | `create_time` | INTEGER | NOT NULL | 创建时间 | | `update_time` | INTEGER | NOT NULL | 更新时间 | | `is_deleted` | INTEGER | DEFAULT 0 | 软删除标记 | | | | **UNIQUE(type, category)** | 同一类型下分类名唯一 | ### 储蓄表:`savings`(定额储备) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | `id` | INTEGER | PK AUTOINCREMENT | 自增主键 | | `type` | TEXT | NOT NULL | 储蓄类型名称 | | `amount` | REAL | NOT NULL | 金额(正数) | | `deposit_date` | INTEGER | NOT NULL | 存入时间(毫秒时间戳) | | `term_months` | INTEGER | NOT NULL DEFAULT 0 | 期限(月),0=不定期 | | `interest_rate` | REAL | NOT NULL DEFAULT 0 | 年利率(%) | | `institution` | TEXT | | 存入机构 | | `note` | TEXT | | 备注 | | `create_time` | INTEGER | NOT NULL | 创建时间 | | `update_time` | INTEGER | NOT NULL | 更新时间 | | `is_deleted` | INTEGER | DEFAULT 0 | 软删除标记 | ### 配置表:`savings_type`(储蓄归类) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | `id` | INTEGER | PK AUTOINCREMENT | 自增主键 | | `name` | TEXT | NOT NULL UNIQUE | 类型名称 | | `remark` | TEXT | | 备注说明 | | `sort_order` | INTEGER | DEFAULT 0 | 排序权重 | | `is_disabled` | INTEGER | DEFAULT 0 | 是否停用 | | `create_time` | INTEGER | NOT NULL | 创建时间 | | `update_time` | INTEGER | NOT NULL | 更新时间 | | `is_deleted` | INTEGER | DEFAULT 0 | 软删除标记 | ### 设计约定 - **无物理外键** — 所有关联通过应用层维护,备份恢复和跨设备迁移无需重建约束 - **软删除** — `is_deleted = 1` 标记删除,永远不执行 `DELETE FROM`,数据可恢复 - **时间戳** — 毫秒级 Unix 时间戳(`DateTime.millisecondsSinceEpoch`),兼容 SQLite 整数运算 - **金额精度** — REAL 类型存储,UI 显示 `toStringAsFixed(2)`,统计用 SQL SUM 聚合 ## 数据库迁移指南 ### 迁移机制 `DatabaseHelper` 使用 SQLite 内置版本号机制(`dbVersion` 常量 + `onUpgrade` 回调)处理架构变更: ```dart static const int dbVersion = 2; // 改表结构时 +1 Future _onUpgrade(Database db, int oldVersion, int newVersion) async { if (oldVersion < 2) { /* v1→v2 的变更 */ } if (oldVersion < 3) { /* v2→v3 的变更 */ } } ``` 每次升级用 `if (oldVersion < N)` 判断,保证从任意旧版本都能连续升级到最新。 ### 常见操作 | 操作 | 方法 | 复杂度 | |------|------|--------| | 新增字段 | `ALTER TABLE ... ADD COLUMN` | ⭐ | | 新增表 | `CREATE TABLE IF NOT EXISTS` | ⭐ | | 减少字段 | 重建表 + DROP + RENAME | ⭐⭐⭐ | | 改字段类型 | 重建表 + DROP + RENAME | ⭐⭐⭐ | | 重命名字段 | `RENAME COLUMN`(SQLite 3.25+)或重建表 | ⭐⭐ | ### 注意事项 1. `onUpgrade` 中不要访问 `DatabaseHelper` 单例(数据库未完全就绪) 2. 始终使用 `dbVersion` 常量,不要硬编码版本号 3. 复杂迁移写在事务中:`await db.transaction((txn) async { ... })` 4. 发布前验证:从上一个版本升到当前版本,确认数据完整 5. 旧版本兼容:用 `if (oldVersion < N)` 保证增量升级链完整 ## 编译运行 ```bash # 1. 安装依赖 flutter pub get # 2. 生成 Freezed 代码(修改模型后需要) flutter pub run build_runner build --delete-conflicting-outputs # 3. 运行 flutter run # 4. 代码分析 flutter analyze ``` ### 平台说明 - **Windows / Linux / macOS** — 使用 `sqflite_common_ffi` 替代原生 sqflite - **Android / iOS** — 原生 sqflite,无需额外配置 ### IDE 配置 - **VS Code** — `lib/` 文件夹直接打开,推荐安装 Flutter / Dart 扩展 - **Android Studio / IntelliJ** — 直接打开项目根目录,自动识别 ## 设计语言 ### 色彩体系 | 元素 | 规格 | |------|------| | 品牌色 | 靛蓝 `#5C6BC0` | | 支出色 | 红 `#D32F2F` | | 收入色 | 绿 `#2E7D32` | | 必要色 | 橙 `#F57C00` | 必要支出标签色 | | 页面背景(亮色) | `#F5F7FA` | | 卡片背景 | `#FFFFFF` | | 输入框填充 | `#F0F1F5` | ### 圆角体系(`AppRadius`) | 常量 | 值 | 用途 | |------|-----|------| | `tag` | 4 | 标签/标记 | | `small` | 6 | 摘要 Chip | | `chip` | 8 | Chip | | `icon` | 10 | 图标容器 | | `input` | 12 | 输入框/按钮 | | `card` | 16 | 卡片 | | `dialog` | 16 | 对话框 | | `sheet` | 20 | 底部弹窗 | ### 字体体系(`AppFont`) 所有字体大小使用 `AppFont` 常量,禁止魔法值。 | 常量 | 值 | 用途 | |------|-----|------| | `xs` | 10 | 极小标签 | | `sm` | 11 | Chip 文字 | | `caption` | 12 | 辅助说明 | | `body` | 13 | 描述文本 | | `md` | 14 | 正文 | | `lg` | 15 | 强调正文 | | `xl` | 16 | 主标题 | | `title` | 18 | 页面标题 | | `headline` | 20 | 大标题 | ### 间距体系(`AppSpacing`) 4px 基准。所有 `SizedBox`、`EdgeInsets` 使用 `AppSpacing` 常量,禁止魔法值。 | 常量 | 值 | 用途 | |------|-----|------| | `xx` | 2 | 极小间隙 | | `xs` | 4 | 标签/按钮内边距 | | `sm` | 8 | 表单元素间距 | | `md` | 12 | 行内间距 | | `lg` | 16 | 外边距/卡片边距 | | `xl` | 20 | 大间距 | | `xxl` | 24 | 区块间距 | | `huge` | 32 | 表单底部 | | `fab` | 80 | 列表底部 FAB 安全间距 | 快捷 EdgeInsets:`zero`、`allXs`~`allHuge`、`hSm`~`hXl`、`vSm`~`vLg`、`symSm`~`symLg`、`tSm`、`tMd`、`bFab`。 ## 第三方依赖 | 名称 | 版本 | 用途 | 许可证 | |------|------|------|--------| | [get](https://github.com/jonataslaw/getx) | 4.7.3 | 状态管理 / 路由 / 依赖注入 | MIT | | [get_storage](https://github.com/jonataslaw/get_storage) | 2.1.1 | 轻量持久化 | MIT | | [sqflite](https://github.com/tekartik/sqflite) | 2.3.0 | SQLite 数据库 | BSD-2 | | [sqflite_common_ffi](https://github.com/tekartik/sqflite) | 2.4.2 | 桌面平台 SQLite | BSD-2 | | [fl_chart](https://github.com/imaNNeo/fl_chart) | 1.2.0 | 统计图表 | MIT | | [csv](https://github.com/polevpn/csv) | 8.0.0 | CSV 编解码 | MIT | | [gbk_codec](https://pub.dev/packages/gbk_codec) | 0.4.0 | GBK 编码解码 | MIT | | [file_picker](https://github.com/miguelpruivo/flutter_file_picker) | 11.0.2 | 文件选择 + 目录选择 | MIT | | [archive](https://github.com/brendan-duncan/archive) | 4.0.0 | ZIP 压缩/解压 + 加密 | MIT | | [freezed_annotation](https://github.com/rrousselGit/freezed) | 3.1.0 | 不可变模型 | MIT | | [json_annotation](https://github.com/google/json_serializable.dart) | 4.9.0 | JSON 序列化 | BSD-3 | | [intl](https://github.com/dart-lang/i18n) | 0.20.2 | 日期格式化 | BSD-3 | | [webdav_client](https://pub.dev/packages/webdav_client) | 1.2.2 | WebDAV 同步 | MIT | | [package_info_plus](https://github.com/fluttercommunity/plus_plugins) | 9.0.1 | 运行时版本信息 | BSD-3 | | [dio](https://pub.dev/packages/dio) | 5.9.2 | HTTP 请求(Gitee API 版本检测) | MIT | | [url_launcher](https://pub.dev/packages/url_launcher) | 6.3.0 | 打开外部链接(浏览器/下载) | BSD-3 | | [path_provider](https://github.com/flutter/packages) | 2.1.0 | 文件路径获取 | BSD-3 | | [flutter_launcher_icons](https://github.com/fluttercommunity/flutter_launcher_icons) | 0.14.4 | 应用图标生成 | MIT | | [flutter_native_splash](https://github.com/jonbhanson/flutter_native_splash) | 2.4.7 | 启动页 | MIT | ## 版本管理 ### 应用版本号 `pubspec.yaml` 顶部 `version` 字段(格式 `x.y.z+n`): ```yaml version: 1.0.12+13 # ← 改这里即可,所有位置自动生效 ``` 修改后自动生效的位置: - 设置页 → 关于 → 版本号 - 备份 ZIP 注释中的 `appVersion` 字段 ### 数据库版本号 `lib/core/database/database_helper.dart`: ```dart static const int dbVersion = 4; // ← 改表结构时 +1,同时添加 onUpgrade 逻辑 ``` ## 开发规范 - **注释** — 文件头部说明用途,公开方法写 `///` 文档注释,复杂逻辑行内注释 - **封装** — 避免过度设计,单个文件 ≤ 300 行(如超过考虑拆分) - **色彩** — 不使用硬编码颜色值,统一使用 `AppTheme` 品牌色和主题色常量 - **字体** — 不使用魔法数字,统一使用 `AppFont.*` 常量 - **间距** — 不使用魔法数字,统一使用 `AppSpacing.*` 常量和快捷 EdgeInsets - **状态** — 使用 GetX(`Obx` + `Rx` 系列),避免 `setState` 在父子组件间传播 - **模型** — 使用 Freezed 生成不可变类,手动编写 `fromMap`/`toMap` 用于 SQLite 序列化 - **错误处理** — 不空吞异常,至少 `debugPrint` 日志或 Toast 提示用户 - **命名** — 望文生义原则:看到名字知道用途,布尔变量用 `is`/`has`/`can` 前缀 - **性能** — 列表渲染设置合理的 `key`,循环内避免频繁创建对象、操作数据库 - **刷新策略** — 子页面(统计/归属人/分类)通过路由 binding 进入时自动 reload;首页(账单列表)通过 `needsRefresh` 标志位联动刷新 - **依赖** — 不加不必要的抽象层和设计模式,保持代码一眼能看懂 ## 构建与发布 ### 发布前配置 1. **更新版本号** — 修改 `pubspec.yaml` 中的 `version`(如 `1.0.12+13`,`+` 前为版本名,后为构建号) 2. **检查 Gitee 仓库配置** — `lib/core/services/update_service.dart` 中的 `GiteeConfig` 确保指向你的仓库 3. **更新应用图标**(可选)— 修改 `assets/icon/` 下的图片,执行 `flutter pub run flutter_launcher_icons` 4. **更新启动屏**(可选)— 修改 `flutter_native_splash.yaml`,执行 `flutter pub run flutter_native_splash:create` ### 版本发布流程(Gitee) 用户打开 App → 设置 → 关于 → 点击「检测更新」→ 自动比对版本号 → 有更新时弹窗提示 → 点击「前往下载」→ 浏览器打开下载链接。同时,每次应用启动时自动检测新版本,在左侧抽屉底部显示提示卡片。 发布新版本步骤: 1. **构建并打包** — 为各平台打包(见下方命令) 2. **创建 Gitee Release**: - 打开仓库 →「发行版」→「创建发行版」 - **标签版本**:输入 `v1.0.1`(推荐格式 `v*.*.*`,如 `v1.0.1`、`v2.0.0`) - **发行标题**:如 `v1.0.1` - **发行说明**:填写更新内容(用户将在此看到) - **上传附件**:把各平台安装包上传 - 点击「创建」 ### 构建命令与输出路径 ```bash # ======================== Android ======================== # (需要 Android SDK + 签名配置,ABI 拆分多架构) flutter build apk --release # 输出:build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk # build/app/outputs/flutter-apk/app-arm64-v8a-release.apk # build/app/outputs/flutter-apk/app-x86_64-release.apk 开源简账_v1.0.12_android.apk # ======================== Windows ======================== # (需要 Visual Studio 构建工具) flutter build windows --release # 输出:build\windows\runner\Release\magicoct_app.exe + 一系列 .dll 文件 # Windows 需要制作为可执行文件(.exe)再分发 # 更新检测会优先匹配 .exe 文件 # 使用 Enigma Virtual Box 打包: 开源简账_v1.0.12_windows.exe # ======================== macOS ======================== # (需要 macOS + Xcode) flutter build macos --release # 输出:build/macos/Build/Products/Release/magicoct_app.app # 通常打包为 .dmg 分发 # 重命名示例: hdiutil create -volname OpenSourceSimpleAccount -srcfolder build/macos/Build/Products/Release/magicoct_app.app OpenSourceSimpleAccount_v1.0.1_macos.dmg # ======================== Linux ======================== flutter build linux --release # 输出:build/linux/x64/release/bundle/ # 通常打包为 .AppImage 或 .deb 分发 # ======================== iOS ======================== # (需要 macOS + Xcode + Apple Developer 账号) flutter build ios --release --no-codesign # 输出:build/ios/iphoneos/Runner.app # 用 Xcode 打包为 .ipa # ======================== Web ======================== flutter build web --release # 输出:build/web/ ``` ### 签名与商店发布 - **Android**:`android/app/build.gradle.kts` 中已配置 `signingConfigs.release`,签名文件在 `keystore/key` - **Windows**:使用 Visual Studio 对生成的 `.exe` 或 `.msix` 进行数字签名 - **iOS/macOS**:在 Xcode 中配置签名证书和 Provisioning Profile ## License MIT