adspecs 0.1.19 → 0.1.21

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.
Files changed (74) hide show
  1. package/.adspecs/feature.json +16 -16
  2. package/.adspecs/feature.yml +28 -28
  3. package/.adspecs/paths.json +17 -17
  4. package/.adspecs/templates/04-/345/211/215/347/253/257/345/212/237/350/203/275/350/256/276/350/256/241/346/250/241/346/235/277.md +1 -1
  5. package/.adspecs/templates/05-/345/220/216/347/253/257/344/273/273/345/212/241/346/270/205/345/215/225/346/250/241/346/235/277.md +613 -724
  6. package/.adspecs/templates/05b-/345/211/215/347/253/257/344/273/273/345/212/241/346/270/205/345/215/225/346/250/241/346/235/277.md +51 -51
  7. package/.claude-plugin/marketplace.json +23 -23
  8. package/.claude-plugin/plugin.json +18 -18
  9. package/.qoder-plugin/plugin.json +31 -31
  10. package/CLAUDE.md +1 -5
  11. package/INSTALL.md +3 -3
  12. package/README.md +395 -395
  13. package/bin/adspecs.js +129 -129
  14. package/hooks/commit-queue.js +245 -245
  15. package/hooks/hooks.json +63 -63
  16. package/hooks/session-start.js +44 -44
  17. package/hooks/wiki-queue.js +127 -127
  18. package/package.json +61 -61
  19. package/references/ant6-front-standard/index.md +99 -99
  20. package/references/antd-front-demo/public/mockServiceWorker.js +361 -361
  21. package/references/ecp-end-standard/index.md +63 -63
  22. package/references/python-end-standard/01-Python/345/220/216/347/253/257/347/274/226/347/240/201/350/247/204/350/214/203.md +372 -372
  23. package/references/python-end-standard/02-/346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/344/270/216/344/275/277/347/224/250/350/247/204/350/214/203.md +226 -226
  24. package/references/python-end-standard/03-Celery/345/274/202/346/255/245/344/273/273/345/212/241/350/247/204/350/214/203.md +237 -237
  25. package/references/python-end-standard/04-Redis/344/275/277/347/224/250/350/247/204/350/214/203.md +231 -231
  26. package/scripts/postinstall.js +107 -107
  27. package/scripts/sync-version.js +105 -105
  28. package/skills/.claude/.wiki-update-queue +26 -26
  29. package/skills/adspecs-constitution/SKILL.md +157 -0
  30. package/skills/adspecs-export-word/SKILL.md +498 -498
  31. package/skills/adspecs-export-word/references/md-to-docx.js +862 -862
  32. package/skills/adspecs-export-word/references/package-lock.json +220 -220
  33. package/skills/adspecs-export-word/references/package.json +10 -10
  34. package/skills/adspecs-front-prototype/SKILL.md +405 -405
  35. package/skills/adspecs-front-spec/SKILL.md +4 -4
  36. package/skills/adspecs-front-tasks/SKILL.md +213 -173
  37. package/skills/adspecs-plan/SKILL.md +59 -69
  38. package/skills/adspecs-prd/SKILL.md +13 -5
  39. package/skills/adspecs-prd-to-demo/SKILL.md +532 -0
  40. package/skills/adspecs-tasks/SKILL.md +175 -204
  41. package/skills/adspecs-update-status/SKILL.md +382 -382
  42. package/skills/adspecs-utest/SKILL.md +107 -116
  43. package/skills/grill-me/SKILL.md +7 -0
  44. package/skills/grill-me/agents/openai.yaml +5 -0
  45. package/skills/playwright-cli/SKILL.md +420 -0
  46. package/skills/playwright-cli/references/element-attributes.md +23 -0
  47. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  48. package/skills/playwright-cli/references/request-mocking.md +87 -0
  49. package/skills/playwright-cli/references/running-code.md +241 -0
  50. package/skills/playwright-cli/references/session-management.md +225 -0
  51. package/skills/playwright-cli/references/storage-state.md +275 -0
  52. package/skills/playwright-cli/references/test-generation.md +433 -0
  53. package/skills/playwright-cli/references/tracing.md +139 -0
  54. package/skills/playwright-cli/references/video-recording.md +143 -0
  55. package/skills/playwright-trace/SKILL.md +171 -0
  56. package/skills/project-init/SKILL.md +93 -22
  57. package/skills/project-init/references/front-demo/.claude/settings.local.json +9 -0
  58. package/skills/wiki-update/SKILL.md +232 -232
  59. package/src/commands/doctor.js +197 -197
  60. package/src/commands/init.js +83 -83
  61. package/src/commands/plugin.js +165 -165
  62. package/src/commands/update.js +87 -87
  63. package/src/lib/area-scanner.js +129 -129
  64. package/src/lib/copier.js +104 -104
  65. package/src/lib/dir-utils.js +161 -133
  66. package/src/lib/json-merge.js +114 -114
  67. package/src/lib/paths-defaults.js +37 -37
  68. package/src/lib/prompts.js +428 -347
  69. package/src/lib/readme-gen.js +143 -143
  70. package/src/lib/report.js +338 -327
  71. package/src/lib/scaffolder.js +551 -518
  72. package/src/lib/short-name.js +36 -36
  73. package/src/utils.js +80 -80
  74. package/references/antd-front-demo/.env +0 -15
@@ -1,405 +1,405 @@
1
- ---
2
- name: "adspecs-front-prototype"
3
- description: "基于 PRD 文件(或前端功能设计文档)+ front-demo 参考工程,生成可在 front-demo 中直接运行的完整页面原型(页面 + API + i18n 语言包 + 配置)。遵循 frontend-integration 规范(不存在时回退到 front-demo/.claude/rules/)。Use when the user asks to generate a frontend prototype, create demo pages from PRD, or build a working demo based on requirements."
4
- argument-hint: "<PRD 文件路径> [front-demo 目录路径]"
5
- compatibility: "需要 references/front-demo/ 参考工程;可选 references/docs/40-project_conventions/frontend-integration/ 规范"
6
- metadata:
7
- author: "Qingwen Chen"
8
- input: "docs/20-prd/{module}/{spec}.md 或 docs/30-system-design/{module}/{spec}_前端设计.md"
9
- output: "references/front-demo/src/{views,api,lang}/..."
10
- user-invocable: true
11
- disable-model-invocation: false
12
- ---
13
-
14
- # 前端原型生成(Frontend Prototype Generator)
15
-
16
- ## 用户输入
17
-
18
- ```text
19
- $ARGUMENTS
20
- ```
21
-
22
- **必须** 在继续之前考虑用户输入(如果非空)。
23
-
24
- 输入格式支持:
25
-
26
- - `<PRD 文件路径>` — 仅指定 PRD
27
- - `<PRD 文件路径> <front-demo 目录路径>` — 同时指定 PRD 和 front-demo 位置
28
- - 空 → 提示用户输入
29
-
30
- ## 定位
31
-
32
- 本 skill 与 `adspecs-front-spec` 互补:
33
-
34
- | 对比项 | adspecs-front-spec(本 skill 上游) | adspecs-front-prototype(本 skill) |
35
- | -------- | ----------------------------------- | ----------------------------------- |
36
- | 输出 | 前端设计文档(Markdown) | 可运行的 Vue 3 原型代码 |
37
- | 目标读者 | 产品经理、前端开发 | 产品经理(演示验收) |
38
- | 关注点 | 怎么用 — 路由/布局/交互语义 | 真正能点、能看、能跑 |
39
- | 产出物 | 1 个 .md 文件 | .vue + .ts + i18n 多文件 |
40
-
41
- **典型工作流**:
42
-
43
- 1. `/adspecs-prd` → PRD(做什么)
44
- 2. `/adspecs-front-spec` → 前端设计(怎么用)
45
- 3. **`/adspecs-front-prototype`** → 可运行原型(真实演示)← 本 skill
46
- 4. `/adspecs-plan` → 后端系统设计(怎么建)
47
-
48
- ## 角色
49
-
50
- 你是一位 10 年以上经验的资深前端工程师 + 原型专家,精通:
51
-
52
- - Vue 3 Composition API 和Element Plus、ant-design6、react19等前端技术栈
53
- - 中后台业务页面(列表、表单、树表、流程页、动态表单)
54
- - 多语言工程(i18n 三语言起步)
55
- - 从 PRD 反推页面结构和交互
56
-
57
- ## 输入
58
-
59
- 1. **PRD 文件**(必需):用户指定的 PRD 或前端功能设计文档
60
- 2. **front-demo 参考工程**(必需):
61
- - 默认位置:`front-demo/`(项目前端演示项目目录)
62
- - 用户可在参数中指定其他 front-demo 目录
63
- 3. **前端规范**(按优先级):
64
- - **优先**:`/docs/40-project_conventions/frontend-integration/`(如有 markdown 文件)
65
- - **回退**:`/front-demo/.claude/rules/`(INDEX.md 索引的规范)
66
-
67
- ## 执行前检查
68
-
69
- ### 1. 检查扩展钩子(`before_front_prototype`)
70
-
71
- 按通用钩子处理规则检查 `.adspecs/extensions.yml`,处理 `hooks.before_front_prototype` 下的条目。无可执行钩子则静默跳过。
72
-
73
- ### 2. 加载路径配置
74
-
75
- 读取 `.adspecs/paths.json` 中的 `front_demo_dir`(默认 `front-demo`)和 `front_prototype_dir`(默认 `web-ui`)。
76
-
77
- ### 3. 校验输入
78
-
79
- - PRD 文件必须存在,否则报错退出
80
- - front-demo 目录必须存在,且包含 `src/views`或 `src/pages`、`src/api`、`src/lang`或`src/locales` 子目录
81
-
82
- ### 4. 加载前端规范
83
-
84
- 按以下顺序加载(先找到即停止):
85
-
86
- ```
87
- A. {PLUGIN_ROOT}/references/docs/40-project_conventions/frontend-integration/*.md
88
- 如果该目录有 .md 文件 → 全部读取,作为规范集
89
- B. 否则回退 → front-demo/.claude/rules/INDEX.md
90
- 按 INDEX.md 的"推荐读取顺序"依次读取
91
- ```
92
-
93
- 把加载到的规范内容作为后续所有代码生成的约束。
94
-
95
- ## 工作流程
96
-
97
- ### 步骤 1:解析 PRD,提取页面需求
98
-
99
- 读取 PRD 文件,提取:
100
-
101
- - **功能模块列表**:每个功能对应一个或多个页面
102
- - **用户故事(US)**:每个 US 的角色、操作、数据
103
- - **字段清单**:列表字段、表单字段、查询字段
104
- - **状态机**:业务状态枚举
105
- - **操作清单**:新增、编辑、删除、审批、导入导出等
106
- - **权限点**:按钮级权限
107
-
108
- ### 步骤 2:为每个页面选择模板模式
109
-
110
- 对照 `page-template-index.md` 中的 15 种模板模式,为每个页面选择最匹配的模式:
111
-
112
- | 模式编号 | 模式名称 | 适用场景 |
113
- | -------- | ---------------------------- | -------------------- |
114
- | 1 | 查询栏 + 高级表格 + 弹窗表单 | CRUD 列表(最常用) |
115
- | 2 | 单表 CRUD + 导入导出 | 带批量导入导出的列表 |
116
- | 3 | 左树右详情 Tab | 菜单/组织/分类管理 |
117
- | 4 | 左列表右内联编辑 | 模板中心 |
118
- | 5 | 权限控制多 Tab 中心 | 模块化后台 |
119
- | 6 | 动态组件配置中心 | 配置中心 |
120
- | 7 | 分段抽屉表单 | 复杂表单 |
121
- | 8 | 调度任务与 Cron 配置 | 定时任务 |
122
- | 9 | 日志列表 + 详情抽屉 | 日志查询 |
123
- | 10 | 开放 API 列表 + 编辑页 | 接口管理 |
124
- | 11 | 权限矩阵 / 授权选择器 | 授权页 |
125
- | 12 | 规则设计 / 多模式编辑器 | 规则引擎 |
126
- | 13 | 基础资料表单 | 简单表单 |
127
- | 14 | 流程表单包装页 | 流程审批 |
128
- | 15 | 动态表单入口 | 设计器产物 |
129
-
130
- 输出选择结果,列出每个页面的模式选择及理由。
131
-
132
- ### 步骤 3:规划文件结构
133
-
134
- 根据 PRD 中的模块名和页面名,规划文件输出路径:
135
-
136
- ```
137
- {FRONT_DEMO_DIR}/src/
138
- ├── views/{module}/{page}/
139
- │ ├── index.vue # 主页面
140
- │ ├── components/ # 子组件(表单弹窗、抽屉等)
141
- │ │ ├── AddForm.vue
142
- │ │ ├── EditForm.vue
143
- │ │ └── DetailDrawer.vue
144
- │ └── config/ # 配置(可选)
145
- │ ├── gridConfig.ts # GsTable 列配置
146
- │ └── searchConfig.ts # GsSearchBar 查询配置
147
- ├── api/{module}/{page}/
148
- │ └── index.ts # API 请求函数
149
- ├── lang/modules/{module}/
150
- │ ├── zh-cn.ts # 中文
151
- │ ├── en-us.ts # 英文
152
- │ └── zh-tw.ts # 繁体
153
- └── router/modules/
154
- └── {module}.ts # 路由配置(仅静态路由场景)
155
- ```
156
-
157
- ### 步骤 4:逐页面生成代码
158
-
159
- **对每个页面按以下顺序生成**:
160
-
161
- #### 4.1 语言包(i18n)先写
162
-
163
- 先写语言包文件,确保后续页面所有文案都能通过 `$t('{module}.{key}')` 引用:
164
-
165
- ```ts
166
- // src/lang/modules/{module}/zh-cn.ts
167
- export default {
168
- list: "XXX 列表",
169
- title: "XXX 管理",
170
- add: "新增",
171
- edit: "编辑",
172
- delete: "删除",
173
- status: {
174
- DRAFT: "草稿",
175
- SUBMITTED: "已提交",
176
- APPROVED: "已审批",
177
- },
178
- field: {
179
- code: "编码",
180
- name: "名称",
181
- // ...从 PRD 字段清单推导
182
- },
183
- msg: {
184
- saveSuccess: "保存成功",
185
- deleteConfirm: "确认删除?",
186
- },
187
- };
188
- ```
189
-
190
- **语言包规则**:
191
-
192
- - 使用嵌套对象结构,**不要**扁平 key
193
- - 至少生成 `zh-cn` / `en-us` / `zh-tw` 三套
194
- - 所有用户可见文案(列名、按钮、提示、校验信息、弹窗标题)都必须进语言包
195
- - 字段命名 `{module}.field.xxx`、状态 `{module}.status.xxx`、消息 `{module}.msg.xxx`
196
-
197
- #### 4.2 API 文件
198
-
199
- ```ts
200
- // src/api/{module}/{page}/index.ts
201
- import request from "@/utils/request";
202
-
203
- export function findPagination(data: any) {
204
- return request({
205
- url: "/api/{module}/{page}/find-pagination",
206
- method: "post",
207
- data,
208
- });
209
- }
210
- export function getById(id: number | string) {
211
- return request({
212
- url: `/api/{module}/{page}/get-id?id=${id}`,
213
- method: "get",
214
- });
215
- }
216
- export function save(data: any) {
217
- return request({
218
- url: "/api/{module}/{page}/save",
219
- method: "post",
220
- data: { params: data },
221
- });
222
- }
223
- export function update(data: any) {
224
- return request({
225
- url: "/api/{module}/{page}/update",
226
- method: "post",
227
- data: { params: data },
228
- });
229
- }
230
- export function remove(ids: string) {
231
- return request({
232
- url: "/api/{module}/{page}/delete",
233
- method: "post",
234
- data: { ids },
235
- });
236
- }
237
- ```
238
-
239
- **API 规则**:
240
-
241
- - 接口前缀参考目标工程同模块已有 API 风格;若无参考,使用 `/api/{module}/{page}/xxx` 占位
242
- - POST 保存/更新使用 `{ params: data }` 包装
243
- - GET 查询单条必须把参数直接拼入 URL(mock 兼容)
244
- - 用户操作成功/失败走 `reqIsSucceed`,不硬编码 `res.code === 800`
245
- - 导出/下载用 Blob 释放 URL
246
-
247
- #### 4.3 主页面
248
-
249
- ```vue
250
- <template>
251
- <section class="{page}-list-page">
252
- <!-- 标题栏 -->
253
- <div class="page-header">
254
- <el-breadcrumb separator="/">
255
- <el-breadcrumb-item>{{ $t("{module}.breadcrumb") }}</el-breadcrumb-item>
256
- <el-breadcrumb-item>{{ $t("{module}.list") }}</el-breadcrumb-item>
257
- </el-breadcrumb>
258
- <h2 class="page-title">{{ $t("{module}.title") }}</h2>
259
- </div>
260
-
261
- <!-- 查询区(按 page-template 模式决定用 GsSearchBar 还是 el-form inline) -->
262
- <!-- 列表区(GsCustomizeTable 或 gs-table) -->
263
- <!-- 弹窗/抽屉组件 -->
264
- </section>
265
- </template>
266
-
267
- <script setup lang="ts">
268
- import { ref, reactive, onMounted } from "vue";
269
- import { ElMessage, ElMessageBox } from "element-plus";
270
- import { useI18n } from "vue-i18n";
271
- import { findPagination, remove } from "@/api/{module}/{page}";
272
-
273
- const { t } = useI18n();
274
- // 数据、方法、事件处理...
275
- </script>
276
-
277
- <style scoped lang="scss">
278
- .{page}-list-page {
279
- padding: 16px;
280
- .page-header { /* ... */ }
281
- }
282
- </style>
283
- ```
284
-
285
- **页面规则**:
286
-
287
- - 必须使用 `<script setup lang="ts">`
288
- - 必须使用 `$t()` 或 `t()` 引用语言包,禁止硬编码中文
289
- - 必须使用 `reqIsSucceed` 判断成功,不硬编码 `res.code === 800`
290
- - 列表页使用 GsTable / GsCustomizeTable,复杂列通过 `slotArr` 开启插槽
291
- - 操作列 `prop: 'action'`、`fixed: 'right'`、`editable: true`
292
- - 所有按钮操作带 loading 防重复点击
293
- - 页面根节点使用唯一 class,样式使用 `<style scoped lang="scss">`
294
- - 不写死 `px` 高度,使用 flex 布局
295
-
296
- #### 4.4 子组件(按需)
297
-
298
- 按所选模板模式的推荐结构生成:
299
-
300
- - 列表页:`AddForm.vue`、`EditForm.vue`、`DetailDrawer.vue`
301
- - 表单页:`BasicForm.vue`
302
- - 左树右详情:`TreePanel.vue`、`XxxTab.vue`
303
-
304
- **子组件规则**:
305
-
306
- - 通过 `props` 接收数据(`visible`、`rowData` 等)
307
- - 通过 `emit` 通知父组件(`update:visible`、`refresh`)
308
- - 弹窗/抽屉使用 `:model-value` + `@update:model-value` 模式,**不**内部再建 `visible` ref
309
- - 表单校验规则里的 `message` 必须用 `t('{module}.field.xxx.required')`
310
-
311
- #### 4.5 配置文件(可选)
312
-
313
- - `gridConfig.ts`:GsTable 列配置,每列 `prop / label / width / align / editable / dictCode`
314
- - `searchConfig.ts`:GsSearchBar 查询项配置
315
-
316
- ### 步骤 5:生成 mock 菜单(可选)
317
-
318
- 如果 front-demo 工程使用动态菜单(`src/permission.ts`),在 mock 菜单文件中追加新页面的菜单项,使原型可通过侧边栏访问:
319
-
320
- ```ts
321
- // 追加到 mock 菜单数组
322
- {
323
- menuId: 9001,
324
- menuCode: '{module}-{page}',
325
- menuUrl: '/{module}/{page}',
326
- menuName: '{页面中文名}',
327
- originalAddr: null, // 关键:必须为 null
328
- children: [],
329
- }
330
- ```
331
-
332
- ### 步骤 6:输出原型生成报告
333
-
334
- 以表格形式列出所有生成的文件:
335
-
336
- ```markdown
337
- ## 原型生成报告
338
-
339
- **模块**: {module}
340
- **页面数**: {N}
341
- **生成文件**: {M}
342
-
343
- ### 文件清单
344
-
345
- | 文件路径 | 类型 | 说明 |
346
- | -------------------------------------------------- | ------ | -------- |
347
- | `src/views/{module}/{page}/index.vue` | 页面 | 主列表页 |
348
- | `src/views/{module}/{page}/components/AddForm.vue` | 子组件 | 新增弹窗 |
349
- | `src/api/{module}/{page}/index.ts` | API | 5 个接口 |
350
- | `src/lang/modules/{module}/zh-cn.ts` | i18n | 中文 |
351
- | ... | ... | ... |
352
-
353
- ### 启动预览
354
-
355
- cd references/front-demo
356
- npm run dev
357
-
358
- 访问 http://localhost:xxxx,在侧边栏找到「{模块名}」菜单进入。
359
- ```
360
-
361
- ## 质量自检清单
362
-
363
- 生成完成后,对每个页面过以下清单:
364
-
365
- - [ ] 所有文案走 i18n(无硬编码中文)
366
- - [ ] 语言包是嵌套对象结构(非扁平 key)
367
- - [ ] API 请求方式与 mock 兼容(GET 参数拼入 URL)
368
- - [ ] 表格操作列设置 `editable: true` 并加入 `slotArr`
369
- - [ ] 弹窗使用 `:model-value` + `@update:model-value` 模式
370
- - [ ] 用户操作按钮带 loading 防重复点击
371
- - [ ] 表单校验 message 使用 `t()` 引用
372
- - [ ] 页面根节点有唯一 class
373
- - [ ] 不直接复制 front-demo 旧页面的硬编码文案、`@ts-nocheck`、`console.log`
374
- - [ ] mock 菜单的 `originalAddr` 为 `null`
375
-
376
- 未通过的项必须修正后再输出。
377
-
378
- ## 必选执行后钩子
379
-
380
- 检查项目根目录是否存在 `.adspecs/extensions.yml`。
381
-
382
- - 如果不存在或 `hooks.after_front_prototype` 下无钩子,跳到完成报告。
383
- - 按通用钩子规则处理(过滤 `enabled: false`、跳过有 `condition` 的钩子、构造斜杠命令时 `.` → `-`)。
384
- - 对 `optional: false` 的必选钩子,必须发出 `EXECUTE_COMMAND: {command}`。
385
-
386
- ## 完成报告
387
-
388
- 向用户输出:
389
-
390
- 1. **原型生成报告**(文件清单表格)
391
- 2. **启动预览命令**
392
- 3. **扩展钩子分发结果**(如有)
393
- 4. **下一步建议**:
394
- - 验收原型后,可用 `/adspecs-plan` 生成后端系统设计
395
- - 如需调整交互,可修改原型文件再次运行本 skill
396
-
397
- ## 完成标志
398
-
399
- - [ ] PRD 已解析,页面需求已提取
400
- - [ ] 每个页面已选择匹配的模板模式
401
- - [ ] 语言包、API、页面、子组件已按规范生成
402
- - [ ] 所有文件写入 front-demo/src/ 对应目录
403
- - [ ] 质量自检清单全部通过
404
- - [ ] 原型生成报告已输出
405
- - [ ] 扩展钩子已按规则分发或跳过
1
+ ---
2
+ name: "adspecs-front-prototype"
3
+ description: "基于 PRD 文件(或前端功能设计文档)+ front-demo 参考工程,生成可在 front-demo 中直接运行的完整页面原型(页面 + API + i18n 语言包 + 配置)。遵循 frontend-integration 规范(不存在时回退到 front-demo/.claude/rules/)。Use when the user asks to generate a frontend prototype, create demo pages from PRD, or build a working demo based on requirements."
4
+ argument-hint: "<PRD 文件路径> [front-demo 目录路径]"
5
+ compatibility: "需要 references/front-demo/ 参考工程;可选 references/docs/40-project_conventions/frontend-integration/ 规范"
6
+ metadata:
7
+ author: "Qingwen Chen"
8
+ input: "docs/20-prd/{module}/{spec}.md 或 docs/30-system-design/{module}/{spec}_前端设计.md"
9
+ output: "references/front-demo/src/{views,api,lang}/..."
10
+ user-invocable: true
11
+ disable-model-invocation: false
12
+ ---
13
+
14
+ # 前端原型生成(Frontend Prototype Generator)
15
+
16
+ ## 用户输入
17
+
18
+ ```text
19
+ $ARGUMENTS
20
+ ```
21
+
22
+ **必须** 在继续之前考虑用户输入(如果非空)。
23
+
24
+ 输入格式支持:
25
+
26
+ - `<PRD 文件路径>` — 仅指定 PRD
27
+ - `<PRD 文件路径> <front-demo 目录路径>` — 同时指定 PRD 和 front-demo 位置
28
+ - 空 → 提示用户输入
29
+
30
+ ## 定位
31
+
32
+ 本 skill 与 `adspecs-front-spec` 互补:
33
+
34
+ | 对比项 | adspecs-front-spec(本 skill 上游) | adspecs-front-prototype(本 skill) |
35
+ | -------- | ----------------------------------- | ----------------------------------- |
36
+ | 输出 | 前端设计文档(Markdown) | 可运行的 Vue 3 原型代码 |
37
+ | 目标读者 | 产品经理、前端开发 | 产品经理(演示验收) |
38
+ | 关注点 | 怎么用 — 路由/布局/交互语义 | 真正能点、能看、能跑 |
39
+ | 产出物 | 1 个 .md 文件 | .vue + .ts + i18n 多文件 |
40
+
41
+ **典型工作流**:
42
+
43
+ 1. `/adspecs-prd` → PRD(做什么)
44
+ 2. `/adspecs-front-spec` → 前端设计(怎么用)
45
+ 3. **`/adspecs-front-prototype`** → 可运行原型(真实演示)← 本 skill
46
+ 4. `/adspecs-plan` → 后端系统设计(怎么建)
47
+
48
+ ## 角色
49
+
50
+ 你是一位 10 年以上经验的资深前端工程师 + 原型专家,精通:
51
+
52
+ - Vue 3 Composition API 和Element Plus、ant-design6、react19等前端技术栈
53
+ - 中后台业务页面(列表、表单、树表、流程页、动态表单)
54
+ - 多语言工程(i18n 三语言起步)
55
+ - 从 PRD 反推页面结构和交互
56
+
57
+ ## 输入
58
+
59
+ 1. **PRD 文件**(必需):用户指定的 PRD 或前端功能设计文档
60
+ 2. **front-demo 参考工程**(必需):
61
+ - 默认位置:`front-demo/`(项目前端演示项目目录)
62
+ - 用户可在参数中指定其他 front-demo 目录
63
+ 3. **前端规范**(按优先级):
64
+ - **优先**:`/docs/40-project_conventions/frontend-integration/`(如有 markdown 文件)
65
+ - **回退**:`/front-demo/.claude/rules/`(INDEX.md 索引的规范)
66
+
67
+ ## 执行前检查
68
+
69
+ ### 1. 检查扩展钩子(`before_front_prototype`)
70
+
71
+ 按通用钩子处理规则检查 `.adspecs/extensions.yml`,处理 `hooks.before_front_prototype` 下的条目。无可执行钩子则静默跳过。
72
+
73
+ ### 2. 加载路径配置
74
+
75
+ 读取 `.adspecs/paths.json` 中的 `front_demo_dir`(默认 `front-demo`)和 `front_prototype_dir`(默认 `web-ui`)。
76
+
77
+ ### 3. 校验输入
78
+
79
+ - PRD 文件必须存在,否则报错退出
80
+ - front-demo 目录必须存在,且包含 `src/views`或 `src/pages`、`src/api`、`src/lang`或`src/locales` 子目录
81
+
82
+ ### 4. 加载前端规范
83
+
84
+ 按以下顺序加载(先找到即停止):
85
+
86
+ ```
87
+ A. {PLUGIN_ROOT}/references/docs/40-project_conventions/frontend-integration/*.md
88
+ 如果该目录有 .md 文件 → 全部读取,作为规范集
89
+ B. 否则回退 → front-demo/.claude/rules/INDEX.md
90
+ 按 INDEX.md 的"推荐读取顺序"依次读取
91
+ ```
92
+
93
+ 把加载到的规范内容作为后续所有代码生成的约束。
94
+
95
+ ## 工作流程
96
+
97
+ ### 步骤 1:解析 PRD,提取页面需求
98
+
99
+ 读取 PRD 文件,提取:
100
+
101
+ - **功能模块列表**:每个功能对应一个或多个页面
102
+ - **用户故事(US)**:每个 US 的角色、操作、数据
103
+ - **字段清单**:列表字段、表单字段、查询字段
104
+ - **状态机**:业务状态枚举
105
+ - **操作清单**:新增、编辑、删除、审批、导入导出等
106
+ - **权限点**:按钮级权限
107
+
108
+ ### 步骤 2:为每个页面选择模板模式
109
+
110
+ 对照 `page-template-index.md` 中的 15 种模板模式,为每个页面选择最匹配的模式:
111
+
112
+ | 模式编号 | 模式名称 | 适用场景 |
113
+ | -------- | ---------------------------- | -------------------- |
114
+ | 1 | 查询栏 + 高级表格 + 弹窗表单 | CRUD 列表(最常用) |
115
+ | 2 | 单表 CRUD + 导入导出 | 带批量导入导出的列表 |
116
+ | 3 | 左树右详情 Tab | 菜单/组织/分类管理 |
117
+ | 4 | 左列表右内联编辑 | 模板中心 |
118
+ | 5 | 权限控制多 Tab 中心 | 模块化后台 |
119
+ | 6 | 动态组件配置中心 | 配置中心 |
120
+ | 7 | 分段抽屉表单 | 复杂表单 |
121
+ | 8 | 调度任务与 Cron 配置 | 定时任务 |
122
+ | 9 | 日志列表 + 详情抽屉 | 日志查询 |
123
+ | 10 | 开放 API 列表 + 编辑页 | 接口管理 |
124
+ | 11 | 权限矩阵 / 授权选择器 | 授权页 |
125
+ | 12 | 规则设计 / 多模式编辑器 | 规则引擎 |
126
+ | 13 | 基础资料表单 | 简单表单 |
127
+ | 14 | 流程表单包装页 | 流程审批 |
128
+ | 15 | 动态表单入口 | 设计器产物 |
129
+
130
+ 输出选择结果,列出每个页面的模式选择及理由。
131
+
132
+ ### 步骤 3:规划文件结构
133
+
134
+ 根据 PRD 中的模块名和页面名,规划文件输出路径:
135
+
136
+ ```
137
+ {FRONT_DEMO_DIR}/src/
138
+ ├── views/{module}/{page}/
139
+ │ ├── index.vue # 主页面
140
+ │ ├── components/ # 子组件(表单弹窗、抽屉等)
141
+ │ │ ├── AddForm.vue
142
+ │ │ ├── EditForm.vue
143
+ │ │ └── DetailDrawer.vue
144
+ │ └── config/ # 配置(可选)
145
+ │ ├── gridConfig.ts # GsTable 列配置
146
+ │ └── searchConfig.ts # GsSearchBar 查询配置
147
+ ├── api/{module}/{page}/
148
+ │ └── index.ts # API 请求函数
149
+ ├── lang/modules/{module}/
150
+ │ ├── zh-cn.ts # 中文
151
+ │ ├── en-us.ts # 英文
152
+ │ └── zh-tw.ts # 繁体
153
+ └── router/modules/
154
+ └── {module}.ts # 路由配置(仅静态路由场景)
155
+ ```
156
+
157
+ ### 步骤 4:逐页面生成代码
158
+
159
+ **对每个页面按以下顺序生成**:
160
+
161
+ #### 4.1 语言包(i18n)先写
162
+
163
+ 先写语言包文件,确保后续页面所有文案都能通过 `$t('{module}.{key}')` 引用:
164
+
165
+ ```ts
166
+ // src/lang/modules/{module}/zh-cn.ts
167
+ export default {
168
+ list: "XXX 列表",
169
+ title: "XXX 管理",
170
+ add: "新增",
171
+ edit: "编辑",
172
+ delete: "删除",
173
+ status: {
174
+ DRAFT: "草稿",
175
+ SUBMITTED: "已提交",
176
+ APPROVED: "已审批",
177
+ },
178
+ field: {
179
+ code: "编码",
180
+ name: "名称",
181
+ // ...从 PRD 字段清单推导
182
+ },
183
+ msg: {
184
+ saveSuccess: "保存成功",
185
+ deleteConfirm: "确认删除?",
186
+ },
187
+ };
188
+ ```
189
+
190
+ **语言包规则**:
191
+
192
+ - 使用嵌套对象结构,**不要**扁平 key
193
+ - 至少生成 `zh-cn` / `en-us` / `zh-tw` 三套
194
+ - 所有用户可见文案(列名、按钮、提示、校验信息、弹窗标题)都必须进语言包
195
+ - 字段命名 `{module}.field.xxx`、状态 `{module}.status.xxx`、消息 `{module}.msg.xxx`
196
+
197
+ #### 4.2 API 文件
198
+
199
+ ```ts
200
+ // src/api/{module}/{page}/index.ts
201
+ import request from "@/utils/request";
202
+
203
+ export function findPagination(data: any) {
204
+ return request({
205
+ url: "/api/{module}/{page}/find-pagination",
206
+ method: "post",
207
+ data,
208
+ });
209
+ }
210
+ export function getById(id: number | string) {
211
+ return request({
212
+ url: `/api/{module}/{page}/get-id?id=${id}`,
213
+ method: "get",
214
+ });
215
+ }
216
+ export function save(data: any) {
217
+ return request({
218
+ url: "/api/{module}/{page}/save",
219
+ method: "post",
220
+ data: { params: data },
221
+ });
222
+ }
223
+ export function update(data: any) {
224
+ return request({
225
+ url: "/api/{module}/{page}/update",
226
+ method: "post",
227
+ data: { params: data },
228
+ });
229
+ }
230
+ export function remove(ids: string) {
231
+ return request({
232
+ url: "/api/{module}/{page}/delete",
233
+ method: "post",
234
+ data: { ids },
235
+ });
236
+ }
237
+ ```
238
+
239
+ **API 规则**:
240
+
241
+ - 接口前缀参考目标工程同模块已有 API 风格;若无参考,使用 `/api/{module}/{page}/xxx` 占位
242
+ - POST 保存/更新使用 `{ params: data }` 包装
243
+ - GET 查询单条必须把参数直接拼入 URL(mock 兼容)
244
+ - 用户操作成功/失败走 `reqIsSucceed`,不硬编码 `res.code === 800`
245
+ - 导出/下载用 Blob 释放 URL
246
+
247
+ #### 4.3 主页面
248
+
249
+ ```vue
250
+ <template>
251
+ <section class="{page}-list-page">
252
+ <!-- 标题栏 -->
253
+ <div class="page-header">
254
+ <el-breadcrumb separator="/">
255
+ <el-breadcrumb-item>{{ $t("{module}.breadcrumb") }}</el-breadcrumb-item>
256
+ <el-breadcrumb-item>{{ $t("{module}.list") }}</el-breadcrumb-item>
257
+ </el-breadcrumb>
258
+ <h2 class="page-title">{{ $t("{module}.title") }}</h2>
259
+ </div>
260
+
261
+ <!-- 查询区(按 page-template 模式决定用 GsSearchBar 还是 el-form inline) -->
262
+ <!-- 列表区(GsCustomizeTable 或 gs-table) -->
263
+ <!-- 弹窗/抽屉组件 -->
264
+ </section>
265
+ </template>
266
+
267
+ <script setup lang="ts">
268
+ import { ref, reactive, onMounted } from "vue";
269
+ import { ElMessage, ElMessageBox } from "element-plus";
270
+ import { useI18n } from "vue-i18n";
271
+ import { findPagination, remove } from "@/api/{module}/{page}";
272
+
273
+ const { t } = useI18n();
274
+ // 数据、方法、事件处理...
275
+ </script>
276
+
277
+ <style scoped lang="scss">
278
+ .{page}-list-page {
279
+ padding: 16px;
280
+ .page-header { /* ... */ }
281
+ }
282
+ </style>
283
+ ```
284
+
285
+ **页面规则**:
286
+
287
+ - 必须使用 `<script setup lang="ts">`
288
+ - 必须使用 `$t()` 或 `t()` 引用语言包,禁止硬编码中文
289
+ - 必须使用 `reqIsSucceed` 判断成功,不硬编码 `res.code === 800`
290
+ - 列表页使用 GsTable / GsCustomizeTable,复杂列通过 `slotArr` 开启插槽
291
+ - 操作列 `prop: 'action'`、`fixed: 'right'`、`editable: true`
292
+ - 所有按钮操作带 loading 防重复点击
293
+ - 页面根节点使用唯一 class,样式使用 `<style scoped lang="scss">`
294
+ - 不写死 `px` 高度,使用 flex 布局
295
+
296
+ #### 4.4 子组件(按需)
297
+
298
+ 按所选模板模式的推荐结构生成:
299
+
300
+ - 列表页:`AddForm.vue`、`EditForm.vue`、`DetailDrawer.vue`
301
+ - 表单页:`BasicForm.vue`
302
+ - 左树右详情:`TreePanel.vue`、`XxxTab.vue`
303
+
304
+ **子组件规则**:
305
+
306
+ - 通过 `props` 接收数据(`visible`、`rowData` 等)
307
+ - 通过 `emit` 通知父组件(`update:visible`、`refresh`)
308
+ - 弹窗/抽屉使用 `:model-value` + `@update:model-value` 模式,**不**内部再建 `visible` ref
309
+ - 表单校验规则里的 `message` 必须用 `t('{module}.field.xxx.required')`
310
+
311
+ #### 4.5 配置文件(可选)
312
+
313
+ - `gridConfig.ts`:GsTable 列配置,每列 `prop / label / width / align / editable / dictCode`
314
+ - `searchConfig.ts`:GsSearchBar 查询项配置
315
+
316
+ ### 步骤 5:生成 mock 菜单(可选)
317
+
318
+ 如果 front-demo 工程使用动态菜单(`src/permission.ts`),在 mock 菜单文件中追加新页面的菜单项,使原型可通过侧边栏访问:
319
+
320
+ ```ts
321
+ // 追加到 mock 菜单数组
322
+ {
323
+ menuId: 9001,
324
+ menuCode: '{module}-{page}',
325
+ menuUrl: '/{module}/{page}',
326
+ menuName: '{页面中文名}',
327
+ originalAddr: null, // 关键:必须为 null
328
+ children: [],
329
+ }
330
+ ```
331
+
332
+ ### 步骤 6:输出原型生成报告
333
+
334
+ 以表格形式列出所有生成的文件:
335
+
336
+ ```markdown
337
+ ## 原型生成报告
338
+
339
+ **模块**: {module}
340
+ **页面数**: {N}
341
+ **生成文件**: {M}
342
+
343
+ ### 文件清单
344
+
345
+ | 文件路径 | 类型 | 说明 |
346
+ | -------------------------------------------------- | ------ | -------- |
347
+ | `src/views/{module}/{page}/index.vue` | 页面 | 主列表页 |
348
+ | `src/views/{module}/{page}/components/AddForm.vue` | 子组件 | 新增弹窗 |
349
+ | `src/api/{module}/{page}/index.ts` | API | 5 个接口 |
350
+ | `src/lang/modules/{module}/zh-cn.ts` | i18n | 中文 |
351
+ | ... | ... | ... |
352
+
353
+ ### 启动预览
354
+
355
+ cd references/front-demo
356
+ npm run dev
357
+
358
+ 访问 http://localhost:xxxx,在侧边栏找到「{模块名}」菜单进入。
359
+ ```
360
+
361
+ ## 质量自检清单
362
+
363
+ 生成完成后,对每个页面过以下清单:
364
+
365
+ - [ ] 所有文案走 i18n(无硬编码中文)
366
+ - [ ] 语言包是嵌套对象结构(非扁平 key)
367
+ - [ ] API 请求方式与 mock 兼容(GET 参数拼入 URL)
368
+ - [ ] 表格操作列设置 `editable: true` 并加入 `slotArr`
369
+ - [ ] 弹窗使用 `:model-value` + `@update:model-value` 模式
370
+ - [ ] 用户操作按钮带 loading 防重复点击
371
+ - [ ] 表单校验 message 使用 `t()` 引用
372
+ - [ ] 页面根节点有唯一 class
373
+ - [ ] 不直接复制 front-demo 旧页面的硬编码文案、`@ts-nocheck`、`console.log`
374
+ - [ ] mock 菜单的 `originalAddr` 为 `null`
375
+
376
+ 未通过的项必须修正后再输出。
377
+
378
+ ## 必选执行后钩子
379
+
380
+ 检查项目根目录是否存在 `.adspecs/extensions.yml`。
381
+
382
+ - 如果不存在或 `hooks.after_front_prototype` 下无钩子,跳到完成报告。
383
+ - 按通用钩子规则处理(过滤 `enabled: false`、跳过有 `condition` 的钩子、构造斜杠命令时 `.` → `-`)。
384
+ - 对 `optional: false` 的必选钩子,必须发出 `EXECUTE_COMMAND: {command}`。
385
+
386
+ ## 完成报告
387
+
388
+ 向用户输出:
389
+
390
+ 1. **原型生成报告**(文件清单表格)
391
+ 2. **启动预览命令**
392
+ 3. **扩展钩子分发结果**(如有)
393
+ 4. **下一步建议**:
394
+ - 验收原型后,可用 `/adspecs-plan` 生成后端系统设计
395
+ - 如需调整交互,可修改原型文件再次运行本 skill
396
+
397
+ ## 完成标志
398
+
399
+ - [ ] PRD 已解析,页面需求已提取
400
+ - [ ] 每个页面已选择匹配的模板模式
401
+ - [ ] 语言包、API、页面、子组件已按规范生成
402
+ - [ ] 所有文件写入 front-demo/src/ 对应目录
403
+ - [ ] 质量自检清单全部通过
404
+ - [ ] 原型生成报告已输出
405
+ - [ ] 扩展钩子已按规则分发或跳过