Files
xiaotutongxue/frontend-pc/AGENTS.md
T
lovife e94e76ba0f fix(pc): 找回被 #feedback 吞掉的表单校验错误 + 收集任务文案精简
naive 的 NFormItem 一旦用了 #feedback 插槽,renderExplains 就永不渲染
(children || feedback ? feedback : …),校验错误被完全遮住 —— 用户看到的是
"红框 + 一句无关的正常提示",现象上等价于"点了保存没反应"。RoleFormModal 里
早就记录过这个机制,但只在自己那个文件绕开了,没固化成约定,于是扩散到 7 处。

- 7 处 validate() 的 catch 改成 message.error(firstError(errors) ?? 兜底)
  (login / org / role / user / task 建改任务 / 材料规则 / 表单设计)
- ⚠️ firstError 必须摊平后再取:naive reject 出来的是嵌套数组,
  errors[0].message 恒为 undefined,兜底文案会把每条错误都吞成"请检查表单填写"
- 批次号在"修改"时置灰(task_code = 批次号 + 4 位序号,且同时是文件目录名,
  而服务端 update 无条件写 batch_no、没有"编码已生成"的保护)
- 删掉「本期范围」区块(收集模式 / 认定类型恒定,请求体里仍写死 1)
- 清掉教材式描述:extras_json / extra_ 前缀 / 幂等 / 接收能力 / 识别结果只用于提示
- 规则沉淀进 frontend-pc/AGENTS.md 第 10 条与交接摘要 §一·四十
2026-10-13 15:06:34 +08:00

103 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md
面向 AI 编码助手的项目指南(PC 管理端)。规范以 `.agents/` 为唯一来源。
> ⚠️ **2026-10 已重搭**:从 **Gi Admin Pro + Arco Design Vue** 换成 **纯 Vue 3 + Naive UI 2.42**。
> 上一版基于 Gi/Arco 的 skills 已全部重写 —— **不要再按 Arco 的组件名(`a-table` / `a-form`)、
> `v-hasPerm`、auto-import、Stylelint 去写代码**。
## 常驻规则(Agent 行为准则)
> 源文件:`.agents/rules/agent.md`(修改后请同步本节)
- 始终使用**简体中文**与用户沟通。
- 未经用户明确要求,**不要**创建说明文档、执行 git commit/push、修改 git 配置。
- 改动范围最小化;优先复用项目已有抽象,禁止凭空引入新架构。
- 改代码前先阅读项目既有实现;任务完成后视情况运行 lint / typecheck。
- **按需读取** skills,不要预加载全部。
**编码前按任务加载 skill:**
| 任务 | 技能 |
|------|------|
| 写/改 `.vue` | `.agents/skills/code-vue/SKILL.md` |
| 写/改样式 | `.agents/skills/code-css/SKILL.md` |
| 写/改 `.ts` / composable | `.agents/skills/code-ts/SKILL.md` |
| 项目约定、Naive UI 组件与目录 | `.agents/skills/project-guide/SKILL.md` |
| CRUD 列表/表单 | `.agents/skills/project-crud/SKILL.md` |
| 接口调用(`src/apis/xt/`) | `.agents/skills/project-api/SKILL.md` |
| 提交代码(git commit) | `.agents/skills/git-commit/SKILL.md` |
## 快速入口
```bash
pnpm dev # 开发(/api 代理到 http://localhost:8080,没有 Mock)
pnpm build # 生产构建
pnpm typecheck # vue-tsc(**当前 0 错**,有报错就是新引入的)
pnpm lint # ESLint(@antfu/eslint-config)
```
- 路径别名:`@` → `src/`
- **开发没有 Mock**:`pnpm dev` 把 `/api` 代理到 `http://localhost:8080`
(见 `vite.config.ts` 的 `server.proxy`)→ **后端不起着就没有数据**
- 接口模块在 `src/apis/xt/`(按业务域分文件),统一从 `@/apis/xt` 或 `@/apis/xt/<域>` 引
- 演示账号:`admin / Admin@123` + 租户码 `demo`(⚠️ **不是** Gi 模板 README 里的 `admin/123456`)
## 十条最容易写错的约定
1. **没有 auto-import**:naive-ui 组件、Vue API、工具函数**全部显式 `import`**,
标签统一写 **PascalCase**(`<NButton>`)。
⚠️ 漏 import 是**静默故障**:写小写 `<n-button>` 而没 import 时,Vue 把它当未知自定义元素渲染,
**不报错、typecheck/lint 全绿,只是样式整块丢掉**(2026-10 实测踩到 4 个文件 6 处)。
`python scripts/check-wiring.py` 第 ⑧ 项会静态核对这件事。
2. **权限判断**:`useUserStore().has('码')` / `hasAny(...)`(**没有 `v-hasPerm` 指令**);
权限码字符串必须与后端 `PermissionDef` **逐字一致**(`progress:viewAll` 是驼峰)。
3. **状态色**:`n-tag` 的 `type` 必须过 **`@/utils/tag.ts`** 的 `tagOf()` ——
`apis/xt/*.ts` 里的展示映射仍是 Arco 色词(`green`/`arcoblue`/`gold`),
直接透传给 `n-tag` 会**静默变灰**且不报错。
4. **图标**:用 `@/icons/AppIcon.vue` + 图标名;图标数据由
`scripts/extract-pc-icons.py` 生成到 `src/icons/icon-data.ts`(37 个),
缺图标是**空占位、不报错** → **图标集升级后要重跑该脚本**。
5. **`n-tab-pane` 的标签用 `#tab` 插槽,不要用 `tab="文字"` 属性** ——
naive-ui 2.45.3 的属性写法只渲染出一个空注释节点,**整排 tab 一个字都不显示**(不报错)。
6. **卡片式版面**:白卡片靠全局的 `--xt-bg` 灰底浮起来;卡片外观(描边/阴影/圆角/卡片头色带)
由 `src/styles/index.scss` 的 `.n-card.n-card` 统一给,**页面不要再自己写**;
卡片内部分区用 `.section-title` + 浅灰小格子,**不要卡里套卡**。
工具条控件同一行尺寸要一致(统一默认尺寸,别混 `size="small"`)。
7. **品牌标**:几何标在 `src/assets/images/logo.svg`(**不要换回文字字形标** —— 形状的出处与
构造参数写在该文件注释里);页签用 `public/favicon.svg`(加粗版),改一个要同步另一个,
外加侧栏/登录页的引用尺寸与 `docs/prototype/admin-web.html` 的 `.mark`。
⚠️ **SVG 的注释里不能出现连续两个减号**(XML 规范禁止):会让整个文件 not well-formed,
表现是图片裂开、**控制台一句话都不报**,typecheck/lint 也全绿。
`python scripts/check-wiring.py` 第 ⑨ 项会核对这件事。
8. **详情用抽屉,不要为详情新开路由**:`NDrawer` + `NDrawerContent` + `NDescriptions`,
模板抄 `src/views/audit/AuditDetailDrawer.vue`。列表页的"详情"入口是操作列里的一个
`text` 按钮(`size="small"`,见第 6 条的行内按钮约定)。
⚠️ 抽屉打开时该调哪个接口要看清楚:**列表接口可能刻意不返回某个字段**
(例:`/tenants` 的 `contactPhone` 恒为 `null`,脱敏值只有 `/tenants/{id}` 给),
拿行数据凑详情会显示成"没有联系电话"。
9. **页面内的页签用工具条上的分段按钮,不要用 `NTabs` / `NTabPane`**:
① `NTabPane` 的内容要额外 flex 化才能维持 `.page-card` 的高度链,
否则表格高度算成 0、**一行数据都看不见**(本仓踩过);
② 见第 5 条,naive 2.45.3 的 `tab="..."` 属性写法本身也是坏的。
两个按钮做的分段控件在视觉上就是页签,且不动高度链。
多个页签各自的 `list` / `total` / `pageNum` / `loading` 要分开维护,切换时重置到第 1 页。
10. **`NFormItem` 一旦用了 `#feedback` 插槽,校验错误就被完全遮住** ——
naive 的渲染是 `children || feedback ? feedback : renderExplains`(2.45.3 的 `FormItem.mjs`),
插槽存在时 `renderExplains` **永不渲染**,用户看到的是「红框 + 一句无关的正常提示」,
现象上等价于「点了保存没反应」。所以**凡是有 `#feedback` 的表单,`validate()` 失败必须自己弹**:
```ts
} catch (errors) {
message.error(firstError(errors) ?? '请检查表单填写')
return
}
```
⚠️ `firstError` **必须摊平后再取**:naive 的 `Form.validate()` reject 的是**嵌套数组**
(`Form.mjs` 把每层 `result.errors` 整个 push 进去),`errors[0].message` 恒为 `undefined`,
兜底文案会把每条错误都吞成「请检查表单填写」。写法抄 `src/views/tenant/TenantEditModal.vue`。
⚠️ 这个插槽**不接收任何参数**(内部用 `resolveWrappedSlot(slot, wrapper)` = `wrapper(slot())`),
所以**没有**「`#feedback="{ status }"` 里顺手渲染错误」这种写法 —— 想内联显示错误只能给
`NFormItem` 的 `feedback` **prop** 传渲染函数,那需要自写包装组件,别顺手试。