@agile-team/wl-skills-kit 1.2.0 → 2.1.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 +130 -0
- package/README.md +169 -366
- package/bin/wl-skills.js +149 -43
- package/files/.github/copilot-instructions.md +105 -42
- package/files/.github/guides/README.md +13 -0
- package/files/.github/guides/architecture.md +555 -0
- package/files/.github/guides/usage.md +166 -0
- package/files/.github/reports/README.md +65 -0
- package/files/.github/reports/SYS_DICT_INFO.md +19 -0
- package/files/.github/reports/SYS_PERMISSION_INFO.md +20 -0
- package/files/.github/reports//347/273/204/344/273/266/346/217/220/345/217/226/345/273/272/350/256/256.md +33 -0
- package/files/.github/reports//350/247/204/350/214/203/345/256/241/346/237/245/346/212/245/345/221/212.md +44 -0
- package/files/.github/skills/_compat/README.md +108 -0
- package/files/.github/skills/_compat/editors.json +61 -0
- package/files/.github/skills/_compat/headers/agents.txt +8 -0
- package/files/.github/skills/_compat/headers/claude-code.txt +7 -0
- package/files/.github/skills/_compat/headers/cline.txt +7 -0
- package/files/.github/skills/_compat/headers/cursor-mdc.txt +16 -0
- package/files/.github/skills/_compat/headers/cursor-rules.txt +7 -0
- package/files/.github/skills/_compat/headers/github-copilot.txt +1 -0
- package/files/.github/skills/_compat/headers/kiro.txt +10 -0
- package/files/.github/skills/_compat/headers/trae.txt +11 -0
- package/files/.github/skills/_compat/headers/windsurf.txt +7 -0
- package/files/.github/skills/_registry.md +81 -0
- package/files/.github/skills/{api-contract → core/api-contract}/SKILL.md +126 -29
- package/files/.github/skills/core/api-contract/USAGE.md +110 -0
- package/files/.github/skills/core/convention-audit/SKILL.md +189 -0
- package/files/.github/skills/core/convention-audit/USAGE.md +99 -0
- package/files/.github/skills/{page-codegen → core/page-codegen}/SKILL.md +67 -22
- package/files/.github/skills/core/page-codegen/USAGE.md +102 -0
- package/files/.github/skills/core/page-codegen/templates/_index.md +46 -0
- package/files/.github/skills/core/page-codegen/templates/domains/_CONTRIBUTING.md +107 -0
- package/files/.github/skills/{page-codegen → 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 -0
- package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-DETAIL-TABS.md +94 -39
- package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-DRIVEN.md +124 -124
- package/files/.github/skills/{prototype-scan → core/prototype-scan}/SKILL.md +87 -3
- package/files/.github/skills/core/prototype-scan/USAGE.md +95 -0
- package/files/.github/skills/core/template-extract/SKILL.md +139 -0
- package/files/.github/skills/core/template-extract/USAGE.md +93 -0
- package/files/.github/skills/domain/README.md +51 -0
- package/files/.github/skills/ops/code-fix/SKILL.draft.md +108 -0
- package/files/.github/skills/sync/dict-sync/SKILL.draft.md +100 -0
- package/files/.github/skills/{menu-sync → sync/menu-sync}/SKILL.md +258 -258
- package/files/.github/skills/sync/menu-sync/USAGE.md +104 -0
- package/files/.github/skills/{menu-sync → sync/menu-sync}/env/guide.md +83 -83
- package/files/.github/skills/sync/permission-sync/SKILL.draft.md +91 -0
- package/files/.github/standards/01-toolchain.md +57 -0
- package/files/.github/standards/02-code-structure.md +111 -0
- package/files/.github/standards/03-comments.md +53 -0
- package/files/.github/standards/04-coding-basics.md +33 -0
- package/files/.github/standards/05-logging.md +38 -0
- package/files/.github/standards/06-security.md +44 -0
- package/files/.github/standards/07-config.md +52 -0
- package/files/.github/standards/08-git.md +60 -0
- package/files/.github/standards/09-typescript.md +71 -0
- package/files/.github/standards/10-pinia.md +57 -0
- package/files/.github/standards/11-form-validation.md +81 -0
- package/files/.github/standards/12-base-table.md +116 -0
- package/files/.github/standards/13-platform-components.md +123 -0
- package/files/.github/standards/index.md +89 -0
- 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/package.json +4 -1
- package/files/.github/docs/menu-sync-design.md +0 -264
- package/files/.github/docs/use-skill.md +0 -382
- package/files/.github/docs/wl-skills-kit.md +0 -266
- package/files/.github/skills/convention-extract/SKILL.md +0 -236
- /package/files/.github/{docs → reports}/SYS_MENU_INFO.md +0 -0
- /package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-CHANGE-HISTORY.md +0 -0
- /package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-FORM-ROUTE.md +0 -0
- /package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-LIST.md +0 -0
- /package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-MASTER-DETAIL.md +0 -0
- /package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-RECORD-FORM.md +0 -0
- /package/files/.github/skills/{page-codegen → core/page-codegen/templates/universal}/TPL-TREE-LIST.md +0 -0
- /package/files/.github/skills/{menu-sync → sync/menu-sync}/env/env.local.json +0 -0
|
@@ -0,0 +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,83 +1,83 @@
|
|
|
1
|
-
# env.local.json 配置说明
|
|
2
|
-
|
|
3
|
-
> 该目录下的 `env.local.json` 已加入 `.gitignore`,**不会提交到远端仓库**。
|
|
4
|
-
> 每位成员在本地维护自己的副本,首次使用时按本文档填写即可。
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## 文件结构
|
|
9
|
-
|
|
10
|
-
```json
|
|
11
|
-
{
|
|
12
|
-
"gatewayPath": "http://192.168.10.50:9000",
|
|
13
|
-
"parentMenuId": "1803456789012345678",
|
|
14
|
-
"sysAppNo": "QjQuXy1kbKxZyjhS5N2",
|
|
15
|
-
"token": "eyJhbGci..."
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 字段说明
|
|
22
|
-
|
|
23
|
-
| 字段 | 说明 | 示例 |
|
|
24
|
-
|---|---|---|
|
|
25
|
-
| `gatewayPath` | 后端网关地址,含协议和端口,**末尾不加斜杠** | `http://192.168.10.50:9000` |
|
|
26
|
-
| `parentMenuId` | 目标父级目录的菜单数据库 ID(每套环境不同) | `1803456789012345678` |
|
|
27
|
-
| `sysAppNo` | 应用编码(非明文,从已有菜单接口响应中获取) | `QjQuXy1kbKxZyjhS5N2` |
|
|
28
|
-
| `token` | 当前登录用户的 Bearer Token,**不含 `bearer ` 前缀** | `eyJhbGci...` |
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## 如何获取各字段
|
|
33
|
-
|
|
34
|
-
### gatewayPath
|
|
35
|
-
|
|
36
|
-
询问后端同事,或查看浏览器 Network 面板中任意接口请求的 URL,取协议 + 域名/IP + 端口部分。
|
|
37
|
-
|
|
38
|
-
### parentMenuId
|
|
39
|
-
|
|
40
|
-
**方法 A(推荐)**:系统管理后台 → 菜单管理 → 找到目标父级目录 → 点编辑/查看 → 复制菜单 ID
|
|
41
|
-
|
|
42
|
-
**方法 B(API 查询)**:
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
GET {gatewayPath}/system/menu/children?menuId=0
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
从顶级节点向下逐层查找,直到找到目标父级目录。也可以告诉 AI「帮我查一下父级菜单 ID」,AI 会自动调接口查询。
|
|
49
|
-
|
|
50
|
-
### sysAppNo
|
|
51
|
-
|
|
52
|
-
系统用编码后的字符串标识应用(如 `QjQuXy1kbKxZyjhS5N2`),而非明文 `produce` / `sale`。
|
|
53
|
-
|
|
54
|
-
**获取方式**:浏览器 F12 → Network → 找任意菜单相关接口的响应体 → 查看已有菜单条目的 `sysAppNo` 字段值,复制即可。
|
|
55
|
-
|
|
56
|
-
> ℹ️ 同一领域下所有菜单的 `sysAppNo` 相同,复制任意一个即可。
|
|
57
|
-
|
|
58
|
-
### token
|
|
59
|
-
|
|
60
|
-
1. 在浏览器中登录系统
|
|
61
|
-
2. 按 F12 打开 DevTools → Network 面板
|
|
62
|
-
3. 随便点一个接口请求
|
|
63
|
-
4. 查看 Request Headers → `authorization` 字段
|
|
64
|
-
5. 去掉 `bearer ` 前缀,复制剩余字符串粘贴到 `token` 字段
|
|
65
|
-
|
|
66
|
-
> Token 有有效期,若创建菜单时提示鉴权失败,重新登录后刷新 token 即可。
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## 使用方式
|
|
71
|
-
|
|
72
|
-
配置完成后,直接对 AI 说:
|
|
73
|
-
|
|
74
|
-
> 「帮我创建菜单」/ 「同步菜单」/ 「补菜单」
|
|
75
|
-
|
|
76
|
-
AI 会自动执行:
|
|
77
|
-
1. 读取 `SYS_MENU_INFO.md`(菜单定义)
|
|
78
|
-
2. 读取 `env.local.json`(环境配置)
|
|
79
|
-
3. 调 `/system/menu/children` 查询父级已有子节点(去重)
|
|
80
|
-
4. 逐条调 `/system/menu/save` 创建缺失菜单
|
|
81
|
-
5. 输出 `created / skipped` 结果表
|
|
82
|
-
|
|
83
|
-
**全程无需手动执行任何命令。**
|
|
1
|
+
# env.local.json 配置说明
|
|
2
|
+
|
|
3
|
+
> 该目录下的 `env.local.json` 已加入 `.gitignore`,**不会提交到远端仓库**。
|
|
4
|
+
> 每位成员在本地维护自己的副本,首次使用时按本文档填写即可。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 文件结构
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"gatewayPath": "http://192.168.10.50:9000",
|
|
13
|
+
"parentMenuId": "1803456789012345678",
|
|
14
|
+
"sysAppNo": "QjQuXy1kbKxZyjhS5N2",
|
|
15
|
+
"token": "eyJhbGci..."
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 字段说明
|
|
22
|
+
|
|
23
|
+
| 字段 | 说明 | 示例 |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `gatewayPath` | 后端网关地址,含协议和端口,**末尾不加斜杠** | `http://192.168.10.50:9000` |
|
|
26
|
+
| `parentMenuId` | 目标父级目录的菜单数据库 ID(每套环境不同) | `1803456789012345678` |
|
|
27
|
+
| `sysAppNo` | 应用编码(非明文,从已有菜单接口响应中获取) | `QjQuXy1kbKxZyjhS5N2` |
|
|
28
|
+
| `token` | 当前登录用户的 Bearer Token,**不含 `bearer ` 前缀** | `eyJhbGci...` |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 如何获取各字段
|
|
33
|
+
|
|
34
|
+
### gatewayPath
|
|
35
|
+
|
|
36
|
+
询问后端同事,或查看浏览器 Network 面板中任意接口请求的 URL,取协议 + 域名/IP + 端口部分。
|
|
37
|
+
|
|
38
|
+
### parentMenuId
|
|
39
|
+
|
|
40
|
+
**方法 A(推荐)**:系统管理后台 → 菜单管理 → 找到目标父级目录 → 点编辑/查看 → 复制菜单 ID
|
|
41
|
+
|
|
42
|
+
**方法 B(API 查询)**:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
GET {gatewayPath}/system/menu/children?menuId=0
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
从顶级节点向下逐层查找,直到找到目标父级目录。也可以告诉 AI「帮我查一下父级菜单 ID」,AI 会自动调接口查询。
|
|
49
|
+
|
|
50
|
+
### sysAppNo
|
|
51
|
+
|
|
52
|
+
系统用编码后的字符串标识应用(如 `QjQuXy1kbKxZyjhS5N2`),而非明文 `produce` / `sale`。
|
|
53
|
+
|
|
54
|
+
**获取方式**:浏览器 F12 → Network → 找任意菜单相关接口的响应体 → 查看已有菜单条目的 `sysAppNo` 字段值,复制即可。
|
|
55
|
+
|
|
56
|
+
> ℹ️ 同一领域下所有菜单的 `sysAppNo` 相同,复制任意一个即可。
|
|
57
|
+
|
|
58
|
+
### token
|
|
59
|
+
|
|
60
|
+
1. 在浏览器中登录系统
|
|
61
|
+
2. 按 F12 打开 DevTools → Network 面板
|
|
62
|
+
3. 随便点一个接口请求
|
|
63
|
+
4. 查看 Request Headers → `authorization` 字段
|
|
64
|
+
5. 去掉 `bearer ` 前缀,复制剩余字符串粘贴到 `token` 字段
|
|
65
|
+
|
|
66
|
+
> Token 有有效期,若创建菜单时提示鉴权失败,重新登录后刷新 token 即可。
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 使用方式
|
|
71
|
+
|
|
72
|
+
配置完成后,直接对 AI 说:
|
|
73
|
+
|
|
74
|
+
> 「帮我创建菜单」/ 「同步菜单」/ 「补菜单」
|
|
75
|
+
|
|
76
|
+
AI 会自动执行:
|
|
77
|
+
1. 读取 `SYS_MENU_INFO.md`(菜单定义)
|
|
78
|
+
2. 读取 `env.local.json`(环境配置)
|
|
79
|
+
3. 调 `/system/menu/children` 查询父级已有子节点(去重)
|
|
80
|
+
4. 逐条调 `/system/menu/save` 创建缺失菜单
|
|
81
|
+
5. 输出 `created / skipped` 结果表
|
|
82
|
+
|
|
83
|
+
**全程无需手动执行任何命令。**
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: permission-sync
|
|
3
|
+
description: "[PLANNED — DRAFT, not yet active] 权限同步 Skill 设计草稿。基于 reports/SYS_PERMISSION_INFO.md 基线,将页面级/按钮级权限码注册到系统权限表,并按角色分配。"
|
|
4
|
+
status: planned
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: 权限同步(permission-sync)— 草稿
|
|
8
|
+
|
|
9
|
+
> ⚠️ **本文件为设计草稿(SKILL.draft.md),未启用,不参与 AI 调度。**
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. 设计目标
|
|
14
|
+
|
|
15
|
+
新增页面后,除菜单外还需注册:
|
|
16
|
+
|
|
17
|
+
- **页面访问权限**(`mmwr:customer:list`)
|
|
18
|
+
- **按钮级权限**(`mmwr:customer:add` / `:edit` / `:remove` / `:approve` / `:export` ...)
|
|
19
|
+
- **数据权限**(可选:客户经理只看自己的客户等)
|
|
20
|
+
- **角色绑定**(哪些角色获得这些权限)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. 数据流
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
本地基线 后端接口 Skill 触发
|
|
28
|
+
──────────────────────────────────────── ────────────────────────────────── ────────────────
|
|
29
|
+
reports/SYS_PERMISSION_INFO.md ─fetch─→ GET /sys/permission/listAll
|
|
30
|
+
←compare── POST /sys/permission/batchSave
|
|
31
|
+
─upload─→ POST /sys/role/assignPermissions ─→ "同步权限"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 3. 权限码命名规范
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
{服务缩写}:{资源camelCase}:{操作}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| 操作 | 含义 | 示例 |
|
|
43
|
+
| -------- | -------------- | ------------------------------- |
|
|
44
|
+
| list | 查看列表 | `mmwr:customer:list` |
|
|
45
|
+
| detail | 查看详情 | `mmwr:customer:detail` |
|
|
46
|
+
| add | 新增 | `mmwr:customer:add` |
|
|
47
|
+
| edit | 编辑 | `mmwr:customer:edit` |
|
|
48
|
+
| remove | 删除 | `mmwr:customer:remove` |
|
|
49
|
+
| export | 导出 | `mmwr:customer:export` |
|
|
50
|
+
| import | 导入 | `mmwr:customer:import` |
|
|
51
|
+
| submit | 提交审批 | `mmwr:customer:submit` |
|
|
52
|
+
| approve | 审批通过 | `mmwr:customer:approve` |
|
|
53
|
+
| reject | 审批驳回 | `mmwr:customer:reject` |
|
|
54
|
+
| {custom} | 自定义业务操作 | `mmwr:customer:convertToFormal` |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 4. 三种工作模式
|
|
59
|
+
|
|
60
|
+
| 模式 | 触发 | 动作 |
|
|
61
|
+
| ---------- | ----------------------- | ------------------------------------------------------ |
|
|
62
|
+
| `scan` | "扫描权限码" | 从 src/views/ 扫 v-permission / hasPerm 调用,输出清单 |
|
|
63
|
+
| `register` | "注册权限码 / 同步权限" | 对比基线 → 创建缺失 + 更新描述 |
|
|
64
|
+
| `assign` | "给 XX 角色分配权限" | 选定角色 + 选定权限码 → 调 /sys/role/assignPermissions |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 5. 安全约束
|
|
69
|
+
|
|
70
|
+
- **生产环境拒绝直接 push**:检测 gatewayPath 含 prod/.com 时强制走"导出 SQL"模式
|
|
71
|
+
- **角色分配二次确认**:每次 assign 必须在 Pre-flight 中列出"角色 → 新增/移除的权限",得到用户 yes 才执行
|
|
72
|
+
- **不删除权限**:永远只新增/更新,删除走人工 SQL(防误删导致大面积失权)
|
|
73
|
+
- **审计**:每次 register/assign 输出 `reports/PERMISSION_SYNC_<YYYYMMDD>.md`,含完整调用日志和回滚 SQL
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 6. 与其他 Skill 联动
|
|
78
|
+
|
|
79
|
+
- **page-codegen**:生成 toolbar 时根据 api.md 操作集自动加 `v-permission` 指令
|
|
80
|
+
- **menu-sync**:菜单注册后提示"是否同步注册访问权限"
|
|
81
|
+
- **convention-audit**:审计按钮是否都有 v-permission
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 7. 转正前的开发任务
|
|
86
|
+
|
|
87
|
+
- [ ] 确认后端权限模型(RBAC / ABAC?是否分页面权限和按钮权限?)
|
|
88
|
+
- [ ] 数据权限是否纳入本 Skill(建议:暂不,单独 data-permission-sync)
|
|
89
|
+
- [ ] 设计 v-permission 指令的项目内实现(如 @jhlc/common-core 提供则复用)
|
|
90
|
+
- [ ] 多租户场景下的权限继承策略
|
|
91
|
+
- [ ] 与 SSO(嘉为蓝鲸)权限同步策略
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 01 — 工具链前置检测
|
|
2
|
+
|
|
3
|
+
> **强制度**:🔴 阻断式。检测未通过 → AI 必须暂停代码生成。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 检测目标
|
|
8
|
+
|
|
9
|
+
确认项目已正确安装 `@robot-admin/git-standards`,工具链有效。
|
|
10
|
+
|
|
11
|
+
## 检测项
|
|
12
|
+
|
|
13
|
+
AI 在执行任何代码生成任务**之前**,必须检查以下三个特征文件是否存在于项目根目录:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
✓ .prettierrc.js
|
|
17
|
+
✓ eslint.config.ts
|
|
18
|
+
✓ .husky/ (目录)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 判定规则
|
|
22
|
+
|
|
23
|
+
| 状态 | 处理 |
|
|
24
|
+
| ------------ | --------------------------- |
|
|
25
|
+
| 三者全部存在 | ✅ 工具链就绪,继续执行任务 |
|
|
26
|
+
| 缺任意一个 | ❌ 暂停任务,输出下方提示 |
|
|
27
|
+
|
|
28
|
+
## 暂停提示标准格式
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
❌ 工具链检测失败:未找到 .prettierrc.js / eslint.config.ts / .husky/
|
|
32
|
+
→ 请执行:npx @robot-admin/git-standards init
|
|
33
|
+
→ 或联系 CHENY(工号 409322)解决
|
|
34
|
+
→ ⛔ 代码生成已暂停,修复后重新触发
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Pre-flight 声明示例
|
|
38
|
+
|
|
39
|
+
工具链就绪:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
✅ 工具链检测:.prettierrc.js ✓ eslint.config.ts ✓ .husky/ ✓ [全部就绪]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
工具链缺失:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
❌ 工具链检测:未检测到 .husky/ → 已暂停,提醒已发出
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 为什么必须前置
|
|
54
|
+
|
|
55
|
+
- `eslint.config.ts` 缺失 → 代码风格无法约束,AI 生成代码可能不通过 lint
|
|
56
|
+
- `.prettierrc.js` 缺失 → 格式不统一,团队协作冲突
|
|
57
|
+
- `.husky/` 缺失 → 提交前钩子失效,console.log / 死代码会进入仓库
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# 02 — 代码结构与顺序规范
|
|
2
|
+
|
|
3
|
+
> **强制度**:🔴 必遵。AI 生成代码必须严格按下列顺序输出。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 4 文件原则(页面目录强制结构)
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/views/[域]/[模块]/[子模块]/[kebab-case目录]/
|
|
11
|
+
├── index.vue ← 纯模板 + 解构,不写业务逻辑
|
|
12
|
+
├── data.ts ← AbstractPageQueryHook 类 + API_CONFIG
|
|
13
|
+
├── index.scss ← 页面样式(可为空)
|
|
14
|
+
└── api.md ← 接口约定文档
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**禁止**:把业务逻辑写在 index.vue;缺少 data.ts;缺少 api.md。
|
|
18
|
+
|
|
19
|
+
## 弹窗组件归属
|
|
20
|
+
|
|
21
|
+
| 场景 | 位置 |
|
|
22
|
+
| ----------------------- | ------------------------------------ |
|
|
23
|
+
| 通用弹窗(2+ 页面复用) | `src/components/local/c_xxxModal/` |
|
|
24
|
+
| 极个性弹窗(仅单页面) | 页面目录下 `components/xxxModal.vue` |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## index.vue 三段式(顺序固定,不可调换)
|
|
29
|
+
|
|
30
|
+
```vue
|
|
31
|
+
<template>
|
|
32
|
+
<!-- 纯模板 + 组件组合 -->
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script setup lang="ts">
|
|
36
|
+
/* 业务逻辑全部从 data.ts 导入,按下方 9 段式 */
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style scoped lang="scss">
|
|
40
|
+
@import "./index.scss";
|
|
41
|
+
/* 仅允许这一行 import,全部样式写在 index.scss */
|
|
42
|
+
</style>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## `<script setup>` 9 段式(按需使用,用到的必须遵守此顺序)
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// ===== 1. import 语句(外部库 → 内部模块 → 类型)=====
|
|
51
|
+
import { ref, computed, onMounted } from "vue";
|
|
52
|
+
import { createPage } from "./data";
|
|
53
|
+
|
|
54
|
+
// ===== 2. 组件宏(defineOptions / defineProps / defineEmits)=====
|
|
55
|
+
defineOptions({ name: "PageName" });
|
|
56
|
+
|
|
57
|
+
// ===== 3. 路由 & Store =====
|
|
58
|
+
const route = useRoute();
|
|
59
|
+
|
|
60
|
+
// ===== 4. createPage() 调用 + 解构(核心模式)=====
|
|
61
|
+
const Page = createPage();
|
|
62
|
+
const {
|
|
63
|
+
tableRef,
|
|
64
|
+
page,
|
|
65
|
+
queryParam,
|
|
66
|
+
list,
|
|
67
|
+
queryItems,
|
|
68
|
+
columns,
|
|
69
|
+
toolbars,
|
|
70
|
+
select,
|
|
71
|
+
} = Page;
|
|
72
|
+
|
|
73
|
+
// ===== 5. 页面补充状态(ref / reactive / computed)=====
|
|
74
|
+
const loading = ref(false);
|
|
75
|
+
|
|
76
|
+
// ===== 6. watch / watchEffect =====
|
|
77
|
+
|
|
78
|
+
// ===== 7. 业务方法(API 调用 / 事件处理)=====
|
|
79
|
+
async function handleSubmit() {}
|
|
80
|
+
|
|
81
|
+
// ===== 8. 生命周期 =====
|
|
82
|
+
onMounted(() => select());
|
|
83
|
+
|
|
84
|
+
// ===== 9. defineExpose =====
|
|
85
|
+
defineExpose({ select });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## data.ts 内部顺序(强制)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// 1. import(类型 → 基类 → API 工具 → 工具函数)
|
|
94
|
+
// 2. API_CONFIG(接口路径集中声明,as const)
|
|
95
|
+
// 3. createPage()(constructor → queryDef → toolbarDef → columnsDef → 业务方法)
|
|
96
|
+
// 4. 页面共用辅助函数(可选,纯函数)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## index.scss 顺序(建议)
|
|
102
|
+
|
|
103
|
+
```scss
|
|
104
|
+
// 1. 变量覆盖
|
|
105
|
+
// 2. 容器级样式 (.app-page-container)
|
|
106
|
+
// 3. 区域级样式 (.search-area / .table-area)
|
|
107
|
+
// 4. 组件深层覆盖 (:deep(.el-table))
|
|
108
|
+
// 5. 响应式 (@media)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
> 禁止 `::v-deep` / `/deep/`,统一使用 `:deep()`。
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# 03 — 注释规范
|
|
2
|
+
|
|
3
|
+
> **强制度**:🟡 建议。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 文件头注释
|
|
8
|
+
|
|
9
|
+
由 VS Code 插件 **koroFileHeader** 自动生成,不手写。
|
|
10
|
+
项目根有 `.fileheader` 配置文件。
|
|
11
|
+
|
|
12
|
+
**插件缺失提示**:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
⚠️ 未检测到 koroFileHeader 配置生效
|
|
16
|
+
→ 请安装插件:VS Code 扩展商店搜索 "koroFileHeader"
|
|
17
|
+
→ 或联系 CHENY(工号 409322)获取一键安装指引
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 函数注释
|
|
23
|
+
|
|
24
|
+
仅复杂业务逻辑需要:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
/**
|
|
28
|
+
* @description 批量提交客户档案
|
|
29
|
+
* @param ids 选中的客户 ID 列表
|
|
30
|
+
* @returns 后端响应结果
|
|
31
|
+
*/
|
|
32
|
+
async function batchSubmit(ids: string[]) { ... }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 行内注释
|
|
38
|
+
|
|
39
|
+
- 解释「**为什么**」而非「是什么」
|
|
40
|
+
- 统一使用 `//`,不使用 `/* */`
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// 后端要求 status 必须先转字符串再传(接口字段类型不一致历史遗留)
|
|
44
|
+
params.status = String(params.status);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 禁止事项
|
|
50
|
+
|
|
51
|
+
- ❌ 提交注释掉的死代码(直接删除,git 可追溯历史)
|
|
52
|
+
- ❌ 显而易见的注释,如 `// 声明变量`、`// 调用接口`
|
|
53
|
+
- ❌ TODO 不带责任人或日期,如 `// TODO: 待优化`,应写为 `// TODO(cheny, 2026-04): 接口字段后端确认中`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# 04 — 基础编码规范
|
|
2
|
+
|
|
3
|
+
> **强制度**:🔴 必遵。
|
|
4
|
+
> 参考 jhat.tech 开发规范 + Robot_Admin 实践。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 13 条核心约定
|
|
9
|
+
|
|
10
|
+
1. **变量声明**:优先 `const`,必须重新赋值时用 `let`,禁止 `var`
|
|
11
|
+
2. **解构赋值**:优先使用 `const { a, b } = obj`,而非 `obj.a` / `obj.b`
|
|
12
|
+
3. **异步处理**:统一 `async/await`,禁止 `.then()` 链式调用
|
|
13
|
+
4. **字符串引号**:统一单引号(以 `.prettierrc.js` 为准)
|
|
14
|
+
5. **模板字符串**:替代字符串拼接,`` `Hello ${name}` `` 而非 `'Hello ' + name`
|
|
15
|
+
6. **大括号**:所有代码块必须使用大括号包裹,即使只有一行
|
|
16
|
+
7. **条件层级**:最多三层,超过三层必须抽成函数
|
|
17
|
+
8. **模板表达式**:`<template>` 中只写简单表达式,复杂逻辑提取为 `computed` 或方法
|
|
18
|
+
9. **对象遍历**:禁止 `for...in`,使用 `Object.keys(obj).forEach()`
|
|
19
|
+
10. **undefined 判断**:使用 `typeof variable !== 'undefined'`
|
|
20
|
+
11. **v-for**:必须设置 `:key`,优先用业务主键 id 而非 index
|
|
21
|
+
12. **指令缩写**:统一 `:`(v-bind)、`@`(v-on)、`#`(v-slot)
|
|
22
|
+
13. **this 别名**:`<script setup>` 中无 `this`;旧 Options API 中的 `this` 别名用 `self`
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 全局禁止事项
|
|
27
|
+
|
|
28
|
+
- ❌ index.vue 中写业务逻辑(逻辑全在 data.ts)
|
|
29
|
+
- ❌ 使用 Vuex(本项目用 Pinia)
|
|
30
|
+
- ❌ `::v-deep` / `/deep/`(用 `:deep()`)
|
|
31
|
+
- ❌ 直接用 axios(用 getAction/postAction,详见 13-platform-components.md)
|
|
32
|
+
- ❌ 手写查询表单/工具栏/分页(用 BaseQuery/BaseToolbar/jh-pagination)
|
|
33
|
+
- ❌ 每个页面重复写弹窗(优先用 `c_modal` / `c_formModal` 等局部公共组件)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# 05 — 日志输出规范
|
|
2
|
+
|
|
3
|
+
> **强制度**:🔴 必遵。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 开发期
|
|
8
|
+
|
|
9
|
+
- 允许 `console.log` 调试,ESLint 仅给 `warn` 提示
|
|
10
|
+
- AI 生成的代码**不要**包含调试用 `console.log`
|
|
11
|
+
|
|
12
|
+
## 提交期
|
|
13
|
+
|
|
14
|
+
- husky pre-commit 钩子自动触发 lint 检查
|
|
15
|
+
- **必须清理** `console.log` / `console.warn` / `console.debug` 才能提交
|
|
16
|
+
|
|
17
|
+
## 生产代码
|
|
18
|
+
|
|
19
|
+
- ❌ 禁止出现 `console.log`、`console.warn`、`console.error`
|
|
20
|
+
- ❌ 大量 console 输出会带来性能问题(参考 jhat.tech 规范)
|
|
21
|
+
|
|
22
|
+
## 替代方案
|
|
23
|
+
|
|
24
|
+
| 场景 | 替代方式 |
|
|
25
|
+
| -------- | ---------------------------------------------- |
|
|
26
|
+
| 错误监控 | 走全局错误处理器(接入 Sentry 或自研上报通道) |
|
|
27
|
+
| 调试信息 | 仅在开发环境通过 `import.meta.env.DEV` 守卫 |
|
|
28
|
+
| 用户提示 | 使用 `ElMessage` / `jh-message` |
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// ✅ 允许:开发期守卫
|
|
32
|
+
if (import.meta.env.DEV) {
|
|
33
|
+
console.log("[debug] payload:", payload);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ❌ 禁止:生产代码无守卫的 console
|
|
37
|
+
console.log("user info:", user);
|
|
38
|
+
```
|