@agile-team/wl-skills-kit 1.0.0
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 +13 -0
- package/README.md +328 -0
- package/bin/wl-skills.js +104 -0
- package/files/.github/copilot-instructions.md +211 -0
- package/files/.github/docs/SYS_MENU_INFO.md +247 -0
- package/files/.github/docs/menu-sync-design.md +265 -0
- package/files/.github/docs/use-skill.md +379 -0
- package/files/.github/docs/wl-skills-kit.md +266 -0
- package/files/.github/skills/api-contract/SKILL.md +247 -0
- package/files/.github/skills/convention-extract/SKILL.md +355 -0
- package/files/.github/skills/menu-sync/SKILL.md +255 -0
- package/files/.github/skills/menu-sync/env/guide.md +73 -0
- package/files/.github/skills/page-codegen/SKILL.md +825 -0
- package/files/.github/skills/page-codegen/TPL-CHANGE-HISTORY.md +281 -0
- package/files/.github/skills/page-codegen/TPL-DETAIL-TABS.md +1112 -0
- package/files/.github/skills/page-codegen/TPL-DRIVEN.md +124 -0
- package/files/.github/skills/page-codegen/TPL-FORM-ROUTE.md +441 -0
- package/files/.github/skills/page-codegen/TPL-LIST.md +196 -0
- package/files/.github/skills/page-codegen/TPL-MASTER-DETAIL.md +153 -0
- package/files/.github/skills/page-codegen/TPL-OPERATION-STATION.md +442 -0
- package/files/.github/skills/page-codegen/TPL-RECORD-FORM.md +376 -0
- package/files/.github/skills/page-codegen/TPL-TREE-LIST.md +191 -0
- package/files/.github/skills/prototype-scan/SKILL.md +414 -0
- package/files/demo/README.md +44 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add/api.md +54 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add/data.ts +346 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add/index.scss +1 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add/index.vue +28 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add-form/data.ts +115 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add-form/index.scss +44 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-add-form/index.vue +43 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change/data.ts +338 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change/index.scss +1 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change/index.vue +28 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-form/data.ts +115 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-form/index.scss +44 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-form/index.vue +43 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/data.ts +196 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.scss +150 -0
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.vue +79 -0
- package/files/demo/produce/aiflow/mmwr-customer-archive/api.md +88 -0
- package/files/demo/produce/aiflow/mmwr-customer-archive/data.ts +601 -0
- package/files/demo/produce/aiflow/mmwr-customer-archive/index.scss +1 -0
- package/files/demo/produce/aiflow/mmwr-customer-archive/index.vue +64 -0
- package/files/demo/produce/aiflow/mmwr-customer-detail/api.md +67 -0
- package/files/demo/produce/aiflow/mmwr-customer-detail/data.ts +286 -0
- package/files/demo/produce/aiflow/mmwr-customer-detail/index.scss +139 -0
- package/files/demo/produce/aiflow/mmwr-customer-detail/index.vue +318 -0
- package/files/demo/produce/aiflow/mmwr-temp-customer-archive/api.md +98 -0
- package/files/demo/produce/aiflow/mmwr-temp-customer-archive/data.ts +543 -0
- package/files/demo/produce/aiflow/mmwr-temp-customer-archive/index.scss +1 -0
- package/files/demo/produce/aiflow/mmwr-temp-customer-archive/index.vue +52 -0
- package/files/demo/sale/demo/add-demo/data.ts +518 -0
- package/files/demo/sale/demo/add-demo/index.scss +207 -0
- package/files/demo/sale/demo/add-demo/index.vue +167 -0
- package/files/demo/sale/demo/billet-flame-cut-plan/data.ts +524 -0
- package/files/demo/sale/demo/billet-flame-cut-plan/index.scss +155 -0
- package/files/demo/sale/demo/billet-flame-cut-plan/index.vue +117 -0
- package/files/demo/sale/demo/domestic-trade-order/data.ts +308 -0
- package/files/demo/sale/demo/domestic-trade-order/index.scss +99 -0
- package/files/demo/sale/demo/domestic-trade-order/index.vue +77 -0
- package/files/demo/sale/demo/heat-batch-return/data.ts +367 -0
- package/files/demo/sale/demo/heat-batch-return/index.scss +100 -0
- package/files/demo/sale/demo/heat-batch-return/index.vue +170 -0
- package/files/demo/sale/demo/heat-batch-return/meltDialog.vue +320 -0
- package/files/demo/sale/demo/metallurgical-spec/data.ts +825 -0
- package/files/demo/sale/demo/metallurgical-spec/index.scss +264 -0
- package/files/demo/sale/demo/metallurgical-spec/index.vue +309 -0
- package/files/docs/jh-date-range.md +257 -0
- package/files/docs/jh-date.md +222 -0
- package/files/docs/jh-dept-picker.md +190 -0
- package/files/docs/jh-drag-row.md +590 -0
- package/files/docs/jh-file-upload.md +216 -0
- package/files/docs/jh-pagination.md +505 -0
- package/files/docs/jh-picker.md +218 -0
- package/files/docs/jh-select.md +148 -0
- package/files/docs/jh-text.md +248 -0
- package/files/docs/jh-user-picker.md +197 -0
- package/files/docs/page-query-hook-best-practices.md +362 -0
- package/files/docs/request.md +925 -0
- package/files/src/components/global/C_ParentView/index.vue +3 -0
- package/files/src/components/global/C_RightToolbar/index.vue +459 -0
- package/files/src/components/global/C_Splitter/index.vue +195 -0
- package/files/src/components/global/C_SvgIcon/index.vue +61 -0
- package/files/src/components/global/C_SvgIcon/svgicon.js +10 -0
- package/files/src/components/global/C_TagStatus/README.md +264 -0
- package/files/src/components/global/C_TagStatus/config.ts +192 -0
- package/files/src/components/global/C_TagStatus/index.vue +127 -0
- package/files/src/components/global/C_TagStatus/types.ts +64 -0
- package/files/src/components/global/C_Tree/README.md +153 -0
- package/files/src/components/global/C_Tree/index.scss +42 -0
- package/files/src/components/global/C_Tree/index.vue +119 -0
- package/files/src/components/global/C_Tree/types.ts +59 -0
- package/files/src/components/local/c_formModal/README.md +235 -0
- package/files/src/components/local/c_formModal/data.ts +95 -0
- package/files/src/components/local/c_formModal/index.scss +8 -0
- package/files/src/components/local/c_formModal/index.vue +107 -0
- package/files/src/components/local/c_formSections/README.md +496 -0
- package/files/src/components/local/c_formSections/data.ts +175 -0
- package/files/src/components/local/c_formSections/index.scss +280 -0
- package/files/src/components/local/c_formSections/index.vue +429 -0
- package/files/src/components/local/c_listModal/data.ts +41 -0
- package/files/src/components/local/c_listModal/index.vue +136 -0
- package/files/src/components/local/c_spliterTitle/index.scss +25 -0
- package/files/src/components/local/c_spliterTitle/index.vue +21 -0
- package/files/src/components/remote/AGGrid/README.md +530 -0
- package/files/src/components/remote/BaseForm/README.md +508 -0
- package/files/src/components/remote/BaseQuery/README.md +865 -0
- package/files/src/components/remote/BaseTable/README.md +941 -0
- package/files/src/components/remote/BaseToolbar/README.md +496 -0
- package/files/src/types/page.ts +24 -0
- package/package.json +31 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.0] - 2026-04-08
|
|
4
|
+
|
|
5
|
+
### 初始发布
|
|
6
|
+
|
|
7
|
+
- 5 个 AI Skills(prototype-scan / api-contract / page-codegen / menu-sync / convention-extract)
|
|
8
|
+
- page-codegen 含 9 个独立模板(TPL-LIST / TPL-FORM-ROUTE / TPL-MASTER-DETAIL / TPL-TREE-LIST / TPL-DETAIL-TABS / TPL-CHANGE-HISTORY / TPL-RECORD-FORM / TPL-OPERATION-STATION / TPL-DRIVEN)
|
|
9
|
+
- 12 个平台组件 API 文档(jh-select / jh-date / jh-drag-row 等)
|
|
10
|
+
- 通用组件(global 6 个 + local 4 个 + remote 5 个 README)
|
|
11
|
+
- 类型桶文件 src/types/page.ts
|
|
12
|
+
- 领域样例 demo/(produce 8 页 + sale 5 页)
|
|
13
|
+
- CLI 工具 bin/wl-skills.js(--dry-run 预览)
|
package/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# @agile-team/wl-skills-kit
|
|
2
|
+
|
|
3
|
+
**AI Skill 模板包** — 一条命令,将 AI 编码指令、组件文档、通用组件、领域样例导入到你的 Vue 3 前端项目。
|
|
4
|
+
|
|
5
|
+
让 AI(Copilot / Cursor / Windsurf 等)**直接理解你的项目规范和组件体系**,从 Axure 原型 / 详细设计文档 → 生成可运行的完整页面代码。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 快速开始
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# 在你的项目根目录执行(无需安装,直接运行)
|
|
13
|
+
npx @agile-team/wl-skills-kit
|
|
14
|
+
|
|
15
|
+
# 预览将写入哪些文件(不实际写入)
|
|
16
|
+
npx @agile-team/wl-skills-kit --dry-run
|
|
17
|
+
|
|
18
|
+
# 更新到最新版
|
|
19
|
+
npx @agile-team/wl-skills-kit@latest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
就这样。108 个文件按原始路径导入到你的项目,**无其他副作用**。
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 导入了什么?
|
|
27
|
+
|
|
28
|
+
执行后你的项目会新增以下内容:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
你的项目/
|
|
32
|
+
├── .github/
|
|
33
|
+
│ ├── copilot-instructions.md ← AI 自动加载的编码规范(项目总纲)
|
|
34
|
+
│ ├── skills/ ← 5 个 AI Skill
|
|
35
|
+
│ │ ├── prototype-scan/SKILL.md ← ① 原型扫描(Axure HTML / 详设文档 → page-spec JSON)
|
|
36
|
+
│ │ ├── api-contract/SKILL.md ← ② 接口约定(page-spec → api.md)
|
|
37
|
+
│ │ ├── page-codegen/ ← ③ 页面代码生成
|
|
38
|
+
│ │ │ ├── SKILL.md ← 主规则文件(约束 + 规范)
|
|
39
|
+
│ │ │ ├── TPL-LIST.md ← 标准列表页模板
|
|
40
|
+
│ │ │ ├── TPL-FORM-ROUTE.md ← 复杂表单独立路由模板
|
|
41
|
+
│ │ │ ├── TPL-MASTER-DETAIL.md ← 主从表模板
|
|
42
|
+
│ │ │ ├── TPL-TREE-LIST.md ← 左树右列表模板
|
|
43
|
+
│ │ │ ├── TPL-DETAIL-TABS.md ← 详情 Tab + 子表模板
|
|
44
|
+
│ │ │ ├── TPL-CHANGE-HISTORY.md ← 变更历史比对模板
|
|
45
|
+
│ │ │ ├── TPL-RECORD-FORM.md ← 录入型实绩页模板
|
|
46
|
+
│ │ │ ├── TPL-OPERATION-STATION.md← 工序操作站模板
|
|
47
|
+
│ │ │ └── TPL-DRIVEN.md ← 配置驱动模板识别参考
|
|
48
|
+
│ │ ├── menu-sync/SKILL.md ← ④ 菜单同步(pages.ts → 后端菜单表)
|
|
49
|
+
│ │ └── convention-extract/SKILL.md ← ⑤ 规范提炼(扫描源码 → 编码规范文档)
|
|
50
|
+
│ └── docs/ ← 设计文档
|
|
51
|
+
│ ├── use-skill.md ← Skill 使用 + 移植一站式指南
|
|
52
|
+
│ ├── menu-sync-design.md ← 菜单同步方案设计
|
|
53
|
+
│ ├── SYS_MENU_INFO.md ← 菜单注册记录模板
|
|
54
|
+
│ └── wl-skills-kit.md ← 本包详细设计文档
|
|
55
|
+
│
|
|
56
|
+
├── docs/ ← 12 个平台组件 API 文档
|
|
57
|
+
│ ├── request.md ← getAction / postAction 等 HTTP 工具
|
|
58
|
+
│ ├── page-query-hook-best-practices.md ← AbstractPageQueryHook 最佳实践
|
|
59
|
+
│ ├── jh-select.md ← 下拉选择组件
|
|
60
|
+
│ ├── jh-date.md / jh-date-range.md ← 日期 / 日期范围选择
|
|
61
|
+
│ ├── jh-drag-row.md ← 上下分栏拖拽组件
|
|
62
|
+
│ ├── jh-pagination.md ← 分页组件
|
|
63
|
+
│ ├── jh-file-upload.md ← 文件上传
|
|
64
|
+
│ ├── jh-text.md ← 文本翻译
|
|
65
|
+
│ ├── jh-picker.md ← 通用选择器
|
|
66
|
+
│ ├── jh-user-picker.md ← 用户选择器
|
|
67
|
+
│ └── jh-dept-picker.md ← 部门选择器
|
|
68
|
+
│
|
|
69
|
+
├── src/
|
|
70
|
+
│ ├── components/
|
|
71
|
+
│ │ ├── global/ ← 6 个全局自动注册组件
|
|
72
|
+
│ │ │ ├── C_Splitter/ ← 左右分割面板
|
|
73
|
+
│ │ │ ├── C_Tree/ ← 带搜索的树形面板
|
|
74
|
+
│ │ │ ├── C_TagStatus/ ← 状态标签(彩色 Tag)
|
|
75
|
+
│ │ │ ├── C_ParentView/ ← 父级视图容器
|
|
76
|
+
│ │ │ ├── C_SvgIcon/ ← SVG 图标
|
|
77
|
+
│ │ │ └── C_RightToolbar/ ← 右侧工具栏
|
|
78
|
+
│ │ ├── local/ ← 4 个按需导入组件
|
|
79
|
+
│ │ │ ├── c_formModal/ ← 通用表单弹窗(add/edit/view 三模式)
|
|
80
|
+
│ │ │ ├── c_formSections/ ← 表单分区组件
|
|
81
|
+
│ │ │ ├── c_listModal/ ← 列表选择弹窗
|
|
82
|
+
│ │ │ └── c_spliterTitle/ ← 分栏标题
|
|
83
|
+
│ │ └── remote/ ← 5 个远程组件 README(API 文档)
|
|
84
|
+
│ │ ├── BaseQuery/ ← 声明式查询区
|
|
85
|
+
│ │ ├── BaseTable/ ← 声明式表格
|
|
86
|
+
│ │ ├── BaseToolbar/ ← 声明式工具栏
|
|
87
|
+
│ │ ├── BaseForm/ ← 声明式表单
|
|
88
|
+
│ │ └── AGGrid/ ← 高性能数据网格
|
|
89
|
+
│ └── types/
|
|
90
|
+
│ └── page.ts ← 类型桶文件(统一 re-export)
|
|
91
|
+
│
|
|
92
|
+
└── demo/ ← 13 个领域样例页面(AI 学习 + 开发参考)
|
|
93
|
+
├── README.md ← 样例索引 + 模板类型标注
|
|
94
|
+
├── produce/aiflow/ ← 生产域 8 个页面
|
|
95
|
+
│ ├── mmwr-customer-archive/ ← LIST + Tabs + c_formModal
|
|
96
|
+
│ ├── mmwr-temp-customer-archive/ ← LIST
|
|
97
|
+
│ ├── mmwr-customer-apply-add/ ← LIST
|
|
98
|
+
│ ├── mmwr-customer-apply-add-form/← FORM_ROUTE
|
|
99
|
+
│ ├── mmwr-customer-apply-change/ ← LIST
|
|
100
|
+
│ ├── mmwr-customer-apply-change-form/ ← FORM_ROUTE
|
|
101
|
+
│ ├── mmwr-customer-apply-change-history/ ← CHANGE_HISTORY
|
|
102
|
+
│ └── mmwr-customer-detail/ ← DETAIL_TABS
|
|
103
|
+
└── sale/demo/ ← 销售域 5 个页面
|
|
104
|
+
├── domestic-trade-order/ ← LIST 标准列表
|
|
105
|
+
├── metallurgical-spec/ ← MASTER_DETAIL 上下分栏
|
|
106
|
+
├── add-demo/ ← FORM_ROUTE 表单页
|
|
107
|
+
├── billet-flame-cut-plan/ ← LIST 变体
|
|
108
|
+
└── heat-batch-return/ ← LIST + 自定义弹窗
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 核心价值:5 个 AI Skill
|
|
114
|
+
|
|
115
|
+
安装后,AI 编辑器自动识别这些 Skill,形成完整的**原型 → 代码**流水线:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Axure 原型 / 详设文档
|
|
119
|
+
│
|
|
120
|
+
▼
|
|
121
|
+
① prototype-scan ─── 扫描 → page-spec JSON(结构化页面描述)
|
|
122
|
+
│
|
|
123
|
+
▼
|
|
124
|
+
② api-contract ───── 生成 → api.md(前后端接口约定)
|
|
125
|
+
│
|
|
126
|
+
▼
|
|
127
|
+
③ page-codegen ───── 生成 → index.vue + data.ts + index.scss + api.md + mock
|
|
128
|
+
│ (4 文件/页 + pages.ts 注册 + mock 数据)
|
|
129
|
+
▼
|
|
130
|
+
④ menu-sync ──────── 同步 → 后端菜单表(AI 自动调 API 创建菜单)
|
|
131
|
+
|
|
132
|
+
⑤ convention-extract 一次性:扫描项目源码 → 生成编码规范文档
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 支持 9 种页面模板
|
|
136
|
+
|
|
137
|
+
| 模板 | 模式 | 说明 |
|
|
138
|
+
|------|------|------|
|
|
139
|
+
| TPL-LIST | LIST | 查询 + 工具栏 + 表格 + 分页 |
|
|
140
|
+
| TPL-FORM-ROUTE | FORM_ROUTE | 复杂表单(多 Tab、多子表)独立路由 |
|
|
141
|
+
| TPL-MASTER-DETAIL | MASTER_DETAIL | jh-drag-row 上下分栏主从表 |
|
|
142
|
+
| TPL-TREE-LIST | TREE_LIST | C_Splitter 左树 + 右列表 |
|
|
143
|
+
| TPL-DETAIL-TABS | DETAIL_TABS | 上方表单 + 下方 Tab 子表 |
|
|
144
|
+
| TPL-CHANGE-HISTORY | CHANGE_HISTORY | 左变更时间线 + 右字段比对 |
|
|
145
|
+
| TPL-RECORD-FORM | RECORD_FORM | 查询 + 表单录入(无分页) |
|
|
146
|
+
| TPL-OPERATION-STATION | OPERATION_STATION | 待处理 + 已处理联动操作 |
|
|
147
|
+
| TPL-DRIVEN | TEMPLATE_DRIVEN | 配置驱动模板页识别参考 |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 使用方式
|
|
152
|
+
|
|
153
|
+
### 方式一:完整流程(Axure 原型 → 代码)
|
|
154
|
+
|
|
155
|
+
> 最推荐。一个模块 5-8 个页面,约 5-10 分钟出完整代码。
|
|
156
|
+
|
|
157
|
+
**对 AI 说**:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
帮我扫描 C:\Users\xxx\原型包\ 下的所有HTML
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
AI 自动执行 5 步:扫描 → 生成接口约定 → 生成页面代码 → 注册路由 → 创建菜单。
|
|
164
|
+
|
|
165
|
+
### 方式二:详设文档 → 代码(更高精度)
|
|
166
|
+
|
|
167
|
+
**对 AI 说**:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
按照这份详设文档帮我生成页面
|
|
171
|
+
|
|
172
|
+
## 前置声明
|
|
173
|
+
- 业务域/模块:生产 > 生产棒线材 > AI流程
|
|
174
|
+
- 服务前缀:/mmwr/
|
|
175
|
+
- 页面清单:客户档案、临时客户档案
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
详设文档中明确写出字段英文名和字典 code,精度可达 95-100%。
|
|
179
|
+
|
|
180
|
+
### 方式三:碎片化使用(按需调用单个 Skill)
|
|
181
|
+
|
|
182
|
+
| 你想做什么 | 对 AI 说 | 触发的 Skill |
|
|
183
|
+
|-----------|---------|-------------|
|
|
184
|
+
| 扫描原型,输出页面清单 | "扫描这些原型" | prototype-scan |
|
|
185
|
+
| 给页面生成接口文档 | "生成 api.md" | api-contract |
|
|
186
|
+
| 只生成单个页面代码 | "帮我生成客户档案页面" | page-codegen |
|
|
187
|
+
| 把 pages.ts 同步到菜单表 | "帮我创建菜单" | menu-sync |
|
|
188
|
+
| 扫描项目提炼编码规范 | "提炼项目规范" | convention-extract |
|
|
189
|
+
| 查看组件怎么用 | "jh-select 怎么用" | AI 读取 docs/jh-select.md |
|
|
190
|
+
| 参考样例写代码 | "参考 demo 里的客户档案" | AI 读取 demo/ 下的代码 |
|
|
191
|
+
|
|
192
|
+
### 方式四:新项目初始化
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# 1. 创建项目后,导入 Skill 体系
|
|
196
|
+
npx @agile-team/wl-skills-kit
|
|
197
|
+
|
|
198
|
+
# 2. 对 AI 说 "提炼项目规范"
|
|
199
|
+
# → 自动扫描你的代码生成 copilot-instructions.md
|
|
200
|
+
|
|
201
|
+
# 3. 改写 page-codegen 模板(替换基类、组件、API 调用方式)
|
|
202
|
+
# → 详见 .github/docs/use-skill.md 第四章
|
|
203
|
+
|
|
204
|
+
# 4. 开始使用:发 Axure 原型给 AI
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 安装行为说明
|
|
210
|
+
|
|
211
|
+
| ✅ 会做 | ❌ 不会做 |
|
|
212
|
+
| ----------------------------------- | ---------------------------- |
|
|
213
|
+
| 写入 `.github/` `docs/` `src/` `demo/` | 不修改 `package.json` |
|
|
214
|
+
| 已存在的同名文件会被覆盖 | 不修改 `node_modules/` |
|
|
215
|
+
| 自动创建不存在的目录 | 不执行 postinstall |
|
|
216
|
+
| | 不删除任何文件 |
|
|
217
|
+
|
|
218
|
+
### 安全路径(不会被覆盖)
|
|
219
|
+
|
|
220
|
+
以下路径不在分发范围,本地修改永远安全:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
.github/skills/my-domain-skill/ ← 自定义 Skill
|
|
224
|
+
.github/docs/my-domain-doc.md ← 自定义文档
|
|
225
|
+
src/components/local/my_custom/ ← 自定义组件
|
|
226
|
+
src/views/ ← 业务页面代码
|
|
227
|
+
mock/ ← Mock 数据
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 注意事项
|
|
233
|
+
|
|
234
|
+
### 1. Skill 生成代码的前置依赖
|
|
235
|
+
|
|
236
|
+
AI 生成的代码依赖以下包,**首次使用前请确认已安装**:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# 核心依赖(项目大概率已有)
|
|
240
|
+
vue / vue-router / element-plus / @jhlc/common-core
|
|
241
|
+
|
|
242
|
+
# 易遗漏的依赖
|
|
243
|
+
pnpm add -D mockjs vite-plugin-mock # Mock 数据支持
|
|
244
|
+
pnpm add lodash-es # RECORD_FORM 模板用到 debounce
|
|
245
|
+
pnpm add xlsx # 仅导出/导入功能需要
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
> ⚠️ `lodash` ≠ `lodash-es`,模板代码 import 的是 ESM 版 `lodash-es`,必须单独安装。
|
|
249
|
+
|
|
250
|
+
### 2. Vite 配置检查
|
|
251
|
+
|
|
252
|
+
确保 `vite.config.ts` 已注册 mock 插件:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { viteMockServe } from "vite-plugin-mock";
|
|
256
|
+
// plugins 中添加:
|
|
257
|
+
viteMockServe({ mockPath: "./mock", enable: command === "serve" })
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### 3. 类型桶文件
|
|
261
|
+
|
|
262
|
+
`src/types/page.ts` 统一 re-export 以下类型,避免在 data.ts 中写长路径 import:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { AbstractPageQueryHook, BaseQueryItemDesc, ActionButtonDesc, TableColumnDesc, BusLogicDataType } from "@/types/page";
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 4. menu-sync 的 env.local.json
|
|
269
|
+
|
|
270
|
+
菜单同步需要网关地址和 Token,首次使用时按 `.github/skills/menu-sync/env/guide.md` 填写:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
.github/skills/menu-sync/env/env.local.json ← 本地维护,已 gitignore
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 5. 更新策略
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
# 拉取最新模板(会覆盖内置文件,不动安全路径)
|
|
280
|
+
npx @agile-team/wl-skills-kit@latest
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
- **通用改进** → 提 PR 到 wl-skills-kit 仓库,合并后所有项目受益
|
|
284
|
+
- **领域专有** → 放在安全路径下,永远不会被覆盖
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 技术栈适配
|
|
289
|
+
|
|
290
|
+
当前模板基于以下技术栈:
|
|
291
|
+
|
|
292
|
+
| 层面 | 技术 |
|
|
293
|
+
|------|------|
|
|
294
|
+
| 框架 | Vue 3.2 + Vite + TypeScript |
|
|
295
|
+
| UI | Element Plus + @jhlc/jh-ui + @jhlc/common-core |
|
|
296
|
+
| 状态 | Pinia |
|
|
297
|
+
| 样式 | Windi CSS + SCSS |
|
|
298
|
+
| 架构 | Module Federation 子应用 |
|
|
299
|
+
| 页面模式 | AbstractPageQueryHook 配置化驱动 |
|
|
300
|
+
|
|
301
|
+
> 移植到其他技术栈项目需改写 page-codegen 模板,详见 `.github/docs/use-skill.md` 第四章。
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 贡献
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
git clone git@github.com:ChenyCHENYU/wl-skills-kit.git
|
|
309
|
+
cd wl-skills-kit
|
|
310
|
+
# 修改 files/ 下的内容
|
|
311
|
+
npx . --dry-run # 本地预览
|
|
312
|
+
# 提 PR → Review → 合并 → npm publish
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### 可贡献内容
|
|
316
|
+
|
|
317
|
+
| 类型 | 路径 | 说明 |
|
|
318
|
+
|------|------|------|
|
|
319
|
+
| Skill 修复 | `files/.github/skills/` | 修正生成规则或模板 bug |
|
|
320
|
+
| 组件文档 | `files/docs/` | 新增或更新 jh-* 文档 |
|
|
321
|
+
| 领域样例 | `files/demo/{domain}/` | 各业务域贡献真实页面样例 |
|
|
322
|
+
| 通用组件 | `files/src/components/` | 新增可复用组件 |
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## License
|
|
327
|
+
|
|
328
|
+
MIT
|
package/bin/wl-skills.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* wl-skills-kit CLI
|
|
5
|
+
*
|
|
6
|
+
* 功能:将 files/ 目录下的所有文件按原始路径拷贝到当前工作目录。
|
|
7
|
+
* 用法:npx @agile-team/wl-skills-kit [--dry-run]
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
const path = require("path");
|
|
12
|
+
|
|
13
|
+
const FILES_DIR = path.resolve(__dirname, "..", "files");
|
|
14
|
+
const TARGET_DIR = process.cwd();
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const dryRun = args.includes("--dry-run");
|
|
17
|
+
const showHelp = args.includes("--help") || args.includes("-h");
|
|
18
|
+
|
|
19
|
+
if (showHelp) {
|
|
20
|
+
console.log(`
|
|
21
|
+
wl-skills-kit — AI Skill 模板包
|
|
22
|
+
|
|
23
|
+
用法:
|
|
24
|
+
npx @agile-team/wl-skills-kit 安装/更新模板文件到当前项目
|
|
25
|
+
npx @agile-team/wl-skills-kit --dry-run 预览将要写入的文件(不实际写入)
|
|
26
|
+
|
|
27
|
+
安装后写入:
|
|
28
|
+
.github/ AI 指令 + Skills + 文档
|
|
29
|
+
docs/ 组件 API 文档
|
|
30
|
+
src/ 通用组件 + 类型定义
|
|
31
|
+
demo/ 领域样例(AI 学习参考)
|
|
32
|
+
`);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 递归遍历目录,返回所有文件的相对路径
|
|
38
|
+
*/
|
|
39
|
+
function walkDir(dir, baseDir, fileList) {
|
|
40
|
+
fileList = fileList || [];
|
|
41
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
const fullPath = path.join(dir, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
walkDir(fullPath, baseDir, fileList);
|
|
46
|
+
} else {
|
|
47
|
+
fileList.push(path.relative(baseDir, fullPath));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return fileList;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 主逻辑
|
|
54
|
+
console.log("");
|
|
55
|
+
console.log(" wl-skills-kit v" + require("../package.json").version);
|
|
56
|
+
console.log(" 目标目录: " + TARGET_DIR);
|
|
57
|
+
console.log("");
|
|
58
|
+
|
|
59
|
+
if (!fs.existsSync(FILES_DIR)) {
|
|
60
|
+
console.error(" ✖ files/ 目录不存在,包可能已损坏");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const files = walkDir(FILES_DIR, FILES_DIR);
|
|
65
|
+
|
|
66
|
+
if (dryRun) {
|
|
67
|
+
console.log(" --dry-run 模式,以下文件将被写入:\n");
|
|
68
|
+
for (const file of files) {
|
|
69
|
+
const targetPath = path.join(TARGET_DIR, file);
|
|
70
|
+
const exists = fs.existsSync(targetPath);
|
|
71
|
+
console.log(" " + (exists ? "覆盖" : "新增") + " " + file);
|
|
72
|
+
}
|
|
73
|
+
console.log("\n 共 " + files.length + " 个文件(未实际写入)");
|
|
74
|
+
process.exit(0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let created = 0;
|
|
78
|
+
let updated = 0;
|
|
79
|
+
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
const src = path.join(FILES_DIR, file);
|
|
82
|
+
const dest = path.join(TARGET_DIR, file);
|
|
83
|
+
const destDir = path.dirname(dest);
|
|
84
|
+
|
|
85
|
+
// 确保目标目录存在
|
|
86
|
+
if (!fs.existsSync(destDir)) {
|
|
87
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const exists = fs.existsSync(dest);
|
|
91
|
+
fs.copyFileSync(src, dest);
|
|
92
|
+
|
|
93
|
+
if (exists) {
|
|
94
|
+
updated++;
|
|
95
|
+
} else {
|
|
96
|
+
created++;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log(" ✔ 完成!");
|
|
101
|
+
console.log(" 新增: " + created + " 个文件");
|
|
102
|
+
console.log(" 覆盖: " + updated + " 个文件");
|
|
103
|
+
console.log(" 总计: " + files.length + " 个文件");
|
|
104
|
+
console.log("");
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# 产品化前端编码指令
|
|
2
|
+
|
|
3
|
+
> 本文件由 AI 编辑器自动加载(VS Code Copilot / Cursor / Windsurf 等),确保生成代码符合项目规范。
|
|
4
|
+
> **前置要求**:AI 首次进入项目时,建议先阅读 `README.md` 了解产品化架构全景。后续对话中依赖本文件的规范约定即可,无需重复扫描。
|
|
5
|
+
|
|
6
|
+
## 架构
|
|
7
|
+
|
|
8
|
+
- Vue 3.2 + Vite + TypeScript(strict: false)
|
|
9
|
+
- Module Federation **子应用**,路由/权限/布局/Store 从主应用 `main` 远程加载
|
|
10
|
+
- UI:Element Plus + @jhlc/jh-ui + @jhlc/common-core
|
|
11
|
+
- 样式:Windi CSS + SCSS
|
|
12
|
+
- 状态:Pinia
|
|
13
|
+
- 页面注册:`vite/plugins/shared/pages.ts` 通过 `gProd()` / `gSale()` 声明
|
|
14
|
+
- 菜单路由配置:后端菜单表是唯一数据源。pages.ts 注册组件后,需在系统管理后台 → 菜单管理 → 新增菜单。批量新增页面时可用后端 batchImport 接口,详见 `.github/docs/menu-sync-design.md`
|
|
15
|
+
|
|
16
|
+
## 页面标准结构(4 文件)
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
src/views/[域]/[模块]/[子模块]/[kebab-case目录]/
|
|
20
|
+
├── index.vue ← 纯模板+解构,不写业务逻辑
|
|
21
|
+
├── data.ts ← AbstractPageQueryHook 类 + API_CONFIG
|
|
22
|
+
├── index.scss ← 页面样式(可为空)
|
|
23
|
+
└── api.md ← 接口约定(前端预留 + 后端出接口依据)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
弹窗组件处理策略:
|
|
27
|
+
|
|
28
|
+
- **通用弹窗**(新增/编辑表单,2+ 页面可复用)→ 提取到 `src/components/local/c_xxxModal/`
|
|
29
|
+
- **极个性弹窗**(仅单页面使用,c_modal 无法满足)→ 放在页面 `components/xxxModal.vue`
|
|
30
|
+
|
|
31
|
+
## data.ts 核心模式
|
|
32
|
+
|
|
33
|
+
> 配置化驱动,通过 `API_CONFIG` + `class extends AbstractPageQueryHook` 实现零 API 层开发。
|
|
34
|
+
> 基类内置 `getAction`/`postAction`/`putAction`/`deleteAction`/`actionBatch` 等 HTTP 方法(详见 `docs/request.md`),标准 CRUD 无需独立 API 文件。
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { AbstractPageQueryHook } from "@jhlc/common-core/src/page-hooks/page-query-hook.ts";
|
|
38
|
+
import { BaseQueryItemDesc } from "@jhlc/common-core/src/components/form/base-query/type.ts";
|
|
39
|
+
import { ActionButtonDesc } from "@jhlc/common-core/src/components/toolbar/type.ts";
|
|
40
|
+
import { TableColumnDesc } from "@jhlc/common-core/src/components/table/base-table/type.ts";
|
|
41
|
+
import { BusLogicDataType } from "@jhlc/types/src/logical-data";
|
|
42
|
+
import { getAction, postAction } from "@jhlc/common-core/src/api/action";
|
|
43
|
+
|
|
44
|
+
export const API_CONFIG = {
|
|
45
|
+
list: "/[服务缩写]/[资源名]/list",
|
|
46
|
+
remove: "/[服务缩写]/[资源名]/remove",
|
|
47
|
+
getById: "/[服务缩写]/[资源名]/getById",
|
|
48
|
+
save: "/[服务缩写]/[资源名]/save",
|
|
49
|
+
update: "/[服务缩写]/[资源名]/update",
|
|
50
|
+
export: "/[服务缩写]/[资源名]/export"
|
|
51
|
+
} as const;
|
|
52
|
+
|
|
53
|
+
export function createPage(addModalRef?: any) {
|
|
54
|
+
let Page = new (class extends AbstractPageQueryHook {
|
|
55
|
+
constructor() {
|
|
56
|
+
super({ url: { list: API_CONFIG.list, remove: API_CONFIG.remove } });
|
|
57
|
+
}
|
|
58
|
+
queryDef(): BaseQueryItemDesc<any>[] {
|
|
59
|
+
return [
|
|
60
|
+
{ name: "fieldName", label: "字段名", placeholder: "请输入" },
|
|
61
|
+
{
|
|
62
|
+
name: "status",
|
|
63
|
+
label: "状态",
|
|
64
|
+
logicType: BusLogicDataType.dict,
|
|
65
|
+
logicValue: "dictCode"
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
toolbarDef(): ActionButtonDesc[] {
|
|
70
|
+
return [
|
|
71
|
+
{
|
|
72
|
+
name: "primary",
|
|
73
|
+
label: "新增",
|
|
74
|
+
plain: true,
|
|
75
|
+
onClick: () => addModalRef?.value?.open()
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
columnsDef(): TableColumnDesc<any>[] {
|
|
80
|
+
return [
|
|
81
|
+
{ type: "selection" },
|
|
82
|
+
{ type: "index" },
|
|
83
|
+
{
|
|
84
|
+
label: "字段名",
|
|
85
|
+
name: "fieldName",
|
|
86
|
+
minWidth: 120,
|
|
87
|
+
sortable: true,
|
|
88
|
+
filterable: true
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
label: "状态",
|
|
92
|
+
name: "status",
|
|
93
|
+
minWidth: 100,
|
|
94
|
+
logicType: BusLogicDataType.dict,
|
|
95
|
+
logicValue: "dictCode",
|
|
96
|
+
sortable: true,
|
|
97
|
+
filterable: true
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
return Page.create() as any;
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## index.vue 标准模板
|
|
107
|
+
|
|
108
|
+
```vue
|
|
109
|
+
<template>
|
|
110
|
+
<div class="app-container app-page-container">
|
|
111
|
+
<BaseQuery
|
|
112
|
+
:form="queryParam"
|
|
113
|
+
:items="queryItems"
|
|
114
|
+
@select="select"
|
|
115
|
+
@reset="select"
|
|
116
|
+
/>
|
|
117
|
+
<BaseToolbar :items="toolbars" />
|
|
118
|
+
<BaseTable ref="tableRef" :data="list" :columns="columns" showToolbar />
|
|
119
|
+
<jh-pagination
|
|
120
|
+
v-show="page.total && page.total > 0"
|
|
121
|
+
:total="page.total || 0"
|
|
122
|
+
v-model:currentPage="page.current"
|
|
123
|
+
v-model:pageSize="page.size"
|
|
124
|
+
@current-change="select"
|
|
125
|
+
@size-change="select"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
</template>
|
|
129
|
+
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
import { createPage } from "./data";
|
|
132
|
+
|
|
133
|
+
const Page = createPage();
|
|
134
|
+
const {
|
|
135
|
+
tableRef,
|
|
136
|
+
page,
|
|
137
|
+
queryParam,
|
|
138
|
+
list,
|
|
139
|
+
queryItems,
|
|
140
|
+
columns,
|
|
141
|
+
toolbars,
|
|
142
|
+
select
|
|
143
|
+
} = Page;
|
|
144
|
+
|
|
145
|
+
onMounted(() => select());
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<style scoped lang="scss">
|
|
149
|
+
@import "./index.scss";
|
|
150
|
+
</style>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 命名规范
|
|
154
|
+
|
|
155
|
+
| 位置 | 规范 | 示例 |
|
|
156
|
+
| ------------ | ----------------------- | -------------------------------- |
|
|
157
|
+
| 目录/路由 | kebab-case | `ompt-mill-plan/` |
|
|
158
|
+
| pages.ts | `["kebab名", "中文名"]` | `["ompt-mill-plan", "轧钢计划"]` |
|
|
159
|
+
| 字段名 | camelCase | `orderNo`, `planStatus` |
|
|
160
|
+
| logicValue | camelCase | `planStatus`, `plineCode` |
|
|
161
|
+
| 全局组件 | `C_PascalCase/` | `C_Tree/` |
|
|
162
|
+
| 局部公共组件 | `c_camelCase/` | `c_modal/`、`c_detailPanel/` |
|
|
163
|
+
| 页面私有组件 | camelCase | `addModal.vue`(仅极个性弹窗) |
|
|
164
|
+
|
|
165
|
+
## 平台组件速查
|
|
166
|
+
|
|
167
|
+
| 用途 | 组件 | 来源 |
|
|
168
|
+
| -------- | -------------- | -------------------------------- |
|
|
169
|
+
| 查询区 | BaseQuery | @jhlc/common-core |
|
|
170
|
+
| 工具栏 | BaseToolbar | @jhlc/common-core |
|
|
171
|
+
| 表格 | BaseTable | @jhlc/common-core |
|
|
172
|
+
| 分页 | jh-pagination | @jhlc/jh-ui |
|
|
173
|
+
| 上下分栏 | jh-drag-row | @jhlc/jh-ui |
|
|
174
|
+
| 下拉选择 | jh-select | @jhlc/jh-ui(dict 属性自动加载) |
|
|
175
|
+
| 单日期 | jh-date | @jhlc/jh-ui |
|
|
176
|
+
| 日期范围 | jh-date-range | @jhlc/jh-ui |
|
|
177
|
+
| 用户选择 | jh-user-picker | @jhlc/jh-ui |
|
|
178
|
+
| 部门选择 | jh-dept-picker | @jhlc/jh-ui |
|
|
179
|
+
| 文件上传 | jh-file-upload | @jhlc/jh-ui |
|
|
180
|
+
| 文本翻译 | jh-text | @jhlc/jh-ui |
|
|
181
|
+
| 左右分割 | C_Splitter | src/components/global |
|
|
182
|
+
| 树形面板 | C_Tree | src/components/global |
|
|
183
|
+
|
|
184
|
+
## 组件提取策略
|
|
185
|
+
|
|
186
|
+
| 场景 | 位置 | 命名 |
|
|
187
|
+
| ------------------------- | ------------------------------------- | ----------------------- |
|
|
188
|
+
| 3+ 页面复用 | `src/components/global/C_PascalCase/` | 全局自动注册 |
|
|
189
|
+
| 2+ 页面复用(如通用弹窗) | `src/components/local/c_camelCase/` | 按需导入,如 `c_modal/` |
|
|
190
|
+
| 仅单页面使用 | 页面 `components/xxxModal.vue` | 仅当 c_modal 无法满足时 |
|
|
191
|
+
|
|
192
|
+
## 禁止事项
|
|
193
|
+
|
|
194
|
+
- ❌ index.vue 中写业务逻辑(逻辑全在 data.ts)
|
|
195
|
+
- ❌ 使用 Vuex(用 Pinia)
|
|
196
|
+
- ❌ `::v-deep` / `/deep/`(用 `:deep()`)
|
|
197
|
+
- ❌ 直接用 axios(用 getAction/postAction)
|
|
198
|
+
- ❌ 手写查询表单/工具栏/分页(用 BaseQuery/BaseToolbar/jh-pagination)
|
|
199
|
+
- ❌ 每个页面重复写弹窗组件(优先用 `c_modal` 等局部公共组件)
|
|
200
|
+
|
|
201
|
+
## Axure → Vue 生成流程
|
|
202
|
+
|
|
203
|
+
详见 `.github/skills/` 下的 5 个 Skill:
|
|
204
|
+
|
|
205
|
+
1. **prototype-scan** — 解析 Axure HTML → 页面清单
|
|
206
|
+
2. **convention-extract** — 项目规范提炼(已固化,新项目时使用)
|
|
207
|
+
3. **api-contract** — 页面清单 → api.md 接口约定
|
|
208
|
+
4. **page-codegen** — 生成 index.vue + data.ts + index.scss + api.md
|
|
209
|
+
5. **menu-sync** — 将 pages.ts 页面同步到后端菜单表(Phase 1:AI 调 `/system/menu/save`;Phase 2:`pnpm run menu:push`)
|
|
210
|
+
|
|
211
|
+
> 完整使用步骤及精度技巧见 `.github/docs/use-skill.md`
|