Bläddra i källkod

feat(auth): 添加菜单权限标识及用户按钮权限控制

- 在表单规则中移除不再使用的用户名正则校验规则
- 新增菜单权限字段 `menuPerms` 的多语言支持(中英文)
- 路由模块中获取并存储用户按钮权限信息
- 类型声明文件中添加 `menuPerms` 字段定义
- 运费配置组件新增动态输入项删除功能,并优化数据处理逻辑
- 普通订单页面增加新的订单状态判断条件
- 用户管理页面集成权限控制,包括按钮和操作列的显示控制
- 菜单管理页面展示权限标识列,并调整部分渲染逻辑
- 角色管理抽屉中移除级联选择属性,优化提交日志输出
zhangtao 1 månad sedan
förälder
incheckning
5ef8003b80

+ 1 - 2
src/hooks/common/form.ts

@@ -1,13 +1,12 @@
 import { ref, toValue } from 'vue';
 import type { ComputedRef, Ref } from 'vue';
 import type { FormInst } from 'naive-ui';
-import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg';
+import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD } from '@/constants/reg';
 import { $t } from '@/locales';
 
 export function useFormRules() {
   const patternRules = {
     userName: {
-      pattern: REG_USER_NAME,
       message: $t('form.userName.invalid'),
       trigger: 'change'
     },

+ 2 - 1
src/locales/langs/en-us.ts

@@ -638,7 +638,8 @@ const local: App.I18n.Schema = {
         iconType: {
           iconify: 'Iconify Icon',
           local: 'Local Icon'
-        }
+        },
+        menuPerms: ''
       }
     }
   },

+ 1 - 0
src/locales/langs/zh-cn.ts

@@ -597,6 +597,7 @@ const local: App.I18n.Schema = {
         buttonCode: '按钮编码',
         buttonDesc: '按钮描述',
         menuStatus: '菜单状态',
+        menuPerms: '权限标识',
         form: {
           home: '请选择首页',
           menuType: '请选择菜单类型',

+ 2 - 0
src/store/modules/route/index.ts

@@ -240,6 +240,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
 
     if (!error) {
       const menu = convertMenuData({ menuList: data?.menuList });
+      const authBtn = data.authorities.map((it: any) => it.perms);
+      authStore.userInfo.buttons = authBtn;
       addAuthRoutes(menu);
 
       handleConstantAndAuthRoutes();

+ 1 - 0
src/typings/app.d.ts

@@ -760,6 +760,7 @@ declare namespace App {
             buttonCode: string;
             buttonDesc: string;
             menuStatus: string;
+            menuPerms: string;
             form: {
               home: string;
               menuType: string;

+ 9 - 3
src/views/config/fright-config/index.vue

@@ -39,6 +39,7 @@ const [registerForm, { getFieldsValue, validate, setFieldsValue }] = useForm({
               v-slots={(row: Options) => handleCreatInput(model, field, row)}
               onCreate={() => handleAdd()}
               max={ChannelOptions.value.length}
+              onRemove={handleRemove}
             ></NDynamicInput>
           </div>
         );
@@ -155,13 +156,18 @@ async function save() {
   isSubmit.value = false;
   getData();
 }
+function handleRemove(idx: number) {
+  const form = getFieldsValue();
+  const id = form.name[idx].channelId;
+  ChannelOptions.value.map(it => (it.id == id ? (it.disabled = false) : it));
+}
 async function handleGetChannelId(channelId: number, idx: number) {
   const res = await fetchGetTransport(channelId);
   const form = getFieldsValue();
   const newName = JSON.parse(JSON.stringify(form.name));
-  newName[idx].distance = res.data?.distance;
-  newName[idx].freightFee = res.data?.freightFee;
-  newName[idx].weight = res.data?.weight;
+  newName[idx].distance = res.data?.distance || null;
+  newName[idx].freightFee = res.data?.freightFee || null;
+  newName[idx].weight = res.data?.weight || null;
   setFieldsValue({ name: newName });
 }
 </script>

+ 2 - 1
src/views/delivery/normal-order/component/normal-modal.vue

@@ -111,7 +111,8 @@ function handleCopy() {
                 v-if="
                   orderInfo.hbOrderStatus == orderStatusEnum.WAIT_DELIVERY ||
                   orderInfo.hbOrderStatus == orderStatusEnum.ORDER_ACCEPT ||
-                  orderInfo.hbOrderStatus == orderStatusEnum.ORDER_DELIVERY
+                  orderInfo.hbOrderStatus == orderStatusEnum.ORDER_DELIVERY ||
+                  orderInfo.hbOrderStatus == orderStatusEnum.ORDER_WAIT_DELIVERY
                 "
               >
                 <div class="text-16px font-semibold">等待商家发货</div>

+ 1 - 0
src/views/delivery/normal-order/index.vue

@@ -174,6 +174,7 @@ const { columns, data, loading, getData, mobilePagination } = useNaivePaginatedT
               查看订单
             </n-button>
             {(row.hbOrderStatus == orderStatusEnum.WAIT_DELIVERY ||
+              row.hbOrderStatus == orderStatusEnum.ORDER_WAIT_DELIVERY ||
               row.hbOrderStatus == orderStatusEnum.ORDER_DELIVERY ||
               row.hbOrderStatus == orderStatusEnum.ORDER_DELIVERY) && (
               <n-button size="small" type="primary" quaternary onClick={() => handleDeivery(row)}>

+ 18 - 7
src/views/government/user-list/index.vue

@@ -10,11 +10,11 @@ import {
   fetchGetUserList
 } from '@/service/api/government/user-list';
 import { fetchGetAllChannelList } from '@/service/api/goods/store-goods';
+import { useAuth } from '@/hooks/business/auth';
 import { useTable } from '@/components/zt/Table/hooks/useTable';
 import { useModalFrom } from '@/components/zt/ModalForm/hooks/useModalForm';
 import { useModal } from '@/components/zt/Modal/hooks/useModal';
 import SVGIcon from '@/components/custom/svg-icon.vue';
-
 const importTemplateRef = useTemplateRef('importTemplateRef');
 const columns: NaiveUI.TableColumn<Api.government.userList>[] = [
   {
@@ -62,6 +62,7 @@ const columns: NaiveUI.TableColumn<Api.government.userList>[] = [
           uncheckedValue={0}
           checkedValue={1}
           value={row.status}
+          disabled={!useAuth().hasAuth('user:list:statusbtn')}
           onUpdate:value={val => {
             row.status = val;
             fetchEditUser(row);
@@ -104,7 +105,7 @@ const [registerTable, { refresh, setTableLoading }] = useTable({
   tableConfig: {
     keyField: 'userId',
     title: '员工列表',
-    showAddButton: true
+    showAddButton: useAuth().hasAuth('user:list:add')
   }
 });
 const [registerModalTable] = useTable({
@@ -116,7 +117,6 @@ const [registerModalTable] = useTable({
     minHeight: 400
   }
 });
-
 const failColumns: NaiveUI.TableColumn<Api.government.importRecordList>[] = [
   {
     key: 'index',
@@ -285,8 +285,17 @@ async function handleSubmitImport(file: File) {
   <LayoutTable>
     <ZTable :columns="columns" :api="fetchGetUserList" @register="registerTable" @add="openModal">
       <template #op="{ row }">
-        <NButton size="small" ghost type="primary" :disabled="Boolean(row.available)" @click="edit(row)">编辑</NButton>
-        <NPopconfirm @positive-click="handleDelete(row)">
+        <NButton
+          v-if="useAuth().hasAuth('user:list:edit')"
+          size="small"
+          ghost
+          type="primary"
+          :disabled="Boolean(row.available)"
+          @click="edit(row)"
+        >
+          编辑
+        </NButton>
+        <NPopconfirm v-if="useAuth().hasAuth('user:list:del')" @positive-click="handleDelete(row)">
           <template #trigger>
             <NButton size="small" type="error" ghost :disabled="Boolean(row.available)">删除</NButton>
           </template>
@@ -295,8 +304,10 @@ async function handleSubmitImport(file: File) {
       </template>
       <template #prefix>
         <NSpace>
-          <NButton size="small" @click="openImportModal">导入员工</NButton>
-          <NButton size="small" @click="openModalFail">导入记录</NButton>
+          <NButton v-if="useAuth().hasAuth('user:list:export')" size="small" @click="openImportModal">导入员工</NButton>
+          <NButton v-if="useAuth().hasAuth('user:list:exportRecord')" size="small" @click="openModalFail">
+            导入记录
+          </NButton>
         </NSpace>
       </template>
     </ZTable>

+ 15 - 3
src/views/manage/menu/index.vue

@@ -73,6 +73,12 @@ const colums: NaiveUI.TableColumn<InternalRowData>[] = [
       return <span>{row.name}</span>;
     }
   },
+  {
+    key: 'perms',
+    title: $t('page.manage.menu.menuPerms'),
+    align: 'center',
+    minWidth: 120
+  },
   {
     key: 'icon',
     title: $t('page.manage.menu.icon'),
@@ -96,7 +102,10 @@ const colums: NaiveUI.TableColumn<InternalRowData>[] = [
     key: 'url',
     title: $t('page.manage.menu.routePath'),
     align: 'center',
-    minWidth: 120
+    minWidth: 120,
+    render: (row: InternalRowData) => {
+      return <div>{row.type == 2 ? '' : row.url}</div>;
+    }
   },
   {
     key: 'hideInMenu',
@@ -136,7 +145,7 @@ const colums: NaiveUI.TableColumn<InternalRowData>[] = [
     fixed: 'right',
     render: (row: any) => (
       <div class="flex-center justify-end gap-8px">
-        {row.type == '0' && (
+        {row.type != 2 && (
           <NButton type="primary" ghost size="small" onClick={() => handleAddChildMenu(row)}>
             {$t('page.manage.menu.addChildMenu')}
           </NButton>
@@ -194,8 +203,10 @@ function handleEdit(item: Api.SystemManage.Menu) {
 function handleAddChildMenu(item: any) {
   operateType.value = 'addChild';
   showModal.value = true;
+  console.log(item, 'asdsadsa');
+
   nextTick(() => {
-    setFieldsValue({ parentId: item.menuId, url: item.url });
+    setFieldsValue({ parentId: item.menuId, url: item.url, type: item.type == 1 ? 2 : item.type });
   });
 }
 
@@ -203,6 +214,7 @@ async function getAllPages() {
   const { data } = await fetchGetMenuList();
   const menuData = buildMenuTree(data);
   menusData.value = menuData;
+  console.log(menusData.value, 'menusData.value');
 }
 
 function init() {

+ 1 - 3
src/views/manage/role/modules/role-operate-drawer.vue

@@ -4,7 +4,6 @@ import { fetchAddRoleMenu, fetchEditRoleMenu, fetchGetMenuList, fetchGetRoleMenu
 import { useFormRules, useNaiveForm } from '@/hooks/common/form';
 import { buildMenuTree } from '@/utils/zt';
 import { $t } from '@/locales';
-
 defineOptions({
   name: 'RoleOperateDrawer'
 });
@@ -80,7 +79,7 @@ function closeDrawer() {
 async function handleSubmit() {
   await validate();
   // request
-  console.log(checks.value);
+
   if (props.operateType == 'add') {
     await fetchAddRoleMenu({ ...model.value, menuIdList: checks.value });
   } else {
@@ -137,7 +136,6 @@ watch(visible, () => {
         class="h-280px"
         label-field="name"
         key-field="menuId"
-        cascade
       />
       <template #footer>
         <NSpace :size="16">