浏览代码

fix:修改了用户详情相关的 API 名称,增加了用户部门的修改 API。
调整了菜单相关 API,新增了菜单的详情查询、修改和删除功能。
重构了多个组件,以提升可读性和一致性,修复了一些变量名称。
实现了权限配置和部门配置的保存功能,同时简化了对应的逻辑。
完善了菜单树和部门树的获取逻辑,优化了一些事件处理。

张涛 1 年之前
父节点
当前提交
93a0036344

+ 44 - 0
package-lock.json

@@ -16,6 +16,7 @@
         "js-cookie": "3.0.5",
         "mitt": "3.0.1",
         "pinia": "2.2.8",
+        "pinia-plugin-persist": "1.0.0",
         "screenfull": "6.0.2",
         "vue": "3.5.13",
         "vue-i18n": "10.0.5",
@@ -3517,6 +3518,49 @@
         }
       }
     },
+    "node_modules/pinia-plugin-persist": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/pinia-plugin-persist/-/pinia-plugin-persist-1.0.0.tgz",
+      "integrity": "sha512-M4hBBd8fz/GgNmUPaaUsC29y1M09lqbXrMAHcusVoU8xlQi1TqgkWnnhvMikZwr7Le/hVyMx8KUcumGGrR6GVw==",
+      "dependencies": {
+        "vue-demi": "^0.12.1"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0",
+        "pinia": "^2.0.0",
+        "vue": "^2.0.0 || >=3.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinia-plugin-persist/node_modules/vue-demi": {
+      "version": "0.12.5",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.12.5.tgz",
+      "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/pinia/node_modules/vue-demi": {
       "version": "0.14.10",
       "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",

+ 11 - 2
src/apis/permission/account.js

@@ -9,8 +9,8 @@ export function QueryUserList(params) {
     params
   });
 }
-// 获取用户详情
-export function QueryUserDetail(userId) {
+// 获取用户机构详情
+export function QueryUserDeptDetail(userId) {
   return request({
     url: `${prefix}/dept`,
     method: 'get',
@@ -20,6 +20,15 @@ export function QueryUserDetail(userId) {
   });
 }
 
+// 修改用户部门
+export function UpdateUserDept(data) {
+  return request({
+    url: `${prefix}/dept`,
+    method: 'put',
+    data
+  });
+}
+
 // 新增用户
 export function AddUser(data) {
   return request({

+ 44 - 1
src/apis/permission/resource.js

@@ -2,10 +2,53 @@ import request from '../../base/ajax';
 
 const prefix = '/api/menu';
 
-// 查询角色列表
+// 查询菜单列表
 export function QueryMenuTree() {
   return request({
     url: `${prefix}/tree_select`,
     method: 'get'
   });
 }
+
+// 查询菜单详情
+export function QueryResourceDetail(resourceId) {
+  return request({
+    url: `${prefix}/${resourceId}`,
+    method: 'get'
+  });
+}
+
+// 修改菜单
+export function UpdateResource(data) {
+  return request({
+    url: `${prefix}/edit_resource`,
+    method: 'put',
+    data
+  });
+}
+
+// 修改菜单的父级
+export function UpdateResourceParent(data) {
+  return request({
+    url: `${prefix}/resource_parent`,
+    method: 'put',
+    data
+  });
+}
+
+// 新增菜单
+export function CreateResource(data) {
+  return request({
+    url: `${prefix}/add_resource`,
+    method: 'post',
+    data
+  });
+}
+
+// 删除菜单
+export function DeleteResource(resourceId) {
+  return request({
+    url: `${prefix}/${resourceId}`,
+    method: 'delete'
+  });
+}

+ 10 - 3
src/modules/permission/TreeParts.vue

@@ -9,7 +9,7 @@
         </a-button>
       </a-tooltip>
     </template>
-    <a-tree :draggable="is_lock" blockNode :data="treeData" :show-line="true" :default-expand-all="true" :fieldNames="{
+    <a-tree :draggable="is_lock" blockNode :data="treeData" :show-line="true" ref="treeRef" :fieldNames="{
       key: 'deptId',
       title: 'deptName',
       children: 'children',
@@ -25,7 +25,7 @@
 </template>
 
 <script setup>
-import { ref, toRefs } from 'vue';
+import { onMounted, ref, toRefs, nextTick } from 'vue';
 const props = defineProps({
   treeData: {
     type: Array,
@@ -36,7 +36,7 @@ const props = defineProps({
 const { treeData } = toRefs(props);
 
 const emit = defineEmits(['nodeClick', 'onAddBtnClick', 'onDrop', 'onDeleteBtnClick']);
-
+const treeRef = ref(null);
 let is_lock = ref(false);
 
 const toggleDraggable = () => {
@@ -57,6 +57,13 @@ const onDeleteBtnClick = (nodeData) => {
 const onDrop = ({ dragNode, dropNode, dropPosition }) => {
   emit('drop', { dragNode, dropNode, dropPosition });
 };
+
+onMounted(() => {
+  //TODO: 展开所有节点
+  nextTick(() => {
+    treeRef.value.expandAll();
+  });
+});
 </script>
 
 <style lang="css" scoped>

+ 22 - 14
src/modules/permission/account/DeptConfigModal.vue

@@ -2,7 +2,7 @@
   <a-modal width="50%" v-model:visible="visible" title="部门配置" @cancel="handleCancel" @ok="editDeptHandleOk">
     <div style="display: flex;">
       <a-card class="card-body" title="机构" hoverable>
-        <a-tree :data="dept_list" v-model:checked-keys="checked_keys" v-model:expanded-keys="expand_kdys"
+        <a-tree :data="dept_list" v-model:checked-keys="checked_keys" v-model:expanded-keys="expand_keys"
           :checkable="true" :show-line="true" @check="onCheck" :fieldNames="{
             key: 'deptId',
             title: 'deptName',
@@ -12,15 +12,15 @@
       </a-card>
       <a-card class="card-body" title="用户所属部门">
         <a-space wrap>
-          <a-tag v-for="(tag, index) of check_strictly" :key="tag.deptId">
-            {{ tag.deptName }}
+          <a-tag v-for="item of check_strictly" :key="item.deptId">
+            {{ item.deptName }}
           </a-tag>
         </a-space>
         <a-divider />
         <div style="margin-bottom: 8px;">部门角色:</div>
         <a-space wrap>
-          <a-tag v-for="(tag, index) of check_strictly_dept_role" :key="tag.roleId" color="arcoblue">
-            {{ tag.roleName }}
+          <a-tag v-for="item of check_strictly_dept_role" :key="item.roleId" color="arcoblue">
+            {{ item.roleName }}
           </a-tag>
         </a-space>
       </a-card>
@@ -51,7 +51,7 @@ const emit = defineEmits(['close', 'ok']);
 // 组件内部状态
 const checked_keys = ref([]);
 // 默认展开第一节
-const expand_kdys = ref(['0']);
+const expand_keys = ref(['0']);
 const check_strictly = ref([]);
 const check_strictly_dept_role = ref([]);
 
@@ -69,14 +69,18 @@ const cancelChildSelection = (node, selected_nodes) => {
     });
   }
 }
-
+// FIXME:选择和取消选择的bug
 // 处理树形组件的勾选变化
 const onCheck = (new_checked_keys, event) => {
   const o = { deptId: event.node.deptId, deptName: event.node.deptName };
   if (event.checked) {
     // 添加部门角色
     event.node.roles.forEach((val) => {
-      check_strictly_dept_role.value.push(val);
+      // 检查是否已经存在相同的 roleId,如果不存在则添加
+      const exists = check_strictly_dept_role.value.some((role) => role.roleId === val.roleId);
+      if (!exists) {
+        check_strictly_dept_role.value.push(val);
+      }
     });
     // 添加部门
     check_strictly.value.push(o);
@@ -100,11 +104,11 @@ const handleCancel = () => {
 
 // 处理确认事件
 const editDeptHandleOk = () => {
-  emit('ok', { checked_keys: checked_keys.value });
+  emit('ok', checked_keys.value);
 };
 
 watch(() => props.dept_detail, (newVal) => {
-  if (newVal) {
+  if (newVal.length > 0) {
     newVal.forEach(val => {
       if (!checked_keys.value.includes(val.deptId)) {
         check_strictly.value.push({
@@ -112,11 +116,12 @@ watch(() => props.dept_detail, (newVal) => {
           deptName: val.deptName
         });
         checked_keys.value.push(val.deptId);
-        expand_kdys.value.push(val.deptId);
+        expand_keys.value.push(val.deptId);
       }
 
       val.roles.forEach((role) => {
-        if (!check_strictly_dept_role.value.some(item => item.roleId === role.roleId && item.deptId === val.deptId)) {
+        // 判断是否存在同样的 roleId,如果不存在则添加
+        if (!check_strictly_dept_role.value.some(item => item.roleId === role.roleId)) {
           check_strictly_dept_role.value.push({
             roleId: role.roleId,
             roleName: role.roleName,
@@ -125,8 +130,11 @@ watch(() => props.dept_detail, (newVal) => {
         }
       });
     });
-
-
+  } else {
+    checked_keys.value = [];
+    expand_keys.value = [];
+    check_strictly.value = [];
+    check_strictly_dept_role.value = [];
   }
 });
 </script>

+ 24 - 6
src/modules/permission/account/index.vue

@@ -31,8 +31,8 @@
     :knowledge_permissions_list="knowledge_permissions_list" :dialog_permissions_list="dialog_permissions_list"
     :agent_permissions_list="agent_permissions_list" />
 
-  <DeptConfigModal :visible.sync="dept_config_visible" :dept_list="dept_list" :dept_detail="dept_detail" @ok=""
-    @cancel="handleDeptConfig(null, false)" />
+  <DeptConfigModal :visible.sync="dept_config_visible" :dept_list="dept_list" :dept_detail="dept_detail"
+    @ok="handleDeptConfigSave" @cancel="handleDeptConfig(null, false)" />
 
 </template>
 
@@ -47,7 +47,7 @@ import ViewPermission from './ViewPermission.vue';
 import DeptConfigModal from './DeptConfigModal.vue';
 
 import {
-  QueryUserList, QueryUserDetail, AddUser,
+  QueryUserList, QueryUserDeptDetail, UpdateUserDept, AddUser,
   UpdateUser, QueryUserPermission, UserStatusSwitch, ResetPassword, DeleteUser
 } from '../../../apis/permission/account';
 import { QueryAllRoleList, QueryDeptTree } from '../../../apis/permission/common';
@@ -107,6 +107,9 @@ const getUserList = async () => {
   if (code === 200) {
     // 处理部门名称和角色名称
     for (const user of data.rows) {
+      user.deptName = ''; // 初始化 deptName
+      user.roleName = ''; // 初始化 roleName
+
       if (user.dept) {
         for (let i = 0; i < user.dept.length; i++) {
           const d = user.dept[i];
@@ -120,9 +123,9 @@ const getUserList = async () => {
           user.roleName += r.roleName + (i < user.roles.length - 1 ? ', ' : '');
         }
       }
-
     }
 
+
     pagination_props.value.total = data.total;
     table_data.value = data.rows;
 
@@ -245,8 +248,8 @@ const handleView = async (record, visible) => {
 // 部门配置
 const handleDeptConfig = async (record, visible) => {
   if (record) {
-    // const { code, data } = await QueryUserDetail(record.userId);
-    const { code, data: { rows } } = await QueryUserDetail(77);
+    edit_form.userId = record.userId;
+    const { code, data: { rows } } = await QueryUserDeptDetail(record.userId);
     if (code === 200) {
       dept_detail.value = rows;
     }
@@ -254,6 +257,21 @@ const handleDeptConfig = async (record, visible) => {
   dept_config_visible.value = visible;
 }
 
+const handleDeptConfigSave = async (checked_keys) => {
+  dept_config_visible.value = false;
+  const data = {
+    userId: edit_form.userId,
+    depts: checked_keys,
+  }
+  const { code } = await UpdateUserDept(data);
+  if (code === 200) {
+    Message.success({
+      title: '部门配置',
+      content: '部门配置成功',
+    });
+    getUserList();
+  }
+}
 // 删除用户
 const handleDelete = async (userId) => {
   const { code } = await DeleteUser(userId);

+ 7 - 7
src/modules/permission/group/PermissionConfigModal.vue

@@ -35,24 +35,24 @@
 
         <div style="margin: 8px 0;">知识库功能:</div>
         <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_knowledge_list" :key="tag.id">
-            {{ tag.name }}
+          <a-tag v-for="item of checked_knowledge_list" :key="item.id">
+            {{ item.name }}
           </a-tag>
         </a-space>
         <a-divider />
 
         <div style="margin: 8px 0;">智能体功能:</div>
         <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_agents_list" :key="tag.id">
-            {{ tag.name }}
+          <a-tag v-for="item of checked_agents_list" :key="item.id">
+            {{ item.name }}
           </a-tag>
         </a-space>
         <a-divider />
 
         <div style="margin: 8px 0;">模型功能:</div>
         <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_model_list" :key="tag.id">
-            {{ tag.name }}
+          <a-tag v-for="item of checked_model_list" :key="item.id">
+            {{ item.name }}
           </a-tag>
         </a-space>
       </a-card>
@@ -94,7 +94,7 @@ const selected_tab_key = ref(tabs[0].key);
 
 // 组件内部状态
 // 默认展开第一节
-const expand_kdys = ref(['0']);
+const expand_keys = ref(['0']);
 
 const checked_knowledge = ref([]);
 const checked_knowledge_list = ref([]);

+ 1 - 1
src/modules/permission/resource/ResourceForm.vue

@@ -38,7 +38,7 @@
 </template>
 
 <script setup>
-import { toRefs } from 'vue';
+import { ref, toRefs } from 'vue';
 import Upload from './Upload.vue';
 
 const uploadAction = '/api/v1/llm/upload'; // 替换为你的上传API

+ 190 - 0
src/modules/permission/resource/index.vue

@@ -0,0 +1,190 @@
+<template>
+  <div class="organization-container">
+    <div class="left">
+      <TreeParts :treeData="org_tree_data" @nodeClick="onNodeClick" @addBtnClick="onAddBtnClick"
+        @deleteBtnClick="onDeleteBtnClick" @drop="onNodeDrop" />
+    </div>
+    <div class="right">
+      <a-card title="详情" style="height: 100%;">
+        <ResourceForm :org_form="org_form" @save="orgFromSave" @reset="orgFromReset">
+          <template #actions>
+            <a-button @click="orgFromSave">保存</a-button>
+            <a-button @click="orgFromReset">重置</a-button>
+          </template>
+        </ResourceForm>
+      </a-card>
+    </div>
+
+    <Modal :visible.sync="org_visible" @ok="orgFromSave" @cancel="orgFromCancel" :title="'新增'">
+      <ResourceForm :org_form="org_form"></ResourceForm>
+    </Modal>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { Message } from '@arco-design/web-vue';
+import TreeParts from '../TreeParts.vue';
+import ResourceForm from './ResourceForm.vue';
+import Modal from '../Modal.vue';
+
+import {
+  QueryResourceDetail, UpdateResource, UpdateResourceParent, CreateResource, DeleteResource
+} from '../../../apis/permission/resource';
+
+import { QueryDeptTree } from '../../../apis/permission/common';
+
+const org_visible = ref(false);
+const is_edit_mode = ref(true);
+const org_tree_data = ref([]);
+
+const org_form = reactive({
+  parentName: '',
+  status: 0,
+  resourceName: '',
+  leader: '',
+  orderNum: '',
+  address: ''
+});
+
+const getDeptTree = async () => {
+  const { code, data: { rows } } = await QueryDeptTree();
+  if (code == 200) {
+    org_tree_data.value = rows;
+  }
+}
+
+
+// 树节点操作相关
+const onNodeClick = async (id) => {
+  const { data: { data } } = await QueryResourceDetail(id);
+  org_form.resourceId = id;
+  org_form.parentName = data.parentName;
+  org_form.status = data.status;
+  org_form.resourceName = data.resourceName;
+  org_form.leader = data.leader;
+  org_form.orderNum = data.orderNum;
+  org_form.address = data.address;
+
+}
+const onAddBtnClick = (nodeData) => {
+  org_form.resourceId = '';
+  org_form.parentName = nodeData.resourceName;
+  org_form.parentId = nodeData.resourceId
+  org_form.status = 0;
+  org_form.resourceName = '';
+  org_form.leader = '';
+  org_form.orderNum = '';
+  org_form.address = '';
+
+  org_visible.value = true;
+  is_edit_mode.value = false;
+}
+
+const onDeleteBtnClick = async ({ resourceId }) => {
+  const { code } = await DeleteResource(resourceId);
+  if (code === 200) {
+    Message.success({
+      title: '删除',
+      content: '删除成功',
+    });
+  }
+  getDeptTree();
+}
+
+const orgFromSave = async () => {
+  const data = {
+    ...org_form,
+    resourceId: (is_edit_mode.value && org_form.resourceId) ? org_form.resourceId[0] : null
+  }
+
+  const apiCall = is_edit_mode.value ? UpdateResource : CreateResource;
+  const { code } = await apiCall(data);
+
+  if (code === 200) {
+    const action = is_edit_mode.value ? '编辑' : '新增';
+    Message.success({
+      title: `${action}账号`,
+      content: `${action}成功`,
+    });
+
+    getDeptTree()
+    org_visible = false;
+  }
+}
+
+const orgFromReset = () => {
+  org_form.resourceId = null;
+  org_form.parentName = '';
+  org_form.status = 0;
+  org_form.resourceName = '';
+  org_form.leader = '';
+  org_form.orderNum = '';
+  org_form.address = '';
+}
+
+const orgFromCancel = () => {
+  is_edit_mode.value = true;
+  org_visible.value = false;
+}
+
+const onNodeDrop = async ({ dropNode, dragNode, dropPosition }) => {
+  const data = org_tree_data.value;
+  UpdateResourceParent({
+    orderNum: '0',
+    parentId: dropNode.resourceId,
+    resourceId: dragNode.resourceId,
+  });
+  const loop = (data, key, callback) => {
+    data.some((item, index, arr) => {
+      if (item.resourceId === key) {
+        callback(item, index, arr);
+        return true;
+      }
+      if (item.children) {
+        return loop(item.children, key, callback);
+      }
+      return false;
+    });
+  };
+
+  loop(data, dragNode.resourceId, (_, index, arr) => {
+    arr.splice(index, 1);
+  });
+
+  if (dropPosition === 0) {
+    loop(data, dropNode.resourceId, (item) => {
+      item.children = item.children || [];
+      item.children.push(dragNode);
+    });
+  } else {
+    loop(data, dropNode.resourceId, (_, index, arr) => {
+      arr.splice(dropPosition < 0 ? index : index + 1, 0, dragNode);
+    });
+  }
+}
+onMounted(() => {
+  getDeptTree();
+})
+</script>
+
+<style lang="css" scoped>
+.organization-container {
+  display: flex;
+  justify-content: space-between;
+  height: calc(100% - 40px);
+  width: 100%;
+}
+
+.left {
+  width: 30%;
+  height: 100%;
+  background-color: #fff;
+}
+
+.right {
+  width: 69%;
+  height: 100%;
+  background-color: #fff;
+}
+</style>

+ 10 - 11
src/modules/permission/role/DeptConfigModal.vue

@@ -2,7 +2,7 @@
   <a-modal width="50%" v-model:visible="visible" title="部门配置" @cancel="handleCancel" @ok="editDeptHandleOk">
     <div :style="{ display: 'flex' }">
       <a-card class="card-body" title="机构" hoverable>
-        <a-tree :data="dept_list" v-model:checked-keys="checked_keys" v-model:expanded-keys="expand_kdys"
+        <a-tree :data="dept_list" v-model:checked-keys="checked_keys" v-model:expanded-keys="expand_keys"
           :checkable="true" :show-line="true" @check="onCheck" :fieldNames="{
             key: 'deptId',
             title: 'deptName',
@@ -12,8 +12,8 @@
       </a-card>
       <a-card class="card-body" title="角色所属部门">
         <a-space wrap>
-          <a-tag v-for="(tag, index) of check_strictly" :key="tag.deptId">
-            {{ tag.deptName }}
+          <a-tag v-for="item of check_strictly" :key="item.deptId">
+            {{ item.deptName }}
           </a-tag>
         </a-space>
       </a-card>
@@ -22,7 +22,7 @@
 </template>
 
 <script setup>
-import { ref, toRefs, onMounted } from 'vue';
+import { ref, toRefs, watch } from 'vue';
 
 // 定义组件的 props 和 emits
 const props = defineProps({
@@ -44,7 +44,7 @@ const emit = defineEmits(['close', 'ok']);
 // 组件内部状态
 const checked_keys = ref([]);
 // 默认展开第一节
-const expand_kdys = ref(['0']);
+const expand_keys = ref(['0']);
 const check_strictly = ref([]);
 
 // 递归取消所有子节点的选择
@@ -85,19 +85,18 @@ const handleCancel = () => {
 
 // 处理确认事件
 const editDeptHandleOk = () => {
-  emit('ok', { checked_keys: checked_keys.value });
+  emit('ok', checked_keys.value);
 };
 
-onMounted(() => {
-  // 处理传入的部门数据
-  if (record?.dept) {
-    record.dept.forEach((val) => {
+watch(() => props.record, (newVal) => {
+  if (newVal?.dept) {
+    newVal.dept.forEach((val) => {
       check_strictly.value.push({
         deptId: val.deptId,
         deptName: val.deptName
       });
       checked_keys.value.push(val.deptId);
-      expand_kdys.value.push(val.deptId);
+      expand_keys.value.push(val.deptId);
     });
   }
 });

+ 23 - 142
src/modules/permission/role/PermissionConfigModal.vue

@@ -1,81 +1,30 @@
 <template>
   <a-modal width="50%" v-model:visible="visible" title="权限配置" @cancel="handleCancel" @ok="editDeptHandleOk">
-    <a-tabs :active-key="selected_tab_key" @change="handleTabChange">
-      <a-tab-pane v-for="tab in tabs" :key="tab.key">
-        <template #title>
-          <component :is="tab.icon" /> {{ tab.title }}
-        </template>
-      </a-tab-pane>
-    </a-tabs>
     <div style="display: flex;">
       <a-card class="card-body" :title="getCurrentTabTitle" hoverable>
-        <a-tree v-if="selected_tab_key === '1'" :data="menu_list" v-model="checked_menu"
-          v-model:expanded-keys="expand_kdys" :checkable="true" :show-line="true" @check="onCheck" :fieldNames="{
+        <a-tree :data="menu_list" v-model:checked-keys="checked_menu" v-model:expanded-keys="expand_keys"
+          :checkable="true" :show-line="true" @check="onCheck" :fieldNames="{
             key: 'menuId',
             title: 'menuName',
             children: 'children',
           }">
         </a-tree>
 
-        <a-checkbox-group v-if="selected_tab_key === '2'" v-model="checked_knowledge" @change="onCheckKnowledge">
-          <a-checkbox v-for="(knowledg, index) of knowledge_list" :value="knowledg.id" :lable="knowledg.name"
-            style="width:150px">
-            {{ knowledg.name }}
-          </a-checkbox>
-        </a-checkbox-group>
-
-        <a-checkbox-group v-if="selected_tab_key === '3'" v-model="checked_agents" @change="onCheckAgents">
-          <a-checkbox v-for="(agents, index) of agents_list" :value="agents.id" :lable="agents.name"
-            style="width:150px">
-            {{ agents.name }}
-          </a-checkbox>
-        </a-checkbox-group>
-
-        <a-checkbox-group v-if="selected_tab_key === '4'" v-model="checked_model" @change="onCheckModel">
-          <a-checkbox v-for="(model, index) of model_list" :value="model.id" :lable="model.name" style="width:150px">
-            {{ model.name }}
-          </a-checkbox>
-        </a-checkbox-group>
-
       </a-card>
-      <a-card class="card-body" title="角色所有权限">
+      <a-card class="card-body" title="角色菜单权限">
         <div style="margin: 8px 0;">菜单功能:</div>
         <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_menu_list" :key="tag.menuId">
+          <a-tag v-for="tag of checked_menu_list" :key="tag.menuId">
             {{ tag.menuName }}
           </a-tag>
         </a-space>
-        <a-divider />
-
-        <div style="margin: 8px 0;">知识库功能:</div>
-        <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_knowledge_list" :key="tag.id">
-            {{ tag.name }}
-          </a-tag>
-        </a-space>
-        <a-divider />
-
-        <div style="margin: 8px 0;">智能体功能:</div>
-        <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_agents_list" :key="tag.id">
-            {{ tag.name }}
-          </a-tag>
-        </a-space>
-        <a-divider />
-
-        <div style="margin: 8px 0;">模型功能:</div>
-        <a-space wrap>
-          <a-tag v-for="(tag, index) of checked_model_list" :key="tag.id">
-            {{ tag.name }}
-          </a-tag>
-        </a-space>
       </a-card>
     </div>
   </a-modal>
 </template>
 
 <script setup>
-import { ref, toRefs, onMounted, computed } from 'vue';
+import { ref, toRefs, watch } from 'vue';
 
 // 定义组件的 props 和 emits
 const props = defineProps({
@@ -84,45 +33,20 @@ const props = defineProps({
     type: Array,
     default: () => []
   },
-  knowledge_list: {
-    type: Array,
-    default: () => []
-  },
-  agents_list: {
-    type: Array,
-    default: () => []
-  },
-  model_list: {
-    type: Array,
-    default: () => []
-  },
   record: Object
 });
 
-const { visible, menu_list, knowledge_list, agents_list, model_list, record } = toRefs(props);
+const { visible, menu_list, record } = toRefs(props);
 
 const emit = defineEmits(['getActiveTab', 'close', 'ok']);
 
-const tabs = [
-  { key: "1", icon: "icon-menu", title: "菜单" },
-  { key: "2", icon: "icon-storage", title: "知识库" },
-  { key: "3", icon: "icon-robot", title: "智能体" },
-  { key: "4", icon: "icon-relation", title: "模型" }
-]
-const selected_tab_key = ref(tabs[0].key);
 
 // 组件内部状态
 // 默认展开第一节
-const expand_kdys = ref(['0']);
+const expand_keys = ref(['0']);
 
 const checked_menu = ref([]);
 const checked_menu_list = ref([]);
-const checked_knowledge = ref([]);
-const checked_knowledge_list = ref([]);
-const checked_agents = ref([]);
-const checked_agents_list = ref([])
-const checked_model = ref([]);
-const checked_model_list = ref([])
 
 
 // 递归取消所有子节点的选择
@@ -183,39 +107,6 @@ const onCheck = (newCheckedKeys, event) => {
   }
 };
 
-const onCheckboxCheck = (newCheckedKeys, event, collection) => {
-  let o = {
-    id: event.target.value,
-    name: event.target.labels[0].innerText,
-  };
-  if (event.target.checked) {
-    collection.value.push(o);
-  } else {
-    collection.value.forEach((val, idx, array) => {
-      if (val['id'] == event.target.value) {
-        collection.value.splice(idx, 1);
-        return true;
-      }
-    });
-  }
-};
-
-const onCheckKnowledge = (newCheckedKeys, event) => {
-  onCheckboxCheck(newCheckedKeys, event, checked_knowledge_list);
-
-};
-const onCheckAgents = (newCheckedKeys, event) => {
-  onCheckboxCheck(newCheckedKeys, event, checked_agents_list);
-};
-const onCheckModel = (newCheckedKeys, event) => {
-  onCheckboxCheck(newCheckedKeys, event, checked_model_list);
-};
-
-const handleTabChange = (key) => {
-  const currentTab = tabs.find(tab => tab.key === key);
-  emit('getActiveTab', currentTab);
-  selected_tab_key.value = key;
-};
 // 处理取消事件
 const handleCancel = () => {
   emit('cancel');
@@ -223,35 +114,25 @@ const handleCancel = () => {
 
 // 处理确认事件
 const editDeptHandleOk = () => {
-  emit('ok', {
-    checkedKeys: {
-      menu: checked_menu.value,
-      knowledge: checked_knowledge.value,
-      agents: checked_agents.value,
-      model: checked_model.value
-    }
-  });
+  emit('ok', checked_menu.value);
 };
 
-const getCurrentTabTitle = computed(() => {
-  const currentTab = tabs.find(tab => tab.key === selected_tab_key.value);
-  return currentTab ? currentTab.title : '菜单';
-});
-
-onMounted(() => {
-  // 处理传入的部门数据
-  // TODO功能 回显
-  // if (record?.dept) {
-  //   record.dept.forEach((val) => {
-  //     checked_menu_list.value.push({
-  //       menuId: val.menuId,
-  //       menuName: val.menuName
-  //     });
-  //     checked_menu.value.push(val.menuId);
-  //     expand_kdys.value.push(val.menuId);
-  //   });
-  // }
 
+watch(() => props.record, (newVal) => {
+  if (newVal?.resources) {
+    newVal.resources.forEach((val) => {
+      checked_menu_list.value.push({
+        menuId: val.menuId,
+        menuName: val.menuName
+      });
+      checked_menu.value.push(val.menuId);
+      expand_keys.value.push(val.menuId);
+    });
+  } else {
+    checked_menu_list.value = [];
+    checked_menu.value = [];
+    expand_keys.value = ['0'];
+  }
 });
 </script>
 

+ 50 - 48
src/modules/permission/role/index.vue

@@ -23,13 +23,11 @@
     <RoleForm :edit_form="edit_form" :is_edit_mode="is_edit_mode" />
   </Modal>
 
-  <!-- TODO -->
-  <PermissionConfigModal :visible.sync="permission_config_visible" :menu_list="menu_list"
-    :knowledge_list="knowledge_list" :agents_list="agents_list" @getActiveTab="handlePermissionModalTab"
+  <PermissionConfigModal :visible.sync="permission_config_visible" :menu_list="menu_list" :record="current_record"
     @ok="handlePermissionConfigSave" @cancel="handlePermissionConfig(null, false)" />
 
-  <DeptConfigModal :visible.sync="dept_config_visible" :dept_list="dept_list" :record="current_record" @ok=""
-    @cancel="handleDeptConfig(null, false)" />
+  <DeptConfigModal :visible.sync="dept_config_visible" :dept_list="dept_list" :record="current_record"
+    @ok="handleDeptConfigSave" @cancel="handleDeptConfig(null, false)" />
 
 </template>
 
@@ -45,7 +43,7 @@ import DeptConfigModal from './DeptConfigModal.vue';
 
 import { QueryRoleList, RoleStatusSwitch, DeleteRole, CreateRole, UpdateRole } from '../../../apis/permission/role';
 import { QueryMenuTree } from '../../../apis/permission/resource';
-import { QueryAllKnowledgeList, QueryAllDialogList } from '../../../apis/permission/common';
+import { QueryDeptTree } from '../../../apis/permission/common';
 
 const keywords = ref('');
 // 表格相关
@@ -75,8 +73,7 @@ const edit_form = reactive({
 // 权限配置相关
 const permission_config_visible = ref(false);
 const menu_list = ref([]);
-const knowledge_list = ref([]);
-const agents_list = ref([]);
+
 
 // 部门配置相关
 const dept_config_visible = ref(false);
@@ -287,39 +284,32 @@ const handleEdit = (record, visible) => {
 const handlePermissionConfig = async (record, visible) => {
   if (record) {
     edit_form.roleId = record.roleId;
-    getConfigList('1');
+    current_record.value = record;
   }
   permission_config_visible.value = visible;
 }
 
-const handlePermissionModalTab = (tab) => {
-  if (tab.key) getConfigList(tab.key);
-}
-
-const handlePermissionConfigSave = async (data) => {
+const handlePermissionConfigSave = async (checked_menu) => {
   permission_config_visible.value = false;
-  console.log('data', data)
-  const { menu, knowledge, agents, model } = data.checkedKeys;
-  // TODO询问 接口
-  // const params = {
-  //   roleId: edit_form.roleId,
-  //   menuIds: menu_list.value.map((item) => item.menuId).join(','),
-  //   knowledgeIds: knowledge_list.value.map((item) => item.knowledgeId).join(','),
-  //   agentIds: agents_list.value.map((item) => item.agentId).join(','),
-  // };
-  // const { code } = await UpdateRole(params);
-  // if (code === 200) {
-  //   Message.success({
-  //     title: '权限配置',
-  //     content: '权限配置成功',
-  //   });
-  // }
+  const params = {
+    roleId: edit_form.roleId,
+    menuIds: checked_menu,
+    editType: 2,
+  };
+  const { code } = await UpdateRole(params);
+  if (code === 200) {
+    Message.success({
+      title: '权限配置',
+      content: '权限配置成功',
+    });
+  }
 }
 
 // 部门配置
 const handleDeptConfig = async (record, visible) => {
   if (record) {
-    // current_record.value = record;
+    edit_form.roleId = record.roleId;
+    current_record.value = record;
     // const { code, data: { rows } } = await QueryUserDept(record.roleId);
     // if (code === 200) {
     //   console.log('rows', rows)
@@ -329,6 +319,22 @@ const handleDeptConfig = async (record, visible) => {
   dept_config_visible.value = visible;
 }
 
+const handleDeptConfigSave = async (dept_ids) => {
+  dept_config_visible.value = false;
+  const params = {
+    roleId: edit_form.roleId,
+    depts: dept_ids,
+    editType: 3,
+  };
+  const { code } = await UpdateRole(params);
+  if (code === 200) {
+    Message.success({
+      title: '部门配置',
+      content: '部门配置成功',
+    });
+  }
+}
+
 // 删除用户
 const handleDelete = async (roleId) => {
   const { code } = await DeleteRole(roleId);
@@ -366,29 +372,25 @@ const tableSizeChange = (size) => {
   table_size.value = size;
 }
 
-const getConfigList = async (tabsKey) => {
-  if (tabsKey === '1') {
-    const { code, data: { rows } } = await QueryMenuTree();
-    if (code === 200) {
-      menu_list.value = rows;
-    }
-  }
-  if (tabsKey === '2') {
-    const { code, data: { rows } } = await QueryAllKnowledgeList();
-    if (code === 200) {
-      knowledge_list.value = rows;
-    }
+// 获取菜单树
+const getMenuTree = async () => {
+  const { code, data: { rows } } = await QueryMenuTree();
+  if (code === 200) {
+    menu_list.value = rows;
   }
-  if (tabsKey === '3') {
-    const { code, data: { rows } } = await QueryAllDialogList();
-    if (code === 200) {
-      agents_list.value = rows;
-    }
+}
+// 获取部门树
+const getDeptTree = async () => {
+  const { code, data: { rows } } = await QueryDeptTree();
+  if (code == 200) {
+    dept_list.value = rows;
   }
 }
 
 onMounted(() => {
   gerRoleList()
+  getMenuTree()
+  getDeptTree()
 })
 </script>
 

+ 4 - 1
src/views/PermissionResource.vue

@@ -1,11 +1,14 @@
 <template>
   <ContentContainer>
     <BreadCrumbMenu :current_label="'资源'" />
-    <div class="permission-resource">权限管理: 资源</div>
+
+    <ResourcePage />
   </ContentContainer>
 </template>
 
 <script setup>
 import ContentContainer from './layout/ContentContainer.vue';
 import BreadCrumbMenu from './common/BreadCrumbMenu.vue';
+
+import ResourcePage from '../modules/permission/resource/index.vue';
 </script>