Commit 8cfc0736faf6a303ebfaee523d9bfc059f1ccdac

Authored by xingyu4j
1 parent 753d8dda

refactor: use vxeCrud refactor menus

yudao-ui-admin-vue3/src/router/index.ts
@@ -14,7 +14,7 @@ import { usePermissionStoreWithOut } from '@/store/modules/permission' @@ -14,7 +14,7 @@ import { usePermissionStoreWithOut } from '@/store/modules/permission'
14 import { getInfoApi } from '@/api/login' 14 import { getInfoApi } from '@/api/login'
15 import { listSimpleDictDataApi } from '@/api/system/dict/dict.data' 15 import { listSimpleDictDataApi } from '@/api/system/dict/dict.data'
16 16
17 -const { wsCache } = useCache('sessionStorage') 17 +const { wsCache } = useCache()
18 18
19 const { start, done } = useNProgress() 19 const { start, done } = useNProgress()
20 20
yudao-ui-admin-vue3/src/views/system/dept/dept.data.ts
@@ -12,8 +12,7 @@ export const rules = reactive({ @@ -12,8 +12,7 @@ export const rules = reactive({
12 email: [required], 12 email: [required],
13 phone: [ 13 phone: [
14 { 14 {
15 - min: 11,  
16 - max: 11, 15 + len: 11,
17 trigger: 'blur', 16 trigger: 'blur',
18 message: '请输入正确的手机号码' 17 message: '请输入正确的手机号码'
19 } 18 }
yudao-ui-admin-vue3/src/views/system/dept/index.vue
@@ -75,16 +75,15 @@ @@ -75,16 +75,15 @@
75 </XModal> 75 </XModal>
76 </template> 76 </template>
77 <script setup lang="ts" name="Dept"> 77 <script setup lang="ts" name="Dept">
78 -import { nextTick, onMounted, reactive, ref, unref } from 'vue' 78 +import { nextTick, onMounted, ref, unref } from 'vue'
79 import { ElSelect, ElTreeSelect, ElOption } from 'element-plus' 79 import { ElSelect, ElTreeSelect, ElOption } from 'element-plus'
80 import { VxeGridInstance } from 'vxe-table' 80 import { VxeGridInstance } from 'vxe-table'
81 import { handleTree, defaultProps } from '@/utils/tree' 81 import { handleTree, defaultProps } from '@/utils/tree'
82 -import { required } from '@/utils/formRules.js'  
83 import { useI18n } from '@/hooks/web/useI18n' 82 import { useI18n } from '@/hooks/web/useI18n'
84 import { useMessage } from '@/hooks/web/useMessage' 83 import { useMessage } from '@/hooks/web/useMessage'
85 import { useVxeGrid } from '@/hooks/web/useVxeGrid' 84 import { useVxeGrid } from '@/hooks/web/useVxeGrid'
86 import { FormExpose } from '@/components/Form' 85 import { FormExpose } from '@/components/Form'
87 -import { allSchemas } from './dept.data' 86 +import { allSchemas, rules } from './dept.data'
88 import * as DeptApi from '@/api/system/dept' 87 import * as DeptApi from '@/api/system/dept'
89 import { getListSimpleUsersApi, UserVO } from '@/api/system/user' 88 import { getListSimpleUsersApi, UserVO } from '@/api/system/user'
90 89
@@ -107,13 +106,6 @@ const actionLoading = ref(false) // 遮罩层 @@ -107,13 +106,6 @@ const actionLoading = ref(false) // 遮罩层
107 const formRef = ref<FormExpose>() // 表单 Ref 106 const formRef = ref<FormExpose>() // 表单 Ref
108 const deptOptions = ref() // 树形结构 107 const deptOptions = ref() // 树形结构
109 const userOption = ref<UserVO[]>([]) 108 const userOption = ref<UserVO[]>([])
110 -// 新增和修改的表单校验  
111 -const rules = reactive({  
112 - name: [required],  
113 - sort: [required],  
114 - path: [required],  
115 - status: [required]  
116 -})  
117 109
118 const getUserList = async () => { 110 const getUserList = async () => {
119 const res = await getListSimpleUsersApi() 111 const res = await getListSimpleUsersApi()
yudao-ui-admin-vue3/src/views/system/menu/index.vue
1 <template> 1 <template>
2 <ContentWrap> 2 <ContentWrap>
3 - <!-- 搜索工作栏 -->  
4 - <el-form :model="queryParams" ref="queryForm" :inline="true">  
5 - <el-form-item label="菜单名称" prop="name">  
6 - <el-input v-model="queryParams.name" placeholder="请输入菜单名称" />  
7 - </el-form-item>  
8 - <el-form-item label="状态" prop="status">  
9 - <el-select v-model="queryParams.status" placeholder="请选择菜单状态">  
10 - <el-option  
11 - v-for="(dict, index) in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"  
12 - :key="index"  
13 - :label="dict.label"  
14 - :value="dict.value"  
15 - />  
16 - </el-select>  
17 - </el-form-item>  
18 - <el-form-item>  
19 - <!-- 操作:搜索 -->  
20 - <XButton  
21 - type="primary"  
22 - preIcon="ep:search"  
23 - :title="t('common.query')"  
24 - @click="handleQuery()"  
25 - />  
26 - <!-- 操作:重置 -->  
27 - <XButton preIcon="ep:refresh-right" :title="t('common.reset')" @click="resetQuery()" />  
28 - </el-form-item>  
29 - </el-form>  
30 - <vxe-toolbar>  
31 - <template #buttons> 3 + <!-- 列表 -->
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" show-overflow class="xtable-scrollbar">
  5 + <template #toolbar_buttons>
32 <!-- 操作:新增 --> 6 <!-- 操作:新增 -->
33 <XButton 7 <XButton
34 type="primary" 8 type="primary"
@@ -37,63 +11,26 @@ @@ -37,63 +11,26 @@
37 v-hasPermi="['system:menu:create']" 11 v-hasPermi="['system:menu:create']"
38 @click="handleCreate()" 12 @click="handleCreate()"
39 /> 13 />
40 - <XButton title="展开所有" @click="xTable?.setAllTreeExpand(true)" />  
41 - <XButton title="关闭所有" @click="xTable?.clearTreeExpand()" /> 14 + <XButton title="展开所有" @click="xGrid?.setAllTreeExpand(true)" />
  15 + <XButton title="关闭所有" @click="xGrid?.clearTreeExpand()" />
42 </template> 16 </template>
43 - </vxe-toolbar>  
44 - <!-- 列表 -->  
45 - <vxe-table  
46 - show-overflow  
47 - keep-source  
48 - ref="xTable"  
49 - :loading="tableLoading"  
50 - :row-config="{ keyField: 'id' }"  
51 - :column-config="{ resizable: true }"  
52 - :tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"  
53 - :print-config="{}"  
54 - :export-config="{}"  
55 - :data="tableData"  
56 - >  
57 - <vxe-column title="菜单名称" field="name" width="200" tree-node>  
58 - <template #default="{ row }">  
59 - <Icon :icon="row.icon" />  
60 - <span class="ml-3">{{ row.name }}</span>  
61 - </template>  
62 - </vxe-column>  
63 - <vxe-column title="菜单类型" field="type">  
64 - <template #default="{ row }">  
65 - <DictTag :type="DICT_TYPE.SYSTEM_MENU_TYPE" :value="row.type" />  
66 - </template>  
67 - </vxe-column>  
68 - <vxe-column title="路由地址" field="path" />  
69 - <vxe-column title="组件路径" field="component" />  
70 - <vxe-column title="权限标识" field="permission" />  
71 - <vxe-column title="排序" field="sort" />  
72 - <vxe-column title="状态" field="status">  
73 - <template #default="{ row }">  
74 - <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />  
75 - </template>  
76 - </vxe-column>  
77 - <vxe-column title="创建时间" field="createTime" formatter="formatDate" />  
78 - <vxe-column title="操作" width="200">  
79 - <template #default="{ row }">  
80 - <!-- 操作:修改 -->  
81 - <XTextButton  
82 - preIcon="ep:edit"  
83 - :title="t('action.edit')"  
84 - v-hasPermi="['system:menu:update']"  
85 - @click="handleUpdate(row.id)"  
86 - />  
87 - <!-- 操作:删除 -->  
88 - <XTextButton  
89 - preIcon="ep:delete"  
90 - :title="t('action.del')"  
91 - v-hasPermi="['system:menu:delete']"  
92 - @click="handleDelete(row.id)"  
93 - />  
94 - </template>  
95 - </vxe-column>  
96 - </vxe-table> 17 + <template #actionbtns_default="{ row }">
  18 + <!-- 操作:修改 -->
  19 + <XTextButton
  20 + preIcon="ep:edit"
  21 + :title="t('action.edit')"
  22 + v-hasPermi="['system:menu:update']"
  23 + @click="handleUpdate(row.id)"
  24 + />
  25 + <!-- 操作:删除 -->
  26 + <XTextButton
  27 + preIcon="ep:delete"
  28 + :title="t('action.del')"
  29 + v-hasPermi="['system:menu:delete']"
  30 + @click="handleDelete(row.id)"
  31 + />
  32 + </template>
  33 + </vxe-grid>
97 </ContentWrap> 34 </ContentWrap>
98 <!-- 添加或修改菜单对话框 --> 35 <!-- 添加或修改菜单对话框 -->
99 <XModal id="menuModel" v-model="dialogVisible" :title="dialogTitle"> 36 <XModal id="menuModel" v-model="dialogVisible" :title="dialogTitle">
@@ -235,7 +172,7 @@ @@ -235,7 +172,7 @@
235 </template> 172 </template>
236 <script setup lang="ts" name="Menu"> 173 <script setup lang="ts" name="Menu">
237 // 全局相关的 import 174 // 全局相关的 import
238 -import { onMounted, reactive, ref } from 'vue' 175 +import { ref } from 'vue'
239 import { useI18n } from '@/hooks/web/useI18n' 176 import { useI18n } from '@/hooks/web/useI18n'
240 import { CACHE_KEY, useCache } from '@/hooks/web/useCache' 177 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
241 import { useMessage } from '@/hooks/web/useMessage' 178 import { useMessage } from '@/hooks/web/useMessage'
@@ -245,9 +182,7 @@ import { @@ -245,9 +182,7 @@ import {
245 ElFormItem, 182 ElFormItem,
246 ElInput, 183 ElInput,
247 ElInputNumber, 184 ElInputNumber,
248 - ElSelect,  
249 ElTreeSelect, 185 ElTreeSelect,
250 - ElOption,  
251 ElRadio, 186 ElRadio,
252 ElRadioGroup, 187 ElRadioGroup,
253 ElRadioButton, 188 ElRadioButton,
@@ -255,21 +190,33 @@ import { @@ -255,21 +190,33 @@ import {
255 } from 'element-plus' 190 } from 'element-plus'
256 import { Tooltip } from '@/components/Tooltip' 191 import { Tooltip } from '@/components/Tooltip'
257 import { IconSelect } from '@/components/Icon' 192 import { IconSelect } from '@/components/Icon'
258 -import { VxeTableInstance } from 'vxe-table' 193 +import { VxeGridInstance } from 'vxe-table'
259 // 业务相关的 import 194 // 业务相关的 import
260 -import * as MenuApi from '@/api/system/menu'  
261 -import { required } from '@/utils/formRules.js'  
262 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 195 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
263 import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' 196 import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants'
264 import { handleTree, defaultProps } from '@/utils/tree' 197 import { handleTree, defaultProps } from '@/utils/tree'
  198 +import * as MenuApi from '@/api/system/menu'
  199 +import { allSchemas, rules } from './menu.data'
  200 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
265 201
266 const { t } = useI18n() // 国际化 202 const { t } = useI18n() // 国际化
267 const message = useMessage() // 消息弹窗 203 const message = useMessage() // 消息弹窗
268 const { wsCache } = useCache() 204 const { wsCache } = useCache()
269 // 列表相关的变量 205 // 列表相关的变量
270 -const xTable = ref<VxeTableInstance>()  
271 -const tableLoading = ref(false)  
272 -const tableData = ref() 206 +// 列表相关的变量
  207 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  208 +const treeConfig = {
  209 + transform: true,
  210 + rowField: 'id',
  211 + parentField: 'parentId',
  212 + expandAll: false
  213 +}
  214 +const { gridOptions, getList, deleteData } = useVxeGrid<MenuApi.MenuVO>({
  215 + allSchemas: allSchemas,
  216 + treeConfig: treeConfig,
  217 + getListApi: MenuApi.getMenuListApi,
  218 + deleteApi: MenuApi.deleteMenuApi
  219 +})
273 // 弹窗相关的变量 220 // 弹窗相关的变量
274 const dialogVisible = ref(false) // 是否显示弹出层 221 const dialogVisible = ref(false) // 是否显示弹出层
275 const dialogTitle = ref('edit') // 弹出层标题 222 const dialogTitle = ref('edit') // 弹出层标题
@@ -292,13 +239,6 @@ const menuForm = ref&lt;MenuApi.MenuVO&gt;({ @@ -292,13 +239,6 @@ const menuForm = ref&lt;MenuApi.MenuVO&gt;({
292 keepAlive: true, 239 keepAlive: true,
293 createTime: new Date() 240 createTime: new Date()
294 }) 241 })
295 -// 新增和修改的表单校验  
296 -const rules = reactive({  
297 - name: [required],  
298 - sort: [required],  
299 - path: [required],  
300 - status: [required]  
301 -})  
302 242
303 // ========== 下拉框[上级菜单] ========== 243 // ========== 下拉框[上级菜单] ==========
304 const menuOptions = ref<any[]>([]) // 树形结构 244 const menuOptions = ref<any[]>([]) // 树形结构
@@ -311,31 +251,6 @@ const getTree = async () =&gt; { @@ -311,31 +251,6 @@ const getTree = async () =&gt; {
311 menuOptions.value.push(menu) 251 menuOptions.value.push(menu)
312 } 252 }
313 253
314 -// ========== 查询 ==========  
315 -const queryParams = reactive<MenuApi.MenuPageReqVO>({  
316 - name: undefined,  
317 - status: undefined  
318 -})  
319 -// 执行查询  
320 -const getList = async () => {  
321 - tableLoading.value = true  
322 - const res = await MenuApi.getMenuListApi(queryParams)  
323 - tableData.value = res  
324 - tableLoading.value = false  
325 -}  
326 -  
327 -// 查询操作  
328 -const handleQuery = async () => {  
329 - await getList()  
330 -}  
331 -  
332 -// 重置操作  
333 -const resetQuery = async () => {  
334 - queryParams.name = undefined  
335 - queryParams.status = undefined  
336 - await getList()  
337 -}  
338 -  
339 // ========== 新增/修改 ========== 254 // ========== 新增/修改 ==========
340 255
341 // 设置标题 256 // 设置标题
@@ -407,7 +322,7 @@ const submitForm = async () =&gt; { @@ -407,7 +322,7 @@ const submitForm = async () =&gt; {
407 actionLoading.value = false 322 actionLoading.value = false
408 wsCache.delete(CACHE_KEY.ROLE_ROUTERS) 323 wsCache.delete(CACHE_KEY.ROLE_ROUTERS)
409 // 操作成功,重新加载列表 324 // 操作成功,重新加载列表
410 - await getList() 325 + await getList(xGrid)
411 } 326 }
412 } 327 }
413 328
@@ -419,15 +334,6 @@ const isExternal = (path: string) =&gt; { @@ -419,15 +334,6 @@ const isExternal = (path: string) =&gt; {
419 // ========== 删除 ========== 334 // ========== 删除 ==========
420 // 删除操作 335 // 删除操作
421 const handleDelete = async (rowId: number) => { 336 const handleDelete = async (rowId: number) => {
422 - message.delConfirm().then(async () => {  
423 - await MenuApi.deleteMenuApi(rowId)  
424 - message.success(t('common.delSuccess'))  
425 - await getList()  
426 - }) 337 + await deleteData(xGrid, rowId)
427 } 338 }
428 -  
429 -// ========== 初始化 ==========  
430 -onMounted(async () => {  
431 - await getList()  
432 -})  
433 </script> 339 </script>
yudao-ui-admin-vue3/src/views/system/menu/menu.data.ts 0 → 100644
  1 +import { reactive } from 'vue'
  2 +import { useI18n } from '@/hooks/web/useI18n'
  3 +import { DICT_TYPE } from '@/utils/dict'
  4 +import { required } from '@/utils/formRules'
  5 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
  6 +const { t } = useI18n() // 国际化
  7 +
  8 +// 新增和修改的表单校验
  9 +export const rules = reactive({
  10 + name: [required],
  11 + sort: [required],
  12 + path: [required],
  13 + status: [required]
  14 +})
  15 +
  16 +// CrudSchema
  17 +const crudSchemas = reactive<VxeCrudSchema>({
  18 + primaryKey: 'id',
  19 + primaryType: null,
  20 + action: true,
  21 + columns: [
  22 + {
  23 + title: '上级菜单',
  24 + field: 'parentId',
  25 + isTable: false
  26 + },
  27 + {
  28 + title: '菜单名称',
  29 + field: 'name',
  30 + isSearch: true,
  31 + table: {
  32 + treeNode: true,
  33 + align: 'left',
  34 + width: '200px'
  35 + }
  36 + },
  37 + {
  38 + title: '菜单类型',
  39 + field: 'type',
  40 + dictType: DICT_TYPE.SYSTEM_MENU_TYPE
  41 + },
  42 + {
  43 + title: '路由地址',
  44 + field: 'path'
  45 + },
  46 + {
  47 + title: '组件路径',
  48 + field: 'component'
  49 + },
  50 + {
  51 + title: '权限标识',
  52 + field: 'permission'
  53 + },
  54 + {
  55 + title: '排序',
  56 + field: 'sort'
  57 + },
  58 + {
  59 + title: t('common.status'),
  60 + field: 'status',
  61 + dictType: DICT_TYPE.COMMON_STATUS,
  62 + dictClass: 'number',
  63 + isSearch: true
  64 + },
  65 + {
  66 + title: t('common.createTime'),
  67 + field: 'createTime',
  68 + formatter: 'formatDate',
  69 + isForm: false
  70 + }
  71 + ]
  72 +})
  73 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)