Quellcode durchsuchen

feat: 系统管理-租户管理 重构

“fujiacheng” vor 1 Jahr
Ursprung
Commit
68e1918fe4

+ 48 - 0
src/api/tenant/index.ts

@@ -1,4 +1,5 @@
 import { http } from '@/utils/http/axios';
+import type { tenantFormType } from '@/types/tenant/type';
 
 /**
  * @description: 租户列表
@@ -65,3 +66,50 @@ export function getListUseZongbu() {
     { isShowErrorMessage: false, isShowMessage: false },
   );
 }
+
+/**
+ * @description: 查询租户树
+ */
+
+export function queryTenantTreeApi(params: { tenantName: string; tenantCode: string }) {
+  return http.request({
+    url: '/admin/tenant/queryTenantTree',
+    method: 'post',
+    params,
+  });
+}
+
+/**
+ * @description: 添加租户(新)
+ */
+
+export function saveTenantApi(params: tenantFormType) {
+  return http.request({
+    url: '/admin/tenant/saveTenant',
+    method: 'post',
+    params,
+  });
+}
+
+/**
+ * @description: 删除租户(新)
+ */
+
+export function deleteTenantApi(tenantId: number) {
+  return http.request({
+    url: `/admin/tenant/deleteTenant?tenantId=${tenantId}`,
+    method: 'post',
+  });
+}
+
+/**
+ * @description: 修改租户(新)
+ */
+
+export function updateTenantApi(params: tenantFormType) {
+  return http.request({
+    url: '/admin/tenant/updateTenant',
+    method: 'post',
+    params,
+  });
+}

+ 0 - 0
src/types/tenant/constants.ts


+ 34 - 0
src/types/tenant/type.ts

@@ -0,0 +1,34 @@
+export type TenantInfoType = {
+  id: number;
+  tenantCode: string; // 租户编码
+  tenantName: string; // 租户名称
+  parentId: number;
+  startTime: string; // 生效时间
+  endTime: string; //失效时间
+  isDisabled: 0 | 1; // 状态
+  createdBy: number; // 创建人
+  updatedBy: number; // 更新人
+  createdAt: string;
+  updatedAt: string;
+  isDeleted: number;
+  children: TenantInfoType[] | [];
+};
+
+export type TenantInfoTreeType = TenantInfoType[];
+
+export const TENANT_STATUS_LABEL = {
+  0: '启用',
+  1: '禁用',
+};
+
+export type tenantDrawerModeType = 'add' | 'edit';
+
+export interface tenantFormType {
+  id?: number;
+  parentId: number | undefined;
+  parentName: string | undefined;
+  tenantName: string;
+  tenantCode: string;
+  startTime: string;
+  endTime: string;
+}

+ 0 - 192
src/views/system/tenant/CreateDrawer.vue

@@ -1,192 +0,0 @@
-<template>
-  <el-drawer v-model="isDrawer" :size="width" :title="title" @close="handleReset">
-    <el-form
-      :model="formParams"
-      :rules="rules"
-      ref="formRef"
-      label-placement="left"
-      :label-width="80"
-    >
-      <el-form-item label="租户编码" prop="tenantCode">
-        <el-input placeholder="请输入租户编码" v-model="formParams.tenantCode" />
-      </el-form-item>
-      <el-form-item label="租户名称" prop="tenantName">
-        <el-input placeholder="请输入租户名称" v-model="formParams.tenantName" />
-      </el-form-item>
-      <el-form-item label="开始时间" prop="beginDate">
-        <el-date-picker
-          v-model="formParams.beginDate"
-          type="datetime"
-          clearable
-          placeholder="请选择开始时间"
-          :disabled-date="handleDisabledBeginDate"
-        />
-      </el-form-item>
-      <el-form-item label="结束时间" prop="endDate">
-        <el-date-picker
-          v-model="formParams.endDate"
-          type="datetime"
-          clearable
-          placeholder="请选择结束时间"
-          :disabled-date="handleDisabledEndDate"
-        />
-      </el-form-item>
-      <el-form-item label="状态" prop="tenantStatus">
-        <el-radio-group v-model="formParams.tenantStatus" name="tenantStatusGroup">
-          <el-radio-button :key="0" :label="0">启用</el-radio-button>
-          <el-radio-button :key="1" :label="1">禁用</el-radio-button>
-        </el-radio-group>
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-space size="middle">
-        <el-button @click="handleReset">重置</el-button>
-        <el-button type="primary" :loading="subLoading" @click="formSubmit">提交</el-button>
-      </el-space>
-    </template>
-  </el-drawer>
-</template>
-
-<script lang="ts" setup>
-  import { ref, onMounted } from 'vue';
-  import { ElMessage, ElSpace } from 'element-plus';
-  import type { FormRules } from 'element-plus';
-  import type { formParamsType } from './types';
-  import { cloneDeep } from 'lodash-es';
-  import { addTenant, editTenant, tenantInfo } from '@/api/tenant/index';
-  import { formatToDateTime } from '@/utils/dateUtil';
-  import dayjs, { Dayjs } from 'dayjs';
-
-  const rules: FormRules = {
-    tenantCode: {
-      required: true,
-      message: '请填写租户编码',
-      trigger: 'blur',
-    },
-    tenantName: {
-      required: true,
-      message: '请填写租户名称',
-      trigger: 'blur',
-    },
-    beginDate: {
-      required: true,
-      message: '请选择开始时间',
-      trigger: 'change',
-      type: 'date',
-    },
-    endDate: {
-      required: true,
-      message: '请选择结束时间',
-      trigger: 'change',
-      type: 'date',
-    },
-  };
-
-  const emit = defineEmits(['change']);
-
-  defineProps({
-    title: {
-      type: String,
-      default: '添加租户',
-    },
-    width: {
-      type: Number,
-      default: 450,
-    },
-    permissionList: {
-      type: Array,
-    },
-  });
-
-  const defaultValueRef = () => ({
-    tenantId: undefined,
-    beginDate: undefined,
-    endDate: undefined,
-    tenantCode: '',
-    tenantStatus: 0,
-    tenantName: '',
-  });
-
-  const message = ElMessage;
-  const formRef: any = ref(null);
-  const isDrawer = ref(false);
-  const subLoading = ref(false);
-
-  const formParams = ref<formParamsType>(defaultValueRef());
-
-  function openDrawer(tenantId?) {
-    if (tenantId) {
-      formParams.value.tenantId = tenantId;
-      getInfo();
-      return;
-    }
-    isDrawer.value = true;
-  }
-
-  function closeDrawer() {
-    isDrawer.value = false;
-  }
-
-  function formSubmit() {
-    formRef.value.validate((valid) => {
-      if (!valid) {
-        return message.error('请填写完整信息');
-      }
-      const params = cloneDeep(formParams.value);
-      params.beginDate = formatToDateTime(params.beginDate || '', 'YYYY-MM-DD HH:mm:ss');
-      params.endDate = formatToDateTime(params.endDate || '', 'YYYY-MM-DD HH:mm:ss');
-      if (formParams.value.tenantId) {
-        editTenant(params).then((_) => {
-          message.success('编辑成功');
-          emit('change');
-          handleReset();
-          closeDrawer();
-        });
-      } else {
-        addTenant(params).then((_) => {
-          message.success('添加成功');
-          emit('change');
-          handleReset();
-          closeDrawer();
-        });
-      }
-    });
-  }
-
-  function handleReset() {
-    formRef.value.resetFields();
-    formParams.value = Object.assign(formParams.value, defaultValueRef());
-  }
-
-  function getInfo() {
-    tenantInfo({ id: formParams.value.tenantId }).then((res) => {
-      const info = {
-        tenantId: res.tenantId,
-        tenantName: res.tenantName,
-        tenantCode: res.tenantCode,
-        beginDate: new Date(res.beginDate).toString(),
-        endDate: new Date(res.endDate).toString(),
-        tenantStatus: res.tenantStatus,
-      };
-      formParams.value = info;
-      isDrawer.value = true;
-    });
-  }
-
-  const handleDisabledBeginDate = (currentDate: Date) => {
-    const endDate = formParams.value.endDate;
-    if (!endDate) return false;
-    return !dayjs(currentDate).isBefore(endDate, 'day');
-  };
-
-  const handleDisabledEndDate = (currentDate: Date) => {
-    const beginDate = formParams.value.beginDate;
-    if (!beginDate) return false;
-    return !dayjs(currentDate).isAfter(beginDate, 'day');
-  };
-
-  defineExpose({
-    openDrawer,
-    closeDrawer,
-  });
-</script>

+ 0 - 41
src/views/system/tenant/columns.ts

@@ -1,41 +0,0 @@
-import { BasicColumn } from '@/components/Table';
-import { ElTag } from 'element-plus';
-import { h } from 'vue';
-
-export const columns: BasicColumn[] = [
-  {
-    label: '租户id',
-    prop: 'tenantId',
-  },
-  {
-    label: '租户编码',
-    prop: 'tenantCode',
-  },
-  {
-    label: '租户名称',
-    prop: 'tenantName',
-  },
-  {
-    label: '状态',
-    prop: 'tenantStatus',
-    render(record) {
-      return h(
-        ElTag,
-        {
-          type: record.row.tenantStatus === 0 ? 'success' : 'danger',
-        },
-        {
-          default: () => (record.row.tenantStatus === 0 ? '启用' : '禁用'),
-        },
-      );
-    },
-  },
-  {
-    label: '开始时间',
-    prop: 'beginDate',
-  },
-  {
-    label: '结束时间',
-    prop: 'endDate',
-  },
-];

+ 128 - 0
src/views/system/tenant/components/AddTenantDrawer.vue

@@ -0,0 +1,128 @@
+<template>
+  <el-drawer
+    v-model="props.showAddTenantDrawer"
+    size="450"
+    :title="`${mode === 'add' ? '添加' : '编辑'}租户`"
+    @close="emit('closeDrawer')"
+  >
+    <el-form
+      :model="tenantForm"
+      :rules="rules"
+      ref="tenantFormRef"
+      label-placement="left"
+      :label-width="80"
+    >
+      <el-form-item label="租户名称" prop="tenantName">
+        <el-input placeholder="请输入租户名称" v-model="props.tenantForm.tenantName" />
+      </el-form-item>
+      <el-form-item label="租户编码" prop="tenantCode">
+        <el-input placeholder="请输入租户编码" v-model="props.tenantForm.tenantCode" />
+      </el-form-item>
+      <el-form-item label="上级租户" v-if="props.mode === 'add'">
+        <el-input :placeholder="props.tenantForm.parentName" disabled />
+      </el-form-item>
+      <el-form-item label="开始时间" prop="startTime">
+        <el-date-picker
+          v-model="tenantForm.startTime"
+          type="datetime"
+          clearable
+          placeholder="请选择开始时间"
+          value-format="YYYY-MM-DD hh:mm:ss"
+        />
+      </el-form-item>
+      <el-form-item label="结束时间" prop="endTime">
+        <el-date-picker
+          v-model="tenantForm.endTime"
+          type="datetime"
+          clearable
+          placeholder="请选择结束时间"
+          value-format="YYYY-MM-DD hh:mm:ss"
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="resetForm(tenantFormRef)">重置</el-button>
+      <el-button type="primary" @click="submitForm(tenantFormRef)">提交</el-button>
+    </template>
+  </el-drawer>
+</template>
+
+<script lang="ts" setup>
+  import { ref } from 'vue';
+  import {
+    ElDrawer,
+    ElForm,
+    ElFormItem,
+    ElInput,
+    ElDatePicker,
+    ElButton,
+    ElMessage,
+  } from 'element-plus';
+  import type { FormInstance, FormRules } from 'element-plus';
+  import type { tenantFormType } from '@/types/tenant/type';
+  import { saveTenantApi, updateTenantApi } from '@/api/tenant/index';
+
+  const props = defineProps<{
+    showAddTenantDrawer: boolean;
+    tenantForm: tenantFormType;
+    mode: 'add' | 'edit';
+  }>();
+  const emit = defineEmits(['closeDrawer', 'loadTenantTable']);
+
+  const tenantFormRef = ref<FormInstance>();
+
+  const rules: FormRules = {
+    tenantName: {
+      required: true,
+      message: '请填写租户名称',
+      trigger: 'blur',
+    },
+    tenantCode: {
+      required: true,
+      message: '请填写租户编码',
+      trigger: 'blur',
+    },
+    startTime: {
+      required: true,
+      message: '请选择租户生效时间',
+      trigger: 'change',
+    },
+    endTime: {
+      required: true,
+      message: '请选择租户失效时间',
+      trigger: 'change',
+    },
+  };
+
+  const submitForm = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return;
+    await formEl.validate((valid) => {
+      if (valid) {
+        if (props.mode === 'add') {
+          saveTenantApi(props.tenantForm).then(() => {
+            emit('closeDrawer');
+            emit('loadTenantTable');
+            ElMessage({
+              type: 'success',
+              message: '添加租户成功',
+            });
+          });
+        } else {
+          updateTenantApi(props.tenantForm).then(() => {
+            emit('closeDrawer');
+            emit('loadTenantTable');
+            ElMessage({
+              type: 'success',
+              message: '修改租户成功',
+            });
+          });
+        }
+      }
+    });
+  };
+
+  const resetForm = (formEl: FormInstance | undefined) => {
+    if (!formEl) return;
+    formEl.resetFields();
+  };
+</script>

+ 167 - 120
src/views/system/tenant/tenant.vue

@@ -1,149 +1,196 @@
 <template>
-  <page-wrapper>
-    <el-card :bordered="false" class="mb-3 proCard">
-      <el-space align="center">
-        <el-input
-          :style="{ width: '320px' }"
-          v-model="params.tenantName"
-          clearable
-          placeholder="请输入租户名称"
-          @keyup.enter="reloadTable"
-        />
-        <el-button type="primary" @click="reloadTable">
-          <template #icon>
-            <el-icon>
-              <SearchOutlined />
-            </el-icon>
-          </template>
-          查询
-        </el-button>
-      </el-space>
-    </el-card>
-    <el-card :bordered="false" class="proCard">
-      <BasicTable
-        :columns="columns"
-        :dataSource="tenantItems"
-        :row-key="(row) => row.id"
-        ref="tableRef"
-        :actionColumn="actionColumn"
-        @update:checked-row-keys="onCheckedRow"
-      >
-        <template #tableTitle>
-          <el-button type="primary" @click="openCreateDrawer">
-            <template #icon>
-              <el-icon>
-                <FileAddOutlined />
-              </el-icon>
-            </template>
-            添加租户
-          </el-button>
+  <div class="tenantPage">
+    <div class="search-bar">
+      <el-input
+        v-model="searchParams.tenantName"
+        clearable
+        placeholder="请输入租户名称"
+        @keyup.enter="loadTenantTable"
+      />
+      <el-button type="primary" @click="loadTenantTable">
+        <template #icon>
+          <el-icon>
+            <SearchOutlined />
+          </el-icon>
         </template>
+        查询
+      </el-button>
+    </div>
 
-        <template #action>
-          <TableAction />
+    <div class="tenant-content">
+      <el-button type="primary" @click="openAddTenantDrawer('add')">
+        <template #icon>
+          <el-icon>
+            <FileAddOutlined />
+          </el-icon>
         </template>
-      </BasicTable>
-    </el-card>
-
-    <CreateDrawer
-      ref="createDrawerRef"
-      :title="drawerTitle"
-      :permissionList="treeData"
-      @change="reloadTable"
-    />
-  </page-wrapper>
+        添加租户
+      </el-button>
+
+      <el-table :data="tenantTable" class="tenant-info-table" row-key="id" default-expand-all>
+        <el-table-column prop="tenantCode" align="center" label="租户编码" />
+        <el-table-column prop="tenantName" align="center" width="200" label="租户名称" />
+        <el-table-column align="center" width="100" label="状态">
+          <template #default="scope">
+            <div class="">
+              {{ TENANT_STATUS_LABEL[scope.row.isDisabled] }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="startTime" align="center" width="200" label="生效时间" />
+        <el-table-column prop="endTime" align="center" width="200" label="失效时间" />
+        <el-table-column align="center" label="操作">
+          <template #default="scope">
+            <div class="operations">
+              <el-button type="primary" @click="openAddTenantDrawer('add', scope.row)">
+                添加下一级
+              </el-button>
+              <el-button type="primary" @click="openAddTenantDrawer('edit', scope.row)">
+                编辑
+              </el-button>
+              <el-button type="primary" @click="handleDelete(scope.row.id)"> 删除 </el-button>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+
+  <AddTenantDrawer
+    :showAddTenantDrawer="showAddTenantDrawer"
+    :mode="tenantDrawerMode"
+    :tenantForm="tenantForm"
+    @closeDrawer="closeTenantDrawer"
+    @loadTenantTable="loadTenantTable"
+  />
 </template>
 
 <script lang="ts" setup>
-  import { reactive, ref, unref, h, onMounted } from 'vue';
-  import { ElMessage } from 'element-plus';
-  import { BasicTable, TableAction, BasicColumn } from '@/components/Table';
-  import { tenantList, deleteTenant } from '@/api/tenant/index';
-  import { columns } from './columns';
+  import { reactive, ref, onMounted } from 'vue';
+  import { ElInput, ElButton, ElIcon, ElTable, ElTableColumn } from 'element-plus';
+  import { ElMessageBox, ElMessage } from 'element-plus';
   import { FileAddOutlined, SearchOutlined } from '@vicons/antd';
-  import CreateDrawer from './CreateDrawer.vue';
-
-  const message = ElMessage;
-  const tableRef = ref();
-  const createDrawerRef = ref();
-  const drawerTitle = ref('添加租户');
-  const treeData = ref([]);
+  import {
+    TenantInfoTreeType,
+    TENANT_STATUS_LABEL,
+    tenantDrawerModeType,
+    tenantFormType,
+  } from '@/types/tenant/type';
+  import AddTenantDrawer from './components/AddTenantDrawer.vue';
+  import { queryTenantTreeApi, deleteTenantApi } from '@/api/tenant/index';
 
-  const tenantItems = ref<any[]>([]);
+  const tenantTable = ref<TenantInfoTreeType>();
 
-  const params = reactive({
+  // drawer相关变量
+  const showAddTenantDrawer = ref<boolean>(false);
+  const tenantDrawerMode = ref<tenantDrawerModeType>('add');
+  // 添加/编辑租户的表单
+  const tenantForm = reactive<tenantFormType>({
+    parentId: 0,
+    parentName: '',
     tenantName: '',
     tenantCode: '',
+    startTime: '',
+    endTime: '',
   });
 
-  const actionColumn: BasicColumn = reactive({
-    width: 150,
-    title: '操作',
-    prop: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableAction as any, {
-        style: 'button',
-        actions: [
-          {
-            label: '删除',
-            isConfirm: true,
-            popConfirm: {
-              onConfirm: handleDelete.bind(null, record.row),
-              title: '您确定要删除吗?',
-              confirmButtonText: '确定',
-              cancelButtonText: '取消',
-            },
-          },
-          {
-            label: '编辑',
-            onClick: handleEdit.bind(null, record.row),
-          },
-        ],
-      });
-    },
+  // 搜索租户变量
+  const searchParams = reactive({
+    tenantName: '',
+    tenantCode: '',
   });
 
-  const loadDataTable = async (res?: any) => {
-    let _params = {
-      ...unref(params),
-      ...res,
-    };
-    const list = await tenantList(_params);
-    tenantItems.value = list;
-  };
-
-  function openCreateDrawer() {
-    const { openDrawer } = createDrawerRef.value;
-    openDrawer();
+  function loadTenantTable() {
+    queryTenantTreeApi(searchParams).then((res) => {
+      tenantTable.value = res;
+    });
   }
 
-  function onCheckedRow(rowKeys: any[]) {
-    console.log(rowKeys);
+  function handleDelete(tenantId: number) {
+    ElMessageBox.confirm('是否删除租户,删除后该租户无法继续使用平台!', '删除租户', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }).then(() => {
+      deleteTenantApi(tenantId).then(() => {
+        loadTenantTable();
+        ElMessage({
+          type: 'success',
+          message: '删除成功',
+        });
+      });
+    });
   }
 
-  function reloadTable() {
-    // tableRef.value.reload();
-    loadDataTable();
+  function openAddTenantDrawer(newTenantDrawerMode: tenantDrawerModeType, row?) {
+    showAddTenantDrawer.value = true;
+    tenantDrawerMode.value = newTenantDrawerMode;
+    // 添加子租户
+    if (newTenantDrawerMode === 'add' && row) {
+      tenantForm.parentId = row.id;
+      tenantForm.parentName = row.tenantName;
+    } else if (newTenantDrawerMode === 'edit') {
+      tenantForm.id = row.id;
+      tenantForm.parentId = undefined;
+      tenantForm.parentName = undefined;
+      tenantForm.tenantName = row.tenantName;
+      tenantForm.tenantCode = row.tenantCode;
+      tenantForm.startTime = row.startTime;
+      tenantForm.endTime = row.endTime;
+    }
+    // 添加父租户
+    else {
+      tenantForm.parentId = 0; //0表示顶层父租户
+      tenantForm.parentName = '顶级租户';
+    }
   }
 
-  function handleEdit(record: Recordable) {
-    console.log('点击了编辑', record);
-    drawerTitle.value = '编辑租户';
-    const { openDrawer } = createDrawerRef.value;
-    openDrawer(record.tenantId);
+  function resetTenantForm() {
+    tenantForm.id = 0;
+    tenantForm.parentId = 0;
+    tenantForm.parentName = '';
+    tenantForm.tenantName = '';
+    tenantForm.tenantCode = '';
+    tenantForm.startTime = '';
+    tenantForm.endTime = '';
   }
 
-  function handleDelete(record: Recordable) {
-    deleteTenant({ id: record.tenantId }).then(() => {
-      message.success('删除成功');
-      reloadTable();
-    });
+  function closeTenantDrawer() {
+    showAddTenantDrawer.value = false;
+    resetTenantForm();
   }
 
-  onMounted(async () => {
-    loadDataTable();
+  onMounted(() => {
+    loadTenantTable();
   });
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+  .tenantPage {
+    height: calc(100vh - 100px);
+    .search-bar {
+      margin-bottom: 10px;
+      padding: 16px;
+      background-color: #fff;
+      .el-input {
+        width: 320px;
+        margin-right: 8px;
+      }
+    }
+
+    .tenant-content {
+      min-height: calc(100% - 60px);
+      padding: 16px;
+      background-color: #fff;
+
+      .el-button {
+        margin-bottom: 10px;
+      }
+      .tenant-info-table {
+        // .el-button {
+        //   width: 30px;
+        // }
+      }
+    }
+  }
+</style>

+ 0 - 8
src/views/system/tenant/types/index.ts

@@ -1,8 +0,0 @@
-export interface formParamsType {
-  tenantId?: number | undefined;
-  tenantName: string;
-  tenantCode: string;
-  beginDate: string | undefined;
-  endDate: string | undefined;
-  tenantStatus: number | undefined;
-}