ソースを参照

feat(系统模块-租户管理): 添加租户管理功能

shizhongming 2 年 前
コミット
7d5ab7344a

+ 2 - 1
src/components/Form/src/components/ApiSelect.vue

@@ -54,6 +54,7 @@
       type: Array<OptionsItem>,
       default: [],
     },
+    labelWithCode: propTypes.bool,
   });
 
   const emit = defineEmits(['options-change', 'change', 'update:value']);
@@ -77,7 +78,7 @@
         const value = get(next, valueField);
         prev.push({
           ...omit(next, [labelField, valueField]),
-          label: get(next, labelField),
+          label: props.labelWithCode ? `${value}-${get(next, labelField)}` : get(next, labelField),
           value: numberToString ? `${value}` : value,
         });
       }

+ 4 - 4
src/components/Form/src/smart-boot/components/SmartApiSelectDict.vue

@@ -10,24 +10,24 @@
 </template>
 
 <script lang="ts" setup>
-  import { computed, inject } from 'vue';
+  import { computed } from 'vue';
   import ApiSelect from '../../components/ApiSelect.vue';
   import { propTypes } from '@/utils/propTypes';
   import { ApiServiceEnum, defHttp } from '@/utils/http/axios';
-  import { SmartProviderConstants } from '@/components/SmartPageProvider';
+  import { useInjectPageDict } from '@/components/SmartPageProvider';
   import SmartApiDictProviderSelect from './provider/SmartApiDictProviderSelect.vue';
 
   const props = defineProps({
     dictCode: propTypes.string.isRequired,
   });
 
-  const registerHandler = inject(SmartProviderConstants.dictRegisterIdent, null) as boolean | null;
+  const { pageDictRegisterIdent } = useInjectPageDict();
 
   /**
    * 是否有注入
    */
   const computedHasProvider = computed(() => {
-    return registerHandler !== null;
+    return pageDictRegisterIdent;
   });
 
   const api = () => {

+ 20 - 18
src/components/Form/src/smart-boot/components/provider/SmartApiDictProviderSelect.vue

@@ -3,10 +3,10 @@
     <template #[item]="data" v-for="item in Object.keys($slots)">
       <slot :name="item" v-bind="data || {}"></slot>
     </template>
-    <template #suffixIcon v-if="loadingRef">
+    <template #suffixIcon v-if="pageDictLoadingRef">
       <LoadingOutlined spin />
     </template>
-    <template #notFoundContent v-if="loadingRef">
+    <template #notFoundContent v-if="pageDictLoadingRef">
       <span>
         <LoadingOutlined spin class="mr-1" />
         {{ t('component.form.apiSelectNotFound') }}
@@ -16,11 +16,11 @@
 </template>
 
 <script setup lang="ts">
-  import { type Ref, inject, type PropType, computed, watch, ref } from 'vue';
+  import { type PropType, computed, watch, ref } from 'vue';
 
   import { Select } from 'ant-design-vue';
   import { LoadingOutlined } from '@ant-design/icons-vue';
-  import { SmartProviderConstants } from '@/components/SmartPageProvider';
+  import { useInjectPageDict } from '@/components/SmartPageProvider';
   import { useI18n } from '@/hooks/web/useI18n';
   import { propTypes } from '@/utils/propTypes';
   import type { SelectValue } from 'ant-design-vue/es/select';
@@ -32,19 +32,17 @@
     dictCode: propTypes.string.isRequired,
     value: { type: [Array, Object, String, Number] as PropType<SelectValue> },
     numberToString: propTypes.bool,
+    labelWithCode: propTypes.bool,
   });
 
   const emit = defineEmits(['change', 'update:value']);
 
   const { t } = useI18n();
-  /**
-   * 加载状态
-   */
-  const loadingRef = inject(SmartProviderConstants.dictLoadingKey, null) as Ref<boolean> | null;
 
-  const registerHandler = inject(SmartProviderConstants.dictRegisterKey, null) as Function | null;
-  if (registerHandler) {
-    registerHandler(props.dictCode);
+  const { pageDictRegister, pageDictLoadingRef, pageDictData } = useInjectPageDict();
+
+  if (pageDictRegister) {
+    pageDictRegister(props.dictCode);
   }
 
   const emitData = ref<OptionsItem[]>([]);
@@ -63,19 +61,23 @@
   /**
    * 注入OPTIONS
    */
-  const dictDataRef = inject(SmartProviderConstants.dictData, null) as Map<
-    string,
-    Recordable[]
-  > | null;
   const computedOptions = computed(() => {
-    if (!dictDataRef) {
+    if (!pageDictData) {
       return [];
     }
-    const dictData = dictDataRef.get(props.dictCode);
+    const dictData = pageDictData.get(props.dictCode);
     if (!dictData) {
       return [];
     }
-    return dictData;
+    return dictData.map((item) => {
+      if (props.labelWithCode) {
+        return {
+          ...item,
+          label: `${item.value}-${item.label}`,
+        };
+      }
+      return item;
+    });
   });
 </script>
 

+ 2 - 0
src/components/SmartPageProvider/index.ts

@@ -1,3 +1,5 @@
 export { default as SmartPageProvider } from './src/SmartPageProvider.vue';
 
 export * from './src/constants';
+
+export * from './src/hooks/useInjectPageProvider';

+ 32 - 0
src/components/SmartPageProvider/src/hooks/useInjectPageProvider.ts

@@ -0,0 +1,32 @@
+import { type ComputedRef, inject, Ref } from 'vue';
+
+import { SmartProviderConstants } from '@/components/SmartPageProvider/src/constants';
+
+/**
+ * 注入页面字典
+ */
+export const useInjectPageDict = () => {
+  const pageDictRegister: (code: string) => void = inject(
+    SmartProviderConstants.dictRegisterKey,
+    () => {},
+  );
+
+  const pageDictLoadingRef: Ref<boolean> | undefined = inject(
+    SmartProviderConstants.dictLoadingKey,
+  );
+
+  const pageDictData: Map<string, Recordable> | undefined = inject(SmartProviderConstants.dictData);
+
+  const pageDictMap: ComputedRef<Recordable<Recordable>> | undefined = inject(
+    SmartProviderConstants.dictMap,
+  );
+
+  const pageDictRegisterIdent: boolean = inject(SmartProviderConstants.dictRegisterIdent, false);
+  return {
+    pageDictRegister,
+    pageDictLoadingRef,
+    pageDictData,
+    pageDictMap,
+    pageDictRegisterIdent,
+  };
+};

+ 9 - 4
src/components/SmartPageProvider/src/hooks/useProviderDict.ts

@@ -4,7 +4,7 @@ import { ApiServiceEnum, defHttp } from '@/utils/http/axios';
 
 export const useProviderDict = () => {
   let hasInitLoad = false;
-  const dictCodeList = reactive<string[]>([]);
+  const dictCodeList = reactive<Set<string>>(new Set<string>());
   const dictDataMap = reactive(new Map<string, Recordable>());
 
   // 字典加载状态
@@ -33,10 +33,15 @@ export const useProviderDict = () => {
    * 批量加载字典数据
    */
   const loadDictData = async () => {
-    if (dictCodeList.length === 0) {
+    if (dictCodeList.size === 0) {
       return;
     }
-    const noLoadDictCodeList = dictCodeList.filter((item) => !dictDataMap.has(item));
+    const noLoadDictCodeList: string[] = [];
+    dictCodeList.forEach((item) => {
+      if (!dictDataMap.has(item)) {
+        noLoadDictCodeList.push(item);
+      }
+    });
     if (noLoadDictCodeList.length === 0) {
       return;
     }
@@ -75,7 +80,7 @@ export const useProviderDict = () => {
    * 注入注册函数
    */
   provide(SmartProviderConstants.dictRegisterKey, (code: string) => {
-    dictCodeList.push(code);
+    dictCodeList.add(code);
   });
 
   /**

+ 4 - 1
src/layouts/page/index.vue

@@ -15,7 +15,9 @@
         appear
       >
         <keep-alive v-if="openCache" :include="getCaches">
-          <component :is="Component" :key="route.fullPath" />
+          <SmartPageProvider>
+            <component :is="Component" :key="route.fullPath" />
+          </SmartPageProvider>
         </keep-alive>
         <component v-else :is="Component" :key="route.fullPath" />
       </transition>
@@ -36,6 +38,7 @@
   import { getTransitionName } from './transition';
 
   import { useMultipleTabStore } from '@/store/modules/multipleTab';
+  import { SmartPageProvider } from '@/components/SmartPageProvider';
 
   defineOptions({ name: 'PageLayout' });
 

+ 7 - 4
src/modules/smart-system/views/tenant/lang/en_US.ts

@@ -6,18 +6,21 @@ export default {
   key: 'system.views.tenant',
   data: {
     title: {
-      id: 'id',
       tenantCode: 'Tenant code',
       tenantName: 'Tenant name',
+      tenantShortName: 'Short name',
+      type: 'Type',
       contacts: 'Contacts',
       contactPhone: 'Contact phone',
+      email: 'Email',
+      isolationStrategy: 'Isolation strategy',
+      industry: 'Industry',
       domain: 'domain',
       availableUserNum: 'Available user num',
       address: 'Address',
       logoId: 'LOGO',
-      startTime: 'Start time',
-      endTime: 'End time',
-      validatedTime: 'Validated time',
+      effectTime: 'Effect time',
+      expireTime: 'Expire time',
     },
     validate: {
       tenantCode: 'Please enter the tenant code',

+ 23 - 9
src/modules/smart-system/views/tenant/lang/zh_CN.ts

@@ -3,39 +3,53 @@
  */
 export default {
   trans: true,
-  key: 'system.views.tenant',
+  key: 'system.views.tenant.manager',
   data: {
     title: {
-      id: 'id',
       tenantCode: '租户编号',
       tenantName: '租户名字',
+      tenantShortName: '简称',
+      type: '类型',
       contacts: '联系人',
       contactPhone: '联系人电话',
+      email: '邮箱',
+      isolationStrategy: '隔离策略',
+      industry: '行业',
       domain: '域名',
       availableUserNum: '可用人数',
+      region: '地区',
       address: '地址',
       logoId: 'LOGO',
-      startTime: '开始时间',
-      endTime: '过期时间',
-      validatedTime: '有效时间',
+      effectTime: '生效时间',
+      expireTime: '过期时间',
     },
     validate: {
-      id: '请输入',
       tenantCode: '请输入租户编号',
       tenantName: '请输入租户名字',
+      tenantShortName: '请输入简称',
+      type: '请输入类型',
       contacts: '请输入联系人',
       contactPhone: '请输入联系人电话',
+      email: '请输入邮箱',
+      isolationStrategy: '请输入隔离策略',
+      industry: '请输入行业',
       domain: '请输入域名',
-      availableUserNum: '请输入可用人数,-1不限制',
+      availableUserNum: '请输入可用人数',
+      region: '请输入地区',
       address: '请输入地址',
       logoId: '请输入LOGO',
-      startTime: '请输入开始时间',
-      endTime: '请输入过期时间',
+      effectTime: '请输入生效时间',
+      expireTime: '请输入过期时间',
     },
     rules: {},
     search: {
       tenantCode: '请输入租户编号',
       tenantName: '请输入租户名字',
+      tenantShortName: '请输入简称',
+      type: '请输入类型',
+      isolationStrategy: '请输入隔离策略',
+      effectTime: '请输入生效时间',
+      expireTime: '请输入过期时间',
     },
   },
 };

+ 34 - 20
src/modules/smart-system/views/tenant/list/SysTenantListView.api.ts

@@ -1,10 +1,12 @@
 import { ApiServiceEnum, defHttp } from '@/utils/http/axios';
 
 enum Api {
-  list = '/sys/tenant/list',
-  getById = '/sys/tenant/getById',
-  batchSaveUpdate = '/sys/tenant/saveUpdateBatch',
-  delete = '/sys/tenant/batchDeleteById',
+  list = '/sys/tenant/manager/list',
+  getById = '/sys/tenant/manager/getById',
+  batchSaveUpdate = '/sys/tenant/manager/saveUpdateBatch',
+  delete = '/sys/tenant/manager/batchDeleteById',
+  setUseYn = '/sys/tenant/manager/setUseYn',
+  listIsolationStrategy = '/sys/tenant/manager/listIsolationStrategy',
 }
 
 export const listApi = (params) => {
@@ -12,20 +14,12 @@ export const listApi = (params) => {
     service: ApiServiceEnum.SMART_SYSTEM,
     url: Api.list,
     data: {
-      sortName: 'seq',
       ...params,
     },
   });
 };
 
 export const batchSaveUpdateApi = (modelList: any[]) => {
-  modelList.forEach((item) => {
-    const { validatedTime } = item;
-    if (validatedTime && validatedTime.length > 0) {
-      item.startTime = validatedTime[0];
-      item.endTime = validatedTime[1];
-    }
-  });
   return defHttp.post({
     service: ApiServiceEnum.SMART_SYSTEM,
     url: Api.batchSaveUpdate,
@@ -41,16 +35,36 @@ export const deleteApi = (removeRecords: Recordable[]) => {
   });
 };
 
-export const getByIdApi = async (id: number) => {
-  const result = await defHttp.post({
+export const getByIdApi = (id: number) => {
+  return defHttp.post({
     service: ApiServiceEnum.SMART_SYSTEM,
     url: Api.getById,
     data: id,
   });
-  if (!result) {
-    return result;
-  }
-  const { startTime, endTime } = result;
-  result.validatedTime = [startTime, endTime];
-  return result;
+};
+
+/**
+ * 启用停用接口
+ * @param rows 选中的数据
+ * @param useYn 启用停用
+ */
+export const setUseYnApi = (rows: any[], useYn: boolean) => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.setUseYn,
+    data: {
+      idList: rows.map((item) => item.id),
+      useYn,
+    },
+  });
+};
+
+/**
+ * 查询隔离策略
+ */
+export const listIsolationStrategyApi = () => {
+  return defHttp.post({
+    service: ApiServiceEnum.SMART_SYSTEM,
+    url: Api.listIsolationStrategy,
+  });
 };

+ 170 - 92
src/modules/smart-system/views/tenant/list/SysTenantListView.config.ts

@@ -1,13 +1,16 @@
 import type { SmartColumn, SmartSearchFormSchema } from '@/components/SmartTable';
 import type { FormSchema } from '@/components/Form';
+import { tableUseYnClass } from '@/components/SmartTable';
+import { Ref, unref } from 'vue';
 
 export enum Permission {
-  query = 'sys:tenant:query',
-  save = 'sys:tenant:save',
-  update = 'sys:tenant:update',
-  delete = 'sys:tenant:delete',
+  save = 'sys:tenant:manager:save',
+  update = 'sys:tenant:manager:update',
+  delete = 'sys:tenant:manager:delete',
+  useYn = 'sys:tenant:manager:setUseYn',
 }
 
+export const SYSTEM_TENANT_TYPE_DICT = 'SYSTEM_TENANT_TYPE';
 /**
  * 表格列表
  */
@@ -17,63 +20,98 @@ export const getTableColumns = (): SmartColumn[] => {
       type: 'checkbox',
       width: 60,
       align: 'center',
-      field: 'checkbox',
       fixed: 'left',
+      field: 'checkbox',
     },
     {
       field: 'tenantCode',
+      title: '{system.views.tenant.manager.title.tenantCode}',
+      width: 120,
       fixed: 'left',
-      title: '{system.views.tenant.title.tenantCode}',
-      width: 180,
     },
     {
       field: 'tenantName',
+      title: '{system.views.tenant.manager.title.tenantName}',
+      width: 120,
       fixed: 'left',
-      title: '{system.views.tenant.title.tenantName}',
-      width: 180,
+    },
+    {
+      field: 'tenantShortName',
+      title: '{system.views.tenant.manager.title.tenantShortName}',
+      width: 120,
+    },
+    {
+      field: 'type',
+      title: '{system.views.tenant.manager.title.type}',
+      width: 120,
+      sortable: true,
+      slots: {
+        default: 'table-type',
+      },
     },
     {
       field: 'contacts',
-      title: '{system.views.tenant.title.contacts}',
+      title: '{system.views.tenant.manager.title.contacts}',
       width: 120,
     },
     {
       field: 'contactPhone',
-      title: '{system.views.tenant.title.contactPhone}',
+      title: '{system.views.tenant.manager.title.contactPhone}',
+      width: 120,
+    },
+    {
+      field: 'email',
+      title: '{system.views.tenant.manager.title.email}',
+      width: 120,
+    },
+    {
+      field: 'isolationStrategy',
+      title: '{system.views.tenant.manager.title.isolationStrategy}',
+      width: 120,
+      slots: {
+        default: 'table-isolationStrategy',
+      },
+    },
+    {
+      field: 'industry',
+      title: '{system.views.tenant.manager.title.industry}',
       width: 120,
     },
     {
       field: 'domain',
-      title: '{system.views.tenant.title.domain}',
-      width: 160,
+      title: '{system.views.tenant.manager.title.domain}',
+      width: 120,
     },
     {
       field: 'availableUserNum',
-      title: '{system.views.tenant.title.availableUserNum}',
-      width: 160,
-      sortable: true,
+      title: '{system.views.tenant.manager.title.availableUserNum}',
+      width: 120,
+    },
+    {
+      field: 'region',
+      title: '{system.views.tenant.manager.title.region}',
+      width: 120,
     },
     {
       field: 'address',
-      title: '{system.views.tenant.title.address}',
+      title: '{system.views.tenant.manager.title.address}',
       width: 120,
     },
     {
       field: 'logoId',
-      visible: false,
-      title: '{system.views.tenant.title.logoId}',
+      title: '{system.views.tenant.manager.title.logoId}',
       width: 120,
     },
     {
-      field: 'startTime',
-      title: '{system.views.tenant.title.startTime}',
-      width: 160,
+      field: 'effectTime',
+      title: '{system.views.tenant.manager.title.effectTime}',
+      width: 165,
       sortable: true,
     },
     {
-      field: 'endTime',
-      title: '{system.views.tenant.title.endTime}',
-      width: 160,
+      field: 'expireTime',
+      title: '{system.views.tenant.manager.title.expireTime}',
+      width: 165,
       sortable: true,
     },
     {
@@ -87,10 +125,14 @@ export const getTableColumns = (): SmartColumn[] => {
       width: 120,
       sortable: true,
     },
+    {
+      ...tableUseYnClass(),
+      sortable: true,
+    },
     {
       field: 'createTime',
       title: '{common.table.createTime}',
-      width: 160,
+      width: 165,
       sortable: true,
     },
     {
@@ -101,119 +143,145 @@ export const getTableColumns = (): SmartColumn[] => {
     {
       field: 'updateTime',
       title: '{common.table.updateTime}',
-      width: 160,
+      width: 165,
+      sortable: true,
     },
     {
       field: 'updateBy',
       title: '{common.table.updateUser}',
       width: 120,
     },
-    {
-      field: 'useYn',
-      title: '{common.table.useYn}',
-      component: 'booleanTag',
-      sortable: true,
-      width: 120,
-    },
-    {
-      title: '{common.table.operation}',
-      field: 'operation',
-      width: 120,
-      fixed: 'right',
-      slots: {
-        default: 'table-operation',
-      },
-    },
   ];
 };
 
 /**
  * 添加修改表单
  */
-export const getFormSchemas = (t: Function): FormSchema[] => {
+export const getFormSchemas = (t: Function, isolationStrategyListRef: Ref): FormSchema[] => {
   return [
     {
       field: 'id',
-      label: t('system.views.tenant.title.id'),
-      component: 'Input',
       show: false,
+      label: t('system.views.tenant.manager.title.id'),
+      component: 'Input',
       componentProps: {},
     },
     {
       field: 'tenantCode',
-      label: t('system.views.tenant.title.tenantCode'),
+      label: t('system.views.tenant.manager.title.tenantCode'),
       component: 'Input',
       componentProps: {},
       required: true,
     },
     {
       field: 'tenantName',
-      label: t('system.views.tenant.title.tenantName'),
+      label: t('system.views.tenant.manager.title.tenantName'),
       component: 'Input',
       componentProps: {},
       required: true,
     },
+    {
+      field: 'tenantShortName',
+      label: t('system.views.tenant.manager.title.tenantShortName'),
+      component: 'Input',
+      componentProps: {},
+    },
+    {
+      field: 'type',
+      label: t('system.views.tenant.manager.title.type'),
+      component: 'SmartApiSelectDict',
+      componentProps: {
+        dictCode: SYSTEM_TENANT_TYPE_DICT,
+        labelWithCode: true,
+      },
+      required: true,
+      defaultValue: '10',
+    },
     {
       field: 'contacts',
-      label: t('system.views.tenant.title.contacts'),
+      label: t('system.views.tenant.manager.title.contacts'),
       component: 'Input',
       componentProps: {},
     },
     {
       field: 'contactPhone',
-      label: t('system.views.tenant.title.contactPhone'),
+      label: t('system.views.tenant.manager.title.contactPhone'),
       component: 'Input',
       componentProps: {},
     },
     {
-      field: 'domain',
-      label: t('system.views.tenant.title.domain'),
+      field: 'email',
+      label: t('system.views.tenant.manager.title.email'),
       component: 'Input',
       componentProps: {},
     },
     {
-      field: 'availableUserNum',
-      label: t('system.views.tenant.title.availableUserNum'),
-      component: 'InputNumber',
-      componentProps: {},
+      field: 'isolationStrategy',
+      label: t('system.views.tenant.manager.title.isolationStrategy'),
+      component: 'Select',
+      componentProps: () => {
+        return {
+          options: unref(isolationStrategyListRef),
+        };
+      },
+      required: true,
     },
     {
-      field: 'address',
-      label: t('system.views.tenant.title.address'),
+      field: 'industry',
+      label: t('system.views.tenant.manager.title.industry'),
       component: 'Input',
       componentProps: {},
     },
     {
-      field: 'logoId',
-      label: t('system.views.tenant.title.logoId'),
+      field: 'domain',
+      label: t('system.views.tenant.manager.title.domain'),
       component: 'Input',
       componentProps: {},
     },
     {
-      field: 'validatedTime',
-      component: 'RangePicker',
-      label: t('system.views.tenant.title.validatedTime'),
+      field: 'availableUserNum',
+      label: t('system.views.tenant.manager.title.availableUserNum'),
+      component: 'Input',
+      componentProps: {},
     },
     {
-      field: 'remark',
-      label: t('common.table.remark'),
-      component: 'Input',
+      field: 'region',
+      label: t('system.views.tenant.manager.title.region'),
+      component: 'Cascader',
       componentProps: {},
     },
+    {
+      field: 'effectExpireTime',
+      label: t('system.views.tenant.manager.title.effectTime'),
+      component: 'RangePicker',
+      componentProps: {
+        showTime: true,
+      },
+    },
     {
       field: 'seq',
       label: t('common.table.seq'),
-      component: 'InputNumber',
+      component: 'Input',
       componentProps: {},
       defaultValue: 1,
-      required: true,
     },
     {
-      field: 'useYn',
-      label: t('common.table.useYn'),
-      component: 'Switch',
+      field: 'address',
+      label: t('system.views.tenant.manager.title.address'),
+      component: 'InputTextArea',
+      componentProps: {},
+    },
+    {
+      field: 'remark',
+      label: t('common.table.remark'),
+      component: 'InputTextArea',
+      componentProps: {},
+    },
+    {
+      field: 'logoId',
+      label: t('system.views.tenant.manager.title.logoId'),
+      component: 'Input',
       componentProps: {},
-      defaultValue: true,
     },
   ];
 };
@@ -222,34 +290,44 @@ export const getSearchFormSchemas = (t: Function): SmartSearchFormSchema[] => {
   return [
     {
       field: 'tenantCode',
-      label: t('system.views.tenant.title.tenantCode'),
+      label: t('system.views.tenant.manager.title.tenantCode'),
       component: 'Input',
       searchSymbol: '=',
     },
     {
       field: 'tenantName',
-      label: t('system.views.tenant.title.tenantName'),
+      label: t('system.views.tenant.manager.title.tenantName'),
       component: 'Input',
-      searchSymbol: 'like',
+      searchSymbol: '=',
     },
     {
-      field: 'useYn',
-      label: t('common.table.useYn'),
-      component: 'Select',
-      defaultValue: 1,
-      componentProps: {
-        style: { width: '120px' },
-        options: [
-          {
-            label: 'Y',
-            value: 1,
-          },
-          {
-            label: 'N',
-            value: 0,
-          },
-        ],
-      },
+      field: 'tenantShortName',
+      label: t('system.views.tenant.manager.title.tenantShortName'),
+      component: 'Input',
+      searchSymbol: '=',
+    },
+    {
+      field: 'type',
+      label: t('system.views.tenant.manager.title.type'),
+      component: 'Input',
+      searchSymbol: '=',
+    },
+    {
+      field: 'isolationStrategy',
+      label: t('system.views.tenant.manager.title.isolationStrategy'),
+      component: 'Input',
+      searchSymbol: '=',
+    },
+    {
+      field: 'effectTime',
+      label: t('system.views.tenant.manager.title.effectTime'),
+      component: 'Input',
+      searchSymbol: '=',
+    },
+    {
+      field: 'expireTime',
+      label: t('system.views.tenant.manager.title.expireTime'),
+      component: 'Input',
       searchSymbol: '=',
     },
   ];

+ 69 - 41
src/modules/smart-system/views/tenant/list/SysTenantListView.vue

@@ -1,111 +1,139 @@
 <template>
   <div class="full-height page-container">
     <SmartTable @register="registerTable" :size="getTableSize">
-      <template #table-operation="{ row }">
-        <SmartVxeTableAction :actions="getActions(row)" />
+      <template #table-isolationStrategy="{ row }">
+        <span>{{ computedIsolationStrategyMap[row.isolationStrategy] }}</span>
+      </template>
+      <template #table-type="{ row }">
+        <span>{{ computedTenantTypeDictMap[row.type] }}</span>
       </template>
     </SmartTable>
   </div>
 </template>
 
 <script lang="ts" setup>
+  import { mapValues, keyBy } from 'lodash-es';
   import { useI18n } from '@/hooks/web/useI18n';
   import { useSizeSetting } from '@/hooks/setting/UseSizeSetting';
 
-  import {
-    ActionItem,
-    SmartTable,
-    SmartVxeTableAction,
-    useSmartTable,
-  } from '@/components/SmartTable';
+  import { SmartTable, useSmartTable } from '@/components/SmartTable';
 
   import {
     getFormSchemas,
     getSearchFormSchemas,
     getTableColumns,
     Permission,
+    SYSTEM_TENANT_TYPE_DICT,
   } from './SysTenantListView.config';
-  import { batchSaveUpdateApi, deleteApi, getByIdApi, listApi } from './SysTenantListView.api';
+  import {
+    batchSaveUpdateApi,
+    deleteApi,
+    getByIdApi,
+    listApi,
+    setUseYnApi,
+    listIsolationStrategyApi,
+  } from './SysTenantListView.api';
+  import { useInjectPageDict } from '@/components/SmartPageProvider';
+  import { computed, onMounted, ref, unref } from 'vue';
 
   const { t } = useI18n();
   const { getTableSize } = useSizeSetting();
 
-  const getActions = (row: Recordable): ActionItem[] => {
-    return [
-      {
-        label: t('common.button.edit'),
-        auth: Permission.update,
-        onClick: () => editByRowModal(row),
-      },
-      {
-        label: t('common.button.delete'),
-        auth: Permission.delete,
-        danger: true,
-        onClick: () => deleteByRow(row),
-      },
-    ];
+  const isolationStrategyListRef = ref<any[]>([]);
+  const computedIsolationStrategyMap = computed(() => {
+    return mapValues(keyBy(unref(isolationStrategyListRef), 'value'), 'label');
+  });
+  const initIsolationStrategy = async () => {
+    isolationStrategyListRef.value = await listIsolationStrategyApi();
   };
 
-  const [registerTable, { editByRowModal, deleteByRow }] = useSmartTable({
-    id: 'system-tenant-list',
-    customConfig: { storage: true },
+  const { pageDictMap, pageDictRegister } = useInjectPageDict();
+  const computedTenantTypeDictMap = computed(() => {
+    return unref(pageDictMap || {})[SYSTEM_TENANT_TYPE_DICT] || {};
+  });
+  onMounted(() => pageDictRegister(SYSTEM_TENANT_TYPE_DICT));
+
+  const [registerTable] = useSmartTable({
     columns: getTableColumns(),
     height: 'auto',
-    pagerConfig: true,
-    useSearchForm: true,
     border: true,
-    stripe: true,
+    sortConfig: {
+      remote: true,
+    },
+    showOverflow: 'tooltip',
     rowConfig: {
-      keyField: 'id',
       isHover: true,
+      isCurrent: true,
     },
     columnConfig: {
       resizable: true,
     },
+    pagerConfig: true,
+    useSearchForm: true,
     searchFormConfig: {
       schemas: getSearchFormSchemas(t),
       searchWithSymbol: true,
       colon: true,
-      layout: 'inline',
       actionColOptions: {
-        span: undefined,
+        span: 5,
       },
       compact: true,
+      baseColProps: { span: 6 },
+      labelCol: { style: { width: '90px' } },
+      wrapperCol: { span: 17 },
     },
     addEditConfig: {
       modalConfig: {
-        width: 800,
+        width: 900,
       },
       formConfig: {
+        schemas: getFormSchemas(t, isolationStrategyListRef),
         colon: true,
-        schemas: getFormSchemas(t),
         baseColProps: { span: 12 },
-        labelCol: { span: 6 },
-        wrapperCol: { span: 17 },
+        labelCol: { style: { width: '90px' } },
       },
     },
-    sortConfig: {
-      remote: true,
-    },
     proxyConfig: {
       ajax: {
-        query: (params) => listApi(params.ajaxParameter),
+        query: async (params) => {
+          if (unref(isolationStrategyListRef).length === 0) {
+            await initIsolationStrategy();
+          }
+          return listApi(params.ajaxParameter);
+        },
         save: ({ body: { insertRecords, updateRecords } }) =>
           batchSaveUpdateApi([...insertRecords, ...updateRecords]),
         delete: ({ body: { removeRecords } }) => deleteApi(removeRecords),
         getById: (params) => getByIdApi(params.id),
+        useYn: setUseYnApi,
       },
     },
     toolbarConfig: {
       zoom: true,
       refresh: true,
-      column: { columnOrder: true },
+      column: {
+        columnOrder: true,
+      },
       buttons: [
         {
           code: 'ModalAdd',
+          auth: Permission.save,
+        },
+        {
+          code: 'ModalEdit',
+          auth: Permission.update,
         },
         {
           code: 'delete',
+          auth: Permission.delete,
+        },
+        {
+          code: 'useYnTrue',
+          auth: Permission.useYn,
+        },
+        {
+          code: 'useYnFalse',
+          auth: Permission.useYn,
         },
       ],
     },