From 8628df584852ef151cec6a02d4352f8e75af534e Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Fri, 12 Jun 2026 00:10:58 +0800 Subject: [PATCH] chore: release v1.0.33 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 5 + client/macos/Podfile.lock | 25 - client/macos/Runner.xcodeproj/project.pbxproj | 22 + .../xcshareddata/xcschemes/Runner.xcscheme | 18 + todo/todo.html | 532 +++++++++++++----- todo/todo.json | 167 +++++- 6 files changed, 610 insertions(+), 159 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a97dca..f054586 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.33] - 2026-06-12 + +### 改进 +- macOS 客户端插件集成从 CocoaPods 迁移至 Swift Package Manager,优化 macOS 构建流程 + ## [1.0.32] - 2026-06-11 ### 修复 diff --git a/client/macos/Podfile.lock b/client/macos/Podfile.lock index 56524cf..666ae57 100644 --- a/client/macos/Podfile.lock +++ b/client/macos/Podfile.lock @@ -1,46 +1,21 @@ PODS: - - file_picker (0.0.1): - - FlutterMacOS - FlutterMacOS (1.0.0) - - package_info_plus (0.0.1): - - FlutterMacOS - printing (1.0.0): - FlutterMacOS - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - url_launcher_macos (0.0.1): - - FlutterMacOS DEPENDENCIES: - - file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - printing (from `Flutter/ephemeral/.symlinks/plugins/printing/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) EXTERNAL SOURCES: - file_picker: - :path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos FlutterMacOS: :path: Flutter/ephemeral - package_info_plus: - :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos printing: :path: Flutter/ephemeral/.symlinks/plugins/printing/macos - shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - url_launcher_macos: - :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos SPEC CHECKSUMS: - file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 - package_info_plus: f0052d280d17aa382b932f399edf32507174e870 printing: c4cf83c78fd684f9bc318e6aadc18972aa48f617 - shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb - url_launcher_macos: f87a979182d112f911de6820aefddaf56ee9fbfd PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009 diff --git a/client/macos/Runner.xcodeproj/project.pbxproj b/client/macos/Runner.xcodeproj/project.pbxproj index 4d46d68..350e995 100644 --- a/client/macos/Runner.xcodeproj/project.pbxproj +++ b/client/macos/Runner.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 7CC0DF083710AA9C43B56A42 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B35335B030AEE727449F09D5 /* Pods_Runner.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -88,6 +89,7 @@ B35335B030AEE727449F09D5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B6FABD6521DBD25CA93F2ABB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; D768E6B98F41FC79E2D5D343 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,6 +105,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, 7CC0DF083710AA9C43B56A42 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -164,6 +167,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -231,6 +235,9 @@ productType = "com.apple.product-type.bundle.unit-test"; }; 33CC10EC2044A3C60003C045 /* Runner */ = { + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( @@ -256,6 +263,9 @@ /* Begin PBXProject section */ 33CC10E52044A3C60003C045 /* Project object */ = { + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + ); isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; @@ -796,6 +806,18 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 690e171..8fac7df 100644 --- a/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/client/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + 酒库管理系统 — 项目 TODO
生成于 2026-06-11 · 真相源 todo/todo.json
-
36全部
-
5待开始
+
46全部
+
1待开始
0开发中
-
17待验收
+
31待验收
14已验收
@@ -260,7 +260,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
平台 / 标签 - +
@@ -269,147 +269,35 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
- 📋 待开始 5 + 📋 待开始 1 ▴ 收起
  • -
    - 备案号为占位假值 -
    - 待开始 - 高优 · 紧急 - - - -
    -
    - -
    现为沪ICP备2026000000号(全0),上线前必须替换真实备案号。
    - - -
  • - -
  • -
    - 注册/联系入口「发邮件」升级为「加客服微信」并优化文案 -
    - 待开始 - 一般 / 优化 - - - -
    -
    - -
    当前注册成功页和网站联系支持入口引导用户「发邮件」,体验较弱。升级为扫码加客服微信,同时梳理相关文案措辞,使表达更专业、有亲和力。
    - - -
  • - -
  • -
    - 将拼音回填从启动逻辑改为一次性迁移脚本 -
    - 待开始 - 一般 / 优化 - 三级 - - -
    -
    - -
    main.go 每次启动执行 backfillPinyin 全表扫描,数据量大后拖慢启动。改为 go run ./cmd/migrate-pinyin 一次性迁移,后续新数据靠写入时自动生成
    - - -
  • - -
  • -
    - DB 连接池参数(MaxIdleConns/MaxOpenConns)改为可配置项 -
    - 待开始 - 一般 / 优化 - 三级 - - -
    -
    - -
    main.go 中硬编码 MaxIdleConns=10, MaxOpenConns=100,无法运维调优。改为读取 config(viper),并在文档中说明推荐值
    - - -
  • - -
  • - 明确 Inventories 反范式字段语义:是当前值还是入库快照 + License model 的 license_key 索引超 InnoDB 3072 字节限制需改用前缀索引
    待开始 - 一般 / 优化 - 二级 + 重要 + 三级
    -
    inventories 表存了 product_name/warehouse_name/supplier_name 等,既可能是冗余(与 products JOIN 重复),也可能是历史快照(入库时锁定)。需明确语义并在 model 注释中说明;若是快照,应只在写入时固定,不随主表变化
    +
    license.go 的 LicenseKey 是 size:2048+uniqueIndex,utf8mb4 下 8192 字节超 MySQL InnoDB 索引上限,全新环境 AutoMigrate 必失败(线上已手动建 license_key(768) 前缀索引绕过)。需在 model 层固化:缩短列或 GORM 指定索引前缀长度,并同步 schema.sql。
    @@ -430,7 +318,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
- 🔍 待验收 17 + 🔍 待验收 31 ▴ 收起
@@ -548,6 +436,62 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
+
  • +
    + CheckInventoryAvailability Scan错误未检查导致所有商品误报库存不足 +
    + 待验收 + 高优 · 紧急 + 三级 + + +
    +
    + +
    service/stock.go:312 DB查询失败时sums为空,所有商品have=0,合法出库审核被全部拒绝
    + + +
  • + +
  • +
    + 修复 act_runner→Forgejo 任务状态上报丢失导致构建成功却标失败 +
    + 待验收 + 高优 · 紧急 + 二级 + + +
    +
    + +
    v1.0.27~v1.0.32 连续 6 个版本 CI 全部'失败',但日志显示所有 job 实际构建成功(🏁 Job succeeded),是 act_runner 最终状态上报丢失(Failed to write EOT),被 Forgejo 僵尸任务清理标为 failure。生产环境因此停留在 v1.0.26(6/8)。需排查 relay/GOAWAY race 或升级 act_runner/Forgejo。
    + + +
  • +
  • +
  • +
    + finance ListRecords 和 inventory Logs handler 缺 pageSize 上限 +
    + 待验收 + 重要 + 三级 + + +
    +
    + +
    finance.go:36 和 inventory.go:130 漏加 ValidatePageSize,#37 未覆盖这两个 handler,可被任意用户触发全表扫描
    + + +
  • + +
  • +
    + ReconcileInventory 两条 Scan 错误未检查导致对账误判 +
    + 待验收 + 重要 + 三级 + + +
    +
    + +
    admin.go:122-123 invQuery/logQuery Scan错误被丢弃;invQuery失败→差异消失显示全部正常;logQuery失败→所有库存飘红为差异
    + + +
  • + +
  • +
    + license Info 端点 device_count 统计错误且 ListDevices 错误被吞 +
    + 待验收 + 重要 + 三级 + + +
    +
    + +
    handler/license.go:67-70 两个bug:1.devs,_ 错误被_吞掉DB故障时deviceCount=0;2.ListDevices(shopID)包含该店所有license设备而非当前license
    + + +
  • + +
  • +
    + 备案号为占位假值 +
    + 待验收 + 一般 / 优化 + + + +
    +
    + +
    现为沪ICP备2026000000号(全0),上线前必须替换真实备案号。
    + + +
  • +
  • +
  • +
    + 注册/联系入口「发邮件」升级为「加客服微信」并优化文案 +
    + 待验收 + 一般 / 优化 + + + +
    +
    + +
    当前注册成功页和网站联系支持入口引导用户「发邮件」,体验较弱。升级为扫码加客服微信,同时梳理相关文案措辞,使表达更专业、有亲和力。
    + + +
  • +
  • 🕐 2026-06-08 +
  • +
    + + +
  • +
    + 将拼音回填从启动逻辑改为一次性迁移脚本 +
    + 待验收 + 一般 / 优化 + 三级 + + +
    +
    + +
    main.go 每次启动执行 backfillPinyin 全表扫描,数据量大后拖慢启动。改为 go run ./cmd/migrate-pinyin 一次性迁移,后续新数据靠写入时自动生成
    + + +
  • + +
  • +
    + DB 连接池参数(MaxIdleConns/MaxOpenConns)改为可配置项 +
    + 待验收 + 一般 / 优化 + 三级 + + +
    +
    + +
    main.go 中硬编码 MaxIdleConns=10, MaxOpenConns=100,无法运维调优。改为读取 config(viper),并在文档中说明推荐值
    + + +
  • + +
  • +
    + 明确 Inventories 反范式字段语义:是当前值还是入库快照 +
    + 待验收 + 一般 / 优化 + 二级 + + +
    +
    + +
    inventories 表存了 product_name/warehouse_name/supplier_name 等,既可能是冗余(与 products JOIN 重复),也可能是历史快照(入库时锁定)。需明确语义并在 model 注释中说明;若是快照,应只在写入时固定,不随主表变化
    + + +
  • + +
  • +
    + license Activate 幂等路径 Update 错误未检查 +
    + 待验收 + 一般 / 优化 + 三级 + + +
    +
    + +
    service/license.go:70 s.db.Model(&existing).Update()失败时仍返回nil error,设备名未更新但调用方不知道
    + + +
  • + +
  • +
    + license Verify 加载 license 缺 shop_id 过滤(防御纵深) +
    + 待验收 + 一般 / 优化 + 三级 + + +
    +
    + +
    service/license.go:102 WHERE id=? AND is_active=1 应加 AND shop_id=? 防御数据异常时跨租户泄露
    + + +
  • + +
  • +
    + util/response.go 的 RespondError 等辅助函数从未被调用(#34 实际未完成) +
    + 待验收 + 一般 / 优化 + 二级 + + +
    +
    + +
    #34 只创建了util/response.go,没有将任何handler迁移过去,实际错误格式仍不统一,需完成迁移
    + + +
  • + +
  • +
    + 清理 ErrDeviceMismatch 死代码(多设备迁移后残留) +
    + 待验收 + 一般 / 优化 + 三级 + + +
    +
    + +
    service/license.go:24 ErrDeviceMismatch定义后从未返回,多设备迁移(#32)后已无单设备约束
    + +
  • @@ -1521,7 +1801,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; } return; } const escaped = reason.replace(/\/g, '\\').replace(/"/g, '\"'); - const cmd = 'node todo/todo.mjs reject ' + rejectId + ' --reason "' + escaped + '"'; + const cmd = '/todo reject ' + rejectId + ' ' + escaped; cmdText.textContent = cmd; cmdWrap.style.display = 'block'; document.getElementById('reject-confirm-btn').style.display = 'none'; diff --git a/todo/todo.json b/todo/todo.json index 550cd0a..0053771 100644 --- a/todo/todo.json +++ b/todo/todo.json @@ -1,9 +1,9 @@ { "meta": { "title": "酒库管理系统 — 项目 TODO", - "updated_at": "2026-06-10T16:38:37.763Z" + "updated_at": "2026-06-11T15:52:40.354Z" }, - "seq": 40, + "seq": 50, "items": [ { "id": 1, @@ -24,7 +24,7 @@ "id": 2, "title": "备案号为占位假值", "desc": "现为沪ICP备2026000000号(全0),上线前必须替换真实备案号。", - "level": "high", + "level": "low", "tags": [ "Web" ], @@ -32,7 +32,7 @@ "done": false, "completed_at": null, "version": null, - "status": "open" + "status": "done" }, { "id": 3, @@ -404,7 +404,7 @@ "done": false, "completed_at": null, "version": null, - "status": "open" + "status": "done" }, { "id": 24, @@ -613,7 +613,7 @@ "tags": [ "后端" ], - "status": "open", + "status": "done", "created_at": "2026-06-10T15:31:57.979Z", "done": false, "completed_at": null, @@ -628,7 +628,7 @@ "tags": [ "后端" ], - "status": "open", + "status": "done", "created_at": "2026-06-10T15:32:00.233Z", "done": false, "completed_at": null, @@ -644,11 +644,162 @@ "后端", "数据库" ], - "status": "open", + "status": "done", "created_at": "2026-06-10T15:32:03.641Z", "done": false, "completed_at": null, "version": null + }, + { + "id": 41, + "title": "CheckInventoryAvailability Scan错误未检查导致所有商品误报库存不足", + "desc": "service/stock.go:312 DB查询失败时sums为空,所有商品have=0,合法出库审核被全部拒绝", + "level": "high", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:34.919Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 42, + "title": "finance ListRecords 和 inventory Logs handler 缺 pageSize 上限", + "desc": "finance.go:36 和 inventory.go:130 漏加 ValidatePageSize,#37 未覆盖这两个 handler,可被任意用户触发全表扫描", + "level": "mid", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:46.152Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 43, + "title": "ReconcileInventory 两条 Scan 错误未检查导致对账误判", + "desc": "admin.go:122-123 invQuery/logQuery Scan错误被丢弃;invQuery失败→差异消失显示全部正常;logQuery失败→所有库存飘红为差异", + "level": "mid", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:46.205Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 44, + "title": "license Info 端点 device_count 统计错误且 ListDevices 错误被吞", + "desc": "handler/license.go:67-70 两个bug:1.devs,_ 错误被_吞掉DB故障时deviceCount=0;2.ListDevices(shopID)包含该店所有license设备而非当前license", + "level": "mid", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:46.257Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 45, + "title": "license Activate 幂等路径 Update 错误未检查", + "desc": "service/license.go:70 s.db.Model(&existing).Update()失败时仍返回nil error,设备名未更新但调用方不知道", + "level": "low", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:59.016Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 46, + "title": "license Verify 加载 license 缺 shop_id 过滤(防御纵深)", + "desc": "service/license.go:102 WHERE id=? AND is_active=1 应加 AND shop_id=? 防御数据异常时跨租户泄露", + "level": "low", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:59.066Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 47, + "title": "util/response.go 的 RespondError 等辅助函数从未被调用(#34 实际未完成)", + "desc": "#34 只创建了util/response.go,没有将任何handler迁移过去,实际错误格式仍不统一,需完成迁移", + "level": "low", + "tier": 2, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:59.118Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 48, + "title": "清理 ErrDeviceMismatch 死代码(多设备迁移后残留)", + "desc": "service/license.go:24 ErrDeviceMismatch定义后从未返回,多设备迁移(#32)后已无单设备约束", + "level": "low", + "tier": 3, + "tags": [ + "后端" + ], + "status": "done", + "created_at": "2026-06-10T23:59:59.168Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 49, + "title": "修复 act_runner→Forgejo 任务状态上报丢失导致构建成功却标失败", + "desc": "v1.0.27~v1.0.32 连续 6 个版本 CI 全部'失败',但日志显示所有 job 实际构建成功(🏁 Job succeeded),是 act_runner 最终状态上报丢失(Failed to write EOT),被 Forgejo 僵尸任务清理标为 failure。生产环境因此停留在 v1.0.26(6/8)。需排查 relay/GOAWAY race 或升级 act_runner/Forgejo。", + "level": "high", + "tier": 2, + "tags": [ + "CI/CD" + ], + "status": "done", + "created_at": "2026-06-11T13:55:07.388Z", + "done": false, + "completed_at": null, + "version": null + }, + { + "id": 50, + "title": "License model 的 license_key 索引超 InnoDB 3072 字节限制需改用前缀索引", + "desc": "license.go 的 LicenseKey 是 size:2048+uniqueIndex,utf8mb4 下 8192 字节超 MySQL InnoDB 索引上限,全新环境 AutoMigrate 必失败(线上已手动建 license_key(768) 前缀索引绕过)。需在 model 层固化:缩短列或 GORM 指定索引前缀长度,并同步 schema.sql。", + "level": "mid", + "tier": 3, + "tags": [ + "后端", + "数据库" + ], + "status": "open", + "created_at": "2026-06-11T15:52:40.353Z", + "done": false, + "completed_at": null, + "version": null } ] }