@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.
@@ -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
- EColumn 元数据完备
41
- pageRef 命名规范
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 EColumn 定义、API_CONFIG、Hook
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
- └── api.md (由 api-contract 生成,codegen 不覆盖)
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 重复 | 多页面同时生成时随机数撞了 | cid 已用 `{首字母缩写}-{Unix秒后6位}`,理论极低概率 |
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: 55 },
189
- { label: "[子项字段]", name: "[fieldName]", minWidth: 120 },
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
- operations: [
195
- {
196
- name: "remove",
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 ref="tableRef" :data="list" :columns="columns" showToolbar />
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
- { label: "操作", width: 100, fixed: "right", operations: [...] }
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
- { label: "操作", width: 100, fixed: "right", operations: [...] }
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: "操作", fixed: "right",
763
- operations: [
764
- {
765
- name: "edit", label: "编辑",
766
- onClick: (row: any) => navigateToForm({ id: row.id })
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
- <!-- 表格列:v-if mode 控制 -->
850
- <el-table-column v-if="isChange" label="使用组织" prop="useOrg" />
851
- <el-table-column
852
- v-if="!isChange && !isView"
853
- label="免息天数"
854
- prop="interestFreeDays"
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
- operations: spec 3 项 = code 3 项,顺序一致
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
- operations: spec [查看, 编辑, 删除] ≠ code [编辑, 删除] — 缺少"查看" → 已补全
1048
+ rowActions: spec [查看, 编辑, 删除] ≠ code [编辑, 删除] — 缺少"查看" → 已补全
1017
1049
  ```
1018
1050
 
1019
1051
  ---