refactor: 后端仓库层收口(A1:课程/产品/素材)+ 收进工作区既有对象化重构
本提交含两部分。第一部分是本轮工作;第二部分是此前一直留在工作区、
从未提交的对象化重构,与第一部分在文件上互相咬合(internal/repository
整个包都是未跟踪状态,且 api 层已有文件引用它),无法拆成两个可编译的提交。
一、仓库层收口 A1 批(本轮工作)
把 api 层手写的 store.DB 查询收进具名仓库方法,只给真正获益的对象做方法,
不机械包裹全量。本批迁移 22 处裸查询(courses.go 9 / media.go 12 / products.go 1),
新增方法:
- MediaFileRepo.ListByBind / ListForAudit / MarkExtracted
- KnowledgeChunkRepo.CountByMediaFile
- ProductRepo.GetVisibleByID
两条业务口径改由仓库单点持有,避免各处手写漂移:
「只有 approved 素材出现在课程详情」与「已停用产品不在课程详情露出」。
修掉两个真实缺陷:
- ProductRepo.GetByID 缺 Where 条件。此前 GET /api/products/{id} 对任意 id 都返回
第一条产品、对不存在的 id 返回 200,且 PUT /api/products/{id} 会覆盖第一条产品
—— 数据损坏级。全仓扫描确认这是唯一一处同型写法。
- ProductRepo.Delete 写 status="deleted",而 DELETE 处理器文档与回包都声称
"inactive",接口在说谎;管理员用 status=all 拉列表会看到前端不认识的状态。
已对齐为 inactive(与 CourseRepo.Delete 一致)。
删除 8 个零调用且列名不存在的死方法(一调即 SQL 报错):
- media_file 上的 file_path / file_type / approval_status 三列并不存在,
GetByPath / ListByType / UpdateStatus 全废
- knowledge_chunk 上的 space_id 列不存在(模型早已改为 knowledge_space_key),
List / Total / ListBySpaceIDs / DeleteBySpace / SearchByVector 全废
取舍边界:能对当前 schema 跑通的死方法保留,跑不通的删或修。
CourseRepo.List 补齐 status=all 档(此前传给它会当作 status='all' 过滤出空列表)。
该方法此前零调用,现与产品列表语义对齐。
验证:go build ./... 与 go test ./... 全绿;另用真实 HTTP 请求验证 34 项
(课程 17 / 产品 3 / 素材 14),跑在数据库副本与独立 KB_DATA_DIR 上,
含 multipart 真上传 → 审批 → pdftotext 提取 → 分片入库的完整链路。
二、此前未提交的对象化重构(非本轮工作)
- 新增 internal/repository 仓库层、connectors、skills、specialists、xapps、jsonutil,
model/task_record|task_run|task_artifact、api/task_runtime|action_definition|chat_message
- 删除 api/app_definition、connectors、my_app_center、notification、office_skill、
export_docx|pptx|xlsx、official_account_* 等,随 XApp/Skill/Specialist/Connector
可插拔打包方向(AR10/AR11)调整
- 资产目录归位:backend-go/knowledge_source → assets/knowledge/source、
training_materials → assets/training/materials;README 内相对路径同步加深两级;
deploy env 补 ASSET_ROOT_DIR 并改 KNOWLEDGE_SOURCE_DIR / TRAINING_MATERIALS_DIR
- 前端新增 skills/ specialists/ connectors/ xapps/ 目录与对应页面
验证:前端 npm run build 通过(7.26s)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+50
-5
@@ -1,7 +1,7 @@
|
||||
# eai_agentplatform 博昇 AI 数字员工平台(EAI Agent Platform)— 编码与调试最高准则
|
||||
|
||||
> **版本:V1.1**
|
||||
> **日期:2026-09-17**
|
||||
> **版本:V1.2**
|
||||
> **日期:2026-09-18**
|
||||
> **状态:必须强制执行 (Highest Priority)**
|
||||
> **适用范围:eai_agentplatform(EAI 数字员工平台)后端(Go)、前端(Vue3)、数据库(SQLite)、AI 检索/对话、考试引擎、素材上传与审批**
|
||||
> **AI 助手启动任何任务前必须先读取并确认本文件。**
|
||||
@@ -16,6 +16,11 @@
|
||||
> 通用部分新增 G09-G18(承接 pj0034 同名文件的通用规则,按本项目 Go / Vue3 / SQLite / Ubuntu 技术栈改写,
|
||||
> 不适用的部分——如 Python 虚拟环境、Playwright E2E、OSS 多租户——明确不抄);
|
||||
> G04 补充第 6-10 条(来自两个项目共同踩过的坑);本项目新增 P06 常见技术陷阱清单。
|
||||
>
|
||||
> **V1.2 补充说明**:把命名前缀从「一条要求」扩成「一套规则」,全部落在 **G03**(不新开 G19,避免命名规则被拆到两处)。
|
||||
> 仍只做加法:G03 原第 1-4 条正文一字未改,只在其后新增第 5-10 条 + 关联节;标题由「变量命名锚定」放宽为「命名锚定」
|
||||
> (前缀要管表名、API 路径、文件名),索引行同步更新。
|
||||
> 展开与可执行化版本在 `docs/02_Architecture/AR09_Object_Naming_Standard.md` §5.7 + §6.2 守卫 G–J + §7.6。
|
||||
|
||||
---
|
||||
|
||||
@@ -28,7 +33,7 @@
|
||||
|
||||
- G01:深度调试日志 — 全链路埋点 + 特殊日志文件
|
||||
- G02:Fail Fast 与零静默兜底
|
||||
- G03:变量命名锚定 — 防命名漂移
|
||||
- G03:命名锚定 — 防命名漂移(含**前缀规范**:必要性判据 / 三类前缀 / 硬约束 / 退出条件 / 改名禁令)
|
||||
- G04:测试与验收 — 完成判定必须靠事实
|
||||
- G05:安全迁移与重构流程
|
||||
- G06:AI 助手行为规范
|
||||
@@ -90,12 +95,52 @@
|
||||
|
||||
---
|
||||
|
||||
## G03 原则:变量命名锚定 — 防命名漂移 (Identity Anchoring)
|
||||
## G03 原则:命名锚定 — 防命名漂移 (Identity Anchoring)
|
||||
|
||||
1. **变量名前缀强制化**:所有业务相关变量必须带明确前缀(如 `media_file_id`, `exam_session_key`, `product_code`)。禁止使用 `id`, `data`, `res` 等模糊命名。
|
||||
> V1.2 起本条从「变量命名」放宽为「命名」:前缀规范要管到表名、API 路径、文件名,不只是变量。
|
||||
|
||||
1. **变量名前缀强制化**:所有业务相关变量必须带明确前缀(如 `media_file_id`, `exam_session_key`, `product_code`)。禁止使用 `id`, `data`, `res` 等模糊命名。(**哪些命名空间需要前缀,见第 5 条**)
|
||||
2. **变量名全链路同步**:同一业务参数在 API、Service、Model 层必须保持变量名完全一致。
|
||||
3. **最小长度约束**:变量名原则上不短于 5 个字符(循环索引除外)。
|
||||
4. **AI 引用已定义标识符必须按字符复制**:AI 在生成或修改代码时,引用任何**已在项目中定义过**的标识符,必须先 Read/Grep 找到定义处,**按字符原样复制**,禁止自行改写大小写或分隔符。例如 `user_id` 不应被写成 `userId` 或 `uid`。
|
||||
5. **前缀的必要性由「命名空间的形状」决定,不由对象的重要性决定**:
|
||||
- **必须加**:SQLite 表名、表内列名、URL query、JSON key、目录内文件名、shell 变量 —— 这些命名空间**平铺且无类型**,名字是唯一的消歧手段。
|
||||
- **不必加**:Go 包内标识符、结构体字段 —— 有作用域,编译器/运行时替你消歧,前缀只是噪音。
|
||||
- **判据一句话**:*去掉它,同一个命名空间里会不会出现两个可能同名的东西?* 会 → 加;不会 → 别加。
|
||||
- **本项目正例(两种写法都对,别去"统一")**:`deploy/eai_agentplatform.env` 用裸名 `PORT`(一个 systemd unit 独占进程环境);`start_dev_10231_10232.sh` 用 `BACKEND_PORT` / `FRONTEND_PORT`(同一 shell 跑两个服务)。
|
||||
6. **三类前缀,各有各的生命周期**:
|
||||
- **对象前缀**(`skill_definition` / `worker_task`):标记归属,**永久**。
|
||||
- **来源前缀**(`staticSkillCatalog` / `normalizeCustomApp` / `legacy_*`):标记来路,**必须写退出条件**(见第 9 条)。
|
||||
- **作用域前缀**(query 的 `app_`、API 的 `my_`):标记入口与归属,**禁止进入模型、表、字段名**。
|
||||
- 对象前缀的白名单 = 正式对象术语表 + 已登记的子系统前缀。**白名单外的前缀不许发明**(同 G10:能用的集合必须封闭,否则每个人都会造自己的)。
|
||||
7. **两条已收敛的规律,守住不回退**:
|
||||
```text
|
||||
数据库表名 API 路径
|
||||
一级对象 specialist /api/specialists
|
||||
归属或复合 worker_task /api/worker/*
|
||||
```
|
||||
DB 层与 API 路径**各自独立**收敛到同一条分法 —— 这是自然规律,不是硬塞的。**写进规范是为了守住,不是为了改造。**
|
||||
8. **前缀硬约束**:
|
||||
- 一个标识符最多带**一个**类型前缀:`worker_task` ✅ / `app_specialist_skill_key` ❌
|
||||
- 次序固定「前缀 + 核心词 + 后缀」:`skill_definition` ✅ / `definition_skill` ❌
|
||||
- 前缀**写全,禁止缩写**:`specialist_` ✅ / `sp_`、`sk_`、`wr_` ❌
|
||||
- **禁止拼音前缀**:中文是对外展示层的事,不进标识符
|
||||
- **过渡前缀禁止嵌套**:`legacy_` 之上不许再叠一层(理由见第 9 条)
|
||||
- **来源前缀不得跨模块引用**:调用方不该知道数据是从哪来的。本项目现状是反例 —— `staticSkillCatalog` 的兜底写法 `skillCatalog.getByKey(k) || staticSkillCatalog.find(...)` 被抄到了 5 个调用点;正解是在 `skillCatalog` 里加 `resolve(key)` 把兜底收进模块
|
||||
9. **来源前缀必须带退出条件**(`static*` / `legacy*` / `tmp*` / `old*` / `deprecated*` 描述的是过程状态,而过程会结束):
|
||||
- **反例(本项目真实)**:`skill_definition` 一个字段先后有 **5 代列名** —— `entry_route → route → legacy_entry_route / legacy_route → legacy_object_entry_route`。过渡前缀叠到第二层,**就是上一次迁移没有退出条件的证据**。
|
||||
- **正例**:该批 legacy 列的删除与迁移逻辑写在**同一笔提交**里,而不是"先留着以后再说"。照这个做。
|
||||
- **要求**:写下来源前缀时,同处注释或相邻 TODO 必须写清「什么时候可以去掉」。
|
||||
10. **前缀改名 = 协议改名,必须按字符串精确锚定**:
|
||||
- 前缀几乎总活在**字符串**里(表名、列名、JSON tag、URL 参数、env 变量名),**编译器一个都管不着** —— 所以要按字符串 grep,不是按符号 grep。
|
||||
- **禁止子串替换、禁止正则通配。** 本项目现成的雷:`role_kind`(正确新名 `object_kind`)与 `role_card_json`(正确新名 `interaction_card_json`)**都以 `role_` 开头但去向完全不同**,一句 `sed 's/role_/object_/g'` 会把第二个误伤成 `object_card_json`。
|
||||
- 宁可一个标识符一个标识符地改,也不要图快。
|
||||
|
||||
### 关联
|
||||
|
||||
- 关联 G04:命名是否真的统一,靠 grep / build 验证,不靠感觉
|
||||
- 关联 G10:白名单机制与"配置化优先"同源 —— 集合封闭才能防漂移
|
||||
- 完整展开见 `docs/02_Architecture/AR09_Object_Naming_Standard.md`:判据 / 对象术语表 / 分层规范 / 机器守卫 G–J / 修复流程 / 现状问题登记 / 反例库
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user