Commit 407ac853cba1b0e3c6685c95d78f1270d8687023

Authored by xingyu4j
1 parent 88cb5497

feat: tenant

yudao-dependencies/pom.xml
... ... @@ -27,7 +27,6 @@
27 27 <mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
28 28 <dynamic-datasource.version>3.5.2</dynamic-datasource.version>
29 29 <redisson.version>3.18.0</redisson.version>
30   - <!-- Config 配置中心相关 -->
31 30 <!-- 服务保障相关 -->
32 31 <lock4j.version>2.2.2</lock4j.version>
33 32 <resilience4j.version>1.7.1</resilience4j.version>
... ...
yudao-ui-admin-vue3/pnpm-lock.yaml
... ... @@ -28,7 +28,7 @@ specifiers:
28 28 dayjs: ^1.11.6
29 29 echarts: ^5.4.0
30 30 echarts-wordcloud: ^2.0.0
31   - element-plus: 2.2.22
  31 + element-plus: 2.2.21
32 32 eslint: ^8.27.0
33 33 eslint-config-prettier: ^8.5.0
34 34 eslint-define-config: ^1.12.0
... ... @@ -92,7 +92,7 @@ dependencies:
92 92 dayjs: registry.npmmirror.com/dayjs/1.11.6
93 93 echarts: registry.npmmirror.com/echarts/5.4.0
94 94 echarts-wordcloud: registry.npmmirror.com/echarts-wordcloud/2.0.0_echarts@5.4.0
95   - element-plus: registry.npmmirror.com/element-plus/2.2.22_vue@3.2.45
  95 + element-plus: registry.npmmirror.com/element-plus/2.2.21_vue@3.2.45
96 96 intro.js: registry.npmmirror.com/intro.js/6.0.0
97 97 js-cookie: registry.npmmirror.com/js-cookie/3.0.1
98 98 jsencrypt: registry.npmmirror.com/jsencrypt/3.3.1
... ... @@ -3645,11 +3645,11 @@ packages:
3645 3645 version: 1.4.284
3646 3646 dev: true
3647 3647  
3648   - registry.npmmirror.com/element-plus/2.2.22_vue@3.2.45:
3649   - resolution: {integrity: sha512-gg2g2WOMNpWf0wGesymUvTV0VZDF/4khQKroSNeCV/vWJ/cqssPYdtqfGxTiFRt/f+JpyFkV7O1mo0yzMCzrBg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/element-plus/-/element-plus-2.2.22.tgz}
3650   - id: registry.npmmirror.com/element-plus/2.2.22
  3648 + registry.npmmirror.com/element-plus/2.2.21_vue@3.2.45:
  3649 + resolution: {integrity: sha512-wZUePoXZ1zuCkzENK/8mn+mekuLJ9OoGYiudjUujzCf+T8HfOQl+TKQStwOkGBNk93fK8e9YdFIty4jH4AX6dg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/element-plus/-/element-plus-2.2.21.tgz}
  3650 + id: registry.npmmirror.com/element-plus/2.2.21
3651 3651 name: element-plus
3652   - version: 2.2.22
  3652 + version: 2.2.21
3653 3653 peerDependencies:
3654 3654 vue: ^3.2.0
3655 3655 dependencies:
... ...
yudao-ui-admin-vue3/src/api/system/tenant/index.ts
1 1 import request from '@/config/axios'
2   -import type { TenantVO } from './types'
  2 +
  3 +export interface TenantVO {
  4 + id: number
  5 + name: string
  6 + packageId: number
  7 + contactName: string
  8 + contactMobile: string
  9 + username: string
  10 + password: string
  11 + accountCount: number
  12 + expireTime: string
  13 + domain: string
  14 + status: number
  15 + createTime: string
  16 +}
  17 +
  18 +export interface TenantPageReqVO extends PageParam {
  19 + name?: string
  20 + contactName?: string
  21 + contactMobile?: string
  22 + status?: number
  23 +}
  24 +
  25 +export interface TenantExportReqVO {
  26 + name?: string
  27 + contactName?: string
  28 + contactMobile?: string
  29 + status?: number
  30 +}
3 31  
4 32 // 查询租户列表
5   -export const getTenantPageApi = (params) => {
  33 +export const getTenantPageApi = (params: TenantPageReqVO) => {
6 34 return request.get({ url: '/system/tenant/page', params })
7 35 }
8 36  
... ... @@ -27,6 +55,6 @@ export const deleteTenantApi = (id: number) =&gt; {
27 55 }
28 56  
29 57 // 导出租户
30   -export const exportTenantApi = (params) => {
  58 +export const exportTenantApi = (params: TenantExportReqVO) => {
31 59 return request.download({ url: '/system/tenant/export-excel', params })
32 60 }
... ...
yudao-ui-admin-vue3/src/api/system/tenant/types.ts deleted
1   -export type TenantVO = {
2   - id: number
3   - name: string
4   - packageId: number
5   - contactName: string
6   - contactMobile: string
7   - username: string
8   - password: string
9   - accountCount: number
10   - expireTime: string
11   - domain: string
12   - status: number
13   - createTime: string
14   -}
yudao-ui-admin-vue3/src/api/system/tenantPackage/index.ts
1 1 import request from '@/config/axios'
2   -import type { TenantPackageVO } from './types'
  2 +
  3 +export interface TenantPackageVO {
  4 + id: number
  5 + name: string
  6 + status: number
  7 + remark: string
  8 + creator: string
  9 + createTime: string
  10 + updater: string
  11 + updateTime: string
  12 + menuIds: string[]
  13 +}
  14 +
  15 +export interface TenantPackagePageReqVO extends PageParam {
  16 + name?: string
  17 + contactName?: string
  18 + contactMobile?: string
  19 + status?: number
  20 +}
3 21  
4 22 // 查询租户套餐列表
5   -export const getTenantPackageTypePageApi = (params) => {
  23 +export const getTenantPackageTypePageApi = (params: TenantPackagePageReqVO) => {
6 24 return request.get({ url: '/system/tenant-package/page', params })
7 25 }
8 26  
... ... @@ -25,7 +43,7 @@ export const updateTenantPackageTypeApi = (data: TenantPackageVO) =&gt; {
25 43 export const deleteTenantPackageTypeApi = (id: number) => {
26 44 return request.delete({ url: '/system/tenant-package/delete?id=' + id })
27 45 }
28   -// // 获取租户套餐精简信息列表
  46 +// 获取租户套餐精简信息列表
29 47 export const getTenantPackageList = () => {
30 48 return request.get({ url: '/system/tenant-package/get-simple-list' })
31 49 }
... ...
yudao-ui-admin-vue3/src/api/system/tenantPackage/types.ts deleted
1   -export type TenantPackageVO = {
2   - id: number
3   - name: string
4   - status: number
5   - remark: string
6   - creator: string
7   - createTime: string
8   - updater: string
9   - updateTime: string
10   - menuIds: string[]
11   -}
yudao-ui-admin-vue3/src/views/system/tenant/index.vue
1 1 <template>
2   - <!-- 搜索工作区 -->
3 2 <ContentWrap>
4   - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
5   - </ContentWrap>
6   - <ContentWrap>
7   - <!-- 操作工具栏 -->
8   - <div class="mb-10px">
9   - <XButton
10   - type="primary"
11   - preIcon="ep:zoom-in"
12   - :title="t('action.add')"
13   - v-hasPermi="['system:tenant:create']"
14   - @click="handleCreate()"
15   - />
16   - <XButton
17   - type="warning"
18   - preIcon="ep:download"
19   - :title="t('action.export')"
20   - v-hasPermi="['system:tenant:export']"
21   - @click="exportList('租户数据.xls')"
22   - />
23   - </div>
24 3 <!-- 列表 -->
25   - <Table
26   - :columns="allSchemas.tableColumns"
27   - :selection="false"
28   - :data="tableObject.tableList"
29   - :loading="tableObject.loading"
30   - :pagination="{
31   - total: tableObject.total
32   - }"
33   - v-model:pageSize="tableObject.pageSize"
34   - v-model:currentPage="tableObject.currentPage"
35   - @register="register"
36   - >
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  5 + <template #toolbar_buttons>
  6 + <!-- 操作:新增 -->
  7 + <XButton
  8 + type="primary"
  9 + preIcon="ep:zoom-in"
  10 + :title="t('action.add')"
  11 + v-hasPermi="['system:tenant:create']"
  12 + @click="handleCreate()"
  13 + />
  14 + <XButton
  15 + type="warning"
  16 + preIcon="ep:download"
  17 + :title="t('action.export')"
  18 + v-hasPermi="['system:tenant:export']"
  19 + @click="handleExport()"
  20 + />
  21 + </template>
37 22 <template #accountCount="{ row }">
38 23 <el-tag> {{ row.accountCount }} </el-tag>
39 24 </template>
40   - <template #status="{ row }">
41   - <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
42   - </template>
43 25 <template #packageId="{ row }">
44 26 <el-tag v-if="row.packageId === 0" type="danger">系统租户</el-tag>
45 27 <el-tag v-else type="success"> {{ getPackageName(row.packageId) }} </el-tag>
46 28 </template>
47   - <template #expireTime="{ row }">
48   - <span>{{ dayjs(row.expireTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
49   - </template>
50   - <template #createTime="{ row }">
51   - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
52   - </template>
53   - <template #action="{ row }">
  29 + <template #actionbtns_default="{ row }">
54 30 <!-- 操作:修改 -->
55 31 <XTextButton
56 32 preIcon="ep:edit"
57 33 :title="t('action.edit')"
58 34 v-hasPermi="['system:tenant:update']"
59   - @click="handleUpdate(row)"
  35 + @click="handleUpdate(row.id)"
60 36 />
61 37 <!-- 操作:详情 -->
62 38 <XTextButton
63 39 preIcon="ep:view"
64 40 :title="t('action.detail')"
65 41 v-hasPermi="['system:tenant:update']"
66   - @click="handleDetail(row)"
  42 + @click="handleDetail(row.id)"
67 43 />
68 44 <!-- 操作:删除 -->
69 45 <XTextButton
70 46 preIcon="ep:delete"
71 47 :title="t('action.del')"
72 48 v-hasPermi="['system:tenant:delete']"
73   - @click="delList(row.id, false)"
  49 + @click="handleDelete(row.id)"
74 50 />
75 51 </template>
76   - </Table>
  52 + </vxe-grid>
77 53 </ContentWrap>
78 54  
79 55 <XModal v-model="dialogVisible" :title="dialogTitle">
... ... @@ -124,27 +100,33 @@
124 100 <script setup lang="ts">
125 101 import { ref, unref, onMounted } from 'vue'
126 102 import dayjs from 'dayjs'
127   -import { ElMessage, ElTag, ElSelect, ElOption } from 'element-plus'
128   -import { DICT_TYPE } from '@/utils/dict'
129   -import { useTable } from '@/hooks/web/useTable'
130 103 import { useI18n } from '@/hooks/web/useI18n'
  104 +import { useMessage } from '@/hooks/web/useMessage'
  105 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
  106 +import { VxeGridInstance } from 'vxe-table'
  107 +import { ElTag, ElSelect, ElOption } from 'element-plus'
131 108 import { FormExpose } from '@/components/Form'
132   -import type { TenantVO } from '@/api/system/tenant/types'
133   -import { rules, allSchemas } from './tenant.data'
134 109 import * as TenantApi from '@/api/system/tenant'
135   -import { getTenantPackageList } from '@/api/system/tenantPackage'
136   -import { TenantPackageVO } from '@/api/system/tenantPackage/types'
137   -const { t } = useI18n() // 国际化
  110 +import { rules, allSchemas } from './tenant.data'
  111 +import { getTenantPackageList, TenantPackageVO } from '@/api/system/tenantPackage'
138 112  
139   -// ========== 列表相关 ==========
140   -const { register, tableObject, methods } = useTable<TenantVO>({
  113 +const { t } = useI18n() // 国际化
  114 +const message = useMessage() // 消息弹窗
  115 +// 列表相关的变量
  116 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  117 +const { gridOptions, getList, deleteData, exportList } = useVxeGrid<TenantApi.TenantVO>({
  118 + allSchemas: allSchemas,
141 119 getListApi: TenantApi.getTenantPageApi,
142   - delListApi: TenantApi.deleteTenantApi,
  120 + deleteApi: TenantApi.deleteTenantApi,
143 121 exportListApi: TenantApi.exportTenantApi
144 122 })
145   -const { getList, setSearchParams, delList, exportList } = methods
146 123  
147   -// ========== 套餐 ==========
  124 +const actionLoading = ref(false) // 遮罩层
  125 +const actionType = ref('') // 操作按钮的类型
  126 +const dialogVisible = ref(false) // 是否显示弹出层
  127 +const dialogTitle = ref('edit') // 弹出层标题
  128 +const formRef = ref<FormExpose>() // 表单 Ref
  129 +const detailRef = ref() // 详情 Ref
148 130 const tenantPackageId = ref() // 套餐
149 131 const tenantPackageOptions = ref<TenantPackageVO[]>([]) //套餐列表
150 132  
... ... @@ -160,12 +142,6 @@ const getPackageName = (packageId: number) =&gt; {
160 142 }
161 143 return '未知套餐'
162 144 }
163   -// ========== CRUD 相关 ==========
164   -const actionLoading = ref(false) // 遮罩层
165   -const actionType = ref('') // 操作按钮的类型
166   -const dialogVisible = ref(false) // 是否显示弹出层
167   -const dialogTitle = ref('edit') // 弹出层标题
168   -const formRef = ref<FormExpose>() // 表单 Ref
169 145  
170 146 // 设置标题
171 147 const setDialogTile = (type: string) => {
... ... @@ -182,15 +158,34 @@ const handleCreate = () =&gt; {
182 158 }
183 159  
184 160 // 修改操作
185   -const handleUpdate = async (row: any) => {
  161 +const handleUpdate = async (rowId: number) => {
186 162 setDialogTile('update')
187 163 // 设置数据
188   - const res = await TenantApi.getTenantApi(row.id)
  164 + const res = await TenantApi.getTenantApi(rowId)
189 165 tenantPackageId.value = res.packageId
190 166 res.expireTime = dayjs(res.expireTime).format('YYYY-MM-DD HH:mm:ss')
191 167 unref(formRef)?.setValues(res)
192 168 }
193 169  
  170 +// 详情操作
  171 +const handleDetail = async (rowId: number) => {
  172 + // 设置数据
  173 + const res = await TenantApi.getTenantApi(rowId)
  174 + tenantPackageId.value = res.packageId
  175 + detailRef.value = res
  176 + setDialogTile('detail')
  177 +}
  178 +
  179 +// 删除操作
  180 +const handleDelete = async (rowId: number) => {
  181 + await deleteData(xGrid, rowId)
  182 +}
  183 +
  184 +// 导出操作
  185 +const handleExport = async () => {
  186 + await exportList(xGrid, '租户列表.xls')
  187 +}
  188 +
194 189 // 提交按钮
195 190 const submitForm = async () => {
196 191 const elForm = unref(formRef)?.getElFormRef()
... ... @@ -200,40 +195,30 @@ const submitForm = async () =&gt; {
200 195 actionLoading.value = true
201 196 // 提交请求
202 197 try {
203   - const data = unref(formRef)?.formModel as TenantVO
  198 + const data = unref(formRef)?.formModel as TenantApi.TenantVO
204 199 data.packageId = tenantPackageId.value
205 200 if (actionType.value === 'create') {
206 201 data.expireTime = dayjs(data.expireTime).valueOf().toString()
207 202 await TenantApi.createTenantApi(data)
208   - ElMessage.success(t('common.createSuccess'))
  203 + message.success(t('common.createSuccess'))
209 204 } else {
210 205 data.expireTime = dayjs(data.expireTime).valueOf().toString()
211 206 await TenantApi.updateTenantApi(data)
212   - ElMessage.success(t('common.updateSuccess'))
  207 + message.success(t('common.updateSuccess'))
213 208 }
214 209 // 操作成功,重新加载列表
215 210 dialogVisible.value = false
216   - await getList()
217 211 } finally {
218 212 actionLoading.value = false
  213 + // 刷新列表
  214 + await getList(xGrid)
219 215 }
220 216 }
221 217 })
222 218 }
223 219  
224   -// ========== 详情相关 ==========
225   -const detailRef = ref() // 详情 Ref
226   -
227   -// 详情操作
228   -const handleDetail = async (row: any) => {
229   - // 设置数据
230   - detailRef.value = row
231   - setDialogTile('detail')
232   -}
233   -
234 220 // ========== 初始化 ==========
235 221 onMounted(async () => {
236   - await getList()
237 222 await getTenantPackageOptions()
238 223 })
239 224 </script>
... ...
yudao-ui-admin-vue3/src/views/system/tenant/tenant.data.ts
1 1 import { reactive } from 'vue'
2 2 import { useI18n } from '@/hooks/web/useI18n'
3 3 import { required } from '@/utils/formRules'
4   -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
5 4 import { DICT_TYPE } from '@/utils/dict'
  5 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
6 6 const { t } = useI18n() // 国际化
7 7  
8 8 // 表单校验
... ... @@ -18,115 +18,82 @@ export const rules = reactive({
18 18 })
19 19  
20 20 // CrudSchema.
21   -const crudSchemas = reactive<CrudSchema[]>([
22   - {
23   - label: t('common.index'),
24   - field: 'id',
25   - type: 'index',
26   - form: {
27   - show: false
  21 +const crudSchemas = reactive<VxeCrudSchema>({
  22 + primaryKey: 'id',
  23 + primaryType: 'seq',
  24 + action: true,
  25 + columns: [
  26 + {
  27 + title: '租户名称',
  28 + field: 'name',
  29 + isSearch: true
28 30 },
29   - detail: {
30   - show: false
31   - }
32   - },
33   - {
34   - label: '租户名称',
35   - field: 'name',
36   - search: {
37   - show: true
38   - }
39   - },
40   - {
41   - label: '租户套餐',
42   - field: 'packageId'
43   - },
44   - {
45   - label: '联系人',
46   - field: 'contactName',
47   - search: {
48   - show: true
49   - }
50   - },
51   - {
52   - label: '联系手机',
53   - field: 'contactMobile',
54   - search: {
55   - show: true
56   - }
57   - },
58   - {
59   - label: '用户名称',
60   - field: 'username',
61   - table: {
62   - show: false
  31 + {
  32 + title: '租户套餐',
  33 + field: 'packageId'
63 34 },
64   - detail: {
65   - show: false
66   - }
67   - },
68   - {
69   - label: '用户密码',
70   - field: 'password',
71   - table: {
72   - show: false
  35 + {
  36 + title: '联系人',
  37 + field: 'contactName',
  38 + isSearch: true
73 39 },
74   - detail: {
75   - show: false
  40 + {
  41 + title: '联系手机',
  42 + field: 'contactMobile',
  43 + isSearch: true
76 44 },
77   - form: {
78   - component: 'InputPassword'
79   - }
80   - },
81   - {
82   - label: '账号额度',
83   - field: 'accountCount',
84   - form: {
85   - component: 'InputNumber'
86   - }
87   - },
88   - {
89   - label: '过期时间',
90   - field: 'expireTime',
91   - form: {
92   - show: true,
93   - component: 'DatePicker',
94   - componentProps: {
95   - type: 'datetime',
96   - valueFormat: 'x'
  45 + {
  46 + title: '用户名称',
  47 + field: 'username',
  48 + isTable: false,
  49 + isDetail: false
  50 + },
  51 + {
  52 + title: '用户密码',
  53 + field: 'password',
  54 + isTable: false,
  55 + isDetail: false,
  56 + form: {
  57 + component: 'InputPassword'
97 58 }
98   - }
99   - },
100   - {
101   - label: '绑定域名',
102   - field: 'domain'
103   - },
104   - {
105   - label: '租户状态',
106   - field: 'status',
107   - dictType: DICT_TYPE.COMMON_STATUS,
108   - dictClass: 'number',
109   - search: {
110   - show: true
111   - }
112   - },
113   - {
114   - label: t('table.createTime'),
115   - field: 'createTime',
116   - form: {
117   - show: false
118   - }
119   - },
120   - {
121   - label: t('table.action'),
122   - field: 'action',
123   - width: '240px',
124   - form: {
125   - show: false
126 59 },
127   - detail: {
128   - show: false
  60 + {
  61 + title: '账号额度',
  62 + field: 'accountCount',
  63 + form: {
  64 + component: 'InputNumber'
  65 + }
  66 + },
  67 + {
  68 + title: '过期时间',
  69 + field: 'expireTime',
  70 + formatter: 'formatDate',
  71 + form: {
  72 + show: true,
  73 + component: 'DatePicker',
  74 + componentProps: {
  75 + type: 'datetime',
  76 + valueFormat: 'x'
  77 + }
  78 + }
  79 + },
  80 + {
  81 + title: '绑定域名',
  82 + field: 'domain'
  83 + },
  84 + {
  85 + title: '租户状态',
  86 + field: 'status',
  87 + dictType: DICT_TYPE.COMMON_STATUS,
  88 + dictClass: 'number',
  89 + isSearch: true
  90 + },
  91 + {
  92 + title: t('table.createTime'),
  93 + field: 'createTime',
  94 + formatter: 'formatDate',
  95 + isForm: false
129 96 }
130   - }
131   -])
132   -export const { allSchemas } = useCrudSchemas(crudSchemas)
  97 + ]
  98 +})
  99 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
... ...
yudao-ui-admin-vue3/src/views/system/tenantPackage/index.vue
1 1 <template>
2   - <!-- 搜索工作区 -->
3 2 <ContentWrap>
4   - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
5   - </ContentWrap>
6   - <ContentWrap>
7   - <!-- 操作工具栏 -->
8   - <div class="mb-10px">
9   - <XButton
10   - type="primary"
11   - preIcon="ep:zoom-in"
12   - :title="t('action.add')"
13   - @click="handleCreate()"
14   - />
15   - </div>
16 3 <!-- 列表 -->
17   - <Table
18   - :columns="allSchemas.tableColumns"
19   - :selection="false"
20   - :data="tableObject.tableList"
21   - :loading="tableObject.loading"
22   - :pagination="{
23   - total: tableObject.total
24   - }"
25   - v-model:pageSize="tableObject.pageSize"
26   - v-model:currentPage="tableObject.currentPage"
27   - @register="register"
28   - >
29   - <template #status="{ row }">
30   - <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
31   - </template>
32   - <template #createTime="{ row }">
33   - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  5 + <template #toolbar_buttons>
  6 + <XButton
  7 + type="primary"
  8 + preIcon="ep:zoom-in"
  9 + :title="t('action.add')"
  10 + @click="handleCreate()"
  11 + />
34 12 </template>
35   - <template #action="{ row }">
36   - <XTextButton preIcon="ep:edit" :title="t('action.edit')" @click="handleUpdate(row)" />
37   - <XTextButton preIcon="ep:delete" :title="t('action.del')" @click="delList(row.id, false)" />
  13 + <template #actionbtns_default="{ row }">
  14 + <XTextButton preIcon="ep:edit" :title="t('action.edit')" @click="handleUpdate(row.id)" />
  15 + <XTextButton preIcon="ep:delete" :title="t('action.del')" @click="handleDelete(row.id)" />
38 16 </template>
39   - </Table>
  17 + </vxe-grid>
40 18 </ContentWrap>
41 19  
42 20 <XModal v-model="dialogVisible" :title="dialogTitle">
... ... @@ -89,28 +67,39 @@
89 67 </template>
90 68 <script setup lang="ts">
91 69 import { onMounted, ref, unref } from 'vue'
92   -import dayjs from 'dayjs'
93 70 import { handleTree } from '@/utils/tree'
94   -import { DICT_TYPE } from '@/utils/dict'
95   -import { useTable } from '@/hooks/web/useTable'
96 71 import { useI18n } from '@/hooks/web/useI18n'
  72 +import { useMessage } from '@/hooks/web/useMessage'
  73 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
  74 +import { VxeGridInstance } from 'vxe-table'
97 75 import { FormExpose } from '@/components/Form'
98   -import { TenantPackageVO } from '@/api/system/tenantPackage/types'
99   -import { ElMessage, ElCard, ElSwitch, ElTree } from 'element-plus'
  76 +import { ElCard, ElSwitch, ElTree } from 'element-plus'
  77 +// 业务相关的 import
100 78 import { rules, allSchemas } from './tenantPackage.data'
101 79 import * as TenantPackageApi from '@/api/system/tenantPackage'
102 80 import { listSimpleMenusApi } from '@/api/system/menu'
  81 +
103 82 const { t } = useI18n() // 国际化
  83 +const message = useMessage() // 消息弹窗
  84 +
  85 +const menuOptions = ref<any[]>([]) // 树形结构
  86 +const menuExpand = ref(false)
  87 +const menuNodeAll = ref(false)
  88 +const treeRef = ref<InstanceType<typeof ElTree>>()
  89 +const treeNodeAll = ref(false)
  90 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  91 +const formRef = ref<FormExpose>() // 表单 Ref
  92 +const loading = ref(false) // 遮罩层
  93 +const actionType = ref('') // 操作按钮的类型
  94 +const dialogVisible = ref(false) // 是否显示弹出层
  95 +const dialogTitle = ref('edit') // 弹出层标题
104 96  
105 97 const defaultProps = {
106 98 children: 'children',
107 99 label: 'name',
108 100 value: 'id'
109 101 }
110   -// ========== 创建菜单树结构 ==========
111   -const menuOptions = ref<any[]>([]) // 树形结构
112   -const treeRef = ref<InstanceType<typeof ElTree>>()
113   -const treeNodeAll = ref(false)
  102 +
114 103 // 全选/全不选
115 104 const handleCheckedTreeNodeAll = () => {
116 105 treeRef.value!.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
... ... @@ -119,22 +108,12 @@ const getTree = async () =&gt; {
119 108 const res = await listSimpleMenusApi()
120 109 menuOptions.value = handleTree(res)
121 110 }
122   -const menuExpand = ref(false)
123   -const menuNodeAll = ref(false)
124 111  
125   -// ========== 列表相关 ==========
126   -const { register, tableObject, methods } = useTable<TenantPackageVO>({
  112 +const { gridOptions, getList, deleteData } = useVxeGrid<TenantPackageApi.TenantPackageVO>({
  113 + allSchemas: allSchemas,
127 114 getListApi: TenantPackageApi.getTenantPackageTypePageApi,
128   - delListApi: TenantPackageApi.deleteTenantPackageTypeApi
  115 + deleteApi: TenantPackageApi.deleteTenantPackageTypeApi
129 116 })
130   -const { getList, setSearchParams, delList } = methods
131   -
132   -// ========== CRUD 相关 ==========
133   -const loading = ref(false) // 遮罩层
134   -const formRef = ref<FormExpose>() // 表单 Ref
135   -const actionType = ref('') // 操作按钮的类型
136   -const dialogVisible = ref(false) // 是否显示弹出层
137   -const dialogTitle = ref('edit') // 弹出层标题
138 117  
139 118 // 设置标题
140 119 const setDialogTile = (type: string) => {
... ... @@ -153,14 +132,20 @@ const handleCreate = () =&gt; {
153 132 }
154 133  
155 134 // 修改操作
156   -const handleUpdate = async (row: any) => {
  135 +const handleUpdate = async (rowId: number) => {
157 136 setDialogTile('update')
158 137 // 设置数据
159   - const res = await TenantPackageApi.getTenantPackageApi(row.id)
  138 + const res = await TenantPackageApi.getTenantPackageApi(rowId)
160 139 unref(formRef)?.setValues(res)
161 140 // 设置选中
162 141 unref(treeRef)?.setCheckedKeys(res.menuIds)
163 142 }
  143 +
  144 +// 删除操作
  145 +const handleDelete = async (rowId: number) => {
  146 + await deleteData(xGrid, rowId)
  147 +}
  148 +
164 149 // 提交按钮
165 150 const submitForm = async () => {
166 151 const elForm = unref(formRef)?.getElFormRef()
... ... @@ -170,20 +155,21 @@ const submitForm = async () =&gt; {
170 155 loading.value = true
171 156 // 提交请求
172 157 try {
173   - const data = unref(formRef)?.formModel as TenantPackageVO
  158 + const data = unref(formRef)?.formModel as TenantPackageApi.TenantPackageVO
174 159 data.menuIds = treeRef.value!.getCheckedKeys(false) as string[]
175 160 if (actionType.value === 'create') {
176 161 await TenantPackageApi.createTenantPackageTypeApi(data)
177   - ElMessage.success(t('common.createSuccess'))
  162 + message.success(t('common.createSuccess'))
178 163 } else {
179 164 await TenantPackageApi.updateTenantPackageTypeApi(data)
180   - ElMessage.success(t('common.updateSuccess'))
  165 + message.success(t('common.updateSuccess'))
181 166 }
182 167 // 操作成功,重新加载列表
183 168 dialogVisible.value = false
184   - await getList()
185 169 } finally {
186 170 loading.value = false
  171 + // 刷新列表
  172 + await getList(xGrid)
187 173 }
188 174 }
189 175 })
... ... @@ -191,7 +177,6 @@ const submitForm = async () =&gt; {
191 177  
192 178 // ========== 初始化 ==========
193 179 onMounted(async () => {
194   - await getList()
195 180 await getTree()
196 181 })
197 182 // getList()
... ...
yudao-ui-admin-vue3/src/views/system/tenantPackage/tenantPackage.data.ts
1 1 import { reactive } from 'vue'
2 2 import { required } from '@/utils/formRules'
3 3 import { useI18n } from '@/hooks/web/useI18n'
4   -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
5 4 import { DICT_TYPE } from '@/utils/dict'
  5 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
6 6 const { t } = useI18n() // 国际化
7 7  
8 8 // 表单校验
... ... @@ -16,75 +16,49 @@ export const rules = reactive({
16 16 })
17 17  
18 18 // CrudSchema
19   -const crudSchemas = reactive<CrudSchema[]>([
20   - {
21   - label: t('common.index'),
22   - field: 'id',
23   - type: 'index',
24   - form: {
25   - show: false
  19 +const crudSchemas = reactive<VxeCrudSchema>({
  20 + primaryKey: 'id',
  21 + primaryType: 'seq',
  22 + action: true,
  23 + columns: [
  24 + {
  25 + title: '套餐名称',
  26 + field: 'name',
  27 + isSearch: true
26 28 },
27   - detail: {
28   - show: false
29   - }
30   - },
31   - {
32   - label: '套餐名称',
33   - field: 'name',
34   - search: {
35   - show: true
36   - }
37   - },
38   - {
39   - label: t('common.status'),
40   - field: 'status',
41   - dictType: DICT_TYPE.COMMON_STATUS,
42   - dictClass: 'number',
43   - search: {
44   - show: true
45   - }
46   - },
47   - {
48   - label: '菜单权限',
49   - field: 'menuIds',
50   - table: {
51   - show: false
52   - }
53   - },
54   - {
55   - label: t('form.remark'),
56   - field: 'remark',
57   - form: {
58   - component: 'Input',
59   - componentProps: {
60   - type: 'textarea',
61   - rows: 4
62   - },
63   - colProps: {
64   - span: 24
65   - }
  29 + {
  30 + title: t('common.status'),
  31 + field: 'status',
  32 + dictType: DICT_TYPE.COMMON_STATUS,
  33 + dictClass: 'number',
  34 + isSearch: true
66 35 },
67   - table: {
68   - show: false
69   - }
70   - },
71   - {
72   - label: '创建时间',
73   - field: 'createTime',
74   - form: {
75   - show: false
76   - }
77   - },
78   - {
79   - label: t('table.action'),
80   - field: 'action',
81   - width: '240px',
82   - form: {
83   - show: false
  36 + {
  37 + title: '菜单权限',
  38 + field: 'menuIds',
  39 + isTable: false
84 40 },
85   - detail: {
86   - show: false
  41 + {
  42 + title: t('form.remark'),
  43 + field: 'remark',
  44 + isTable: false,
  45 + form: {
  46 + component: 'Input',
  47 + componentProps: {
  48 + type: 'textarea',
  49 + rows: 4
  50 + },
  51 + colProps: {
  52 + span: 24
  53 + }
  54 + }
  55 + },
  56 + {
  57 + title: '创建时间',
  58 + field: 'createTime',
  59 + formatter: 'formatDate',
  60 + isForm: false
87 61 }
88   - }
89   -])
90   -export const { allSchemas } = useCrudSchemas(crudSchemas)
  62 + ]
  63 +})
  64 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
... ...