Quellcode durchsuchen

perf(系统模块): 用户管理完善启用停用功能,支持按租户启用停用

shizhongming vor 2 Jahren
Ursprung
Commit
6d05616390

+ 5 - 5
src/components/SmartTable/src/hooks/useSmartTable.ts

@@ -118,7 +118,7 @@ export const useSmartTable = (
     deleteByCheckbox: () => {
       getTableAction().deleteByCheckbox();
     },
-    getCheckboxRecords: (isFull: boolean) => {
+    getCheckboxRecords: (isFull?: boolean) => {
       return getTableAction().getCheckboxRecords(isFull);
     },
     getRadioRecord: (isFull: boolean) => {
@@ -163,11 +163,11 @@ export const useSmartTable = (
     getData: (rowIndex?: number) => {
       return getTableAction().getData(rowIndex);
     },
-    useYnByCheckbox: (useYn: boolean) => {
-      return getTableAction().useYnByCheckbox(useYn);
+    useYnByCheckbox: (useYn: boolean, params?: Recordable) => {
+      return getTableAction().useYnByCheckbox(useYn, params);
     },
-    useYnByRow: (row: any | any[], useYn: boolean) => {
-      return getTableAction().useYnByRow(row, useYn);
+    useYnByRow: (row: any | any[], useYn: boolean, params?: Recordable) => {
+      return getTableAction().useYnByRow(row, useYn, params);
     },
   };
   return [register, methods];

+ 10 - 6
src/components/SmartTable/src/hooks/useTableAjax.ts

@@ -213,23 +213,27 @@ export const useTableAjax = (
     });
   };
 
-  const useYnByCheckbox = async (useYn: boolean) => {
+  const useYnByCheckbox = async (useYn: boolean, params?: Recordable) => {
     const rows = getCheckboxRecords(false);
     if (!rows.length) {
       warnMessage(t('common.notice.select'));
       return false;
     }
-    return doUseYn(rows, useYn);
+    return doUseYn(rows, useYn, params);
   };
 
-  const useYnByRow = (row: any | any[], useYn: boolean) => {
+  const useYnByRow = (row: any | any[], useYn: boolean, params?: Recordable) => {
     if (isArray(row)) {
       return doUseYn(row, useYn);
     }
-    return doUseYn([row], useYn);
+    return doUseYn([row], useYn, params);
   };
 
-  const doUseYn = async (rows: any[], useYn: boolean): Promise<boolean | undefined> => {
+  const doUseYn = async (
+    rows: any[],
+    useYn: boolean,
+    params?: Recordable,
+  ): Promise<boolean | undefined> => {
     const proxyConfig = unref(propsRef)?.proxyConfig;
     const useYnMethod = proxyConfig?.ajax?.useYn;
     if (!useYnMethod) {
@@ -243,7 +247,7 @@ export const useTableAjax = (
       iconType: 'warning',
       content: useYn ? t('common.notice.useYnTrueConfirm') : t('common.notice.useYnFalseConfirm'),
       onOk: async () => {
-        const result = await useYnMethod(rows, useYn);
+        const result = await useYnMethod(rows, useYn, params);
         successMessage({
           message: t('common.message.OperationSucceeded'),
         });

+ 7 - 3
src/components/SmartTable/src/types/SmartTableType.ts

@@ -49,7 +49,7 @@ export interface SmartTableProxyConfig<T = any> extends VxeGridPropTypes.ProxyCo
     delete?(params: VxeGridPropTypes.ProxyAjaxDeleteParams, ...args: any[]): Promise<any>;
     save?(params: VxeGridPropTypes.ProxyAjaxSaveParams, ...args: any[]): Promise<any>;
     getById?(params: T): Promise<T>;
-    useYn?(rows: T[], useYn: boolean): Promise<any>;
+    useYn?(rows: T[], useYn: boolean, params?: Recordable): Promise<any>;
   };
   // 删除回调
   afterDelete?: (result?: any) => void;
@@ -159,8 +159,12 @@ export interface TableActionType {
   validateAddEdit: (nameList?: NamePath[]) => Promise<any>;
   getTableInstance: () => VxeGridInstance;
   getData: (rowIndex?: number) => any[];
-  useYnByCheckbox: (useYn: boolean) => Promise<boolean | undefined>;
-  useYnByRow: (row: any | any[], useYn: boolean) => Promise<boolean | undefined>;
+  useYnByCheckbox: (useYn: boolean, params?: Recordable) => Promise<boolean | undefined>;
+  useYnByRow: (
+    row: any | any[],
+    useYn: boolean,
+    params?: Recordable,
+  ) => Promise<boolean | undefined>;
 }
 
 /**

+ 35 - 8
src/hooks/web/useMessage.tsx

@@ -6,6 +6,8 @@ import { useI18n } from './useI18n';
 import { isString } from '@/utils/is';
 import { Result } from '#/axios';
 import { useSystemExceptionStore } from '@/store/modules/exception';
+import { Button, ButtonProps } from '@/components/Button';
+import { createVNode } from 'vue';
 
 export interface NotifyApi {
   info(config: NotificationArgsProps): void;
@@ -23,6 +25,8 @@ export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft
 export declare type IconType = 'success' | 'info' | 'error' | 'warning';
 export interface ModalOptionsEx extends Omit<ModalFuncProps, 'iconType'> {
   iconType: 'warning' | 'success' | 'error' | 'info';
+  buttons?: Array<string | (ButtonProps & { name: string })>;
+  footerProps?: Recordable;
 }
 export type ModalOptionsPartial = Partial<ModalOptionsEx> & Pick<ModalOptionsEx, 'content'>;
 
@@ -52,13 +56,19 @@ function renderContent({ content }: Pick<ModalOptionsEx, 'content'>) {
 function createConfirm(options: ModalOptionsEx) {
   const iconType = options.iconType || 'warning';
   Reflect.deleteProperty(options, 'iconType');
-  const opt: ModalFuncProps = {
-    centered: true,
-    icon: getIcon(iconType),
-    ...options,
-    content: renderContent(options),
-  };
-  return Modal.confirm(opt);
+  const modalOptions = createModalOptions(
+    {
+      ...options,
+      footerProps: {
+        ...(options.footerProps || {}),
+        class: ['ant-modal-confirm-btns'],
+      },
+    },
+    iconType,
+  );
+  return Modal.confirm({
+    ...modalOptions,
+  });
 }
 
 const getBaseOptions = () => {
@@ -70,12 +80,29 @@ const getBaseOptions = () => {
 };
 
 function createModalOptions(options: ModalOptionsPartial, icon: string): ModalOptionsPartial {
-  return {
+  const { buttons, footerProps } = options;
+  const modalOptions: ModalOptionsPartial = {
     ...getBaseOptions(),
     ...options,
     content: renderContent(options),
     icon: getIcon(icon),
   };
+  if (!buttons) {
+    return modalOptions;
+  }
+  const buttonsSlots = () =>
+    buttons.map((button) => {
+      const stringYn = isString(button);
+      const buttonName = stringYn ? button : button.name;
+      const buttonProps = stringYn ? {} : button;
+      return <Button {...buttonProps}>{buttonName}</Button>;
+    });
+
+  const footer = () => createVNode('div', footerProps || {}, { default: buttonsSlots });
+  return {
+    ...modalOptions,
+    footer,
+  };
 }
 
 function createSuccessModal(options: ModalOptionsPartial) {

+ 2 - 2
src/modules/smart-app/i18n/lang/zh_CN.ts

@@ -57,8 +57,8 @@ export default {
       deleteChoose: '请选择要删除的数据',
       select: '请选择',
       choseOne: '请选择一行数据',
-      useYnTrueConfirm: '确认要执行启用操作吗?',
-      useYnFalseConfirm: '确认要执行停用操作吗?',
+      useYnTrueConfirm: '确认启用所选数据吗?',
+      useYnFalseConfirm: '确认停用所选数据吗?',
     },
     message: {
       saveSuccess: '保存成功',

+ 13 - 1
src/modules/smart-system/views/user/UserListView.api.ts

@@ -16,6 +16,7 @@ enum Api {
   unlockUserAccount = 'sys/user/unlockUserAccount',
   resetPassword = 'sys/user/resetPassword',
   setUserRole = 'sys/user/setRole',
+  listTenant = '/sys/tenant/manager/list',
 }
 
 export const listApi = (ajaxParameter) => {
@@ -64,13 +65,14 @@ export const getByIdWithDataScopeApi = async (params) => {
   };
 };
 
-export const setUseYnApi = (userList: any[], useYn: boolean) => {
+export const setUseYnApi = (userList: any[], useYn: boolean, params?: Recordable) => {
   return defHttp.post({
     service: ApiServiceEnum.SMART_SYSTEM,
     url: Api.setUseYn,
     data: {
       idList: userList.map((item) => item.userId),
       useYn,
+      ...(params || {}),
     },
   });
 };
@@ -145,3 +147,13 @@ export const setUserRoleApi = (data: Recordable) => {
     data,
   });
 };
+
+export const listTenantApi = (params) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.listTenant,
+    data: {
+      ...params,
+    },
+  });
+};

+ 0 - 1
src/modules/smart-system/views/user/UserListView.config.ts

@@ -260,7 +260,6 @@ export const getSearchSchemas = (t: Function): SmartSearchFormSchema[] => {
       field: 'useYn',
       component: 'Select',
       defaultValue: 1,
-      searchSymbol: '=',
       componentProps: {
         style: {
           width: '100px',

+ 42 - 1
src/modules/smart-system/views/user/UserListView.vue

@@ -44,17 +44,20 @@
     </SmartLayoutSeparate>
     <UserAccountUpdateModal @register="registerAccountModal" />
     <UserSetRole @register="registerSetRoleModal" />
+    <UserUseYnModal @register="registerUseYnModal" />
   </div>
 </template>
 
 <script lang="ts" setup>
   import { computed, ref, unref } from 'vue';
   import { useI18n } from '@/hooks/web/useI18n';
+  import { storeToRefs } from 'pinia';
 
   import { useLoadDictItem } from '@/modules/smart-system/hooks/SysDictHooks';
   import { useSizeSetting } from '@/hooks/setting/UseSizeSetting';
   import { hasPermission } from '@/utils/auth';
   import { useModal } from '@/components/Modal';
+  import { useUserStore } from '@/store/modules/user';
 
   import { SmartLayoutSeparate } from '@/components/SmartLayoutSeparate';
   import SysDeptTree from '@/modules/smart-system/components/SysDept/SysDeptTree.vue';
@@ -68,6 +71,7 @@
   } from '@/components/SmartTable';
   import UserAccountUpdateModal from './account/UserAccountUpdateModal.vue';
   import UserSetRole from './components/UserSetRole.vue';
+  import UserUseYnModal from './components/UserUseYnModal.vue';
 
   import { getAddEditFormSchemas, getSearchSchemas, getTableColumns } from './UserListView.config';
   import {
@@ -89,6 +93,8 @@
   const { t } = useI18n();
   const { warnMessage, errorMessage, createConfirm, successMessage } = useMessage();
   const { getTableSize } = useSizeSetting();
+  const { getIsPlatformTenant } = storeToRefs(useUserStore());
+  const [registerUseYnModal, { openModal: openUseYnModal }] = useModal();
 
   const { dictData: userTypeListRef } = useLoadDictItem(ref('SYSTEM_USER_TYPE'));
   const getUserTypeMap = computed(() => {
@@ -264,9 +270,18 @@
     });
   };
 
+  const validateSelectRows = () => {
+    const rows = getCheckboxRecords();
+    if (!rows.length) {
+      warnMessage(t('common.notice.select'));
+      return false;
+    }
+    return rows;
+  };
+
   const [
     registerTable,
-    { editByRowModal, getCheckboxRecords, query, deleteByCheckbox, showAddModal },
+    { editByRowModal, getCheckboxRecords, query, deleteByCheckbox, showAddModal, useYnByCheckbox },
   ] = useSmartTable({
     columns: getTableColumns(),
     stripe: true,
@@ -376,9 +391,35 @@
         },
         {
           code: 'useYnTrue',
+          props: {
+            onClick() {
+              if (!unref(getIsPlatformTenant)) {
+                useYnByCheckbox(true);
+              } else {
+                const rows = validateSelectRows();
+                if (!rows) {
+                  return false;
+                }
+                openUseYnModal(true, { rows, useYn: true });
+              }
+            },
+          },
         },
         {
           code: 'useYnFalse',
+          props: {
+            onClick() {
+              if (!unref(getIsPlatformTenant)) {
+                useYnByCheckbox(true);
+              } else {
+                const rows = validateSelectRows();
+                if (!rows) {
+                  return false;
+                }
+                openUseYnModal(true, { rows, useYn: false });
+              }
+            },
+          },
         },
         {
           name: t('system.views.user.button.resetPassword'),

+ 88 - 0
src/modules/smart-system/views/user/components/UserUseYnModal.vue

@@ -0,0 +1,88 @@
+<template>
+  <BasicModal @register="registerModal" :canFullscreen="false" :closable="false" @ok="handleOk">
+    <SmartTable @register="registerTable" />
+  </BasicModal>
+</template>
+
+<script setup lang="ts">
+  import { BasicModal, useModalInner } from '@/components/Modal';
+  import { SmartTable, useSmartTable } from '@/components/SmartTable';
+
+  import { listTenantApi, setUseYnApi } from '../UserListView.api';
+  import { successMessage, warnMessage } from '@/utils/message/SystemNotice';
+  import { useI18n } from '@/hooks/web/useI18n';
+
+  const { t } = useI18n();
+
+  let selectRows: Recordable[] = [];
+  let useYnValue = null;
+
+  const [registerModal, { changeOkLoading, closeModal }] = useModalInner(({ rows, useYn }) => {
+    selectRows = rows || [];
+    useYnValue = useYn;
+    query();
+  });
+
+  const handleOk = async () => {
+    const selectTenants = getCheckboxRecords();
+    if (selectTenants.length === 0) {
+      warnMessage(t('common.notice.select'));
+      return false;
+    }
+    try {
+      changeOkLoading(true);
+      await setUseYnApi(selectRows, useYnValue!, {
+        tenantIdList: selectTenants.map((item) => item.id),
+      });
+      successMessage(t('common.message.OperationSucceeded'));
+      closeModal();
+    } finally {
+      changeOkLoading(false);
+    }
+  };
+  const [registerTable, { query, getCheckboxRecords }] = useSmartTable({
+    border: true,
+    stripe: true,
+    rowConfig: {
+      isHover: true,
+    },
+    columnConfig: {
+      resizable: true,
+    },
+    proxyConfig: {
+      autoLoad: false,
+      ajax: {
+        query() {
+          return listTenantApi({});
+        },
+      },
+    },
+    showOverflow: 'tooltip',
+    columns: [
+      {
+        type: 'checkbox',
+        width: 60,
+        align: 'center',
+        fixed: 'left',
+        field: 'checkbox',
+      },
+      {
+        field: 'tenantCode',
+        title: '{system.views.tenant.manager.title.tenantCode}',
+        minWidth: 120,
+      },
+      {
+        field: 'tenantShortName',
+        title: '{system.views.tenant.manager.title.tenantShortName}',
+        minWidth: 120,
+      },
+      {
+        field: 'tenantName',
+        title: '{system.views.tenant.manager.title.tenantName}',
+        minWidth: 120,
+      },
+    ],
+  });
+</script>
+
+<style scoped lang="less"></style>

+ 2 - 0
src/modules/smart-system/views/user/lang/zh_CN.ts

@@ -29,6 +29,8 @@ export default {
           resetPassword: '重置密码',
           setRole: '设置角色',
           copyPassword: '复制密码',
+          currentTenant: '当前租户',
+          allTenant: '所有租户',
         },
         account: {
           title: '账户信息',