فهرست منبع

删除多个无效的图片资源,更新表格列宽、状态和操作列的固定属性,调整页面高度,重构权限路由的访问逻辑,新增图标选择功能,更新一些组件的样式及逻辑,并删除不再使用的上传组件。

张涛 1 سال پیش
والد
کامیت
1bea5075d1

BIN
src/assets/header-agent-1.png


BIN
src/assets/header-agent-2.png


BIN
src/assets/header-huihua-1.png


BIN
src/assets/header-huihua-2.png


BIN
src/assets/header-moxingguanli-1.png


BIN
src/assets/header-moxingguanli-2.png


BIN
src/assets/header-zhishiku-1.png


BIN
src/assets/header-zhishiku-2.png


+ 11 - 12
src/modules/permission/account/index.vue

@@ -58,12 +58,12 @@ const keywords = ref('');
 // 表格相关
 const table_data = ref([]);
 const table_columns = ref([
-  { title: '序号', slotName: 'index' },
-  { title: '用户名', dataIndex: 'userName', titleSlotName: 'userName' },
-  { title: '角色', dataIndex: 'roleName', titleSlotName: 'roleName' },
-  { title: '所属部门', dataIndex: 'deptName', titleSlotName: 'deptName' },
-  { title: '状态', dataIndex: 'status', slotName: 'status' },
-  { title: '操作', dataIndex: 'operation', slotName: 'operationSlot' },
+  { title: '序号', width: 80, slotName: 'index' },
+  { title: '用户名', dataIndex: 'userName', width: 150, titleSlotName: 'userName' },
+  { title: '角色', dataIndex: 'roleName', width: 400, titleSlotName: 'roleName' },
+  { title: '所属部门', dataIndex: 'deptName', width: 600, titleSlotName: 'deptName' },
+  { title: '状态', dataIndex: 'status', width: 100, slotName: 'status' },
+  { title: '操作', dataIndex: 'operation', fixed: 'right', slotName: 'operationSlot' },
 ]);
 const pagination_props = ref({
   total: 10,
@@ -111,11 +111,10 @@ const getUserList = async () => {
     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];
-          user.deptName += d.deptName + (i < user.dept.length - 1 ? ', ' : '');
+      if (user.depts) {
+        for (let i = 0; i < user.depts.length; i++) {
+          const d = user.depts[i];
+          user.deptName += d.deptName + (i < user.depts.length - 1 ? ', ' : '');
         }
       }
 
@@ -339,6 +338,6 @@ onMounted(() => {
 
 <style lang="css" scoped>
 .account-page-card {
-  height: calc(100% - 40px);
+  height: calc(100% - 56px);
 }
 </style>

+ 6 - 6
src/modules/permission/group/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <a-card class="account-page-card">
+  <a-card class="group-page-card">
     <Action :btn_text="$t('permission.group.createUserGroup')" :btn_permission="'system:group:add'"
       @searchClick="searchClick" @resetClick="resetClick" @createClick="createClick" @sizeChange="tableSizeChange"
       @refreshClick="refreshClick">
@@ -14,7 +14,7 @@
       <template #operationSlot="{ record }">
         <a-button v-hasPermi="'system:group:edit'" type="text" @click="handleEdit(record, true)">{{
           $t('permission.group.edit')
-          }}</a-button>
+        }}</a-button>
         <a-button v-hasPermi="'system:group:memberConfig'" type="text" @click="handleMembertConfig(record, true)">{{
           $t('permission.group.memberManagement') }}</a-button>
         <a-button v-hasPermi="'system:group:permissionConfig'" type="text"
@@ -65,9 +65,9 @@ const table_data = ref([]);
 const table_columns = ref([
   { title: t('permission.group.serialNumber'), width: 80, slotName: 'index' },
   { title: t('permission.group.groupName'), dataIndex: 'groupName', width: 150, titleSlotName: 'groupName' },
-  { title: t('permission.group.description'), dataIndex: 'description', ellipsis: true, tooltip: true, titleSlotName: 'description' },
+  { title: t('permission.group.description'), dataIndex: 'description', tooltip: true, titleSlotName: 'description' },
   { title: t('permission.group.status'), dataIndex: 'status', slotName: 'status' },
-  { title: t('permission.group.action'), dataIndex: 'operation', slotName: 'operationSlot' },
+  { title: t('permission.group.action'), dataIndex: 'operation', fixed: 'right', slotName: 'operationSlot' },
 ]);
 const pagination_props = ref({
   total: 10,
@@ -305,7 +305,7 @@ onMounted(() => {
 </script>
 
 <style lang="css" scoped>
-.account-page-card {
-  height: calc(100% - 40px);
+.group-page-card {
+  height: calc(100% - 56px);
 }
 </style>

+ 1 - 1
src/modules/permission/org/index.vue

@@ -203,7 +203,7 @@ onMounted(() => {
 .organization-container {
   display: flex;
   justify-content: space-between;
-  height: calc(100% - 40px);
+  height: calc(100% - 56px);
   width: 100%;
 }
 

+ 82 - 0
src/modules/permission/resource/IconPicker.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="icon-selector">
+    <div class="icon-box">
+      <a-popover trigger="click" position="right">
+        <component :is="modelValue" />
+
+        <template #content>
+          <a-scrollbar style="height:60vh;width: 45vw;overflow-y: auto;">
+            <div class="icons-grid">
+              <div v-for="(iconName, index) in iconsList" :key="index" @click="selectIcon(iconName)" class="icon-item">
+                <component :is="iconName" />
+                <span>{{ iconName }}</span>
+              </div>
+            </div>
+          </a-scrollbar>
+        </template>
+      </a-popover>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { toRefs } from 'vue';
+import arcoIconList from './arcoIcon.json';
+
+const props = defineProps({
+  modelValue: {
+    type: String,
+    default: '',
+  },
+});
+const { modelValue } = toRefs(props);
+
+const emit = defineEmits(['update:modelValue']);
+// 图标选择方法
+const iconsList = arcoIconList.iconsList || [];
+
+const selectIcon = (iconName) => {
+  emit('update:modelValue', iconName);
+}
+
+</script>
+
+<style scoped>
+.icon-selector {
+  /* 添加样式 */
+}
+
+svg {
+  font-size: 28px;
+}
+
+.icon-box {
+  height: 60px;
+  width: 60px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border-radius: 12px;
+  border: 1px solid #d9d9d9;
+  cursor: pointer;
+}
+
+.icons-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
+  gap: 1rem;
+}
+
+.icon-item {
+  display: flex;
+  cursor: pointer;
+  text-align: center;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+
+.icon-item:hover {
+  background-color: #f0f0f0;
+}
+</style>

+ 3 - 5
src/modules/permission/resource/ResourceForm.vue

@@ -16,8 +16,7 @@
       <a-input v-model="resource_form.path" />
     </a-form-item>
     <a-form-item field="icon" label="资源图标">
-      <Upload :action="uploadAction" :limit="1" :url="resource_form.icon" @update:fileList="updateFileList"
-        @success="handleSuccess"></Upload>
+      <IconPicker v-model="resource_form.icon" />
     </a-form-item>
     <a-form-item field="menuType" label="资源类型" :rules="[{ required: true, message: '资源类型必填' }]">
       <a-select v-model="resource_form.menuType" :options="options" :field-names="fieldNames"
@@ -44,9 +43,8 @@
 
 <script setup>
 import { ref, toRefs } from 'vue';
-import Upload from './Upload.vue';
-// TODO 图标上传功能待实现
-const uploadAction = '/api/v1/llm/upload'; // 替换为你的上传API
+import IconPicker from './IconPicker.vue';
+
 const fileList = ref([]);
 const imageUrls = ref([]);
 

+ 0 - 72
src/modules/permission/resource/Upload.vue

@@ -1,72 +0,0 @@
-<template>
-  <a-upload v-model:fileList="fileList" list-type="picture-card" :limit="limit" :action="action" @change="handleChange"
-    @before-remove="beforeRemove" image-preview />
-</template>
-
-<script setup>
-import { computed, ref, onMounted, watch, watchEffect } from 'vue';
-
-const props = defineProps({
-  limit: {
-    type: Number,
-    default: 1,
-  },
-  action: String, // 上传的服务器地址
-  url: String, //回显的文件地址
-});
-
-const emit = defineEmits(['fileListChange', 'fileListRemove', 'success']);
-const urls = computed(() => props.url);
-const fileList = ref([]);
-
-watch(
-  () => props.url,
-  (newVal) => {
-    if (newVal) {
-      fileList.value = newVal.split(',').map((item) => ({
-        uid: item,
-        name: item,
-        status: 'done',
-        url: item,
-      }));
-    }
-  },
-  {
-    deep: true, // 开启深度监听
-  }
-);
-
-onMounted(() => {
-  if (urls.value) {
-    fileList.value = urls.value.split(',').map((item) => ({
-      uid: item,
-      name: item,
-      status: 'done',
-      url: item,
-    }));
-  }
-
-  // console.log(
-  //   window.location.origin,
-  //   import.meta.env.VITE_API_BASE_URL,
-  //   8988
-  // );
-});
-
-// console.log(urls.value, 8988);
-const beforeRemove = (file) => {
-  emit('fileListRemove');
-  fileList.value = [];
-};
-
-const handleChange = (fileList) => {
-  emit('fileListChange', fileList);
-  const successFiles = fileList.filter((item) => item.status === 'done');
-  if (successFiles.length > 0) {
-    emit(
-      'success',
-      successFiles.map((item) => item.response.data)
-    );
-  }
-};
-</script>

+ 84 - 0
src/modules/permission/resource/arcoIcon.json

@@ -0,0 +1,84 @@
+{
+  "iconsList": [
+    "iconVoice",
+    "IconSunFill",
+    "IconApps",
+    "IconArchive",
+    "IconBarChart",
+    "IconBook",
+    "IconBookmark",
+    "IconBranch",
+    "IconBug",
+    "IconBulb",
+    "IconCalendar",
+    "IconCamera",
+    "IconCloud",
+    "IconCommand",
+    "IconCommon",
+    "IconCompass",
+    "IconComputer",
+    "IconCopyright",
+    "IconDashboard",
+    "IconDesktop",
+    "IconDice",
+    "IconDriveFile",
+    "IconEar",
+    "IconEmail",
+    "IconEmpty",
+    "IconExperiment",
+    "IconFileAudio",
+    "IconFileImage",
+    "IconFilePdf",
+    "IconFileVideo",
+    "IconFile",
+    "IconFire",
+    "IconFolderAdd",
+    "IconFolderDelete",
+    "IconFolder",
+    "IconGift",
+    "IconIdcard",
+    "IconImageClose",
+    "IconImage",
+    "IconInteraction",
+    "IconLanguage",
+    "IconLayers",
+    "IconLayout",
+    "IconLocation",
+    "IconLock",
+    "IconLoop",
+    "IconMan",
+    "IconMenu",
+    "IconMobile",
+    "IconMoon",
+    "IconMosaic",
+    "IconNav",
+    "IconPalette",
+    "IconPen",
+    "IconPhone",
+    "IconPrinter",
+    "IconPublic",
+    "IconPushpin",
+    "IconQrcode",
+    "IconRelation",
+    "IconRobotAdd",
+    "IconRobot",
+    "IconSafe",
+    "IconSchedule",
+    "IconShake",
+    "IconSkin",
+    "IconStamp",
+    "IconStorage",
+    "IconSun",
+    "IconTag",
+    "IconTags",
+    "IconThunderbolt",
+    "IconTool",
+    "IconTrophy",
+    "IconUnlock",
+    "IconUserAdd",
+    "IconUserGroup",
+    "IconUser",
+    "IconVideoCamera",
+    "IconWifi"
+  ]
+}

+ 1 - 2
src/modules/permission/resource/index.vue

@@ -179,7 +179,7 @@ onMounted(() => {
 .organization-container {
   display: flex;
   justify-content: space-between;
-  height: calc(100% - 40px);
+  height: calc(100% - 56px);
   width: 100%;
 }
 
@@ -187,7 +187,6 @@ onMounted(() => {
   width: 30%;
   height: 100%;
   background-color: #fff;
-  /* TODO优化 使用滚动组件 */
   overflow-y: auto;
 }
 

+ 4 - 3
src/modules/permission/role/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <a-card class="account-page-card">
+  <a-card class="role-page-card">
     <Action :btn_text="'新建角色'" :btn_permission="'system:role:add'" @searchClick="searchClick" @resetClick="resetClick"
       @createClick="createClick" @sizeChange="tableSizeChange" @refreshClick="refreshClick"></Action>
     <DataTable :data="table_data" :columns="table_columns" row-key="roleId" :size="table_size" :loading="table_loading"
@@ -189,6 +189,7 @@ const handleDeptConfig = async (record, visible) => {
     edit_form.roleId = record.roleId;
     current_record.value = record;
   }
+
   dept_config_visible.value = visible;
 };
 
@@ -278,7 +279,7 @@ onMounted(() => {
 </script>
 
 <style lang="css" scoped>
-.account-page-card {
-  height: calc(100% - 40px);
+.role-page-card {
+  height: calc(100% - 56px);
 }
 </style>

+ 24 - 20
src/router/guard.js

@@ -1,29 +1,33 @@
 import router from './index';
 import { kuky_Authorization } from '../base/storage';
-import { firstPage, accessRoutes } from '../utils/permission';
+import { firstPage, accessFlatRoutes } from '../utils/permission';
 
-// /** 免登录白名单 */
-const whiteList = ['/login', '/reg'];
+/** 免验证白名单 */
+const whiteList = ['/login', '/reg', '/noPer'];
+
+// 导入所需的模块
 router.beforeEach((to, from, next) => {
-  if (kuky_Authorization.get()) {
-    next();
-    // TODO无权限页面
-    // if (to.path === '/login') {
-    //   next({ path: firstPage });
-    // } else if (!accessRoutes.some((route) => route.path === to.path)) {
-    //   console.log('无权限访问');
-    //   next({ path: '/noPer' }); // 如果访问的路由不在accessRoutes中,则去无权限页面
-    // } else {
-    //   next();
-    // }
+  const isAuthorized = kuky_Authorization.get();
+
+  const isLoginPage = to.path === '/login';
+  const isInWhiteList = whiteList.includes(to.path);
+  const hasAccess = accessFlatRoutes.some((route) => route.path === to.path);
+  // 用户已授权的情况
+  if (isAuthorized) {
+    if (isLoginPage) {
+      next({ path: firstPage }); // 已登录用户访问登录页,重定向到首页
+    } else if (!hasAccess && !isInWhiteList) {
+      // 无权限访问且不在白名单中,重定向到无权限页面
+      next({ path: '/noPer' });
+    } else {
+      next(); // 其他情况,正常访问
+    }
   } else {
-    // 如果没有 Token
-    if (whiteList.includes(to.path)) {
-      // 如果在免登录的白名单中,则允许进入
-      next();
+    // 用户未授权的情况
+    if (isInWhiteList) {
+      next(); // 在免登录白名单中,允许进入
     } else {
-      // 其他没有访问权限的页面将被重定向到登录页面
-      next('/login');
+      next('/login'); // 否则重定向到登录页面
     }
   }
 });

+ 2 - 1
src/router/index.js

@@ -1,9 +1,10 @@
 import { createRouter, createWebHashHistory } from 'vue-router';
 import { systemRoutes } from './route';
 import { accessRoutes } from '../utils/permission';
+
 const router = createRouter({
   history: createWebHashHistory(),
-  routes: [...systemRoutes],
+  routes: [...systemRoutes, ...accessRoutes],
   scrollBehavior: () => ({ left: 0, top: 0 })
 });
 

+ 44 - 42
src/router/route.js

@@ -9,46 +9,48 @@ export const systemRoutes = [
   // 登录与注册 白名单页面
   { path: '/login', component: () => import('../views/Login.vue') },
   { path: '/reg', component: () => import('../views/Register.vue') },
-  { path: '/noPer', component: () => import('../views/NoPer.vue') },
-
-  // 会话
-  // { path: '/chat', redirect: '/chat/qa' },
-  { path: '/chat', component: () => import('../views/Conversation.vue') },
-  { path: '/chat/qa', component: () => import('../views/ConversationQA.vue') },
-  { path: '/chat/history', component: () => import('../views/ConversationHistory.vue') },
-  { path: '/chat/board', component: () => import('../views/ConversationBoard.vue') },
-
-  // // 知识库
-  { path: '/knowledge', component: () => import('../views/Knowledge.vue') },
-  { path: '/knowledge/detail', component: () => import('../views/KnowledgeDetail.vue') },
-  // 模型
-  { path: '/model', component: () => import('../views/Model.vue') },
-  // Agent
-  { path: '/agent', component: () => import('../views/Agent.vue') },
-  // 智能体
-  { path: '/intelligent', component: () => import('../views/Intelligent.vue') },
-  // dify智能体详情
-  { path: '/intelligent/detail', component: () => import('../views/difyDetail.vue') },
-
-  // 权限管理
-  {
-    path: '/permission',
-    component: () => import('../views/layout/LayoutPermission.vue'),
-    children: [
-      { path: '/permission/account', component: () => import('../views/PermissionAccount.vue') },
-      { path: '/permission/org', component: () => import('../views/PermissionOrganization.vue') },
-      { path: '/permission/resource', component: () => import('../views/PermissionResource.vue') },
-      { path: '/permission/role', component: () => import('../views/PermissionRole.vue') },
-      { path: '/permission/group', component: () => import('../views/PermissionGroup.vue') }
-    ]
-  },
-
-  // 个人中心
-  { path: '/profile', component: () => import('../views/Profiles.vue') },
-  { path: '/setting', component: () => import('../views/Settings.vue') },
-
-  { path: '/xiaoshu', component: () => import('../views/Xiaoshu.vue') },
-
-  { path: '/ragchat', component: () => import('../views/RagFlowChat.vue') },
-  { path: '/about', component: () => import('../views/About.vue') }
+
+  // 错误页面
+  { path: '/noPer', component: () => import('../views/NoPer.vue') }
+
+  // // 会话
+  // // { path: '/chat', redirect: '/chat/qa' },
+  // { path: '/chat', component: () => import('../views/Conversation.vue') },
+  // { path: '/chat/qa', component: () => import('../views/ConversationQA.vue') },
+  // { path: '/chat/history', component: () => import('../views/ConversationHistory.vue') },
+  // { path: '/chat/board', component: () => import('../views/ConversationBoard.vue') },
+
+  // // // 知识库
+  // { path: '/knowledge', component: () => import('../views/Knowledge.vue') },
+  // { path: '/knowledge/detail', component: () => import('../views/KnowledgeDetail.vue') },
+  // // 模型
+  // { path: '/model', component: () => import('../views/Model.vue') },
+  // // Agent
+  // { path: '/agent', component: () => import('../views/Agent.vue') },
+  // // 智能体
+  // { path: '/intelligent', component: () => import('../views/Intelligent.vue') },
+  // // dify智能体详情
+  // { path: '/intelligent/detail', component: () => import('../views/difyDetail.vue') },
+
+  // // 权限管理
+  // {
+  //   path: '/permission',
+  //   component: () => import('../views/layout/LayoutPermission.vue'),
+  //   children: [
+  //     { path: '/permission/account', component: () => import('../views/PermissionAccount.vue') },
+  //     { path: '/permission/org', component: () => import('../views/PermissionOrganization.vue') },
+  //     { path: '/permission/resource', component: () => import('../views/PermissionResource.vue') },
+  //     { path: '/permission/role', component: () => import('../views/PermissionRole.vue') },
+  //     { path: '/permission/group', component: () => import('../views/PermissionGroup.vue') }
+  //   ]
+  // },
+
+  // // 个人中心
+  // { path: '/profile', component: () => import('../views/Profiles.vue') },
+  // { path: '/setting', component: () => import('../views/Settings.vue') },
+
+  // { path: '/xiaoshu', component: () => import('../views/Xiaoshu.vue') },
+
+  // { path: '/ragchat', component: () => import('../views/RagFlowChat.vue') },
+  // { path: '/about', component: () => import('../views/About.vue') }
 ];

+ 21 - 0
src/utils/permission.js

@@ -18,6 +18,7 @@ export const hasPermission = (str) => {
     return false;
   }
 };
+// 格式化路由数据
 export const formatRoutes = (data) => {
   const routes = [];
 
@@ -58,11 +59,31 @@ export const formatRoutes = (data) => {
 
   return routes;
 };
+
+// 扁平化路由数据
+export const flattenRoutes = (routes) => {
+  let flatRoutes = [];
+
+  function recurse(routeList) {
+    routeList.forEach((route) => {
+      flatRoutes.push(route);
+      if (route.children) {
+        recurse(route.children);
+      }
+    });
+  }
+
+  recurse(routes);
+  return flatRoutes;
+};
+
 // 获取有权限的路由
 const routesList = JSON.parse(localST_RoutesList.getItem());
 const formattedRoutes = formatRoutes(routesList);
 export const accessRoutes = formattedRoutes;
 
+export const accessFlatRoutes = flattenRoutes(accessRoutes);
+
 // 获取有权限的第一个路由
 const firstRoute = (() => {
   let page;

+ 22 - 12
src/views/NoPer.vue

@@ -1,23 +1,33 @@
 <template>
-  <a-result status="warning" title="抱歉,您无权限访问此页面">
-    <template #subtitle>
-      您没有权限访问此页面,请联系管理员
-    </template>
+  <div class="no-per">
+    <a-result status="warning" title="抱歉,您无权限访问此页面">
+      <template #subtitle>
+        您没有权限访问此页面,请联系管理员
+      </template>
 
-    <template #extra>
-      <a-space>
-        <a-button type='primary' @click="handleBack">返回</a-button>
-      </a-space>
-    </template>
-  </a-result>
+      <template #extra>
+        <a-space>
+          <a-button type='primary' @click="handleBack">返回首页</a-button>
+        </a-space>
+      </template>
+    </a-result>
+  </div>
 </template>
 
 <script setup>
 import { useRouter } from 'vue-router';
-
+import { firstPage } from '../utils/permission';
 const router = useRouter();
 
 const handleBack = () => {
-  router.back();
+  router.push({ path: firstPage });
 }
 </script>
+<style lang="css" scoped>
+.no-per {
+  height: 90vh;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+</style>

+ 3 - 4
src/views/common/Header.vue

@@ -9,7 +9,7 @@
     <div class="header-center">
       <a-space>
         <div v-for="item in nav_list" :key="item.to">
-          <NavItem :label="$t(item.label)" :to="item.to" :icon_name="item.icon_name" />
+          <NavItem :label="$t(item.label)" :to="item.to" :icon="item.icon" />
         </div>
 
         <PermissionDropdownV1 :dropdown_list="dropdown_list" :label="$t('header.权限管理')" />
@@ -56,7 +56,6 @@ import BtnFullScreen from './header-btns/BtnFullScreen.vue';
 import BtnSettings from './header-btns/BtnSettings.vue';
 import BtnCurrentUser from './header-btns/BtnCurrentUser.vue';
 
-const currentUser = useCurrentUserStore();
 const nav_list = ref([]);
 const dropdown_list = ref([]);
 /**
@@ -84,7 +83,7 @@ const formatMenuItems = (list) => {
           return {
             label: `header.${item.meta.title}`,
             to: item.path,
-            icon_name: item.meta.icon || 'header-zhinengti' // 假设icon_name是根据name字段来命名的
+            icon: item.meta.icon || 'IconRobot' // 假设icon_name是根据name字段来命名的
           };
         }
       })
@@ -106,7 +105,7 @@ const formatPermissionItems = (permissionList) => {
 onMounted(() => {
   // 延迟渲染菜单,防止菜单渲染时还没获取到权限信息
   const routesList = JSON.parse(localST_RoutesList.getItem());
-
+  console.log('routesList', routesList)
   if (routesList && Array.isArray(routesList)) {
     nav_list.value = formatMenuItems(routesList);
     const permissionList = routesList.find((item) => item.meta.title === '权限管理');

+ 4 - 28
src/views/common/NavItem.vue

@@ -1,24 +1,21 @@
 <template>
   <router-link :to="to">
     <div class="nav-item" :class="{ 'is-active': is_active }">
-      <span class="nav-item-icon"><img :src="img_src" /></span>
+      <component class="nav-item-icon" :is="icon" />
       <span>{{ label }}</span>
     </div>
   </router-link>
 </template>
 
 <script setup>
-import { ref, computed } from 'vue';
+import { computed } from 'vue';
 import { useRoute } from 'vue-router';
 
-import { header_icon_map } from './header-icon-map';
-
 const props = defineProps({
   label: String,
   to: String,
-  icon_name: String
+  icon: String
 });
-
 const route = useRoute();
 const target = props.to;
 
@@ -55,21 +52,6 @@ const is_active = computed(() => {
   return cur_path === target;
 });
 
-const img_src = computed(() => {
-  const icon_name = props.icon_name;
-
-  if (is_active.value) {
-    if (icon_name in header_icon_map) {
-      return header_icon_map[icon_name].t2;
-    }
-
-    // 资源目录应该添加名为 2 的图标
-  } else {
-    if (icon_name in header_icon_map) {
-      return header_icon_map[icon_name].t1;
-    }
-  }
-});
 </script>
 
 <style lang="css" scoped>
@@ -101,14 +83,8 @@ const img_src = computed(() => {
 }
 
 .nav-item-icon {
-  display: flex;
-  justify-content: center;
-  align-items: center;
+  font-size: 22px;
 
   margin-right: 5px;
 }
-
-.nav-item-icon img {
-  width: 18px;
-}
 </style>

+ 0 - 34
src/views/common/header-icon-map.js

@@ -1,40 +1,6 @@
-import icon_huihua_1 from '../../assets/header-huihua-1.png';
-import icon_huihua_2 from '../../assets/header-huihua-2.png';
-import icon_zhishiku_1 from '../../assets/header-zhishiku-1.png';
-import icon_zhishiku_2 from '../../assets/header-zhishiku-2.png';
-import icon_moxingguanli_1 from '../../assets/header-moxingguanli-1.png';
-import icon_moxingguanli_2 from '../../assets/header-moxingguanli-2.png';
-import icon_agent_1 from '../../assets/header-agent-1.png';
-import icon_agent_2 from '../../assets/header-agent-2.png';
-import icon_zhinengti_1 from '../../assets/header-zhinengti-1.png';
-import icon_zhinengti_2 from '../../assets/header-zhinengti-2.png';
-
 import icon_quanxian_1 from '../../assets/header-quanxian-1.png';
 import icon_quanxian_2 from '../../assets/header-quanxian-2.png';
 
-export const header_icon_map = {
-  'header-huihua': {
-    t1: icon_huihua_1,
-    t2: icon_huihua_2
-  },
-  'header-zhishiku': {
-    t1: icon_zhishiku_1,
-    t2: icon_zhishiku_2
-  },
-  'header-moxingguanli': {
-    t1: icon_moxingguanli_1,
-    t2: icon_moxingguanli_2
-  },
-  'header-agent': {
-    t1: icon_agent_1,
-    t2: icon_agent_2
-  },
-  'header-zhinengti': {
-    t1: icon_zhinengti_1,
-    t2: icon_zhinengti_2
-  }
-};
-
 export const header_icon_quanxian = {
   t1: icon_quanxian_1,
   t2: icon_quanxian_2

+ 1 - 1
src/views/layout/ContentContainer.vue

@@ -14,7 +14,7 @@ const props = defineProps({
 .content-container {
   background-color: var(--color-fill-2);
   flex-grow: 1;
-  height: calc(100% - 80px);
+  height: calc(100% - 60px);
   padding: 16px;
   overflow-y: auto;
 }