@agile-team/wl-skills-kit 2.4.2 → 2.5.1
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.
- package/CHANGELOG.md +44 -1
- package/README.md +68 -45
- package/bin/wl-skills.js +196 -12
- package/files/.github/copilot-instructions.md +361 -322
- package/files/.github/guides/architecture.md +1 -1
- package/files/.github/guides/usage.md +32 -10
- package/files/.github/skills/_registry.md +18 -16
- package/files/.github/skills/core/page-codegen/SKILL.md +200 -97
- package/files/.github/skills/core/page-codegen/USAGE.md +33 -12
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-DETAIL-TABS.md +80 -48
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-FORM-ROUTE.md +183 -55
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-LIST.md +110 -21
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-MASTER-DETAIL.md +29 -9
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-RECORD-FORM.md +93 -48
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-TREE-LIST.md +49 -29
- package/files/.github/skills/core/prototype-scan/SKILL.md +16 -0
- package/files/.github/skills/sync/menu-sync/SKILL.md +27 -13
- package/mcp/server.js +279 -195
- package/mcp/tools/menuSync.js +416 -96
- package/mcp/tools/projectTools.js +336 -124
- package/package.json +5 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
## 这个 Skill 解决什么问题
|
|
9
9
|
|
|
10
|
-
基于《页面清单》+ `api.md`,**自动生成符合项目规范的 Vue 页面**(标准页面骨架:index.vue / data.ts / index.scss + api.md 按需),并跑一遍内部规范自检(Pre-flight + 完成摘要)。
|
|
10
|
+
基于《页面清单》+ `api.md`,**自动生成符合项目规范的 Vue 页面**(标准页面骨架:index.vue / data.ts / index.scss + api.md + mock 按需),并跑一遍内部规范自检(Pre-flight + 完成摘要)。
|
|
11
11
|
|
|
12
12
|
生成出来的代码**满足 13 条 standards**,无需手工改语法/命名。
|
|
13
13
|
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
|
|
24
24
|
## 触发关键词
|
|
25
25
|
|
|
26
|
-
`生成页面` / `创建页面` / `代码生成` / `vue 页面` / `按原型生成` / `帮我生成`
|
|
26
|
+
`生成页面` / `创建页面` / `代码生成` / `vue 页面` / `按原型生成` / `帮我生成` / `列表页` / `管理页` / `台账` / `mock` / `先能跑` / `AGGrid` / `skills-ui`
|
|
27
|
+
|
|
28
|
+
用户不需要精确说出 Skill 名。只要表达“做个页面”“根据截图生成”“先用假数据”“菜单也加上”“风格没生效”,AI 应自动进入 Intent Router,读取 `page-codegen/SKILL.md`、模板索引、匹配模板和 `standards/12-base-table.md`。
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
@@ -37,8 +39,9 @@ AI:[Pre-flight]
|
|
|
37
39
|
模板基线:templates/domains/produce/customer/
|
|
38
40
|
13 条 standards 自检通过项预估:
|
|
39
41
|
✓ AbstractPageQueryHook 正确继承
|
|
40
|
-
✓
|
|
41
|
-
✓
|
|
42
|
+
✓ BaseTable render-type="agGrid"
|
|
43
|
+
✓ TABLE_CID / 列级 cid 完整
|
|
44
|
+
✓ defineColumns / renderOps 已使用
|
|
42
45
|
✓ scoped scss
|
|
43
46
|
⚠ 待确认:customerStatus 字典 logicValue 名
|
|
44
47
|
[生成中... 8 分钟]
|
|
@@ -56,10 +59,11 @@ AI:[Pre-flight]
|
|
|
56
59
|
|
|
57
60
|
```
|
|
58
61
|
src/views/<域>/<模块>/<子模块>/<page-name>/
|
|
59
|
-
├── data.ts
|
|
62
|
+
├── data.ts API_CONFIG、Hook 类、TABLE_CID、defineColumns/renderOps
|
|
60
63
|
├── index.vue template + script + import data.ts
|
|
61
64
|
├── index.scss 页面专属样式(已 :deep / scoped 包好)
|
|
62
|
-
|
|
65
|
+
├── api.md (由 api-contract 生成,codegen 不覆盖)
|
|
66
|
+
└── mock/*.ts mock-first 场景下生成,端点与 API_CONFIG 对齐
|
|
63
67
|
```
|
|
64
68
|
|
|
65
69
|
外加生成报告:`.github/reports/PAGE_CODEGEN_<模块>_<YYYYMMDD>.md`
|
|
@@ -81,12 +85,29 @@ src/views/<域>/<模块>/<子模块>/<page-name>/
|
|
|
81
85
|
|
|
82
86
|
## 常见踩坑
|
|
83
87
|
|
|
84
|
-
| 现象 | 原因 | 解法
|
|
85
|
-
| ----------------------------------- | -------------------------------------- |
|
|
86
|
-
| 生成出来的页面 console 报字典查不到 | 字典还没在 reports/SYS_DICT_INFO.md 中 | 先跑 `dict-sync` 拉取,或手动补 dict
|
|
87
|
-
| 表单弹窗未加 v-loading | api.md 没标记 save/update 为耗时操作 | 在 api.md 接口清单中加 `**预计耗时:> 2s**` 标记
|
|
88
|
-
| `EColumn` 字段缺 `width` | 模板默认不指定 width | 模板里手动加,或选用 `templates/domains/` 下的成品
|
|
89
|
-
| AGGrid cid 重复 |
|
|
88
|
+
| 现象 | 原因 | 解法 |
|
|
89
|
+
| ----------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------- |
|
|
90
|
+
| 生成出来的页面 console 报字典查不到 | 字典还没在 reports/SYS_DICT_INFO.md 中 | 先跑 `dict-sync` 拉取,或手动补 dict |
|
|
91
|
+
| 表单弹窗未加 v-loading | api.md 没标记 save/update 为耗时操作 | 在 api.md 接口清单中加 `**预计耗时:> 2s**` 标记 |
|
|
92
|
+
| `EColumn` 字段缺 `width` | 模板默认不指定 width | 模板里手动加,或选用 `templates/domains/` 下的成品 |
|
|
93
|
+
| AGGrid cid 重复 | cid 生成不规范 | 使用 `{页面目录首字母缩写}-{Date.now().toString(36)}`,多表追加 `-sub1/-sub2` |
|
|
94
|
+
| 表格不是 AGGrid | 模板未写 `render-type="agGrid"` | 使用最新模板,或运行 `wl-skills validate-page <页面目录>` |
|
|
95
|
+
| 操作列还是旧按钮 | 生成了 `operations: []` | 改成 `defaultSlot + renderOps()` |
|
|
96
|
+
| skills-ui 安装但风格没生效 | tokens/styles/preset/runtime 未接入 | 运行 `wl-skills doctor-ui` 查看缺项 |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 生成后建议命令
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
wl-skills validate-page src/views/<module>/<subModule>/<page>
|
|
104
|
+
wl-skills doctor-ui
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
若 AI 可调用 MCP,优先使用:
|
|
108
|
+
|
|
109
|
+
- `wls_validate_page`
|
|
110
|
+
- `wls_doctor_ui`
|
|
90
111
|
|
|
91
112
|
---
|
|
92
113
|
|
|
@@ -81,6 +81,8 @@
|
|
|
81
81
|
</div>
|
|
82
82
|
<BaseTable
|
|
83
83
|
ref="itemTableRef"
|
|
84
|
+
render-type="agGrid"
|
|
85
|
+
:cid="ITEM_TABLE_CID"
|
|
84
86
|
:data="itemList"
|
|
85
87
|
:columns="itemColumns"
|
|
86
88
|
showToolbar
|
|
@@ -110,6 +112,7 @@ import {
|
|
|
110
112
|
itemList,
|
|
111
113
|
itemColumns,
|
|
112
114
|
itemPage,
|
|
115
|
+
ITEM_TABLE_CID,
|
|
113
116
|
formRef,
|
|
114
117
|
itemTableRef,
|
|
115
118
|
handleSave,
|
|
@@ -136,6 +139,9 @@ import { ElMessage } from "element-plus";
|
|
|
136
139
|
import type { FormInstance, FormRules } from "element-plus";
|
|
137
140
|
import type { TableColumnDesc } from "@/types/page";
|
|
138
141
|
import envConfig from "@jhlc/common-core/src/store/env-config";
|
|
142
|
+
import { defineColumns, renderOps } from "@agile-team/wk-skills-ui/runtime";
|
|
143
|
+
|
|
144
|
+
export const ITEM_TABLE_CID = "[pageAbbr]-[base36Timestamp]-sub1";
|
|
139
145
|
|
|
140
146
|
export const API_CONFIG = {
|
|
141
147
|
getById: "/[服务缩写]/[主资源]/getById",
|
|
@@ -184,22 +190,25 @@ export const itemTableRef = ref();
|
|
|
184
190
|
export const itemList = ref<any[]>([]);
|
|
185
191
|
export const itemPage = reactive({ current: 1, size: 10, total: 0 });
|
|
186
192
|
|
|
187
|
-
export const itemColumns: TableColumnDesc<any>[] = [
|
|
188
|
-
{ type: "index", width:
|
|
189
|
-
{
|
|
193
|
+
export const itemColumns: TableColumnDesc<any>[] = defineColumns([
|
|
194
|
+
{ type: "index", label: "序号", width: 60, align: "center" },
|
|
195
|
+
{
|
|
196
|
+
label: "[子项字段]",
|
|
197
|
+
name: "[fieldName]",
|
|
198
|
+
cid: `${ITEM_TABLE_CID}-[fieldName]`,
|
|
199
|
+
minWidth: 120,
|
|
200
|
+
},
|
|
190
201
|
{
|
|
191
202
|
label: "操作",
|
|
203
|
+
name: "_action",
|
|
204
|
+
cid: `${ITEM_TABLE_CID}-action`,
|
|
192
205
|
width: 100,
|
|
193
206
|
fixed: "right",
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
label: "删除",
|
|
198
|
-
onClick: (row: any) => removeItem(row),
|
|
199
|
-
},
|
|
200
|
-
],
|
|
207
|
+
align: "center",
|
|
208
|
+
defaultSlot: ({ row }: any) =>
|
|
209
|
+
renderOps([{ type: "del", onClick: () => removeItem(row) }]),
|
|
201
210
|
},
|
|
202
|
-
];
|
|
211
|
+
] as any) as TableColumnDesc<any>[];
|
|
203
212
|
|
|
204
213
|
// ===== 数据加载 =====
|
|
205
214
|
export async function loadItems() {
|
|
@@ -453,7 +462,14 @@ defineExpose({ open });
|
|
|
453
462
|
@reset="select"
|
|
454
463
|
/>
|
|
455
464
|
<BaseToolbar :items="toolbars" />
|
|
456
|
-
<BaseTable
|
|
465
|
+
<BaseTable
|
|
466
|
+
ref="tableRef"
|
|
467
|
+
render-type="agGrid"
|
|
468
|
+
:cid="TABLE_CID"
|
|
469
|
+
:data="list"
|
|
470
|
+
:columns="columns"
|
|
471
|
+
showToolbar
|
|
472
|
+
/>
|
|
457
473
|
<jh-pagination
|
|
458
474
|
v-show="page.total && page.total > 0"
|
|
459
475
|
:total="page.total || 0"
|
|
@@ -468,7 +484,7 @@ defineExpose({ open });
|
|
|
468
484
|
</template>
|
|
469
485
|
|
|
470
486
|
<script setup lang="ts">
|
|
471
|
-
import { createPage } from "./data";
|
|
487
|
+
import { createPage, TABLE_CID } from "./data";
|
|
472
488
|
import AddModal from "./components/addModal.vue";
|
|
473
489
|
|
|
474
490
|
const addModalRef = ref();
|
|
@@ -547,22 +563,44 @@ let _editModalRef: any = null;
|
|
|
547
563
|
|
|
548
564
|
/** 管理视角列定义 */
|
|
549
565
|
export function managementColumns(): TableColumnDesc<any>[] {
|
|
550
|
-
return [
|
|
551
|
-
{ type: "selection" },
|
|
552
|
-
{ type: "index" },
|
|
566
|
+
return defineColumns([
|
|
567
|
+
{ type: "selection", width: 55, fixed: "left", align: "center", headerAlign: "center" },
|
|
568
|
+
{ type: "index", label: "序号", width: 60, align: "center" },
|
|
553
569
|
// ... 管理视角列(按原型顺序)
|
|
554
|
-
{
|
|
555
|
-
|
|
570
|
+
{
|
|
571
|
+
label: "操作",
|
|
572
|
+
name: "_action",
|
|
573
|
+
cid: `${TABLE_CID}-management-action`,
|
|
574
|
+
width: 120,
|
|
575
|
+
fixed: "right",
|
|
576
|
+
align: "center",
|
|
577
|
+
defaultSlot: ({ row }: any) => renderOps([
|
|
578
|
+
{ type: "edit", onClick: () => _editModalRef?.value?.open(row.id) },
|
|
579
|
+
{ type: "del", onClick: () => Page?.remove(row.id) }
|
|
580
|
+
])
|
|
581
|
+
}
|
|
582
|
+
] as any) as TableColumnDesc<any>[];
|
|
556
583
|
}
|
|
557
584
|
|
|
558
585
|
/** 使用视角列定义(含业务明细字段) */
|
|
559
586
|
export function usageColumns(): TableColumnDesc<any>[] {
|
|
560
|
-
return [
|
|
561
|
-
{ type: "selection" },
|
|
562
|
-
{ type: "index" },
|
|
587
|
+
return defineColumns([
|
|
588
|
+
{ type: "selection", width: 55, fixed: "left", align: "center", headerAlign: "center" },
|
|
589
|
+
{ type: "index", label: "序号", width: 60, align: "center" },
|
|
563
590
|
// ... 使用视角列(按原型顺序,通常比管理视角多出业务字段)
|
|
564
|
-
{
|
|
565
|
-
|
|
591
|
+
{
|
|
592
|
+
label: "操作",
|
|
593
|
+
name: "_action",
|
|
594
|
+
cid: `${TABLE_CID}-usage-action`,
|
|
595
|
+
width: 120,
|
|
596
|
+
fixed: "right",
|
|
597
|
+
align: "center",
|
|
598
|
+
defaultSlot: ({ row }: any) => renderOps([
|
|
599
|
+
{ type: "edit", onClick: () => _editModalRef?.value?.open(row.id) },
|
|
600
|
+
{ type: "del", onClick: () => Page?.remove(row.id) }
|
|
601
|
+
])
|
|
602
|
+
}
|
|
603
|
+
] as any) as TableColumnDesc<any>[];
|
|
566
604
|
}
|
|
567
605
|
|
|
568
606
|
let Page: any = null;
|
|
@@ -756,18 +794,20 @@ export function createPage() {
|
|
|
756
794
|
];
|
|
757
795
|
}
|
|
758
796
|
columnsDef() {
|
|
759
|
-
return [
|
|
797
|
+
return defineColumns([
|
|
760
798
|
// ...
|
|
761
799
|
{
|
|
762
|
-
label: "操作",
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
800
|
+
label: "操作",
|
|
801
|
+
name: "_action",
|
|
802
|
+
cid: `${TABLE_CID}-action`,
|
|
803
|
+
fixed: "right",
|
|
804
|
+
align: "center",
|
|
805
|
+
defaultSlot: ({ row }: any) =>
|
|
806
|
+
renderOps([
|
|
807
|
+
{ type: "edit", onClick: () => navigateToForm({ id: row.id }) }
|
|
808
|
+
])
|
|
769
809
|
}
|
|
770
|
-
];
|
|
810
|
+
] as any) as TableColumnDesc<any>[];
|
|
771
811
|
}
|
|
772
812
|
}
|
|
773
813
|
```
|
|
@@ -846,22 +886,14 @@ onMounted(() => {
|
|
|
846
886
|
### 实现方式
|
|
847
887
|
|
|
848
888
|
```vue
|
|
849
|
-
<!--
|
|
850
|
-
<
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
889
|
+
<!-- 表格列:按 mode 在 data.ts 中切换 columns,仍使用 BaseTable + AGGrid -->
|
|
890
|
+
<BaseTable
|
|
891
|
+
render-type="agGrid"
|
|
892
|
+
:cid="DETAIL_TABLE_CID"
|
|
893
|
+
:data="list"
|
|
894
|
+
:columns="isChange ? changeColumns : addColumns"
|
|
855
895
|
/>
|
|
856
896
|
|
|
857
|
-
<!-- 操作列:变更模式多一个编辑按钮 -->
|
|
858
|
-
<el-table-column v-if="!isView" label="操作" :width="isChange ? 120 : 80">
|
|
859
|
-
<template #default="{ row, $index }">
|
|
860
|
-
<el-button v-if="isChange" type="primary" link @click="editRow(row, $index)">编辑</el-button>
|
|
861
|
-
<el-button type="danger" link @click="list.splice($index, 1)">删除</el-button>
|
|
862
|
-
</template>
|
|
863
|
-
</el-table-column>
|
|
864
|
-
|
|
865
897
|
<!-- 底部新增行链接(变更模式) -->
|
|
866
898
|
<div
|
|
867
899
|
v-if="isChange && !isView"
|
|
@@ -1000,7 +1032,7 @@ spec.features.hiddenMenu === true:
|
|
|
1000
1032
|
✅ query: spec 12 项 = code 12 项,顺序一致
|
|
1001
1033
|
✅ columns: spec 16 项 = code 16 项,顺序一致
|
|
1002
1034
|
✅ toolbar: spec 7 项 = code 7 项,顺序一致,颜色正确
|
|
1003
|
-
✅
|
|
1035
|
+
✅ rowActions: spec 3 项 = code 3 项,顺序一致
|
|
1004
1036
|
✅ tabs: spec 3 项 = code 3 项,顺序一致
|
|
1005
1037
|
✅ subTables: businessInfo(editable) — 有新增/删除
|
|
1006
1038
|
✅ dict 字段: 8 个全部配置 logicType
|
|
@@ -1013,7 +1045,7 @@ spec.features.hiddenMenu === true:
|
|
|
1013
1045
|
```
|
|
1014
1046
|
❌ columns: spec 35 项 ≠ code 34 项 — 缺少 customerName 列 → 已补全
|
|
1015
1047
|
❌ toolbar 顺序: spec [新增申请, 删除, 启用] ≠ code [新增, 启用, 删除] → 已调整
|
|
1016
|
-
❌
|
|
1048
|
+
❌ rowActions: spec [查看, 编辑, 删除] ≠ code [编辑, 删除] — 缺少"查看" → 已补全
|
|
1017
1049
|
```
|
|
1018
1050
|
|
|
1019
1051
|
---
|