Agent Skills 系列(5):一个管理后台查询页案例,怎么把“隐性规范”变成可执行 Skill
系列说明
前几篇讲了为什么要 Skill、怎么写、怎么分发、什么值得做成 Skill。这一篇只做一件事:给一个具体落地案例,演示如何把“需求文档没写、但团队一直默认遵守”的规则,固化成项目级 Skill。
为什么“看起来对”的代码会在测试里翻车
场景很典型:你让 AI 生成一个管理后台查询页,代码能跑,页面也能看。但一测就出问题:
- 分页组件只写了
pageSize,却漏掉showSizeChanger,导致用户无法切换每页条数 - 需求文档说查询范围不超过一年,默认开发会按照惯例来写,但AI如何判断不超过一年?
- 查询项只有一两行却默认折叠,用户得多点一次
- 机构筛选忽略了权限差异,导致普通用户也能改机构条件
- 导出接口返回异常 JSON 时没有提示,用户只看到“下载失败”
这些不是“复杂业务”,而是“隐性项目约定”。文档常只写本次需求,不会把这些历史惯例全部重复写一遍。结果就是:AI 每次都按通用范式写,你每次都在补同一批修正意见。
这个案例的核心结论
把“会重复纠正 AI 的内容”拆成项目 Skill,而不是继续靠口头补充。
判断标准很直接:
- 重复出现:两周内被你纠正 3 次以上
- 口径稳定:半年内不会频繁变化
- 可检查:能写成 checklist,而不是抽象口号
符合这三条,就别再留在聊天里,直接沉淀成 Skill。
数据先行:先定义约束对象,再写规则
先把数据关系说清,这个案例里最关键的是 5 组数据:
- 查询参数:
QueryParams(表单字段 + 分页字段) - 后端请求参数:
ApiParams(把pageSize/current映射成count/page) - 时间范围:
dateRange -> startTime/endTime/durationDays - 机构权限状态:
canSelectOrg与fixedOrgCode - 导出状态:
loading、blob、errorJson
不变约束(invariants)也要写死:
- 分页映射永远做:
pageSize -> count,current -> page - 未触发查询前不请求列表(可选策略)
- 时间范围校验必须统一(31 天或 365 天按场景选其一)
- 无权限用户不能修改机构,只能用自身归属机构
- 导出响应先尝试识别异常 JSON,再按文件流处理
这一步做完,Skill 才有“可执行的骨架”,而不是一堆口号。
脱敏后的项目 Skill 示例(可直接用)
下面是脱敏版结构,项目名与路径都用通用写法,代码只保留伪代码。
先看目录结构:
admin-pc-query-guidelines/
├── SKILL.md
└── references/
├── query-page.md
├── query-form-fields.md
└── export-download.md
1)SKILL.md(主文件)
---
name: admin-pc-query-guidelines
description: 在开发 admin-pc 管理后台查询页、详情页、导出功能时使用。覆盖分页参数映射、机构权限查询、时间范围约束、查询折叠策略与导出异常处理。
tags:
- admin-pc
- 管理后台
- 查询页
---
# 管理后台开发指南
## 何时使用
- 新建或修改查询页(ProTable)
- 新建或修改详情页中的查询模块
- 新增报表导出功能
- 涉及机构筛选与时间范围筛选
## 参考文档
开发时必须参考以下规范文档:
### 查询页面开发
- [ProTable 查询页面开发规范](references/query-page.md) - 包含完整的模板代码、必要配置说明、列配置示例和检查清单
### 查询项配置
- [查询项配置规范](references/query-form-fields.md) - 包含项目、分公司/中支机构选择、时间范围约束(默认一个月、最多一年)等
### 报表下载
- [报表下载功能](references/export-download.md) - 包含下载接口定义、异常处理等
2)references/query-page.md(查询页模板与检查)
# 查询页面规范
## 必要配置
- 定义 actionRef / formRef
- 设置 rowKey
- 设置完整 pagination(包含 `showSizeChanger`)
- request 中执行分页参数映射
## 示例代码
```tsx
const pagination = {
defaultPageSize: 10,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total, range) =>
`第${range[0]}-${range[1]}条/总共${total}条`,
showSizeChanger: true,
};
function requestList(params) {
if (!shouldRequest) return emptyResult();
const apiParams = {
...params,
count: params.pageSize ?? 10,
page: params.current ?? 1,
};
const res = await queryList(apiParams);
return normalizeTableResult(res);
}
```
## 折叠策略
- 若查询项渲染后不超过两行:`defaultCollapsed = false`
- 否则允许默认折叠
3)references/query-form-fields.md(机构与时间范围)
# 查询项配置规范
## 机构筛选
- 先查询当前用户权限
- 无权限切换机构时:隐藏机构选择框,使用固定机构值
- 有权限时:展示机构选择框
## 时间范围
- 默认值:当月(本月1号到昨天)
- 转换为 startTime / endTime(00:00:00 ~ 23:59:59)
- 校验 durationDays,不满足直接提示并阻断提交
- 默认 MAX_DAYS 为 30 天
## 伪代码
```ts
if (durationDays > MAX_DAYS) {
showError(`请选择 ${MAX_DAYS} 天以内的数据`);
return false;
}
```
4)references/export-download.md(导出逻辑)
# 导出规范
## 请求约束
- responseType = blob
- 导出按钮与查询条件同源
## 异常处理
- 先尝试把响应按文本解析为 JSON
- 若解析成功且 code != 0,提示业务错误
- 解析失败则按文件流继续下载
## 伪代码
```ts
async function handleExport(params) {
const hide = showLoading("正在导出...");
try {
const blob = await exportApi(params);
await tryParseBusinessError(blob);
triggerFileDownload(blob);
return true;
} catch {
showError("导出失败,请重试");
return false;
} finally {
hide();
}
}
```
为什么这套写法有效
关键不是“模板多完整”,而是把容易漏的点变成可检查项:
- AI 首轮就拿到项目“真约束”,不再靠默认猜测
- 代码 review 从“凭经验挑错”变成“对 checklist 勾选”
- 需求文档即使只写增量,也不会把历史惯例丢掉
- 新同学能按 Skill 对齐,不必每次口口相传
一句话:把隐性知识从人脑搬到版本化文件里。
落地顺序(不要一口吃成胖子)
建议按这个顺序推进,最稳:
- 先只收一类高频页面(比如查询页)
- 先固化 5~8 条“最常漏”的硬规则
- 连续两周只观察首轮通过率与返工轮次
- 再把导出、权限、时间校验扩展到同类页面
别一上来写“全项目万能 Skill”,那一定会失控。
给非技术场景的迁移提示
同一套路可以迁移到市场、内容、运营写作:
- 市场:把品牌禁用词、合规口径、活动文案结构写成 Skill
- 内容:把选题结构、标题约束、引用规范、发布检查写成 Skill
- 运营:把 SOP、话术边界、异常升级路径写成 Skill
底层逻辑不变:重复、稳定、可检查。
系列导航(姊妹篇)
| 篇 | 文章 | 在讲什么 |
|---|---|---|
| 1 | 痛点与动机 | 为什么需要 Skill |
| 2 | 概念实战篇 | SKILL.md 结构与渐进式披露 |
| 3 | 工具引入篇 | skill-base / skb 分发安装 |
| 4 | 什么值得做成 Skill | 选题标准与反例 |
| 6 | 运维手册 | 触发、冲突与版本治理 |
| 延伸 | 碎片化困局 | 多工具并存下的触发与治理 |