chore: release v1.0.18
Deploy / build-linux-web (push) Successful in 53s
Deploy / build-windows (push) Successful in 1m48s
Deploy / build-macos (push) Successful in 1m17s
Deploy / build-android (push) Successful in 4m13s
Deploy / build-ios (push) Successful in 9s
Deploy / release-deploy (push) Successful in 1m37s

移动端响应式适配(抽屉导航/列表卡片/弹窗自适应)、Android 正式签名与 APK 发布、
iOS(TestFlight) 工程与 CI、多平台构建流水线、相关文档同步。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-07 07:55:33 +08:00
parent 94f0fb2095
commit 480ce836bb
81 changed files with 3096 additions and 366 deletions
+68 -3
View File
@@ -40,7 +40,8 @@ jiu/
│ ├── main.go # 入口,启动时执行 AutoMigrate
│ ├── config/
│ │ ├── config.go # 配置结构体(含 mapstructure 标签)
│ │ ── config.yaml # 本地开发配置(不提交 git)
│ │ ── config.yaml # 本地开发配置(不提交 git)
│ │ └── version.yaml # 版本清单(version + download_urls,发版时由 release.sh 更新)
│ ├── internal/
│ │ ├── handler/ # HTTP 处理器(每模块一文件)
│ │ │ └── *_test.go # Handler 集成测试(SQLite in-memory
@@ -59,10 +60,13 @@ jiu/
│ │ └── S001.sql # 门店 S001 测试种子数据(SQL 命令形式)
│ └── schema/schema.sql # 完整建表 SQLMySQL
├── client/ # Flutter 跨端客户端
│ └── android/ ios/ macos/ web/ windows/ # 五个平台目录(均已初始化)
├── deploy/
│ └── docker-compose.yml # 本地开发:MySQL(3306) + Adminer(8888)
├── .gitea/workflows/ # Forgejo Actionsdeploy.yml=tag 发版,及备份/重置等)
├── scripts/
│ ├── dev.sh # 一站式开发脚本(见下方用法)
│ ├── ci/ # CI 编译/发布脚本(compile-*.sh / release.sh / deploy.sh / provision-*.sh
│ └── .logs/ # 脚本运行日志(已加入 .gitignore,不提交)
└── docs/
├── context/project.md # 本文件(项目全貌)
@@ -164,6 +168,7 @@ sh scripts/dev.sh seed S001
版本(无需 JWT:
GET /version # 返回最新版本信息(读取 version.yaml,缺失返回 500
GET /api/v1/public/release # 版本 + download_urls(驱动客户端更新提示与下载页)
商品:
GET/POST /api/v1/products
@@ -204,6 +209,12 @@ sh scripts/dev.sh seed S001
数据导入:
POST /api/v1/import/products (Excel/CSV)
POST /api/v1/import/partners (Excel/CSV)
意见反馈:
POST /api/v1/feedback # 提交反馈(bug/suggestion,文字+图片,认证)
POST /api/v1/feedback/images # 上传反馈附图(认证)
GET /api/v1/admin/feedback # 反馈列表(仅 superadmin
PATCH /api/v1/admin/feedback/:id # 标记处理状态(仅 superadmin
```
## Flutter 客户端结构
@@ -218,6 +229,9 @@ client/lib/
│ ├── config/app_config.dart # 全局 URL 配置(通过 --dart-define=BASE_URL=... 注入)
│ ├── router/app_router.dart # go_router_RouterNotifier + refreshListenable
│ ├── storage/login_history.dart # 登录历史(shared_preferences,支持候选词自动填充)
│ ├── responsive/responsive.dart # 响应式:context.isMobile<600)、context.dialogWidth(X)
│ ├── update/app_updater*.dart # 应用内更新(_io: Win/macOS 装;_web: 刷新;移动端/兜底开下载链接)
│ ├── errors/error_reporter.dart # 异常上报(reportError
│ ├── models/page_result.dart # 通用分页结果模型
│ └── exceptions.dart # 自定义异常类型
├── models/ # 数据模型(与后端 JSON 对应)
@@ -239,19 +253,24 @@ client/lib/
│ └── number_rule_provider.dart # 编号规则
├── screens/
│ ├── auth/login_screen.dart # 登录页(含候选词下拉,150ms 延迟防止覆盖 onTap
│ ├── shell/app_shell.dart # 主框架(顶栏 + 侧边栏 + 状态栏 + 更新提示 banner
│ ├── shell/app_shell.dart # 主框架(顶栏 + 侧边栏/窄屏 Drawer 抽屉 + 状态栏 + 更新 banner
│ ├── stock_in/ # 入库管理
│ ├── stock_out/ # 出库管理
│ ├── inventory/ # 库存管理(含批次追踪 batch_tracking_screen.dart
│ ├── partners/ # 往来单位
│ ├── finance/ # 财务管理
│ ├── products/ # 商品管理(含分类)
── settings/ # 系统设置(用户/仓库/编号规则/关于
── about/ # 关于我们(含意见反馈:文字+附图直接提交后台
│ ├── public/ # 商品扫码公开展示页(无需登录)
│ └── settings/ # 系统设置(用户/仓库/编号规则)
└── widgets/
├── page_scaffold.dart # Tab 页面封装
├── data_table_card.dart # 含工具栏+分页的数据表格
│ # StatefulWidget,用 Table + IntrinsicColumnWidth 实现
│ # ValueNotifier<int> _hoveredRow 驱动行 hover 高亮
│ # mobileCards 入参:窄屏渲染卡片流,宽屏仍表格
├── mobile_list_card.dart # 移动端列表卡片:MobileListCard / MobileCardField
│ # 标题 + 右上角徽章 + 字段竖排 + 底部操作,替代窄屏表格行
├── multi_select_dropdown.dart # 多选筛选组件(多个导出):
│ # MultiSelectDropdown — 独立多选按钮(toolbar 使用)
│ # FilterableColumnHeader — 列头内嵌筛选图标
@@ -327,6 +346,48 @@ final warehouseOptions = _records
- `required: true` — 不可隐藏
- `minWidth: 1000` — 屏幕宽度不足时自动隐藏
## 移动端 / 响应式 UI 规范
客户端同一套代码跑桌面/Web/平板/手机。**窄屏(手机)自动切换为移动布局,宽屏保持桌面布局不变**。
### 断点判定
统一用 `client/lib/core/responsive/responsive.dart` 的扩展,不要散落魔法数:
```dart
context.isMobile // 宽度 < 600kMobileBreakpoint
context.dialogWidth(720) // 固定宽度弹窗的安全宽度,≤ 屏宽 92%
```
### 列表 → 卡片
列表屏用 `DataTableCard` 时同时传 `mobileCards`,窄屏渲染卡片流、宽屏仍表格:
```dart
DataTableCard(
columns: [...], rows: [...], // 宽屏表格
mobileCards: items.map(_buildCard).toList(), // 窄屏卡片(MobileListCard
)
```
卡片复用 `MobileListCard`(标题/徽章/字段/操作)+ `MobileCardField``widgets/mobile_list_card.dart`)。
顶部并排汇总卡片在窄屏改为横向滚动。
### 弹窗宽度
固定宽度弹窗一律 `width: context.dialogWidth(X)`**禁止**裸写 `width: <固定值>`(窄屏会溢出)。
表单字段(`_FormField`)窄屏占满整行。
### 导航
窄屏用 Drawer 抽屉(`app_shell.dart``_buildDrawer`,汉堡按钮打开),隐藏底部状态栏;宽屏保持侧边栏。
新增页面挂在 shell 下即可,自动适配,无需单独处理。
## 跨端分发
| 平台 | 构建产物 | 分发方式 |
|------|----------|----------|
| Web | `flutter build web` | 部署到 `jiu.51yanmei.com/app` |
| Windows | Inno Setup `setup.exe` | 下载页 `/downloads/` + 应用内更新 |
| macOS | `.app` zip | 下载页 `/downloads/` + 应用内更新 |
| Android | 签名 `jiu-android.apk` | 下载页 `/downloads/`(见 docs/android-signing.md |
| iOS | 签名 IPA | TestFlight(见 docs/ios-signing.md |
版本清单:`backend/config/version.yaml``download_urls`(含各平台下载地址);客户端 `GET /api/v1/public/release` 读取,驱动更新提示与下载页。
## 文档索引
| 文档 | 路径 | 说明 |
@@ -337,3 +398,7 @@ final warehouseOptions = _records
| S001 种子 | backend/seeds/S001.sql | 门店 S001 测试数据(含完整入库/出库/库存历史) |
| S002 种子 | backend/seeds/S002.sql | 门店 S002 测试数据(基础数据相同,无库存/单据,模拟新门店) |
| 用户手册 | docs/user-manual.md | 酒行员工操作手册(登录/入库/出库/库存/财务/设置) |
| Android 签名 | docs/android-signing.md | 生成 keystore + 配置 Forgejo secretsCI 给 APK 正式签名 |
| iOS 分发 | docs/ios-signing.md | 证书/Profile/API Key + secretsCI 构建并上传 TestFlight |
| 部署(NAS/Gitea | docs/deployment-nas-gitea.md | 自建 Forgejo + runner 部署说明 |
| 待办 | docs/TODO.md | 后续迭代事项(iOS 上架、应用内 APK 安装、平板布局等) |