@routerhub/agent-rules 1.5.22 → 1.5.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.base.md CHANGED
@@ -33,6 +33,7 @@
33
33
 
34
34
  ```markdown
35
35
  ## Description
36
+
36
37
  背景:当前在并发刷新 token 时存在竞态,会导致少量请求拿到过期 token 被拒。
37
38
 
38
39
  改动:给 token 刷新加分布式锁,保证同一时刻只有一个刷新在飞,其余请求等待复用结果。
@@ -53,6 +54,7 @@ Closes #456
53
54
 
54
55
  ```markdown
55
56
  ## Test Plan
57
+
56
58
  1. 单元测试:
57
59
  $ npm test -- auth/token/
58
60
  -> 全部通过(截图见下)
@@ -114,6 +116,7 @@ Closes #456
114
116
  - 新增或更新的测试用例必须接入项目回归测试中心的可运行范围:用户明确说明当前版本号或版本名称时,归档到对应版本测试范围;用户未说明版本时,归档到全量测试,确保“全量测试”会执行或展示该用例。
115
117
  - 使用 Superpowers 或其他代理流程处理需求时,测试设计是交付的一部分;需求文档、实现计划、代码改动与测试接入必须同步考虑,禁止只完成业务代码而遗漏全量或版本回归用例。
116
118
  - 交付说明必须列出新增或更新的测试用例名称、所在文件、归属范围(版本或全量)以及已执行的测试命令与结果。
119
+ - 用户未明确豁免时,默认按 Superpowers 等价流程执行新需求交付;每次需求都必须新增或更新至少一个可自动化回归用例,并接入“全量测试”范围。
117
120
 
118
121
  ## Superpowers 安装与缺失处理
119
122
 
@@ -225,7 +228,7 @@ Closes #456
225
228
  ## Docker 与部署
226
229
 
227
230
  - 默认本地 `docker build`,构建后 `docker push` 到 `ghcr.io`,推送前确保正确 tag。
228
- - 部署时打镜像 tag 必须对项目内所有服务/镜像统一打 tag,无论该镜像是否有代码改动;确保所有镜像版本号一致后再发版。
231
+ - 部署时打包镜像必须统一使用当前 git 提交的 short hash 作为镜像 tag 和版本号;项目内所有服务/镜像都必须使用同一个值,无论该镜像是否有代码改动,确保所有镜像版本号一致后再发版。
229
232
  - 部署通过 Portainer 管理界面操作,禁止 SSH 手动执行 docker 命令;地址和账号配置在 `AGENTS.private.md` 或环境变量中,禁止硬编码。
230
233
  - 始终通过 Portainer API 更新 Stack 环境变量触发重新部署,不要 SSH 手动操作 Portainer 管理的容器。
231
234
  - 测试环境和生产环境都通过 Portainer 部署,严禁 SSH 手动操作。测试环境是 Edge Agent(endpoint 7, stack 31),tunnel 按需建立、空闲自动断开,调 API 前必须先请求 `/endpoints/7/docker/info` 预热 tunnel;推荐直接用 `python3 portainer-update-stack.py <VERSION>` 部署(内置 tunnel 预热 + 重试)。生产环境是 Docker API(endpoint 8, stack 26),`APP_VERSION` 三服务共用。
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  所有对 @routerhub/agent-rules 的重大更改都会记录在这个文件中。
4
4
 
5
+ ## [1.5.24] - 2026-06-17
6
+
7
+ ### Added
8
+
9
+ - 新增镜像版本规则:打包镜像时必须统一使用当前 git 提交的 short hash 作为镜像 tag 和版本号,并在所有服务间保持一致。
10
+
5
11
  ## [1.5.21] - 2026-06-10
6
12
 
7
13
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routerhub/agent-rules",
3
- "version": "1.5.22",
3
+ "version": "1.5.24",
4
4
  "description": "Shared Copilot agent rules and guidelines for RouterHub projects",
5
5
  "main": "AGENTS.base.md",
6
6
  "bin": {
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: "DevOps 部署规则"
3
+ applyTo: ["**/Dockerfile","**/Dockerfile.*","**/docker-compose*.yml","**/docker-compose*.yaml","**/*.sh","**/.gitlab-ci.yml","**/.github/workflows/*.yml","**/.github/workflows/*.yaml"]
4
+ outputName: "devops"
5
+ ---
6
+
7
+ ## Docker 与部署
8
+
9
+ - 默认本地 `docker build`,构建后 `docker push` 到 `ghcr.io`,推送前确保正确 tag。
10
+ - 部署时打包镜像必须统一使用当前 git 提交的 short hash 作为镜像 tag 和版本号;项目内所有服务/镜像都必须使用同一个值,无论该镜像是否有代码改动,确保所有镜像版本号一致后再发版。
11
+ - 部署通过 Portainer 管理界面操作,禁止 SSH 手动执行 docker 命令;地址和账号配置在 `AGENTS.private.md` 或环境变量中,禁止硬编码。
12
+ - 始终通过 Portainer API 更新 Stack 环境变量触发重新部署,不要 SSH 手动操作 Portainer 管理的容器。
13
+ - 测试环境和生产环境都通过 Portainer 部署,严禁 SSH 手动操作。测试环境是 Edge Agent(endpoint 7, stack 31),tunnel 按需建立、空闲自动断开,调 API 前必须先请求 `/endpoints/7/docker/info` 预热 tunnel;推荐直接用 `python3 portainer-update-stack.py <VERSION>` 部署(内置 tunnel 预热 + 重试)。生产环境是 Docker API(endpoint 8, stack 26),`APP_VERSION` 三服务共用。
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: "前端规则"
3
+ applyTo: ["**/*.ts","**/*.tsx","**/*.js","**/*.jsx","**/*.vue","**/*.css","**/*.scss"]
4
+ outputName: "frontend"
5
+ ---
6
+
7
+ ## Figma 还原规范
8
+
9
+ - 实现 Figma 设计时,必须以 Figma 文件为唯一视觉与交互事实源,逐项还原布局、尺寸、间距、颜色、字体、层级、组件状态、响应式规则和可见文案,禁止按个人审美或主观推测重设计。
10
+ - Figma 中配置或表达的跳转、链接、页面流、弹窗、hover/click 等交互必须同步实现;原型未明确但影响流程闭环的交互,需先核对现有产品或询问用户,禁止自行脑补。
11
+ - 交付前必须对照 Figma 做视觉和交互验收,发现无法完全还原的素材、字体、数据或平台限制时,必须明确说明差异和原因。
12
+
13
+ ## 文件约束
14
+
15
+ - 不随意修改核心业务文件和 API 相关代码,不编写或修改 `README.md`。
16
+ - TypeScript 类型优先复用 `typings.d.ts`,不存在时再自定义。
17
+
18
+ ## 命名与类型
19
+
20
+ - 驼峰命名(小驼峰/大驼峰),禁止下划线;变量至少两个单词。
21
+ - 禁止 `as` 和 `any`;`props` 类型优先复用,不重复定义。
22
+
23
+ ## 代码风格
24
+
25
+ - 函数式编程,不写 `class`,不写 `try/catch`。
26
+ - 禁止重复实现:复用现有函数/组件/配置,发现重复必须提取封装为公共方法。
27
+ - 同一数据/配置只在一处维护,其余通过引用获取,改一处全局生效。
28
+ - 禁止硬编码数字;常量/枚举定义在 `Const.ts` 或 `constants.ts`,`tab` 索引统一使用常量,时间用 `dayjs`。
29
+ - 遵循 SOLID 原则,避免过度设计;数据回显优先用展开运算符(`...`)。
30
+ - 复用组件通过 `fromType`(值为当前页面名)区分来源,内部差异逻辑基于 `fromType` 分支。
31
+
32
+ ## 样式(Tailwind CSS)
33
+
34
+ - 统一 Tailwind CSS,禁止新增 `*.module.scss`、`*.module.css`、`.css` 文件(历史文件可保留)。
35
+ - 项目未集成 Tailwind 时,先完成安装配置再开发。
36
+ - 新增样式通过 utility classes 在 JSX/TSX 中编写;不满足时优先 `tailwind.config` extend → `@apply` 封装 → 行内 `style`。
37
+ - 复杂/重复样式提取为 Tailwind 组件类或 React 组件,避免工具类堆砌。
38
+ - 类名小驼峰,禁止 `span` 标签选择器。
39
+
40
+ ## 组件复用
41
+
42
+ - 优先复用已有组件,能通过 `props` 定制就不建新组件;新功能尽量封装为可复用组件。
43
+
44
+ ## 前端 API 规范
45
+
46
+ - API 请求严格使用 OpenAPI 生成的方法,禁止手写请求或直接拼接路径。
47
+ - 接口变更后先更新 OpenAPI 定义并重新生成 API 代码,再进行业务开发。
48
+
49
+ ## 依赖与构建
50
+
51
+ - 依赖安装统一 `pnpm`,禁止 `npm install`/`yarn install`。
52
+ - 写完代码先 `npm run format`,再 `npm run build`,构建通过才可发版。
53
+
54
+ ## 测试
55
+
56
+ - 测试描述、断言使用中文,覆盖中文场景;充值类测试默认用充值 1 的数据。
57
+ - 用户明确要求由代理自行执行自动化测试时,允许使用无头浏览器进行测试与验证。
58
+ - 写完业务后执行 `pnpm run test:e2e:ui`,告知开发者对应测试用例名称;通过后打开 UI 供手动验证。
59
+ - 端口被占用时自动切换新端口。
60
+ - 自动化测试中,若 Mock 数据不影响业务逻辑验证,优先使用 Mock 数据代替真实接口调用,减少外部依赖和测试不稳定性。
61
+
62
+ ## 错误日志
63
+
64
+ - 用 `console.error` 记录错误(含函数名/模块名上下文),禁止 `console.log` 输出错误。
65
+ - 提交前移除调试日志和临时代码。
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: "通用规则"
3
+ ---
4
+
5
+ ## 语言与内容
6
+
7
+ - 始终使用中文回答,代码注释使用中文,每行代码配中文注释。
8
+ - 我是测试用的。
9
+ - 页面 UI 内容(按钮、字段名、提示等)全部英文;如需中文在 `AGENTS.private.md` 中声明。
10
+ - 仅修改网站协议、条款、页面文案等文本内容时,必须保留原有结构、格式、样式和布局,只替换文字;只有用户明确要求调整样式时,才允许同步修改样式。
11
+
12
+ ## Git 规范
13
+
14
+ - 分支用 Git Flow(`feature/`、`bugfix/`、`hotfix/`、`refactor/`、`chore/`、`docs/`、`test/`),英文小写中划线分隔。
15
+ - commit 信息必须中文,禁止 `git push --force`。
16
+
17
+ ## PR 提交、评审与合入规范
18
+
19
+ - PR 的目标是让审阅者在不依赖私下沟通的情况下独立理解、验证并放心 Approve;一个好的 PR 必须自解释。
20
+ - 一个 PR 只做一件事(One logical change per PR),必须是完整、独立、可审阅的逻辑改动,禁止把重构、修 bug、加功能混在同一个 PR。
21
+ - PR 应保持小而聚焦,尽量控制在约 200 行以内,超过 500 行应优先拆分;小 PR 审得快、回滚风险低、`git bisect` 定位更精准。
22
+ - 大改动必须拆成 Stacked PRs(例如 PR1 → PR2 → PR3),每个 PR 都要能独立 review、独立合入;底层先合,上层后合。
23
+ - 每个 PR 必须能独立通过编译与测试,禁止出现“这个 PR 编译不过,要等下一个 PR 才能跑”的状态;每一层都应是绿色可发布状态。
24
+ - PR Title 必须用祈使句、现在时态描述“做了什么”,建议加模块/组件前缀,保持简洁且一行说清。
25
+ - PR Title 示例:`[auth] Fix token refresh race condition on concurrent requests`、`[payments] Add idempotency key to charge API`、`[infra] Migrate cache layer from Redis 6 to Redis 7`。
26
+ - PR Title 禁止使用 `fix bug`、`update code`、`改了一下` 等无法表达实际改动的标题。
27
+ - PR Description 必须足够充分,至少回答 What(改了什么)、Why(为什么改,解决什么问题或满足什么需求)、How(采用什么方案,为什么选该方案)。
28
+ - PR Description 和 Test Plan 的文字应尽可能简洁明了,优先用页面操作路径、按钮点击、表单输入、可见结果描述验证过程;尽量少用代码片段解释,除非代码是理解变更或复现问题的必要证据。
29
+ - 涉及行为变更、接口变更、数据迁移、性能影响时,必须在 Description 中显式写出。
30
+ - 有意不做的事、已知局限、后续 follow-up 必须写清楚,避免 reviewer 重复追问。
31
+ - 关联 issue 必须在 PR 中链接,并优先使用 GitHub 关键字自动关闭,例如 `Closes #123`、`Fixes #123`。
32
+ - Description 推荐模板:
33
+
34
+ ```markdown
35
+ ## Description
36
+
37
+ 背景:当前在并发刷新 token 时存在竞态,会导致少量请求拿到过期 token 被拒。
38
+
39
+ 改动:给 token 刷新加分布式锁,保证同一时刻只有一个刷新在飞,其余请求等待复用结果。
40
+
41
+ 方案取舍:考虑过乐观重试,但在高并发下重试风暴更糟,故选锁方案。锁超时 2s 兜底。
42
+
43
+ 不在本 PR 范围:监控告警接入留作后续 follow-up(#457)。
44
+
45
+ Closes #456
46
+ ```
47
+
48
+ - Test Plan 是硬性必填项,没有 Test Plan 的 PR 不允许进入审阅,建议写进 `.github/PULL_REQUEST_TEMPLATE.md` 固定章节。
49
+ - Test Plan 必须说明如何验证改动正确,并提供可复现步骤或证据,包括自动化测试命令与结果、手动验证步骤、截图、录屏、日志输出、请求响应、修复前后对比等。
50
+ - UI 改动必须贴前后对比截图;接口改动必须贴请求响应;修 bug 必须贴复现前与修复后的对比。
51
+ - Test Plan 必须覆盖必要边界情况,例如并发、异常、空值、回滚路径等。
52
+ - 禁止只写 `tested locally`、`测了没问题`;能用文字日志说明的,也要贴日志原文。
53
+ - Test Plan 推荐模板:
54
+
55
+ ```markdown
56
+ ## Test Plan
57
+
58
+ 1. 单元测试:
59
+ $ npm test -- auth/token/
60
+ -> 全部通过(截图见下)
61
+
62
+ 2. 手动复现原 bug:
63
+ - 开 50 并发同时调 /refresh
64
+ - 修复前:约 3% 请求返回 401(日志附后)
65
+ - 修复后:0 失败(截图:dashboard 401 曲线归零)
66
+
67
+ 3. 回滚验证:关闭 feature flag 后行为回到旧逻辑,正常。
68
+
69
+ [截图1:测试通过结果]
70
+ [截图2:修复前后 401 曲线对比]
71
+ ```
72
+
73
+ - 每个 PR 至少需要一名 reviewer Approve 才能合入,建议用 Branch protection 强制 `Require a pull request before merging` 和至少 1 个 Approval。
74
+ - Reviewer 优先指定最熟悉对应模块的 owner,并通过 `CODEOWNERS` 自动请求对应 owner 审阅。
75
+ - 涉及多模块时,每个模块都要指定对应 reviewer。
76
+ - 高风险改动(安全、支付、数据迁移、对外接口)必须通过 `CODEOWNERS` 设置 Required review,由对应 owner 通过后才能合入。
77
+ - 作者不能 Approve 自己的 PR。
78
+ - PR 其他元数据必须完整:Assignees 填负责人,Labels 填类型/优先级/模块,Linked Issues/Projects 关联需求来源与项目看板,Milestone 按需关联发布里程碑。
79
+ - 尚未准备好审阅时必须先开 Draft PR,准备好后再标记 `Ready for review`。
80
+ - 作者提交审阅前必须完成自查:PR 只做一件事;没有夹带格式化、顺手改动等无关改动;Title 清晰;Description 写明 What/Why/How;Test Plan 完整且带证据;已自审 `Files changed`;已移除调试代码、注释代码和无效 TODO;没有泄露密钥、token、内部地址、PII 等敏感信息;已指定合适 reviewer;已关联 issue;本地编译、lint、测试通过;CI status checks 全绿。
81
+ - 满足以下全部条件才允许 Merge:至少一名 reviewer 已 Approve;`CODEOWNERS` required review(如有)已通过;所有 required status checks(构建、单测、lint、静态分析等)全部绿色;所有 review 评论和 `Request changes` 均已解决并 Resolve conversation;分支与目标分支无冲突且已更新到最新;Stacked PR 的所有底层依赖已先行合入。
82
+ - 建议开启 Branch protection 强制合入门禁,并开启 `Require branches to be up to date`。
83
+ - 团队应统一 Merge 方式,多数情况用 `Squash and merge` 保持主干历史干净;需要保留完整提交历史时再用 merge commit。
84
+ - Reviewer 收到 review 请求后应尽量在 1 个工作日内给出首次反馈。
85
+ - Reviewer 必须看懂再 Approve;看不懂就提问,禁止为了快而盲目 Approve。
86
+ - Reviewer 反馈必须区分等级:必须改用 `Request changes`,建议项标注 `nit:` 或 `optional:`,疑问标注 `question:`,避免作者误判优先级。
87
+ - Review 评论必须对事不对人,针对代码与方案并保持尊重。
88
+ - Reviewer Approve 即代表认可该改动可以上线,并对该判断负责。
89
+ - 作者必须回复每一条 review 评论,即使只是 `Done` 或解释为何不改,并 Resolve 对应 conversation。
90
+ - 有分歧时优先在 PR 上公开讨论,结论必须写回 PR,避免私聊后无记录。
91
+ - 较大方案分歧可以升级为线下或会议讨论,但最终结论必须回写到 PR。
92
+ - 改动后必须使用 `Re-request review` 重新请求审阅,并在评论里简述本次更新改了什么。
93
+ - 必须避免以下反模式:Test Plan 只写“测了没问题”;一个 PR 改 2000 行且跨多个模块;Description 只有“fix bug”;CI 红着或跳过检查直接合;把格式化/重命名和逻辑改动混在一起;评论不回复、不 Resolve 就直接重提 review。
94
+ - PR 规范可按团队约定微调字段,但“充分的 Description + 带证据的 Test Plan + 至少一人 Approve + 状态检查全绿才能 Merge”是不可妥协的核心要求。
95
+
96
+ ## 安全
97
+
98
+ - 用户明确要求上线/部署生产环境时,直接执行,无需二次确认。
99
+ - 执行过程中自行触及生产环境操作(非用户明确要求),必须先向用户二次确认后再执行。
100
+
101
+ ## 需求文档
102
+
103
+ - 新需求先在 `docs/` 写文档,含:目标、范围、功能要求、验收标准。
104
+
105
+ ## 文档格式
106
+
107
+ - 所有新建文档必须使用 HTML 格式(`.html`),禁止使用 Markdown(`.md`)格式。
108
+ - 已有的 `.md` 文件可保留,但新增文档一律使用 HTML。
109
+ - 编写 HTML 文档时,文档标题、正文、章节、说明文字、图注、表格等内容必须使用中文;仅代码、命令、专有名词、接口字段或页面 UI 原文可保留英文。
110
+ - 编写 HTML 文档时,核心内容必须优先用截图、图片、流程图、对比图、标注图等可视化形式表达;图片内需添加箭头、圈选和简短中文标注,尽量减少英文字段和长段文字,能用可视化表达的内容不得只用文字说明。
111
+ - 编写 HTML 文档时,所有图片资源(包括截图、图表、插图等)必须以 base64 data URI 形式内嵌到 HTML 中,禁止引用或额外输出独立的 PNG、JPG、JPEG、SVG、WebP 等图片文件,确保他人只打开 HTML 文件即可看到全部内容并用于发版。
112
+
113
+ ## 新需求与回归测试准入
114
+
115
+ - 每个新需求必须同步新增或更新可自动化回归用例;仅纯文案、纯文档或无可自动化行为的改动可例外,但交付时必须说明无需新增用例的原因与人工验证方式。
116
+ - 新增或更新的测试用例必须接入项目回归测试中心的可运行范围:用户明确说明当前版本号或版本名称时,归档到对应版本测试范围;用户未说明版本时,归档到全量测试,确保“全量测试”会执行或展示该用例。
117
+ - 使用 Superpowers 或其他代理流程处理需求时,测试设计是交付的一部分;需求文档、实现计划、代码改动与测试接入必须同步考虑,禁止只完成业务代码而遗漏全量或版本回归用例。
118
+ - 交付说明必须列出新增或更新的测试用例名称、所在文件、归属范围(版本或全量)以及已执行的测试命令与结果。
119
+ - 用户未明确豁免时,默认按 Superpowers 等价流程执行新需求交付;每次需求都必须新增或更新至少一个可自动化回归用例,并接入“全量测试”范围。
120
+
121
+ ## Superpowers 安装与缺失处理
122
+
123
+ - 团队统一推荐使用 Superpowers 插件或同等技能流程处理新需求、调试、计划、测试驱动开发和完成前验证。
124
+ - 代理或开发者进入项目后,如果当前环境无法使用 Superpowers,应先提示用户安装或启用 Superpowers;当前代理支持插件安装工具时,应优先发起安装建议,当前代理不支持时,应给出清晰的手动安装说明。
125
+ - 用户暂不安装或当前环境无法安装时,不得因此中断任务;必须按本规则中的等价流程继续执行,包括需求文档、实现计划、测试准入、代码实现和完成前验证。
126
+ - 不得把某一台电脑已安装 Superpowers 当作团队默认事实;交付说明中应明确本次是使用 Superpowers 流程,还是按 AGENTS 规则执行了等价流程。
127
+
128
+ ## 新需求与回归测试准入
129
+
130
+ - 每个新需求必须同步新增或更新可自动化回归用例;仅纯文案、纯文档或无可自动化行为的改动可例外,但交付时必须说明无需新增用例的原因与人工验证方式。
131
+ - 新增或更新的测试用例必须接入项目回归测试中心的可运行范围:用户明确说明当前版本号或版本名称时,归档到对应版本测试范围;用户未说明版本时,归档到全量测试,确保“全量测试”会执行或展示该用例。
132
+ - 使用 Superpowers 或其他代理流程处理需求时,测试设计是交付的一部分;需求文档、实现计划、代码改动与测试接入必须同步考虑,禁止只完成业务代码而遗漏全量或版本回归用例。
133
+ - 交付说明必须列出新增或更新的测试用例名称、所在文件、归属范围(版本或全量)以及已执行的测试命令与结果。
134
+
135
+ ## 优先级
136
+
137
+ 1. 项目私有规则(AGENTS.private.md)
138
+ 2. 基础规则(此文件)
139
+
140
+ ## 截图规范
141
+
142
+ - 当用户要求截图时,必须截取整页(full page),不得只截可视区域。
143
+ - 截图结果必须包含当前页面 URL(地址栏可见或在截图说明中明确写出完整 URL)。
144
+ - 在截图上添加箭头、标注、提示文字等注释时,必须放在页面空白区域,不得覆盖页面原有内容(文字、按钮、表格数据等)。
145
+
146
+ ## 可视化汇报
147
+
148
+ - 完成任务后的汇报优先提供可视化结果,能打开页面时就直接在集成浏览器中打开,并定位到相关区域后再汇报。
149
+ - 涉及配置、官网或其他系统联动时,需同时打开所有相关页面,并按实际操作路径展示联动结果,方便直接验证。
150
+ - 若客观上无法可视化展示,需说明原因,并补充截图、录屏、日志或请求响应作为替代证据。
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: "Go 后端规则"
3
+ applyTo: ["**/*.go"]
4
+ outputName: "go-backend"
5
+ ---
6
+
7
+ ## Go 语言规则
8
+
9
+ - 优先值传递与局部变量生命周期控制,避免内存逃逸;无必要不返回局部变量指针。
10
+ - 所有删除操作必须使用软删除机制;`DeletedAt` 字段类型必须用 `gorm.DeletedAt`,禁止用 `*time.Time`(后者不实现 `DeleteClausesInterface`,会导致硬删除)。
11
+
12
+ ## GORM Model 规范
13
+
14
+ - `DeletedAt` 字段必须使用 `gorm.DeletedAt` 类型,严禁使用 `*time.Time`。`*time.Time` 不会触发 GORM v2 的软删除机制,会导致 `Delete()` 执行物理删除(DELETE FROM)而非软删除(UPDATE SET deleted_at)。
15
+ - 新建 Model 时,优先嵌入已有的公共基础结构体(如包含 ID、CreatedAt、UpdatedAt、DeletedAt 的 BaseModel),避免各 Model 独立定义这些字段导致类型不一致。