Files
lovife 624a05aa66 feat(pc): 平台运营的租户管理(详情/用量/编辑/停用)与日志详情
需求:「设计开发平台运营人员对租户的管理功能,还有日志的详情查看功能。」

⚠️ **口径变更**(覆盖 2026-10 走查的旧结论):views/tenant/index.vue 原先写着「列表**没有操作列**:
不提供编辑 / 停用入口(客户 2026-10 走查确认的口径)」。本轮用户明确选了全量范围,所以列表现在
有操作列(详情 / 编辑 / 停用·启用)。旧注释是**改写而不是删掉**,并写明推翻理由 —— 运营的真实
诉求是:① 到期日变了要能自己改,而不是每次找开发;② 欠费 / 停止合作时要能当场停掉;
③ 每周核对"谁快到期了"时要能点进详情看用量。

1) 租户管理:操作列用 tenant:view 门控「详情」、tenant:manage 门控「编辑 / 停用 / 启用」,
   拿不到管理权限时整列显示"只读",而不是留一个点了报 403 的按钮。停用走 NPopconfirm 二次确认
   且文案写明后果("停用后该校所有学生与老师会立刻无法登录");只发 {status} 一个字段 ——
   PUT 是部分更新,回传整行会把列表里看不见的字段覆盖成空。

2) 详情抽屉 TenantDetailDrawer:打开时**同时**调 getTenantDetail 与 getTenantUsage ——
   列表接口的 contactPhone **恒为 null**(电话以密文入库,列表不能成为批量拉取联系方式的通道),
   脱敏值只有详情接口给,拿行数据凑详情会显示成"没有联系电话"。用量区写明"学生数与存储是**实时值**,
   周期只影响计费项",否则会以为"2026Q3 的学生数"是历史值;notes 如实全列(它解释"为什么这几项是 0")。
   统计周期只给本月 / 上月 / 本季三个固定选项,不做自由文本输入。

3) 编辑弹窗 TenantEditModal:类型 4 选项、状态 3 选项;数字下拉的校验规则必须带 type: 'number'
   (只写 required 会"看起来填了但校验不过",而且 #feedback 会把报错遮住);联系电话留空 = 不修改;
   租户编码只读展示并注明"出现在扫码落地页与对接文档里,开通后不可修改"。不做"清空到期日"
   (MyBatis-Plus 忽略 null 更新,清不掉就不在界面上承诺)。

4) 日志页:操作日志 / 登录日志两个模式,各自维护 list / total / pageNum / pageSize / loading /
   筛选条件,切换时重置到第 1 页。⚠️ 页签用工具条上的**分段按钮**而不是 NTabs / NTabPane:
   ① NTabPane 的内容要额外 flex 化才能维持 .page-card 的高度链,否则表格高度算成 0、
   **一行数据都看不见**(本仓踩过);② naive 2.45.3 的 tab="..." 属性写法本身也是坏的,
   必须用 #tab 插槽。

5) 日志详情 LogDetailDrawer:变更前后**完整不截断** + break-all + 各一个复制按钮;
   extraJson 格式化成 <pre>(解析失败原样展示);traceId 带复制;request_param / duration_ms
   如实写"本版本未采集"(这两列从来没有写入点),不编。抽屉**不再打接口** —— 列表 SELECT 已经
   把抽屉要的字段都带出来了。

6) 「单位」列只对平台显示(0 → 「平台」),两张表统一用「单位」这个词:这一列要装得下
   tenant_id = 0 的「平台」,表头写「租户」而格子里写「平台」是自相矛盾的;且与筛选栏两个下拉的
   占位符、租户管理页的「单位名称」一致。登录日志刻意**不要「归属地」列**(location 恒为 null,
   整列空白看起来像功能坏了)。

7) 日志页的模块下拉换成导出的 MODULE_OPTIONS / TARGET_TYPE_OPTIONS:原先那 4 项里 AUDIT / EXPORT
   **后端一个写入点都没有**,而真会写的 FILE(代传材料)与 ROLE(6 个角色动作)**不在里面** ——
   选中死项只会得到一张空表,让人以为"这段时间没有审核动作"。

8) 菜单显示名「操作日志」→「日志」(key 保持 'log' 不动:后端 BuiltinRole 的菜单键与
   check-wiring 第 ⑥ 项都按它核对,改 key 会让平台角色的菜单静默少一项)。

同步 frontend-pc/AGENTS.md 与 .agents/:「最容易写错的约定」由 7 条扩到 **9 条** —— 新增
第 8 条「详情用抽屉、不要为详情新开路由」(含"列表接口可能刻意不返回某个字段"的坑)与
第 9 条「页面内的页签用工具条分段按钮」(写明高度链的原因)。

验证:pnpm typecheck **0 错**、pnpm lint **0 错 0 警告**、pnpm build 通过。
浏览器实测(平台账号,5173 + 8080):租户页出现操作列且三档到期配色正确、卡片上内边距仍是 16px、
高度链未破(表格 570px / 日志表 528px);详情抽屉显示脱敏电话 138****8000 —— 而库里存的是
**历史明文** 13800138000,也就是说这条同时验了"读路径容错"(否则是永久 500);停用二次确认文案
正确;清空单位名称提交后弹窗不关且错误可见;登录日志同一张表里同时出现「示范职业学校」
(tenant_id=1)与「平台」(tenant_id=0)两种映射;**学校管理员视角两张表都没有「单位」列**。
2026-10-13 14:04:53 +08:00

1.5 KiB
Raw Permalink Blame History

.agents/

本目录为 AI 编码助手规范的唯一来源(Single Source of Truth),适用于 Cursor、OpenCode、Codex 等工具。

⚠️ 2026-10 已整体重写:PC 端从 Gi Admin Pro + Arco Design Vue 换成 纯 Vue 3 + Naive UI。 上一版 skills 里的 Arco 组件名(a-table / a-form / a-modal)、v-hasPerm、auto-import、 Stylelint、Gi 的 useTable/usePagination 全部不再适用 —— 照着写会编译不过或静默失效。 唯一保留原样的是 git-commit(与框架无关)。

结构

.agents/
├── rules/
│   └── agent.md                # 唯一常驻规则(AGENTS.md 内联注入)
└── skills/                   # 按需加载
    ├── code-ts/SKILL.md          # TS 命名 / 导入 / 显式 import
    ├── code-vue/SKILL.md         # SFC 写法与模板约定
    ├── code-css/SKILL.md         # SCSS 与样式边界
    ├── project-guide/SKILL.md    # 技术栈 / 目录 / 九条最容易写错的约定
    ├── project-crud/SKILL.md     # 列表 + 表单的标准写法
    ├── project-api/SKILL.md      # 接口调用(没有 Mock)
    └── git-commit/SKILL.md       # 提交规范(与框架无关)

工具适配

工具 适配方式
Cursor AGENTS.md(内联 behavior 规则 + 技能索引)+ .agents/skills/(按需)
OpenCode AGENTS.md + .agents/rules/ + .agents/skills/
Codex AGENTS.md + .agents/skills/