@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,15 +1,15 @@
|
|
|
1
|
-
.sub-el-icon,
|
|
2
|
-
.nav-icon {
|
|
3
|
-
display: inline-block;
|
|
4
|
-
font-size: 15px;
|
|
5
|
-
margin-right: 12px;
|
|
6
|
-
position: relative;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.svg-icon {
|
|
10
|
-
width: 1em;
|
|
11
|
-
height: 1em;
|
|
12
|
-
position: relative;
|
|
13
|
-
fill: currentColor;
|
|
14
|
-
vertical-align: -2px;
|
|
15
|
-
}
|
|
1
|
+
.sub-el-icon,
|
|
2
|
+
.nav-icon {
|
|
3
|
+
display: inline-block;
|
|
4
|
+
font-size: 15px;
|
|
5
|
+
margin-right: 12px;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.svg-icon {
|
|
10
|
+
width: 1em;
|
|
11
|
+
height: 1em;
|
|
12
|
+
position: relative;
|
|
13
|
+
fill: currentColor;
|
|
14
|
+
vertical-align: -2px;
|
|
15
|
+
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
.status-fallback {
|
|
2
|
-
display: inline-block;
|
|
3
|
-
padding: 0 8px;
|
|
4
|
-
font-size: 12px;
|
|
5
|
-
color: #909399;
|
|
6
|
-
line-height: 22px;
|
|
7
|
-
white-space: nowrap;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// 增强 el-tag 的视觉效果
|
|
11
|
-
:deep(.el-tag) {
|
|
12
|
-
font-weight: 500;
|
|
13
|
-
border: none;
|
|
14
|
-
|
|
15
|
-
// 为淡色效果添加边框
|
|
16
|
-
&.el-tag--light {
|
|
17
|
-
border: 1px solid currentColor;
|
|
18
|
-
border-color: var(--el-tag-border-color);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
1
|
+
.status-fallback {
|
|
2
|
+
display: inline-block;
|
|
3
|
+
padding: 0 8px;
|
|
4
|
+
font-size: 12px;
|
|
5
|
+
color: #909399;
|
|
6
|
+
line-height: 22px;
|
|
7
|
+
white-space: nowrap;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// 增强 el-tag 的视觉效果
|
|
11
|
+
:deep(.el-tag) {
|
|
12
|
+
font-weight: 500;
|
|
13
|
+
border: none;
|
|
14
|
+
|
|
15
|
+
// 为淡色效果添加边框
|
|
16
|
+
&.el-tag--light {
|
|
17
|
+
border: 1px solid currentColor;
|
|
18
|
+
border-color: var(--el-tag-border-color);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
import { ref, watch } from "vue";
|
|
2
|
-
import { Search } from "@element-plus/icons-vue";
|
|
3
|
-
|
|
4
|
-
// ===== 类型定义 =====
|
|
5
|
-
export interface Props {
|
|
6
|
-
tabs?: Array<{ label: string; name: string }>;
|
|
7
|
-
treeData: any[];
|
|
8
|
-
treeProps?: Record<string, string>;
|
|
9
|
-
defaultActiveTab?: string;
|
|
10
|
-
showSearch?: boolean;
|
|
11
|
-
searchPlaceholder?: string;
|
|
12
|
-
defaultExpandAll?: boolean;
|
|
13
|
-
highlightCurrent?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// ===== 组件逻辑 =====
|
|
17
|
-
export function createTree(
|
|
18
|
-
props: Props,
|
|
19
|
-
emit: (e: "node-click" | "tab-change", ...args: any[]) => void,
|
|
20
|
-
) {
|
|
21
|
-
const activeTab = ref(props.defaultActiveTab ?? "tab1");
|
|
22
|
-
const searchKeyword = ref("");
|
|
23
|
-
const treeRef = ref<any>(null);
|
|
24
|
-
|
|
25
|
-
const filterNode = (value: string, data: any) => {
|
|
26
|
-
if (!value) return true;
|
|
27
|
-
const label = data[props.treeProps?.label || "label"];
|
|
28
|
-
return label && label.includes(value);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const handleNodeClick = (data: any) => {
|
|
32
|
-
emit("node-click", data);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
watch(searchKeyword, (val) => {
|
|
36
|
-
treeRef.value?.filter(val);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
watch(activeTab, (val) => {
|
|
40
|
-
emit("tab-change", val);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const clearSearch = () => {
|
|
44
|
-
searchKeyword.value = "";
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const switchTab = (tabName: string) => {
|
|
48
|
-
activeTab.value = tabName;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
Search,
|
|
53
|
-
activeTab,
|
|
54
|
-
searchKeyword,
|
|
55
|
-
treeRef,
|
|
56
|
-
filterNode,
|
|
57
|
-
handleNodeClick,
|
|
58
|
-
clearSearch,
|
|
59
|
-
switchTab,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
1
|
+
import { ref, watch } from "vue";
|
|
2
|
+
import { Search } from "@element-plus/icons-vue";
|
|
3
|
+
|
|
4
|
+
// ===== 类型定义 =====
|
|
5
|
+
export interface Props {
|
|
6
|
+
tabs?: Array<{ label: string; name: string }>;
|
|
7
|
+
treeData: any[];
|
|
8
|
+
treeProps?: Record<string, string>;
|
|
9
|
+
defaultActiveTab?: string;
|
|
10
|
+
showSearch?: boolean;
|
|
11
|
+
searchPlaceholder?: string;
|
|
12
|
+
defaultExpandAll?: boolean;
|
|
13
|
+
highlightCurrent?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ===== 组件逻辑 =====
|
|
17
|
+
export function createTree(
|
|
18
|
+
props: Props,
|
|
19
|
+
emit: (e: "node-click" | "tab-change", ...args: any[]) => void,
|
|
20
|
+
) {
|
|
21
|
+
const activeTab = ref(props.defaultActiveTab ?? "tab1");
|
|
22
|
+
const searchKeyword = ref("");
|
|
23
|
+
const treeRef = ref<any>(null);
|
|
24
|
+
|
|
25
|
+
const filterNode = (value: string, data: any) => {
|
|
26
|
+
if (!value) return true;
|
|
27
|
+
const label = data[props.treeProps?.label || "label"];
|
|
28
|
+
return label && label.includes(value);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const handleNodeClick = (data: any) => {
|
|
32
|
+
emit("node-click", data);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
watch(searchKeyword, (val) => {
|
|
36
|
+
treeRef.value?.filter(val);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
watch(activeTab, (val) => {
|
|
40
|
+
emit("tab-change", val);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const clearSearch = () => {
|
|
44
|
+
searchKeyword.value = "";
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const switchTab = (tabName: string) => {
|
|
48
|
+
activeTab.value = tabName;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
Search,
|
|
53
|
+
activeTab,
|
|
54
|
+
searchKeyword,
|
|
55
|
+
treeRef,
|
|
56
|
+
filterNode,
|
|
57
|
+
handleNodeClick,
|
|
58
|
+
clearSearch,
|
|
59
|
+
switchTab,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.dialog-footer {
|
|
2
|
-
display: flex;
|
|
3
|
-
justify-content: flex-end;
|
|
4
|
-
}
|
|
1
|
+
.dialog-footer {
|
|
2
|
+
display: flex;
|
|
3
|
+
justify-content: flex-end;
|
|
4
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { wlsFetch } = require('./client')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 查询角色列表(分页)
|
|
7
|
+
* GET /system/role/list?current=1&size=10
|
|
8
|
+
*/
|
|
9
|
+
function queryRoleList(params, config) {
|
|
10
|
+
const current = (params && params.current) || 1
|
|
11
|
+
const size = (params && params.size) || 100
|
|
12
|
+
return wlsFetch(
|
|
13
|
+
`/system/role/list?current=${current}&size=${size}`,
|
|
14
|
+
{},
|
|
15
|
+
config
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 新增角色
|
|
21
|
+
* POST /system/role/save
|
|
22
|
+
* body: { roleName, code, configDesc }
|
|
23
|
+
*/
|
|
24
|
+
function saveRole(body, config) {
|
|
25
|
+
return wlsFetch('/system/role/save', { method: 'POST', body }, config)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 查询全量可授权菜单(用于角色分配菜单)
|
|
30
|
+
* GET /system/menu/get/subMenu?size=999
|
|
31
|
+
*/
|
|
32
|
+
function queryAssignableMenus(config) {
|
|
33
|
+
return wlsFetch('/system/menu/get/subMenu?size=999', {}, config)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 给角色批量分配菜单权限
|
|
38
|
+
* POST /system/role/saveRoleMenus
|
|
39
|
+
* body: { roleId, menuIds: "id1,id2,id3" } // 注意 menuIds 是逗号分隔字符串
|
|
40
|
+
*/
|
|
41
|
+
function saveRoleMenus(body, config) {
|
|
42
|
+
return wlsFetch('/system/role/saveRoleMenus', { method: 'POST', body }, config)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 查询父菜单下的子菜单/动作列表
|
|
47
|
+
* GET /system/menu/children?current=1&size=10&menuId=xxx
|
|
48
|
+
*/
|
|
49
|
+
function queryMenuChildren(menuId, config) {
|
|
50
|
+
const params = `current=1&size=999&menuId=${encodeURIComponent(menuId)}`
|
|
51
|
+
return wlsFetch(`/system/menu/children?${params}`, {}, config)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
queryRoleList,
|
|
56
|
+
saveRole,
|
|
57
|
+
queryAssignableMenus,
|
|
58
|
+
saveRoleMenus,
|
|
59
|
+
queryMenuChildren,
|
|
60
|
+
}
|
package/mcp/server.js
CHANGED
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
* wl-skills MCP Server
|
|
6
6
|
*
|
|
7
7
|
* 实现 MCP 协议(stdio transport,JSON-RPC 2.0)
|
|
8
|
-
*
|
|
9
|
-
* wls_menu_query
|
|
10
|
-
* wls_menu_upsert
|
|
11
|
-
* wls_dict_query
|
|
12
|
-
* wls_dict_upsert
|
|
8
|
+
* 暴露工具:
|
|
9
|
+
* wls_menu_query 查询菜单树
|
|
10
|
+
* wls_menu_upsert 批量新增/更新菜单
|
|
11
|
+
* wls_dict_query 查询字典模块
|
|
12
|
+
* wls_dict_upsert 新增/更新字典模块及字典项
|
|
13
|
+
* wls_role_query 查询角色列表
|
|
14
|
+
* wls_role_upsert 批量新增角色(按 code 去重)
|
|
15
|
+
* wls_assignable_menus_query 查询全量可授权菜单(用于角色授权)
|
|
16
|
+
* wls_role_assign_menus 给角色批量分配菜单权限
|
|
17
|
+
* wls_action_query 查询页面菜单下的动作(type=A)
|
|
18
|
+
* wls_action_upsert 批量新增动作(按 permission 去重)
|
|
13
19
|
*
|
|
14
20
|
* 启动方式(由 .cursor/mcp.json 自动注入):
|
|
15
21
|
* node node_modules/@agile-team/wl-skills-kit/mcp/server.js
|
|
@@ -19,6 +25,14 @@ const readline = require('readline')
|
|
|
19
25
|
const { loadConfig } = require('./config')
|
|
20
26
|
const { handleMenuQuery, handleMenuUpsert } = require('./tools/menuSync')
|
|
21
27
|
const { handleDictQuery, handleDictUpsert } = require('./tools/dictSync')
|
|
28
|
+
const {
|
|
29
|
+
handleRoleQuery,
|
|
30
|
+
handleRoleUpsert,
|
|
31
|
+
handleRoleAssignMenus,
|
|
32
|
+
handleAssignableMenusQuery,
|
|
33
|
+
handleActionQuery,
|
|
34
|
+
handleActionUpsert,
|
|
35
|
+
} = require('./tools/permissionSync')
|
|
22
36
|
|
|
23
37
|
const PKG = require('../package.json')
|
|
24
38
|
|
|
@@ -102,6 +116,94 @@ const TOOLS = [
|
|
|
102
116
|
required: ['module'],
|
|
103
117
|
},
|
|
104
118
|
},
|
|
119
|
+
{
|
|
120
|
+
name: 'wls_role_query',
|
|
121
|
+
description:
|
|
122
|
+
'查询角色列表。可选参数 current/size 翻页,默认 size=100。返回精简字段:id, roleName, code, sysAppNo, roleDesc。',
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: 'object',
|
|
125
|
+
properties: {
|
|
126
|
+
current: { type: 'number', description: '页码,默认 1' },
|
|
127
|
+
size: { type: 'number', description: '每页数量,默认 100' },
|
|
128
|
+
},
|
|
129
|
+
required: [],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'wls_role_upsert',
|
|
134
|
+
description:
|
|
135
|
+
'批量新增角色(按 code 字段自动去重;已存在则跳过)。每项必填 roleName 和 code,可选 configDesc。' +
|
|
136
|
+
'注意:角色仅新增不更新,因角色变更通常需要业务确认。',
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: 'object',
|
|
139
|
+
properties: {
|
|
140
|
+
items: {
|
|
141
|
+
type: 'array',
|
|
142
|
+
description:
|
|
143
|
+
'角色数组。字段:roleName(必填,显示名), code(必填,唯一标识), configDesc(可选,描述)',
|
|
144
|
+
items: { type: 'object' },
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
required: ['items'],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'wls_assignable_menus_query',
|
|
152
|
+
description:
|
|
153
|
+
'查询全量可授权菜单列表(扁平结构,含菜单 id/menuName/permission)。' +
|
|
154
|
+
'在 wls_role_assign_menus 前调用,AI 据此选出要分配给角色的 menuIds。',
|
|
155
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'wls_role_assign_menus',
|
|
159
|
+
description:
|
|
160
|
+
'给指定角色批量分配菜单权限。menuIds 传字符串数组,内部自动拼成逗号分隔字符串提交后端。' +
|
|
161
|
+
'该接口为全量覆盖式,应包含该角色所有菜单(含已有的,否则会被移除)。',
|
|
162
|
+
inputSchema: {
|
|
163
|
+
type: 'object',
|
|
164
|
+
properties: {
|
|
165
|
+
roleId: { type: 'string', description: '角色 id(来自 wls_role_query)' },
|
|
166
|
+
menuIds: {
|
|
167
|
+
type: 'array',
|
|
168
|
+
description: '该角色应拥有的全部菜单 id 数组',
|
|
169
|
+
items: { type: 'string' },
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
required: ['roleId', 'menuIds'],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'wls_action_query',
|
|
177
|
+
description:
|
|
178
|
+
'查询指定页面菜单(type=C)下的动作按钮列表(type=A)。返回 id/menuName/permission/orderNum/icon。',
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: 'object',
|
|
181
|
+
properties: {
|
|
182
|
+
menuId: { type: 'string', description: '父菜单 id(页面菜单)' },
|
|
183
|
+
},
|
|
184
|
+
required: ['menuId'],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'wls_action_upsert',
|
|
189
|
+
description:
|
|
190
|
+
'在指定页面菜单下批量新增动作按钮(type=A),按 permission 字段自动去重。' +
|
|
191
|
+
'权限码命名规范:{资源camelCase}_{动作} 或 {模块}:{资源}:{动作}(与项目既有约定保持一致)。' +
|
|
192
|
+
'常见动作:add/edit/remove/export/import/approve。',
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {
|
|
196
|
+
parentId: { type: 'string', description: '页面菜单 id(动作挂在它下面)' },
|
|
197
|
+
items: {
|
|
198
|
+
type: 'array',
|
|
199
|
+
description:
|
|
200
|
+
'动作数组。字段:menuName(必填,显示名), permission(必填,权限码), icon(可选,默认list), orderNum(可选,默认1), useCache(可选,默认1)',
|
|
201
|
+
items: { type: 'object' },
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
required: ['parentId', 'items'],
|
|
205
|
+
},
|
|
206
|
+
},
|
|
105
207
|
]
|
|
106
208
|
|
|
107
209
|
// ─── JSON-RPC 协议层 ────────────────────────────────────────────────────
|
|
@@ -145,6 +247,24 @@ async function dispatchTool(id, toolName, toolArgs) {
|
|
|
145
247
|
case 'wls_dict_upsert':
|
|
146
248
|
text = await handleDictUpsert(toolArgs, config)
|
|
147
249
|
break
|
|
250
|
+
case 'wls_role_query':
|
|
251
|
+
text = await handleRoleQuery(toolArgs, config)
|
|
252
|
+
break
|
|
253
|
+
case 'wls_role_upsert':
|
|
254
|
+
text = await handleRoleUpsert(toolArgs, config)
|
|
255
|
+
break
|
|
256
|
+
case 'wls_assignable_menus_query':
|
|
257
|
+
text = await handleAssignableMenusQuery(toolArgs, config)
|
|
258
|
+
break
|
|
259
|
+
case 'wls_role_assign_menus':
|
|
260
|
+
text = await handleRoleAssignMenus(toolArgs, config)
|
|
261
|
+
break
|
|
262
|
+
case 'wls_action_query':
|
|
263
|
+
text = await handleActionQuery(toolArgs, config)
|
|
264
|
+
break
|
|
265
|
+
case 'wls_action_upsert':
|
|
266
|
+
text = await handleActionUpsert(toolArgs, config)
|
|
267
|
+
break
|
|
148
268
|
default:
|
|
149
269
|
sendError(id, -32601, `未知工具: ${toolName}`)
|
|
150
270
|
return
|