Browse Source

添加权限

yangg 1 day ago
parent
commit
43ad5c4929
3 changed files with 290 additions and 0 deletions
  1. BIN
      src/assets/lock.png
  2. 288 0
      src/components/PermissionConfig/index.vue
  3. 2 0
      src/views/report.vue

BIN
src/assets/lock.png


+ 288 - 0
src/components/PermissionConfig/index.vue

@@ -0,0 +1,288 @@
+<template>
+  <div class="permission-config">
+    <div class="config-header" @click="togglePanel">
+      <img src="../../assets/lock.png" alt="permission" class="config-icon" />
+      <span>权限配置</span>
+      <img
+        :src="isPanelOpen ? upIcon : downIcon"
+        alt="toggle"
+        class="toggle-icon"
+      />
+    </div>
+    
+    <div v-show="isPanelOpen" class="config-panel">
+      <div class="permission-list">
+        <div class="permission-group" v-for="group in permissionGroups" :key="group.label">
+          <div class="group-header"> 
+            <a-checkbox :value="group.value"
+            :checked="getParentChecked(group)" 
+            @change="(e) => handleParentChange(group, e)">
+                  {{ group.label }}
+                </a-checkbox>
+            </div>
+          <div class="checkbox-list">
+            <a-checkbox-group v-model:value="selectedPermissions[group.key]">
+              <div v-for="item in group.items" :key="item.value" class="checkbox-item">
+                <a-checkbox :value="item.value">
+                  {{ item.label }}
+                  <span class="item-desc">{{ item.description }}</span>
+                </a-checkbox>
+              </div>
+            </a-checkbox-group>
+          </div>
+        </div>
+      </div>
+
+      <div class="action-buttons">
+        <a-button type="primary" :loading="saving" @click="saveConfig">
+          保存配置
+        </a-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { message } from 'ant-design-vue';
+import axios from 'axios';
+import upIcon from '@/assets/svg/ups.svg';
+import downIcon from '@/assets/svg/down.svg';
+
+// 计算父级选中状态
+const getParentChecked = (group) => {
+  if (!selectedPermissions[group.key] || !group.items || group.items.length === 0) {
+    return false;
+  }
+  // 如果所有子项都被选中,则父级也选中
+  return group.items.every(item => 
+    selectedPermissions[group.key].includes(item.value)
+  );
+};
+// 处理父级选中状态变化
+const handleParentChange = (parent, e) => {
+  const checked = e.target.checked;
+  // 获取当前组的选中状态数组
+  if (!selectedPermissions[parent.key]) {
+    selectedPermissions[parent.key] = [];
+  }
+  
+  // 如果父级被选中,将所有子项添加到选中数组
+  if (checked) {
+    selectedPermissions[parent.key] = parent.items.map(item => item.value);
+  } else {
+    // 如果父级取消选中,清空该组的选中数组
+    selectedPermissions[parent.key] = [];
+  }
+};
+
+// 权限组数据
+const permissionGroups = ref([]);
+const isPanelOpen = ref(false);
+const saving = ref(false);
+
+// 用于存储每个权限组的选中状态
+const selectedPermissions = reactive({});
+
+const togglePanel = () => {
+  isPanelOpen.value = !isPanelOpen.value;
+};
+
+const saveConfig = async () => {
+  saving.value = true;
+  try {
+    // 保存配置到 localStorage
+    localStorage.setItem('permissionConfig', JSON.stringify(selectedPermissions));
+    message.success('权限配置保存成功');
+  } catch (error) {
+    message.error('权限配置保存失败');
+  } finally {
+    saving.value = false;
+  }
+};
+
+// 初始化配置
+const initConfig = () => {
+  const savedConfig = localStorage.getItem('permissionConfig');
+  if (savedConfig) {
+    const config = JSON.parse(savedConfig);
+    Object.keys(config).forEach(key => {
+      selectedPermissions[key] = config[key];
+    });
+  }
+};
+
+// 获取权限列表
+const fetchPermissionGroups = async () => {
+  try {
+    const response = await axios.get(`https://backend.qicai321.com/api/system/role_menu_button_permission/get_role_menu/?roleId=5`,{
+      headers: {
+        'authorization': `JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzg2Njg0Nzk0LCJpYXQiOjE3NTUxNDg3OTQsImp0aSI6IjdlYTI0Yzg2N2IzNTQ5NDA5Y2RlZGM1NGI5MGMxYWQzIiwidXNlcl9pZCI6MX0._yM1AMRyxVyf2J2-Kz9PlAErkXhEV5bfz9hBVkIg6OQ`
+      }
+    });
+    console.log(response);
+    // 构建权限树
+    const buildPermissionTree = (permissions) => {
+      // 创建一个映射表,用于快速查找权限项
+      const permMap = {};
+      permissions.forEach(perm => {
+        permMap[perm.id] = {
+          label: perm.name,
+          value: perm.id,
+          is_catalog: perm.is_catalog,
+          isCheck: perm.isCheck,
+          children: []
+        };
+      });
+
+      // 构建树形结构
+      const tree = [];
+      permissions.forEach(perm => {
+        const currentNode = permMap[perm.id];
+        if (perm.parent === null) {
+          // 如果没有父节点,则为根节点
+          tree.push(currentNode);
+        } else {
+          // 如果有父节点,将当前节点添加到父节点的children中
+          const parentNode = permMap[perm.parent];
+          if (parentNode) {
+            parentNode.children.push(currentNode);
+          }
+        }
+      });
+
+      return tree;
+    };
+
+    // 处理权限数据
+    const permissionTree = buildPermissionTree(response.data.data);
+    
+    // 转换为组件所需的数据格式
+    const groupsData = permissionTree.map(node => ({
+      label: node.label,
+      key: node.value,
+      is_catalog: node.is_catalog,
+      value: node.isCheck,
+
+      items: node.children.map(child => ({
+        label: child.label,
+        value: child.value,
+        is_catalog: child.is_catalog,
+        isCheck: child.isCheck
+      }))
+    }));
+
+    permissionGroups.value = groupsData;
+    
+    // 初始化选中状态对象
+    permissionGroups.value.forEach(group => {
+      if (!selectedPermissions[group.key]) {
+        selectedPermissions[group.key] = [];
+      }
+    });
+  } catch (error) {
+    message.error('获取权限信息失败');
+    console.error('获取权限信息失败:', error);
+  }
+};
+
+// 组件挂载时获取数据
+onMounted(async () => {
+  await fetchPermissionGroups();
+  initConfig();
+});
+</script>
+
+<style scoped>
+.permission-config {
+  border-top: 1px solid rgba(0, 0, 0, 0.06);
+  background: var(--secondary-bg);
+  color: var(--primary-text);
+}
+
+.config-header {
+  padding: 12px 20px;
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  cursor: pointer;
+  transition: background-color 0.2s;
+}
+
+.config-header:hover {
+  background: rgba(0, 0, 0, 0.02);
+}
+
+.config-icon {
+  width: 16px;
+  height: 16px;
+}
+
+.toggle-icon {
+  width: 12px;
+  height: 12px;
+  margin-left: auto;
+}
+
+.config-panel {
+  padding: 12px 20px;
+  border-top: 1px solid rgba(0, 0, 0, 0.06);
+}
+
+.permission-list {
+  margin-bottom: 16px;
+  height: 450px;
+    overflow: auto;
+}
+
+.permission-group {
+  margin-bottom: 16px;
+}
+
+.permission-group:last-child {
+  margin-bottom: 0;
+}
+
+.group-header {
+  font-size: 13px;
+  color: var(--primary-text);
+  margin-bottom: 8px;
+}
+
+.checkbox-list {
+margin-left: 14px;
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+.checkbox-item {
+  display: flex;
+  align-items: flex-start;
+}
+
+.item-desc {
+  margin-left: 8px;
+  font-size: 12px;
+  color: var(--primary-text);
+}
+
+.action-buttons {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 16px;
+}
+
+:deep(.ant-checkbox-wrapper) {
+  font-size: 14px;
+}
+
+:deep(.ant-checkbox-group) {
+  width: 100%;
+  flex-direction: column;
+}
+
+:deep(.ant-checkbox-wrapper + .ant-checkbox-wrapper) {
+  margin-left: 0;
+}
+</style>

+ 2 - 0
src/views/report.vue

@@ -97,6 +97,7 @@
 
       <!-- 添加模型配置和语音配置的容器 -->
       <div class="config-container">
+        <PermissionConfig/>
         <KnowledgeConfig />
         <ModelConfig />
         <VoiceConfig />
@@ -808,6 +809,7 @@ import ModelConfig from "../components/ModelConfig/index.vue";
 import SearchResults from "../components/SearchResults/index.vue";
 import VoiceConfig from "../components/VoiceConfig/index.vue";
 import KnowledgeConfig from "../components/KnowledgeConfig/index.vue";
+import PermissionConfig from "../components/PermissionConfig/index.vue";
 import ExportButton from "../components/ExportButton/index.vue";
 import dayjs from 'dayjs';
 import DocumentPreview from "../components/DocumentPreview/index.vue";