Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 02082df525 | |||
| 4c75f328c7 | |||
| 8628df5848 |
@@ -5,6 +5,24 @@ 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.35] - 2026-06-12
|
||||
|
||||
### 改进
|
||||
- Debug 版本窗口标题增加 [DEBUG] 后缀,便于与正式安装版区分
|
||||
|
||||
## [1.0.34] - 2026-06-12
|
||||
|
||||
### 修复
|
||||
- 修复 macOS 客户端打印时应用卡死、只能强制退出的问题
|
||||
|
||||
### 改进
|
||||
- 「关于我们」中「打开文档」「更新日志」等链接指向新域名 jiu.51yanmei.com
|
||||
|
||||
## [1.0.33] - 2026-06-12
|
||||
|
||||
### 改进
|
||||
- macOS 客户端插件集成从 CocoaPods 迁移至 Swift Package Manager,优化 macOS 构建流程
|
||||
|
||||
## [1.0.32] - 2026-06-11
|
||||
|
||||
### 修复
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"provider": "岩美技术有限公司",
|
||||
"website": "https://jiu.yanmei.com",
|
||||
"website": "https://jiu.51yanmei.com",
|
||||
"email": "yammy2023@163.com",
|
||||
"phone": "",
|
||||
"wechat": "",
|
||||
"terms_url": "https://jiu.yanmei.com/terms/",
|
||||
"privacy_url": "https://jiu.yanmei.com/privacy/",
|
||||
"docs_url": "https://jiu.yanmei.com/docs/"
|
||||
"terms_url": "https://jiu.51yanmei.com/terms/",
|
||||
"privacy_url": "https://jiu.51yanmei.com/privacy/",
|
||||
"docs_url": "https://jiu.51yanmei.com/docs/"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter/services.dart';
|
||||
import '../errors/error_reporter.dart';
|
||||
import 'package:pdf/pdf.dart';
|
||||
@@ -198,8 +200,14 @@ Future<void> printProductLabelImpl({
|
||||
),
|
||||
));
|
||||
|
||||
// 预生成 PDF 字节,避免 macOS NSPrintPanel 打开后再调 doc.save() 导致主线程卡住。
|
||||
final bytes = await doc.save();
|
||||
if (!kIsWeb && Platform.isMacOS) {
|
||||
// 让当前帧完成,再打开 macOS 原生打印面板,防止 sheet 动画与 Flutter 渲染死锁。
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
}
|
||||
await Printing.layoutPdf(
|
||||
name: '标签_${_fileTs()}', onLayout: (_) async => doc.save());
|
||||
name: '标签_${_fileTs()}', onLayout: (_) async => bytes);
|
||||
} catch (e, st) {
|
||||
reportError(e, st);
|
||||
throw Exception('打印失败,请检查打印机连接和驱动是否正常。\n详情:$e');
|
||||
@@ -439,8 +447,12 @@ Future<void> printStockInOrderImpl(StockInOrder order) async {
|
||||
),
|
||||
],
|
||||
));
|
||||
final bytes = await doc.save();
|
||||
if (!kIsWeb && Platform.isMacOS) {
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
}
|
||||
await Printing.layoutPdf(
|
||||
name: '入库单_${_fileTs()}', onLayout: (_) async => doc.save());
|
||||
name: '入库单_${_fileTs()}', onLayout: (_) async => bytes);
|
||||
} catch (e, st) {
|
||||
reportError(e, st);
|
||||
throw Exception('打印失败,请检查打印机连接和驱动是否正常。\n详情:$e');
|
||||
@@ -495,8 +507,12 @@ Future<void> printStockOutOrderImpl(StockOutOrder order) async {
|
||||
],
|
||||
));
|
||||
try {
|
||||
final bytes = await doc.save();
|
||||
if (!kIsWeb && Platform.isMacOS) {
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
}
|
||||
await Printing.layoutPdf(
|
||||
name: '出库单_${_fileTs()}', onLayout: (_) async => doc.save());
|
||||
name: '出库单_${_fileTs()}', onLayout: (_) async => bytes);
|
||||
} catch (e, st) {
|
||||
reportError(e, st);
|
||||
throw Exception('打印失败,请检查打印机连接和驱动是否正常。\n详情:$e');
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@@ -107,7 +108,7 @@ class _JiuAppState extends ConsumerState<JiuApp> {
|
||||
Widget build(BuildContext context) {
|
||||
final router = ref.watch(appRouterProvider);
|
||||
return MaterialApp.router(
|
||||
title: '岩美',
|
||||
title: kDebugMode ? '岩美 [DEBUG]' : '岩美',
|
||||
theme: AppTheme.light(),
|
||||
routerConfig: router,
|
||||
debugShowCheckedModeBanner: false,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||
/* 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 */;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,24 @@
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<PreActions>
|
||||
<ExecutionAction
|
||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Prepare Flutter Framework Script"
|
||||
scriptText = ""$FLUTTER_ROOT"/packages/flutter_tools/bin/macos_assemble.sh prepare ">
|
||||
<EnvironmentBuildable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "jiu_client.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</EnvironmentBuildable>
|
||||
</ActionContent>
|
||||
</ExecutionAction>
|
||||
</PreActions>
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
||||
+406
-126
@@ -223,10 +223,10 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
<h1>酒库管理系统 — 项目 TODO</h1>
|
||||
<div class="header-meta">生成于 2026-06-11 · 真相源 todo/todo.json</div>
|
||||
<div class="stats">
|
||||
<div class="stat-pill"><strong>36</strong>全部</div>
|
||||
<div class="stat-pill"><strong>5</strong>待开始</div>
|
||||
<div class="stat-pill"><strong>46</strong>全部</div>
|
||||
<div class="stat-pill"><strong>1</strong>待开始</div>
|
||||
<div class="stat-pill"><strong>0</strong>开发中</div>
|
||||
<div class="stat-pill"><strong>17</strong>待验收</div>
|
||||
<div class="stat-pill"><strong>31</strong>待验收</div>
|
||||
<div class="stat-pill"><strong>14</strong>已验收</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -260,7 +260,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
<div class="filter-sep"></div>
|
||||
<div class="filter-group">
|
||||
<span class="filter-label">平台 / 标签</span>
|
||||
<button class="filter-chip" data-filter-tag="Android">Android</button><button class="filter-chip" data-filter-tag="Web">Web</button><button class="filter-chip" data-filter-tag="Windows">Windows</button><button class="filter-chip" data-filter-tag="iOS">iOS</button><button class="filter-chip" data-filter-tag="mac">mac</button><button class="filter-chip" data-filter-tag="前端">前端</button><button class="filter-chip" data-filter-tag="后端">后端</button><button class="filter-chip" data-filter-tag="安全">安全</button><button class="filter-chip" data-filter-tag="数据库">数据库</button><button class="filter-chip" data-filter-tag="文档">文档</button>
|
||||
<button class="filter-chip" data-filter-tag="Android">Android</button><button class="filter-chip" data-filter-tag="CI/CD">CI/CD</button><button class="filter-chip" data-filter-tag="Web">Web</button><button class="filter-chip" data-filter-tag="Windows">Windows</button><button class="filter-chip" data-filter-tag="iOS">iOS</button><button class="filter-chip" data-filter-tag="mac">mac</button><button class="filter-chip" data-filter-tag="前端">前端</button><button class="filter-chip" data-filter-tag="后端">后端</button><button class="filter-chip" data-filter-tag="安全">安全</button><button class="filter-chip" data-filter-tag="数据库">数据库</button><button class="filter-chip" data-filter-tag="文档">文档</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -269,147 +269,35 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
|
||||
<div class="section-block" id="section-open">
|
||||
<div class="section-title st-open" data-toggle="open">
|
||||
📋 待开始 <span class="s-count">5</span>
|
||||
📋 待开始 <span class="s-count">1</span>
|
||||
<span class="s-arrow">▴ 收起</span>
|
||||
</div>
|
||||
<div class="section-list-wrap " id="list-wrap-open">
|
||||
<ul class="todo-list" id="list-open">
|
||||
|
||||
<li class="todo-card s-open"
|
||||
data-id="2"
|
||||
data-level="high"
|
||||
data-status="open"
|
||||
data-tier=""
|
||||
data-tags="Web">
|
||||
<div class="card-header">
|
||||
<span class="item-title">备案号为占位假值</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-open">待开始</span>
|
||||
<span class="tag t-block">高优 · 紧急</span>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">现为沪ICP备2026000000号(全0),上线前必须替换真实备案号。</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="Web">Web</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-08</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-open"
|
||||
data-id="23"
|
||||
data-level="low"
|
||||
data-status="open"
|
||||
data-tier=""
|
||||
data-tags="前端,Web">
|
||||
<div class="card-header">
|
||||
<span class="item-title">注册/联系入口「发邮件」升级为「加客服微信」并优化文案</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-open">待开始</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">当前注册成功页和网站联系支持入口引导用户「发邮件」,体验较弱。升级为扫码加客服微信,同时梳理相关文案措辞,使表达更专业、有亲和力。</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-08</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-open"
|
||||
data-id="38"
|
||||
data-level="low"
|
||||
data-id="50"
|
||||
data-level="mid"
|
||||
data-status="open"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">将拼音回填从启动逻辑改为一次性迁移脚本</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-open">待开始</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">main.go 每次启动执行 backfillPinyin 全表扫描,数据量大后拖慢启动。改为 go run ./cmd/migrate-pinyin 一次性迁移,后续新数据靠写入时自动生成</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-10</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-open"
|
||||
data-id="39"
|
||||
data-level="low"
|
||||
data-status="open"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">DB 连接池参数(MaxIdleConns/MaxOpenConns)改为可配置项</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-open">待开始</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">main.go 中硬编码 MaxIdleConns=10, MaxOpenConns=100,无法运维调优。改为读取 config(viper),并在文档中说明推荐值</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-10</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-open"
|
||||
data-id="40"
|
||||
data-level="low"
|
||||
data-status="open"
|
||||
data-tier="2"
|
||||
data-tags="后端,数据库">
|
||||
<div class="card-header">
|
||||
<span class="item-title">明确 Inventories 反范式字段语义:是当前值还是入库快照</span>
|
||||
<span class="item-title">License model 的 license_key 索引超 InnoDB 3072 字节限制需改用前缀索引</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-open">待开始</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-2">二级</span>
|
||||
<span class="tag t-high">重要</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">inventories 表存了 product_name/warehouse_name/supplier_name 等,既可能是冗余(与 products JOIN 重复),也可能是历史快照(入库时锁定)。需明确语义并在 model 注释中说明;若是快照,应只在写入时固定,不随主表变化</div>
|
||||
<div class="item-desc">license.go 的 LicenseKey 是 size:2048+uniqueIndex,utf8mb4 下 8192 字节超 MySQL InnoDB 索引上限,全新环境 AutoMigrate 必失败(线上已手动建 license_key(768) 前缀索引绕过)。需在 model 层固化:缩短列或 GORM 指定索引前缀长度,并同步 schema.sql。</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span> <span class="tag t-tag" data-tag="数据库">数据库</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-10</span>
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -430,7 +318,7 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
</div>
|
||||
<div class="section-block" id="section-done">
|
||||
<div class="section-title st-done" data-toggle="done">
|
||||
🔍 待验收 <span class="s-count">17</span>
|
||||
🔍 待验收 <span class="s-count">31</span>
|
||||
<span class="s-arrow">▴ 收起</span>
|
||||
</div>
|
||||
<div class="section-list-wrap " id="list-wrap-done">
|
||||
@@ -548,6 +436,62 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="41"
|
||||
data-level="high"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">CheckInventoryAvailability Scan错误未检查导致所有商品误报库存不足</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-block">高优 · 紧急</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="41" data-title="CheckInventoryAvailability Scan错误未检查导致所有商品误报库存不足">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">service/stock.go:312 DB查询失败时sums为空,所有商品have=0,合法出库审核被全部拒绝</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="49"
|
||||
data-level="high"
|
||||
data-status="done"
|
||||
data-tier="2"
|
||||
data-tags="CI/CD">
|
||||
<div class="card-header">
|
||||
<span class="item-title">修复 act_runner→Forgejo 任务状态上报丢失导致构建成功却标失败</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-block">高优 · 紧急</span>
|
||||
<span class="tag tier-2">二级</span>
|
||||
|
||||
<button class="reject-btn" data-id="49" data-title="修复 act_runner→Forgejo 任务状态上报丢失导致构建成功却标失败">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-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。</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="CI/CD">CI/CD</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="20"
|
||||
data-level="mid"
|
||||
@@ -772,6 +716,118 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="42"
|
||||
data-level="mid"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">finance ListRecords 和 inventory Logs handler 缺 pageSize 上限</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-high">重要</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="42" data-title="finance ListRecords 和 inventory Logs handler 缺 pageSize 上限">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">finance.go:36 和 inventory.go:130 漏加 ValidatePageSize,#37 未覆盖这两个 handler,可被任意用户触发全表扫描</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="43"
|
||||
data-level="mid"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">ReconcileInventory 两条 Scan 错误未检查导致对账误判</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-high">重要</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="43" data-title="ReconcileInventory 两条 Scan 错误未检查导致对账误判">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">admin.go:122-123 invQuery/logQuery Scan错误被丢弃;invQuery失败→差异消失显示全部正常;logQuery失败→所有库存飘红为差异</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="44"
|
||||
data-level="mid"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">license Info 端点 device_count 统计错误且 ListDevices 错误被吞</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-high">重要</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="44" data-title="license Info 端点 device_count 统计错误且 ListDevices 错误被吞">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">handler/license.go:67-70 两个bug:1.devs,_ 错误被_吞掉DB故障时deviceCount=0;2.ListDevices(shopID)包含该店所有license设备而非当前license</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="2"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier=""
|
||||
data-tags="Web">
|
||||
<div class="card-header">
|
||||
<span class="item-title">备案号为占位假值</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
|
||||
|
||||
<button class="reject-btn" data-id="2" data-title="备案号为占位假值">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">现为沪ICP备2026000000号(全0),上线前必须替换真实备案号。</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="Web">Web</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-08</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="21"
|
||||
data-level="low"
|
||||
@@ -882,6 +938,34 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="23"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier=""
|
||||
data-tags="前端,Web">
|
||||
<div class="card-header">
|
||||
<span class="item-title">注册/联系入口「发邮件」升级为「加客服微信」并优化文案</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
|
||||
|
||||
<button class="reject-btn" data-id="23" data-title="注册/联系入口「发邮件」升级为「加客服微信」并优化文案">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">当前注册成功页和网站联系支持入口引导用户「发邮件」,体验较弱。升级为扫码加客服微信,同时梳理相关文案措辞,使表达更专业、有亲和力。</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="前端">前端</span> <span class="tag t-tag" data-tag="Web">Web</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-08</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="24"
|
||||
data-level="low"
|
||||
@@ -962,6 +1046,202 @@ ul.todo-list { list-style: none; margin: 0; padding: 0; }
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-08</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="38"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">将拼音回填从启动逻辑改为一次性迁移脚本</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="38" data-title="将拼音回填从启动逻辑改为一次性迁移脚本">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">main.go 每次启动执行 backfillPinyin 全表扫描,数据量大后拖慢启动。改为 go run ./cmd/migrate-pinyin 一次性迁移,后续新数据靠写入时自动生成</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-10</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="39"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">DB 连接池参数(MaxIdleConns/MaxOpenConns)改为可配置项</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="39" data-title="DB 连接池参数(MaxIdleConns/MaxOpenConns)改为可配置项">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">main.go 中硬编码 MaxIdleConns=10, MaxOpenConns=100,无法运维调优。改为读取 config(viper),并在文档中说明推荐值</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-10</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="40"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="2"
|
||||
data-tags="后端,数据库">
|
||||
<div class="card-header">
|
||||
<span class="item-title">明确 Inventories 反范式字段语义:是当前值还是入库快照</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-2">二级</span>
|
||||
|
||||
<button class="reject-btn" data-id="40" data-title="明确 Inventories 反范式字段语义:是当前值还是入库快照">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">inventories 表存了 product_name/warehouse_name/supplier_name 等,既可能是冗余(与 products JOIN 重复),也可能是历史快照(入库时锁定)。需明确语义并在 model 注释中说明;若是快照,应只在写入时固定,不随主表变化</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span> <span class="tag t-tag" data-tag="数据库">数据库</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-10</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="45"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">license Activate 幂等路径 Update 错误未检查</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="45" data-title="license Activate 幂等路径 Update 错误未检查">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">service/license.go:70 s.db.Model(&existing).Update()失败时仍返回nil error,设备名未更新但调用方不知道</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="46"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">license Verify 加载 license 缺 shop_id 过滤(防御纵深)</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="46" data-title="license Verify 加载 license 缺 shop_id 过滤(防御纵深)">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">service/license.go:102 WHERE id=? AND is_active=1 应加 AND shop_id=? 防御数据异常时跨租户泄露</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="47"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="2"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">util/response.go 的 RespondError 等辅助函数从未被调用(#34 实际未完成)</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-2">二级</span>
|
||||
|
||||
<button class="reject-btn" data-id="47" data-title="util/response.go 的 RespondError 等辅助函数从未被调用(#34 实际未完成)">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">#34 只创建了util/response.go,没有将任何handler迁移过去,实际错误格式仍不统一,需完成迁移</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="todo-card s-done"
|
||||
data-id="48"
|
||||
data-level="low"
|
||||
data-status="done"
|
||||
data-tier="3"
|
||||
data-tags="后端">
|
||||
<div class="card-header">
|
||||
<span class="item-title">清理 ErrDeviceMismatch 死代码(多设备迁移后残留)</span>
|
||||
<div class="card-badges">
|
||||
<span class="tag status-badge s-done">待验收</span>
|
||||
<span class="tag t-low">一般 / 优化</span>
|
||||
<span class="tag tier-3">三级</span>
|
||||
|
||||
<button class="reject-btn" data-id="48" data-title="清理 ErrDeviceMismatch 死代码(多设备迁移后残留)">拒绝验收</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-desc">service/license.go:24 ErrDeviceMismatch定义后从未返回,多设备迁移(#32)后已无单设备约束</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="tag-row"><span class="tag t-tag" data-tag="后端">后端</span></div>
|
||||
<div class="item-meta">
|
||||
<span class="meta-date">🕐 2026-06-11</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@@ -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';
|
||||
|
||||
+159
-8
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user