Skip to content

Commit 1822d97

Browse files
committed
feat: add bind-menu-for-role mcp
1 parent 647cb0f commit 1822d97

4 files changed

Lines changed: 64 additions & 1 deletion

File tree

template/tinyvue/src/utils/tree.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export function getIdByLabel(tree, targetLabel) {
2+
const stack = [...tree];
3+
4+
while (stack.length > 0) {
5+
const node = stack.pop();
6+
7+
if (node.label === targetLabel) {
8+
return node.id;
9+
}
10+
11+
if (node.children) {
12+
stack.push(...node.children);
13+
}
14+
}
15+
16+
return null;
17+
}

template/tinyvue/src/views/role/info/components/info-tab.vue

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script lang="ts" setup>
2+
import { WebMcpServer, z } from '@opentiny/next-sdk'
23
import type { RoleAddData } from './add-role.vue'
34
import type { Permission } from '@/api/permission'
45
import type { ITreeNodeData } from '@/router/guard/menu'
@@ -10,7 +11,7 @@ import {
1011
TinyModal,
1112
Pager as TinyPager,
1213
} from '@opentiny/vue'
13-
import { computed, inject, ref } from 'vue'
14+
import { computed, inject, ref, onMounted } from 'vue'
1415
import { useI18n } from 'vue-i18n'
1516
import { useRouter } from 'vue-router'
1617
import { getAllMenu } from '@/api/menu'
@@ -25,6 +26,8 @@ import constant from '@/router/constant'
2526
import { toRoutes } from '@/router/guard/menu'
2627
import { useTabStore } from '@/store'
2728
import { useMenuStore } from '@/store/modules/router'
29+
import { sleep } from '@/utils/base-utils'
30+
import { getIdByLabel } from '@/utils/tree'
2831
import addRole from './add-role.vue'
2932
import menuDrawer from './menu-drawer.vue'
3033
import roleTable from './role-table.vue'
@@ -71,6 +74,7 @@ const pagerConfigLg = {
7174
attrs: { currentPage: 1, pageSize: 10, pageSizes: [10, 20, 50, 100], total: 10, layout: 'sizes, total, prev, pager, next, jumper' },
7275
}
7376
const roleTableRef = ref()
77+
const menuDrawerRef = ref()
7478
const allFilter = {
7579
inputFilter: {
7680
inputFilter: true,
@@ -203,6 +207,41 @@ function onRoleUpdateSuccess() {
203207
function onRoleDelete() {
204208
roleTableRef.value.reload()
205209
}
210+
211+
onMounted(async () => {
212+
const server = new WebMcpServer({
213+
name: 'bind-menu-mcp-server',
214+
version: '1.0.0',
215+
})
216+
const serverTransport = inject<any>('serverTransport')
217+
218+
server.registerTool(
219+
'bind-menu-for-role',
220+
{
221+
title: '绑定菜单',
222+
description: '给某个角色绑定菜单',
223+
inputSchema: {
224+
role: z.string().describe('需要绑定菜单的角色名称'),
225+
menu: z.string().describe('需要绑定的菜单名称'),
226+
},
227+
},
228+
async ({ role, menu }) => {
229+
const rowData = tableData.value.find(item => item.name === role)
230+
roleTableRef.value.openMenuModal(rowData.menus, rowData.id, rowData)
231+
await sleep(1000)
232+
233+
// 先从菜单名称获取菜单 ID,再勾选菜单
234+
const menuId = getIdByLabel(i18MenuDatas.value, menu)
235+
menuDrawerRef.value.treeRef.setChecked(menuId, true, false)
236+
await sleep(1000)
237+
238+
menuDrawerRef.value.onConfirm()
239+
return { content: [{ type: 'text', text: `收到: ${role}` }] }
240+
},
241+
)
242+
243+
await server.connect(serverTransport)
244+
})
206245
</script>
207246

208247
<template>
@@ -232,6 +271,7 @@ function onRoleDelete() {
232271
</div>
233272
<menu-drawer
234273
v-if="open"
274+
ref="menuDrawerRef"
235275
v-loading="loading"
236276
:visible="open"
237277
:menus="i18MenuDatas"

template/tinyvue/src/views/role/info/components/menu-drawer.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ onMounted(() => {
4444
treeRef.value.setChecked(id, true, false)
4545
})
4646
})
47+
48+
defineExpose({
49+
onConfirm,
50+
treeRef,
51+
})
4752
</script>
4853

4954
<template>

template/tinyvue/src/views/role/info/components/role-table.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ defineExpose({
113113
reload: () => {
114114
grid.value.handleFetch()
115115
},
116+
openMenuModal: onMenuUpdate,
116117
})
117118
</script>
118119

0 commit comments

Comments
 (0)