@agile-team/wl-skills-kit 2.3.4 → 2.3.6
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 -0
- package/README.md +16 -10
- package/files/.cursor/mcp.json +8 -8
- package/files/.github/guides/README.md +13 -13
- package/files/.github/guides/architecture.md +555 -555
- package/files/.github/guides/mcp-setup.md +109 -109
- package/files/.github/guides/usage.md +184 -184
- package/files/.github/reports/README.md +65 -65
- package/files/.github/reports/SYS_DICT_INFO.md +50 -50
- package/files/.github/reports/SYS_MENU_INFO.md +247 -247
- package/files/.github/reports/SYS_PERMISSION_INFO.md +20 -20
- package/files/.github/reports//347/273/204/344/273/266/346/217/220/345/217/226/345/273/272/350/256/256.md +33 -33
- package/files/.github/reports//350/247/204/350/214/203/345/256/241/346/237/245/346/212/245/345/221/212.md +44 -44
- package/files/.github/skills/_compat/README.md +108 -108
- package/files/.github/skills/_compat/headers/agents.txt +8 -8
- package/files/.github/skills/_compat/headers/claude-code.txt +7 -7
- package/files/.github/skills/_compat/headers/cline.txt +7 -7
- package/files/.github/skills/_compat/headers/cursor-mdc.txt +16 -16
- package/files/.github/skills/_compat/headers/cursor-rules.txt +7 -7
- package/files/.github/skills/_compat/headers/github-copilot.txt +1 -1
- package/files/.github/skills/_compat/headers/kiro.txt +10 -10
- package/files/.github/skills/_compat/headers/qoder.txt +8 -8
- package/files/.github/skills/_compat/headers/trae.txt +11 -11
- package/files/.github/skills/_compat/headers/windsurf.txt +7 -7
- package/files/.github/skills/_registry.md +81 -81
- package/files/.github/skills/core/api-contract/SKILL.md +344 -344
- package/files/.github/skills/core/api-contract/USAGE.md +110 -110
- package/files/.github/skills/core/convention-audit/SKILL.md +189 -189
- package/files/.github/skills/core/convention-audit/USAGE.md +99 -99
- package/files/.github/skills/core/page-codegen/SKILL.md +973 -973
- package/files/.github/skills/core/page-codegen/USAGE.md +102 -102
- package/files/.github/skills/core/page-codegen/templates/_index.md +46 -46
- package/files/.github/skills/core/page-codegen/templates/domains/_CONTRIBUTING.md +107 -107
- package/files/.github/skills/core/page-codegen/templates/domains/produce/TPL-OPERATION-STATION.md +442 -442
- package/files/.github/skills/core/page-codegen/templates/domains/sale/README.md +26 -26
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-CHANGE-HISTORY.md +276 -276
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-DETAIL-TABS.md +1145 -1145
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-DRIVEN.md +309 -309
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-FORM-ROUTE.md +436 -436
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-LIST.md +191 -191
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-MASTER-DETAIL.md +148 -148
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-RECORD-FORM.md +376 -376
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-TREE-LIST.md +186 -186
- package/files/.github/skills/core/prototype-scan/SKILL.md +498 -498
- package/files/.github/skills/core/prototype-scan/USAGE.md +95 -95
- package/files/.github/skills/core/template-extract/SKILL.md +139 -139
- package/files/.github/skills/core/template-extract/USAGE.md +93 -93
- package/files/.github/skills/domain/README.md +51 -51
- package/files/.github/skills/sync/env.local.json +0 -5
- package/files/.github/skills/sync/menu-sync/SKILL.md +263 -263
- package/files/.github/skills/sync/menu-sync/USAGE.md +104 -104
- package/files/.github/skills/sync/menu-sync/env/env.local.json +7 -7
- package/files/.github/skills/sync/menu-sync/env/guide.md +99 -99
- package/files/.github/skills/sync/permission-sync/SKILL.md +239 -0
- package/files/.github/skills/sync/permission-sync/USAGE.md +93 -0
- package/files/.github/standards/01-toolchain.md +57 -57
- package/files/.github/standards/02-code-structure.md +111 -111
- package/files/.github/standards/03-comments.md +53 -53
- package/files/.github/standards/04-coding-basics.md +33 -33
- package/files/.github/standards/05-logging.md +38 -38
- package/files/.github/standards/06-security.md +44 -44
- package/files/.github/standards/07-config.md +52 -52
- package/files/.github/standards/08-git.md +60 -60
- package/files/.github/standards/09-typescript.md +71 -71
- package/files/.github/standards/10-pinia.md +57 -57
- package/files/.github/standards/11-form-validation.md +81 -81
- package/files/.github/standards/12-base-table.md +153 -153
- package/files/.github/standards/13-platform-components.md +123 -123
- package/files/.github/standards/index.md +89 -89
- package/files/.kiro/settings/mcp.json +8 -8
- package/files/.mcp.json +8 -8
- package/files/.vscode/mcp.json +9 -9
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/data.ts +196 -196
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.scss +150 -150
- package/files/demo/produce/aiflow/mmwr-customer-apply-change-history/index.vue +79 -79
- package/files/docs/jh-date-range.md +257 -257
- package/files/docs/jh-date.md +222 -222
- package/files/docs/jh-dept-picker.md +190 -190
- package/files/docs/jh-drag-row.md +590 -590
- package/files/docs/jh-file-upload.md +216 -216
- package/files/docs/jh-picker.md +218 -218
- package/files/docs/jh-select.md +148 -148
- package/files/docs/jh-text.md +248 -248
- package/files/docs/jh-user-picker.md +197 -197
- package/files/src/components/global/C_RightToolbar/data.ts +228 -228
- package/files/src/components/global/C_RightToolbar/index.scss +44 -44
- package/files/src/components/global/C_Splitter/index.scss +61 -61
- package/files/src/components/global/C_SvgIcon/index.scss +15 -15
- package/files/src/components/global/C_TagStatus/index.scss +20 -20
- package/files/src/components/global/C_Tree/data.ts +61 -61
- package/files/src/components/local/c_listModal/index.scss +4 -4
- package/mcp/api/roleApi.js +60 -0
- package/mcp/server.js +125 -5
- package/mcp/tools/permissionSync.js +321 -0
- package/package.json +1 -1
- package/files/.github/skills/sync/permission-sync/SKILL.draft.md +0 -91
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
# 使用指南:menu-sync(菜单同步)
|
|
2
|
-
|
|
3
|
-
> **谁读这个文档**:团队成员(前端 + 后端联调时)
|
|
4
|
-
> **AI 触发文件**:同目录 `SKILL.md`
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## 这个 Skill 解决什么问题
|
|
9
|
-
|
|
10
|
-
新页面写完后,需要在系统菜单中**注册一条菜单记录**才能从 UI 访问。这个 Skill:
|
|
11
|
-
|
|
12
|
-
1. 拉取**线上菜单数据**到 `reports/SYS_MENU_INFO.md`(团队基线)
|
|
13
|
-
2. 对比已生成页面 vs 线上菜单,**自动补齐缺失菜单项**
|
|
14
|
-
3. 调用菜单注册接口(或生成 SQL 让后端执行)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 何时使用
|
|
19
|
-
|
|
20
|
-
- 新增页面后,从 UI 访问报"菜单不存在"
|
|
21
|
-
- 一次性创建一批页面,需要批量注册菜单
|
|
22
|
-
- 同步线上菜单基线(PROD/UAT/DEV 拉齐)
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## 触发关键词
|
|
27
|
-
|
|
28
|
-
`创建菜单` / `注册菜单` / `同步菜单` / `补菜单`
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 前置条件
|
|
33
|
-
|
|
34
|
-
`.github/skills/sync/menu-sync/env/env.local.json`(首次使用先填写):
|
|
35
|
-
|
|
36
|
-
```json
|
|
37
|
-
{
|
|
38
|
-
"gatewayPath": "https://uat-api.example.com",
|
|
39
|
-
"token": "Bearer xxx",
|
|
40
|
-
"tenantId": "10001",
|
|
41
|
-
"rootMenuId": "1234567890"
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
> **`env.local.json` 不入 git**(已加 .gitignore)。每个开发者本地填自己的 token。
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## 标准对话示例
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
你:把 src/views/produce/aiflow/ 下新建的 7 个页面同步到菜单
|
|
53
|
-
AI:[Pre-flight]
|
|
54
|
-
步骤 1:读取线上菜单基线 reports/SYS_MENU_INFO.md(最新更新:2025-04-20)
|
|
55
|
-
步骤 2:扫描 src/views/produce/aiflow/ 共 7 个页面
|
|
56
|
-
步骤 3:对比缺失:5 项缺失,2 项已存在
|
|
57
|
-
步骤 4:将调用 /sys/menu/save 创建 5 项
|
|
58
|
-
[需你确认]:
|
|
59
|
-
- 父菜单:精整作业 → 客户管理(rootMenuId: xxx)
|
|
60
|
-
- 排序:sortNo 自动递增
|
|
61
|
-
- 权限标识:mmwr:customer:list 等
|
|
62
|
-
确认 yes/no?
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## 输出物
|
|
68
|
-
|
|
69
|
-
1. **基线文件**:`.github/reports/SYS_MENU_INFO.md` —— 线上菜单的本地基线(团队 review 用)
|
|
70
|
-
2. **同步报告**:`.github/reports/MENU_SYNC_<YYYYMMDD>.md` —— 本次新增/更新了哪些菜单
|
|
71
|
-
3. **回滚 SQL**:报告里附带 DELETE SQL,用于回退
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## 常见踩坑
|
|
76
|
-
|
|
77
|
-
| 现象 | 原因 | 解法 |
|
|
78
|
-
| -------------------- | ---------------------------- | ---------------------------------------------- |
|
|
79
|
-
| 同步成功但 UI 看不到 | 用户角色没分配新菜单 | 跑 permission-sync(PLANNED)或后台手工分配 |
|
|
80
|
-
| 401/403 报错 | env.local.json 的 token 过期 | 重新登录系统,从 Network 抓 Authorization 替换 |
|
|
81
|
-
| 同名菜单重复创建 | 没读 SYS_MENU_INFO.md 基线 | 先跑一遍"刷新基线"再 sync |
|
|
82
|
-
| 父菜单 ID 不对 | rootMenuId 配错 | 从浏览器开发者工具看父菜单的 dom data-id |
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## 团队协作流程
|
|
87
|
-
|
|
88
|
-
1. 新人入职,让他先把 `env.local.json` 填一份(参考 env.example.json)
|
|
89
|
-
2. **每周一**由 lead 跑一次"刷新基线",确保 reports/SYS_MENU_INFO.md 最新
|
|
90
|
-
3. PR 提交前自查"我加的菜单有没有提交进基线"
|
|
91
|
-
4. 上线前再 sync 一次到生产环境(切换 env 文件中的 gatewayPath)
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## FAQ
|
|
96
|
-
|
|
97
|
-
**Q:env.local.json 泄露 token 危险吗?**
|
|
98
|
-
A:危险。token 视同密码。已加 .gitignore + .npmignore。**不要 commit**。
|
|
99
|
-
|
|
100
|
-
**Q:能不能直接给 SQL 让后端跑?**
|
|
101
|
-
A:能。在指令里加"只生成 SQL,不调用接口"即可。
|
|
102
|
-
|
|
103
|
-
**Q:和 dict-sync / permission-sync 关系?**
|
|
104
|
-
A:菜单是入口,字典是值域,权限是访问控制。三者独立但配合。建议顺序:menu-sync → permission-sync → dict-sync。
|
|
1
|
+
# 使用指南:menu-sync(菜单同步)
|
|
2
|
+
|
|
3
|
+
> **谁读这个文档**:团队成员(前端 + 后端联调时)
|
|
4
|
+
> **AI 触发文件**:同目录 `SKILL.md`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 这个 Skill 解决什么问题
|
|
9
|
+
|
|
10
|
+
新页面写完后,需要在系统菜单中**注册一条菜单记录**才能从 UI 访问。这个 Skill:
|
|
11
|
+
|
|
12
|
+
1. 拉取**线上菜单数据**到 `reports/SYS_MENU_INFO.md`(团队基线)
|
|
13
|
+
2. 对比已生成页面 vs 线上菜单,**自动补齐缺失菜单项**
|
|
14
|
+
3. 调用菜单注册接口(或生成 SQL 让后端执行)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 何时使用
|
|
19
|
+
|
|
20
|
+
- 新增页面后,从 UI 访问报"菜单不存在"
|
|
21
|
+
- 一次性创建一批页面,需要批量注册菜单
|
|
22
|
+
- 同步线上菜单基线(PROD/UAT/DEV 拉齐)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 触发关键词
|
|
27
|
+
|
|
28
|
+
`创建菜单` / `注册菜单` / `同步菜单` / `补菜单`
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 前置条件
|
|
33
|
+
|
|
34
|
+
`.github/skills/sync/menu-sync/env/env.local.json`(首次使用先填写):
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"gatewayPath": "https://uat-api.example.com",
|
|
39
|
+
"token": "Bearer xxx",
|
|
40
|
+
"tenantId": "10001",
|
|
41
|
+
"rootMenuId": "1234567890"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> **`env.local.json` 不入 git**(已加 .gitignore)。每个开发者本地填自己的 token。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 标准对话示例
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
你:把 src/views/produce/aiflow/ 下新建的 7 个页面同步到菜单
|
|
53
|
+
AI:[Pre-flight]
|
|
54
|
+
步骤 1:读取线上菜单基线 reports/SYS_MENU_INFO.md(最新更新:2025-04-20)
|
|
55
|
+
步骤 2:扫描 src/views/produce/aiflow/ 共 7 个页面
|
|
56
|
+
步骤 3:对比缺失:5 项缺失,2 项已存在
|
|
57
|
+
步骤 4:将调用 /sys/menu/save 创建 5 项
|
|
58
|
+
[需你确认]:
|
|
59
|
+
- 父菜单:精整作业 → 客户管理(rootMenuId: xxx)
|
|
60
|
+
- 排序:sortNo 自动递增
|
|
61
|
+
- 权限标识:mmwr:customer:list 等
|
|
62
|
+
确认 yes/no?
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 输出物
|
|
68
|
+
|
|
69
|
+
1. **基线文件**:`.github/reports/SYS_MENU_INFO.md` —— 线上菜单的本地基线(团队 review 用)
|
|
70
|
+
2. **同步报告**:`.github/reports/MENU_SYNC_<YYYYMMDD>.md` —— 本次新增/更新了哪些菜单
|
|
71
|
+
3. **回滚 SQL**:报告里附带 DELETE SQL,用于回退
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 常见踩坑
|
|
76
|
+
|
|
77
|
+
| 现象 | 原因 | 解法 |
|
|
78
|
+
| -------------------- | ---------------------------- | ---------------------------------------------- |
|
|
79
|
+
| 同步成功但 UI 看不到 | 用户角色没分配新菜单 | 跑 permission-sync(PLANNED)或后台手工分配 |
|
|
80
|
+
| 401/403 报错 | env.local.json 的 token 过期 | 重新登录系统,从 Network 抓 Authorization 替换 |
|
|
81
|
+
| 同名菜单重复创建 | 没读 SYS_MENU_INFO.md 基线 | 先跑一遍"刷新基线"再 sync |
|
|
82
|
+
| 父菜单 ID 不对 | rootMenuId 配错 | 从浏览器开发者工具看父菜单的 dom data-id |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 团队协作流程
|
|
87
|
+
|
|
88
|
+
1. 新人入职,让他先把 `env.local.json` 填一份(参考 env.example.json)
|
|
89
|
+
2. **每周一**由 lead 跑一次"刷新基线",确保 reports/SYS_MENU_INFO.md 最新
|
|
90
|
+
3. PR 提交前自查"我加的菜单有没有提交进基线"
|
|
91
|
+
4. 上线前再 sync 一次到生产环境(切换 env 文件中的 gatewayPath)
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## FAQ
|
|
96
|
+
|
|
97
|
+
**Q:env.local.json 泄露 token 危险吗?**
|
|
98
|
+
A:危险。token 视同密码。已加 .gitignore + .npmignore。**不要 commit**。
|
|
99
|
+
|
|
100
|
+
**Q:能不能直接给 SQL 让后端跑?**
|
|
101
|
+
A:能。在指令里加"只生成 SQL,不调用接口"即可。
|
|
102
|
+
|
|
103
|
+
**Q:和 dict-sync / permission-sync 关系?**
|
|
104
|
+
A:菜单是入口,字典是值域,权限是访问控制。三者独立但配合。建议顺序:menu-sync → permission-sync → dict-sync。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_notice": "【已迁移】请改用 skills/sync/env.local.json(菜单+字典+权限统一配置)。此文件仍受保护,向下兼容保留。",
|
|
3
|
-
"gatewayPath": "http://你的网关地址:端口",
|
|
4
|
-
"parentMenuId": "父级菜单ID",
|
|
5
|
-
"sysAppNo": "应用编码(从已有菜单接口响应中获取,非明文)",
|
|
6
|
-
"token": "你的Bearer Token(不含bearer前缀)"
|
|
7
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"_notice": "【已迁移】请改用 skills/sync/env.local.json(菜单+字典+权限统一配置)。此文件仍受保护,向下兼容保留。",
|
|
3
|
+
"gatewayPath": "http://你的网关地址:端口",
|
|
4
|
+
"parentMenuId": "父级菜单ID",
|
|
5
|
+
"sysAppNo": "应用编码(从已有菜单接口响应中获取,非明文)",
|
|
6
|
+
"token": "你的Bearer Token(不含bearer前缀)"
|
|
7
|
+
}
|
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
# env.local.json 配置说明
|
|
2
|
-
|
|
3
|
-
> 每位成员在本地维护自己的副本,已加入 `.gitignore`,**不会提交到远端仓库**。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 配置文件位置(优先使用新统一路径)
|
|
8
|
-
|
|
9
|
-
**新路径(v2.1.5+ 推荐)**:`.github/skills/sync/env.local.json`
|
|
10
|
-
**兼容路径(老版)**:`.github/skills/sync/menu-sync/env/env.local.json`
|
|
11
|
-
|
|
12
|
-
AI 优先读新路径,如不存在自动回落到兼容路径。
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 配置格式(菜单/字典/权限三合一)
|
|
17
|
-
|
|
18
|
-
```json
|
|
19
|
-
{
|
|
20
|
-
"gatewayPath": "http://192.168.10.50:9000",
|
|
21
|
-
"sysAppNo": "QjQuXy1kbKxZyjhS5N2",
|
|
22
|
-
"token": "eyJhbGci...",
|
|
23
|
-
|
|
24
|
-
"menu": {
|
|
25
|
-
"parentMenuId": "1803456789012345678"
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
"dict": {
|
|
29
|
-
"moduleId": "7C909G0U2F8HI7E305LV0135LSJ3UBIO"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 字段说明
|
|
37
|
-
|
|
38
|
-
| 字段 | 说明 | 示例 |
|
|
39
|
-
|---|---|---|
|
|
40
|
-
| `gatewayPath` | 后端网关地址,含协议和端口,**末尾不加斜杠** | `http://192.168.10.50:9000` |
|
|
41
|
-
| `sysAppNo` | 应用编码(非明文,从已有菜单接口响应中获取) | `QjQuXy1kbKxZyjhS5N2` |
|
|
42
|
-
| `token` | 当前登录用户的 Bearer Token,**不含 `bearer ` 前缀** | `eyJhbGci...` |
|
|
43
|
-
| `menu.parentMenuId` | 目标父级目录的菜单数据库 ID(每套环境不同) | `1803456789012345678` |
|
|
44
|
-
| `dict.moduleId` | 字典所属模块 ID(字典管理后台获取) | `7C909G0U2F8HI7E305LV0135LSJ3UBIO` |
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## 如何获取各字段
|
|
49
|
-
|
|
50
|
-
### gatewayPath
|
|
51
|
-
|
|
52
|
-
询问后端同事,或查看浏览器 Network 面板中任意接口请求的 URL,取协议 + 域名/IP + 端口部分。
|
|
53
|
-
|
|
54
|
-
### menu.parentMenuId
|
|
55
|
-
|
|
56
|
-
**方法 A(推荐)**:系统管理后台 → 菜单管理 → 找到目标父级目录 → 点编辑/查看 → 复制菜单 ID
|
|
57
|
-
|
|
58
|
-
**方法 B(API 查询)**:
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
GET {gatewayPath}/system/menu/children?menuId=0
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
从顶级节点向下逐层查找,直到找到目标父级目录。也可以告诉 AI「帮我查一下父级菜单 ID」,AI 会自动调接口查询。
|
|
65
|
-
|
|
66
|
-
### sysAppNo
|
|
67
|
-
|
|
68
|
-
系统用编码后的字符串标识应用(如 `QjQuXy1kbKxZyjhS5N2`),而非明文 `produce` / `sale`。
|
|
69
|
-
|
|
70
|
-
**获取方式**:浏览器 F12 → Network → 找任意菜单相关接口的响应体 → 查看已有菜单条目的 `sysAppNo` 字段值,复制即可。
|
|
71
|
-
|
|
72
|
-
> ℹ️ 同一领域下所有菜单的 `sysAppNo` 相同,复制任意一个即可。
|
|
73
|
-
|
|
74
|
-
### token
|
|
75
|
-
|
|
76
|
-
1. 在浏览器中登录系统
|
|
77
|
-
2. 按 F12 打开 DevTools → Network 面板
|
|
78
|
-
3. 随便点一个接口请求
|
|
79
|
-
4. 查看 Request Headers → `authorization` 字段
|
|
80
|
-
5. 去掉 `bearer ` 前缀,复制剩余字符串粘贴到 `token` 字段
|
|
81
|
-
|
|
82
|
-
> Token 有有效期,若创建菜单时提示鉴权失败,重新登录后刷新 token 即可。
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## 使用方式
|
|
87
|
-
|
|
88
|
-
配置完成后,直接对 AI 说:
|
|
89
|
-
|
|
90
|
-
> 「帮我创建菜单」/ 「同步菜单」/ 「补菜单」
|
|
91
|
-
|
|
92
|
-
AI 会自动执行:
|
|
93
|
-
1. 读取 `SYS_MENU_INFO.md`(菜单定义)
|
|
94
|
-
2. 读取 `env.local.json`(环境配置)
|
|
95
|
-
3. 调 `/system/menu/children` 查询父级已有子节点(去重)
|
|
96
|
-
4. 逐条调 `/system/menu/save` 创建缺失菜单
|
|
97
|
-
5. 输出 `created / skipped` 结果表
|
|
98
|
-
|
|
99
|
-
**全程无需手动执行任何命令。**
|
|
1
|
+
# env.local.json 配置说明
|
|
2
|
+
|
|
3
|
+
> 每位成员在本地维护自己的副本,已加入 `.gitignore`,**不会提交到远端仓库**。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 配置文件位置(优先使用新统一路径)
|
|
8
|
+
|
|
9
|
+
**新路径(v2.1.5+ 推荐)**:`.github/skills/sync/env.local.json`
|
|
10
|
+
**兼容路径(老版)**:`.github/skills/sync/menu-sync/env/env.local.json`
|
|
11
|
+
|
|
12
|
+
AI 优先读新路径,如不存在自动回落到兼容路径。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 配置格式(菜单/字典/权限三合一)
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"gatewayPath": "http://192.168.10.50:9000",
|
|
21
|
+
"sysAppNo": "QjQuXy1kbKxZyjhS5N2",
|
|
22
|
+
"token": "eyJhbGci...",
|
|
23
|
+
|
|
24
|
+
"menu": {
|
|
25
|
+
"parentMenuId": "1803456789012345678"
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
"dict": {
|
|
29
|
+
"moduleId": "7C909G0U2F8HI7E305LV0135LSJ3UBIO"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 字段说明
|
|
37
|
+
|
|
38
|
+
| 字段 | 说明 | 示例 |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `gatewayPath` | 后端网关地址,含协议和端口,**末尾不加斜杠** | `http://192.168.10.50:9000` |
|
|
41
|
+
| `sysAppNo` | 应用编码(非明文,从已有菜单接口响应中获取) | `QjQuXy1kbKxZyjhS5N2` |
|
|
42
|
+
| `token` | 当前登录用户的 Bearer Token,**不含 `bearer ` 前缀** | `eyJhbGci...` |
|
|
43
|
+
| `menu.parentMenuId` | 目标父级目录的菜单数据库 ID(每套环境不同) | `1803456789012345678` |
|
|
44
|
+
| `dict.moduleId` | 字典所属模块 ID(字典管理后台获取) | `7C909G0U2F8HI7E305LV0135LSJ3UBIO` |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 如何获取各字段
|
|
49
|
+
|
|
50
|
+
### gatewayPath
|
|
51
|
+
|
|
52
|
+
询问后端同事,或查看浏览器 Network 面板中任意接口请求的 URL,取协议 + 域名/IP + 端口部分。
|
|
53
|
+
|
|
54
|
+
### menu.parentMenuId
|
|
55
|
+
|
|
56
|
+
**方法 A(推荐)**:系统管理后台 → 菜单管理 → 找到目标父级目录 → 点编辑/查看 → 复制菜单 ID
|
|
57
|
+
|
|
58
|
+
**方法 B(API 查询)**:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
GET {gatewayPath}/system/menu/children?menuId=0
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
从顶级节点向下逐层查找,直到找到目标父级目录。也可以告诉 AI「帮我查一下父级菜单 ID」,AI 会自动调接口查询。
|
|
65
|
+
|
|
66
|
+
### sysAppNo
|
|
67
|
+
|
|
68
|
+
系统用编码后的字符串标识应用(如 `QjQuXy1kbKxZyjhS5N2`),而非明文 `produce` / `sale`。
|
|
69
|
+
|
|
70
|
+
**获取方式**:浏览器 F12 → Network → 找任意菜单相关接口的响应体 → 查看已有菜单条目的 `sysAppNo` 字段值,复制即可。
|
|
71
|
+
|
|
72
|
+
> ℹ️ 同一领域下所有菜单的 `sysAppNo` 相同,复制任意一个即可。
|
|
73
|
+
|
|
74
|
+
### token
|
|
75
|
+
|
|
76
|
+
1. 在浏览器中登录系统
|
|
77
|
+
2. 按 F12 打开 DevTools → Network 面板
|
|
78
|
+
3. 随便点一个接口请求
|
|
79
|
+
4. 查看 Request Headers → `authorization` 字段
|
|
80
|
+
5. 去掉 `bearer ` 前缀,复制剩余字符串粘贴到 `token` 字段
|
|
81
|
+
|
|
82
|
+
> Token 有有效期,若创建菜单时提示鉴权失败,重新登录后刷新 token 即可。
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 使用方式
|
|
87
|
+
|
|
88
|
+
配置完成后,直接对 AI 说:
|
|
89
|
+
|
|
90
|
+
> 「帮我创建菜单」/ 「同步菜单」/ 「补菜单」
|
|
91
|
+
|
|
92
|
+
AI 会自动执行:
|
|
93
|
+
1. 读取 `SYS_MENU_INFO.md`(菜单定义)
|
|
94
|
+
2. 读取 `env.local.json`(环境配置)
|
|
95
|
+
3. 调 `/system/menu/children` 查询父级已有子节点(去重)
|
|
96
|
+
4. 逐条调 `/system/menu/save` 创建缺失菜单
|
|
97
|
+
5. 输出 `created / skipped` 结果表
|
|
98
|
+
|
|
99
|
+
**全程无需手动执行任何命令。**
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: permission-sync
|
|
3
|
+
description: "Use when: managing roles, authorizing menus to roles, attaching action buttons (type=A) to page menus, or wiring v-permission directives in Vue code. Triggers on: 创建角色, 角色管理, 角色授权, 给角色分配菜单, 挂动作, 添加动作按钮, 同步权限, 权限码注册, role assign, permission sync."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: 权限同步(permission-sync)
|
|
7
|
+
|
|
8
|
+
将系统的**角色 → 菜单授权 → 动作按钮 → 业务代码 v-permission**串成一条链路,覆盖从权限注册到代码落地的全流程。
|
|
9
|
+
|
|
10
|
+
> **与 menu-sync / dict-sync 的关系**:完全对称,统一从 `.github/skills/sync/env.local.json` 读取配置。`menu-sync` 负责页面菜单(type=M/C),`permission-sync` 负责其上的角色与动作(type=A)。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 配置(统一配置文件,复用 menu-sync 的配置)
|
|
15
|
+
|
|
16
|
+
读取 `.github/skills/sync/env.local.json`:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"gatewayPath": "http://你的网关地址:端口",
|
|
21
|
+
"sysAppNo": "应用编码",
|
|
22
|
+
"token": "Bearer Token(不含 bearer 前缀)"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**permission-sync 不需要额外字段**——角色和动作的 `parentId` 由 AI 在执行流程中通过查询接口动态获取。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 三种工作模式
|
|
31
|
+
|
|
32
|
+
| 模式 | 触发关键词 | 动作 |
|
|
33
|
+
| ---------------- | -------------------------------- | ----------------------------------------------------------------------------------- |
|
|
34
|
+
| `role-manage` | 创建角色 / 角色管理 / 列出角色 | 查询/新增角色(按 `code` 去重,幂等) |
|
|
35
|
+
| `role-assign` | 角色授权 / 给 XX 角色分配菜单 | 查询全量可授权菜单 → 选定 menuIds → 调用 `saveRoleMenus` 批量分配 |
|
|
36
|
+
| `action-attach` | 挂动作 / 给页面加按钮 / 注册权限码 | 在指定页面菜单下批量新增 type=A 动作(按 `permission` 去重)+ 在代码加 v-permission |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Pre-flight 声明(执行前必须输出)
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
🚀 已触发技能 permission-sync/SKILL.md → 权限同步
|
|
44
|
+
✅ 已读取 skills/sync/env.local.json → 网关地址、token、sysAppNo
|
|
45
|
+
✅ 操作模式:{role-manage / role-assign / action-attach}
|
|
46
|
+
✅ 目标:{角色名 / roleId / 页面菜单 menuId 与权限码列表}
|
|
47
|
+
✅ 安全检查:{生产环境拒绝 / 角色分配二次确认 / 仅新增不删除}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## MCP 工具调用规范
|
|
53
|
+
|
|
54
|
+
permission-sync 通过 6 个 MCP 工具完成所有操作(无需手动 fetch):
|
|
55
|
+
|
|
56
|
+
| 工具 | 用途 |
|
|
57
|
+
| ----------------------------- | ------------------------------------------ |
|
|
58
|
+
| `wls_role_query` | 查询角色列表(带分页) |
|
|
59
|
+
| `wls_role_upsert` | 批量新增角色(按 code 去重) |
|
|
60
|
+
| `wls_assignable_menus_query` | 查询全量可授权菜单 |
|
|
61
|
+
| `wls_role_assign_menus` | 给角色批量分配菜单(**全量覆盖**,注意!) |
|
|
62
|
+
| `wls_action_query` | 查询页面菜单下的动作(type=A) |
|
|
63
|
+
| `wls_action_upsert` | 批量新增动作(按 permission 去重) |
|
|
64
|
+
|
|
65
|
+
> 编辑器不支持 MCP 时(如纯命令行使用),可参考 §6 调用接口直连方式手动跑通。
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 1. role-manage(角色管理)
|
|
70
|
+
|
|
71
|
+
### 输入示例
|
|
72
|
+
|
|
73
|
+
> "创建一个测试角色,code 是 test_qa,描述:QA 测试用"
|
|
74
|
+
|
|
75
|
+
### 流程
|
|
76
|
+
|
|
77
|
+
1. AI 调用 `wls_role_query` 检查 `code=test_qa` 是否已存在
|
|
78
|
+
2. 若不存在,调用 `wls_role_upsert`:
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"items": [
|
|
82
|
+
{ "roleName": "测试角色(QA)", "code": "test_qa", "configDesc": "QA 测试用" }
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
3. 输出表格:角色名 / code / 状态(✅ 创建成功 / ⏭ 已存在)
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 2. role-assign(角色授权)
|
|
91
|
+
|
|
92
|
+
### 输入示例
|
|
93
|
+
|
|
94
|
+
> "给『档案普通人员』角色挂上『客户档案』『客户申请』两个菜单"
|
|
95
|
+
|
|
96
|
+
### 流程
|
|
97
|
+
|
|
98
|
+
1. **查询角色 id**:`wls_role_query` → 找到 `roleName="档案普通人员"` 对应的 `id`
|
|
99
|
+
2. **查询可授权菜单**:`wls_assignable_menus_query` → 获取全部菜单清单
|
|
100
|
+
3. **匹配 menuIds**:在结果中找到「客户档案」「客户申请」对应的 menu id
|
|
101
|
+
4. **⚠️ 二次确认**:在 Pre-flight 中列出"将给角色 X 分配菜单 [A, B]",得到用户 yes 才执行
|
|
102
|
+
5. **调用授权**:`wls_role_assign_menus`
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"roleId": "VERUFQ77SS0BCCE6GJVU21IFEP1EKFBQ",
|
|
106
|
+
"menuIds": ["2049380552157999105", "2049388746804604929"]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### ⚠️ 全量覆盖式陷阱
|
|
111
|
+
|
|
112
|
+
后端 `saveRoleMenus` 是**全量覆盖**:
|
|
113
|
+
- 传 `[A, B]` 后,原先 `[A, B, C]` 中的 C 会被移除
|
|
114
|
+
- AI 在执行前**必须先告知用户**:"此操作会替换该角色全部菜单,原有未列出的将被移除"
|
|
115
|
+
- 若用户只是想"追加 C",AI 应自行合并:取出旧 menuIds + 新增的 → 一起传
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 3. action-attach(挂动作 + 加 v-permission)
|
|
120
|
+
|
|
121
|
+
### 输入示例
|
|
122
|
+
|
|
123
|
+
> "给『客户档案』页面挂上 新增/编辑/删除/导出 四个动作按钮"
|
|
124
|
+
|
|
125
|
+
### 流程
|
|
126
|
+
|
|
127
|
+
#### 3.1 服务端注册动作
|
|
128
|
+
|
|
129
|
+
1. **查询页面菜单 id**:先用 `wls_menu_query` 或 `wls_assignable_menus_query` 找到「客户档案」页面菜单 id(type=C)
|
|
130
|
+
2. **查询已有动作**:`wls_action_query({ menuId: <页面id> })` 看哪些已存在
|
|
131
|
+
3. **批量新增**:`wls_action_upsert`
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"parentId": "<页面菜单 id>",
|
|
135
|
+
"items": [
|
|
136
|
+
{ "menuName": "新增", "permission": "customer_add", "orderNum": 1 },
|
|
137
|
+
{ "menuName": "编辑", "permission": "customer_edit", "orderNum": 2 },
|
|
138
|
+
{ "menuName": "删除", "permission": "customer_remove", "orderNum": 3 },
|
|
139
|
+
{ "menuName": "导出", "permission": "customer_export", "orderNum": 4 }
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### 3.2 在 Vue 代码中加 v-permission 指令
|
|
145
|
+
|
|
146
|
+
注册动作后,AI 自动改造对应页面的 toolbar/操作列,加上 `v-permission`:
|
|
147
|
+
|
|
148
|
+
```vue
|
|
149
|
+
<el-button v-permission="'customer_add'" @click="onAdd">新增</el-button>
|
|
150
|
+
<el-button v-permission="'customer_edit'" @click="onEdit">编辑</el-button>
|
|
151
|
+
<el-button v-permission="'customer_remove'" @click="onRemove">删除</el-button>
|
|
152
|
+
<el-button v-permission="'customer_export'" @click="onExport">导出</el-button>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
> `v-permission` 指令通常由项目基座(如 `@jhlc/common-core` 或登录鉴权模块)注册。若项目未注册,AI 应在 Pre-flight 提示用户"未检测到 v-permission 指令实现,仅完成服务端注册,代码侧指令请由架构组补全"。
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 4. 权限码命名规范(项目内统一)
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
{资源camelCase}_{动作} ← 当前项目主流(短,便于阅读)
|
|
163
|
+
{模块}:{资源}:{动作} ← 通用平台风格(语义完整)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| 动作 | 含义 | 示例(短) | 示例(长) |
|
|
167
|
+
| ------------ | -------- | --------------------------- | -------------------------------- |
|
|
168
|
+
| `add` | 新增 | `customer_add` | `mmwr:customer:add` |
|
|
169
|
+
| `edit` | 编辑 | `customer_edit` | `mmwr:customer:edit` |
|
|
170
|
+
| `remove` | 删除 | `customer_remove` | `mmwr:customer:remove` |
|
|
171
|
+
| `export` | 导出 | `customer_export` | `mmwr:customer:export` |
|
|
172
|
+
| `import` | 导入 | `customer_import` | `mmwr:customer:import` |
|
|
173
|
+
| `submit` | 提交审批 | `customer_submit` | `mmwr:customer:submit` |
|
|
174
|
+
| `approve` | 审批通过 | `customer_approve` | `mmwr:customer:approve` |
|
|
175
|
+
| `reject` | 审批驳回 | `customer_reject` | `mmwr:customer:reject` |
|
|
176
|
+
| `{custom}` | 自定义 | `customer_convertToFormal` | `mmwr:customer:convertToFormal` |
|
|
177
|
+
|
|
178
|
+
> AI 在生成时**先扫描项目内已有 v-permission 用法**,沿用现有风格;项目无既定风格时优先短形式(`xxx_add`),与示例数据保持一致。
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 5. 安全约束(强制)
|
|
183
|
+
|
|
184
|
+
- ✅ **生产环境拒绝直接 push**:`gatewayPath` 含 `prod` / `.com` 时切换为"导出 SQL/JSON"模式,不直接调接口
|
|
185
|
+
- ✅ **角色分配二次确认**:`role-assign` 模式下,必须在 Pre-flight 中列出"角色 → 完整菜单清单"得到用户 yes 才执行
|
|
186
|
+
- ✅ **仅新增不删除**:所有 upsert 工具按唯一键去重跳过;删除走人工 SQL(防误删导致大面积失权)
|
|
187
|
+
- ✅ **审计报告**:每次执行后,在 `reports/PERMISSION_SYNC_<YYYYMMDD>.md` 追加日志(角色/动作变更、调用接口、响应、回滚提示)
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 6. 直连接口参考(无 MCP 时的兜底)
|
|
192
|
+
|
|
193
|
+
所有接口共用 Headers:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
Content-Type: application/json
|
|
197
|
+
Authorization: Bearer <token>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
| 操作 | 方法 | 路径 | Body |
|
|
201
|
+
| -------------------- | ---- | --------------------------------------------------- | ------------------------------------------------------------- |
|
|
202
|
+
| 查询角色列表 | GET | `/system/role/list?current=1&size=100` | - |
|
|
203
|
+
| 新增角色 | POST | `/system/role/save` | `{ roleName, code, configDesc }` |
|
|
204
|
+
| 查询全量可授权菜单 | GET | `/system/menu/get/subMenu?size=999` | - |
|
|
205
|
+
| 角色分配菜单 | POST | `/system/role/saveRoleMenus` | `{ roleId, menuIds: "id1,id2" }` (**逗号分隔字符串**) |
|
|
206
|
+
| 查询页面下子菜单/动作 | GET | `/system/menu/children?current=1&size=10&menuId=X` | - |
|
|
207
|
+
| 新增动作(type=A) | POST | `/system/menu/save` | `{ parentId, type:"A", menuName, permission, icon, orderNum, sysAppNo, intIsActive:1, useCache:1 }` |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 7. 与其他 Skill 联动
|
|
212
|
+
|
|
213
|
+
- **page-codegen**:生成 toolbar 时根据 `api.md` 的操作集自动加 `v-permission` 指令(在动作 upsert 完成后)
|
|
214
|
+
- **menu-sync**:菜单注册成功后,AI 应主动询问"是否给该页面挂动作?" → 触发 action-attach
|
|
215
|
+
- **convention-audit**:审计页面 toolbar 是否所有按钮都有 `v-permission`(缺失视为偏差)
|
|
216
|
+
- **prototype-scan**:扫描原型时识别按钮 → 写入 `reports/SYS_PERMISSION_INFO.md` 基线
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 8. 报告输出(reports/PERMISSION_SYNC_<日期>.md)
|
|
221
|
+
|
|
222
|
+
```md
|
|
223
|
+
# 权限同步报告 2026-04-29
|
|
224
|
+
|
|
225
|
+
## role-manage
|
|
226
|
+
- ✅ 新增角色:测试角色(QA)/ test_qa
|
|
227
|
+
|
|
228
|
+
## role-assign
|
|
229
|
+
- ✅ 角色 default_role 已分配 5 个菜单:[id1, id2, ...]
|
|
230
|
+
- ⚠️ 替换原有 7 个菜单(已确认)
|
|
231
|
+
|
|
232
|
+
## action-attach
|
|
233
|
+
- ✅ customer 页面新增 4 个动作:add/edit/remove/export
|
|
234
|
+
- ✅ 代码已加 v-permission(src/views/customer/list/index.vue 第 32-45 行)
|
|
235
|
+
|
|
236
|
+
## 回滚提示
|
|
237
|
+
- 角色分配可通过重新调用 saveRoleMenus 传旧 menuIds 恢复
|
|
238
|
+
- 新增的角色/动作建议通过后端管理界面手动删除(防止误删生产数据)
|
|
239
|
+
```
|