Commit 120417b792576d87f1b94b27340d351bc47b2c79

Authored by xingyu4j
1 parent 7cbd6cfb

refactor: vxe crud

yudao-ui-admin-vue3/src/api/system/menu/index.ts
1 import request from '@/config/axios' 1 import request from '@/config/axios'
2 -import type { MenuVO } from './types'  
3 2
  3 +export interface MenuVO {
  4 + id: number
  5 + name: string
  6 + permission: string
  7 + type: number
  8 + sort: number
  9 + parentId: number
  10 + path: string
  11 + icon: string
  12 + component: string
  13 + status: number
  14 + visible: boolean
  15 + keepAlive: boolean
  16 + createTime: string
  17 +}
  18 +
  19 +export interface MenuPageReqVO {
  20 + name?: string
  21 + status?: number
  22 +}
4 // 查询菜单(精简)列表 23 // 查询菜单(精简)列表
5 export const listSimpleMenusApi = () => { 24 export const listSimpleMenusApi = () => {
6 return request.get({ url: '/system/menu/list-all-simple' }) 25 return request.get({ url: '/system/menu/list-all-simple' })
7 } 26 }
8 27
9 // 查询菜单列表 28 // 查询菜单列表
10 -export const getMenuListApi = (params) => { 29 +export const getMenuListApi = (params: MenuPageReqVO) => {
11 return request.get({ url: '/system/menu/list', params }) 30 return request.get({ url: '/system/menu/list', params })
12 } 31 }
13 32
yudao-ui-admin-vue3/src/api/system/menu/types.ts deleted
1 -export type MenuVO = {  
2 - id: number  
3 - name: string  
4 - permission: string  
5 - type: number  
6 - sort: number  
7 - parentId: number  
8 - path: string  
9 - icon: string  
10 - component: string  
11 - status: number  
12 - visible: boolean  
13 - keepAlive: boolean  
14 - createTime: string  
15 -}  
yudao-ui-admin-vue3/src/api/system/notice/index.ts
1 import request from '@/config/axios' 1 import request from '@/config/axios'
2 -import type { NoticeVO } from './types' 2 +export interface NoticeVO {
  3 + id: number
  4 + title: string
  5 + type: number
  6 + content: string
  7 + status: number
  8 + remark: string
  9 + creator: string
  10 + createTime: string
  11 + updater: string
  12 + updateTime: string
  13 +}
  14 +
  15 +export interface NoticePageReqVO extends BasePage {
  16 + title?: string
  17 + status?: number
  18 +}
3 19
4 // 查询公告列表 20 // 查询公告列表
5 -export const getNoticePageApi = (params) => { 21 +export const getNoticePageApi = (params: NoticePageReqVO) => {
6 return request.get({ url: '/system/notice/page', params }) 22 return request.get({ url: '/system/notice/page', params })
7 } 23 }
8 24
yudao-ui-admin-vue3/src/api/system/notice/types.ts deleted
1 -export type NoticeVO = {  
2 - id: number  
3 - title: string  
4 - type: number  
5 - content: string  
6 - status: number  
7 - remark: string  
8 - creator: string  
9 - createTime: string  
10 - updater: string  
11 - updateTime: string  
12 -}  
yudao-ui-admin-vue3/src/api/system/post/index.ts
1 import request from '@/config/axios' 1 import request from '@/config/axios'
2 -import type { PostVO, PostPageReqVO, PostExportReqVO } from './types' 2 +
  3 +export interface PostVO {
  4 + id?: number
  5 + name: string
  6 + code: string
  7 + sort: number
  8 + status: number
  9 + remark: string
  10 + createTime?: string
  11 +}
  12 +
  13 +export interface PostPageReqVO extends BasePage {
  14 + code?: string
  15 + name?: string
  16 + status?: number
  17 +}
  18 +
  19 +export interface PostExportReqVO {
  20 + code?: string
  21 + name?: string
  22 + status?: number
  23 +}
3 24
4 // 查询岗位列表 25 // 查询岗位列表
5 export const getPostPageApi = async (params: PostPageReqVO) => { 26 export const getPostPageApi = async (params: PostPageReqVO) => {
@@ -31,7 +52,6 @@ export const deletePostApi = async (id: number) => { @@ -31,7 +52,6 @@ export const deletePostApi = async (id: number) => {
31 } 52 }
32 53
33 // 导出岗位 54 // 导出岗位
34 -// TODO @星语:导出这块,咱怎么弄哈  
35 export const exportPostApi = async (params: PostExportReqVO) => { 55 export const exportPostApi = async (params: PostExportReqVO) => {
36 return await request.download({ url: '/system/post/export', params }) 56 return await request.download({ url: '/system/post/export', params })
37 } 57 }
yudao-ui-admin-vue3/src/api/system/post/types.ts deleted
1 -export type PostVO = {  
2 - id?: number  
3 - name: string  
4 - code: string  
5 - sort: number  
6 - status: number  
7 - remark: string  
8 - createTime?: string  
9 -}  
10 -  
11 -// TODO @星语:要不要搞个 Page 基类呀?和后端对应  
12 -export type PostPageReqVO = {  
13 - code: string  
14 - name: string  
15 - status?: number  
16 - pageSize?: number  
17 - pageNo?: number  
18 -}  
19 -  
20 -export type PostExportReqVO = {  
21 - code: string  
22 - name: string  
23 - status?: number  
24 -}  
yudao-ui-admin-vue3/src/components/DictTag/src/DictTag.vue
@@ -38,7 +38,7 @@ onUpdated(() => { @@ -38,7 +38,7 @@ onUpdated(() => {
38 dictData?.colorType === '' || 38 dictData?.colorType === '' ||
39 dictData?.colorType === undefined 39 dictData?.colorType === undefined
40 " 40 "
41 - :key="dictData?.value" 41 + :key="dictData?.value.toString()"
42 :class="dictData?.cssClass" 42 :class="dictData?.cssClass"
43 > 43 >
44 {{ dictData?.label }} 44 {{ dictData?.label }}
yudao-ui-admin-vue3/src/hooks/web/useMessage.ts
@@ -71,6 +71,18 @@ export const useMessage = () => { @@ -71,6 +71,18 @@ export const useMessage = () => {
71 } 71 }
72 ) 72 )
73 }, 73 },
  74 + // 导出窗体
  75 + exportConfirm(content?: string, tip?: string) {
  76 + return ElMessageBox.confirm(
  77 + content ? content : t('common.exportMessage'),
  78 + tip ? tip : t('common.confirmTitle'),
  79 + {
  80 + confirmButtonText: t('common.ok'),
  81 + cancelButtonText: t('common.cancel'),
  82 + type: 'warning'
  83 + }
  84 + )
  85 + },
74 // 提交内容 86 // 提交内容
75 prompt(content: string, tip: string) { 87 prompt(content: string, tip: string) {
76 return ElMessageBox.prompt(content, tip, { 88 return ElMessageBox.prompt(content, tip, {
yudao-ui-admin-vue3/src/hooks/web/useVxeGrid.ts
@@ -13,6 +13,7 @@ interface UseVxeGridConfig<T = any> { @@ -13,6 +13,7 @@ interface UseVxeGridConfig<T = any> {
13 getListApi: (option: any) => Promise<T> 13 getListApi: (option: any) => Promise<T>
14 delListApi?: (option: any) => Promise<T> 14 delListApi?: (option: any) => Promise<T>
15 exportListApi?: (option: any) => Promise<T> 15 exportListApi?: (option: any) => Promise<T>
  16 + exportName?: string
16 } 17 }
17 18
18 const appStore = useAppStore() 19 const appStore = useAppStore()
@@ -88,10 +89,29 @@ export const useVxeGrid = &lt;T = any&gt;(config?: UseVxeGridConfig&lt;T&gt;) =&gt; { @@ -88,10 +89,29 @@ export const useVxeGrid = &lt;T = any&gt;(config?: UseVxeGridConfig&lt;T&gt;) =&gt; {
88 return new Promise(async (resolve) => { 89 return new Promise(async (resolve) => {
89 resolve(await config?.getListApi(queryParams)) 90 resolve(await config?.getListApi(queryParams))
90 }) 91 })
  92 + },
  93 + queryAll: ({ form }) => {
  94 + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
  95 + return new Promise(async (resolve) => {
  96 + if (config?.exportListApi) {
  97 + resolve(await config?.exportListApi(queryParams))
  98 + } else {
  99 + resolve(await config?.getListApi(queryParams))
  100 + }
  101 + })
91 } 102 }
92 } 103 }
  104 + },
  105 + exportConfig: {
  106 + filename: config?.exportName,
  107 + // 默认选中类型
  108 + type: 'csv',
  109 + // 自定义数据量列表
  110 + modes: ['current', 'all'],
  111 + columns: config?.allSchemas.printSchema
93 } 112 }
94 }) 113 })
  114 +
95 const delList = (ids: string | number | string[] | number[]) => { 115 const delList = (ids: string | number | string[] | number[]) => {
96 return new Promise(async () => { 116 return new Promise(async () => {
97 message.delConfirm().then(() => { 117 message.delConfirm().then(() => {
yudao-ui-admin-vue3/src/store/modules/dict.ts
@@ -3,7 +3,7 @@ import { store } from &#39;../index&#39; @@ -3,7 +3,7 @@ import { store } from &#39;../index&#39;
3 import { DictDataVO } from '@/api/system/dict/types' 3 import { DictDataVO } from '@/api/system/dict/types'
4 4
5 export interface DictValueType { 5 export interface DictValueType {
6 - value: string 6 + value: string | number | boolean
7 label: string 7 label: string
8 clorType: string 8 clorType: string
9 cssClass: string 9 cssClass: string
yudao-ui-admin-vue3/src/utils/dict.ts
@@ -15,7 +15,7 @@ const dictStore = useDictStoreWithOut() @@ -15,7 +15,7 @@ const dictStore = useDictStoreWithOut()
15 export interface DictDataType { 15 export interface DictDataType {
16 dictType: string 16 dictType: string
17 label: string 17 label: string
18 - value: string | number 18 + value: string | number | boolean
19 colorType: ElementPlusInfoType | '' | 'default' | 'primary' 19 colorType: ElementPlusInfoType | '' | 'default' | 'primary'
20 cssClass: string 20 cssClass: string
21 } 21 }
@@ -34,10 +34,10 @@ export const getDictOptions = (dictType: string) =&gt; { @@ -34,10 +34,10 @@ export const getDictOptions = (dictType: string) =&gt; {
34 export const getIntDictOptions = (dictType: string) => { 34 export const getIntDictOptions = (dictType: string) => {
35 const dictOptions: DictDataType[] = [] 35 const dictOptions: DictDataType[] = []
36 dictStore.getDictMap.forEach((dict: DictDataType) => { 36 dictStore.getDictMap.forEach((dict: DictDataType) => {
37 - if (dict.dictType + '' === dictType) { 37 + if (dict.dictType.toString() === dictType) {
38 dictOptions.push({ 38 dictOptions.push({
39 ...dict, 39 ...dict,
40 - value: parseInt(dict.value + '') 40 + value: dict.value
41 }) 41 })
42 } 42 }
43 }) 43 })
yudao-ui-admin-vue3/src/views/system/menu/index.vue
@@ -42,7 +42,6 @@ @@ -42,7 +42,6 @@
42 </template> 42 </template>
43 </vxe-toolbar> 43 </vxe-toolbar>
44 <!-- 列表 --> 44 <!-- 列表 -->
45 - <!-- TODO 星语:是不是也搞成 grid 会好点,后续代码就统一走 grid 风格? -->  
46 <vxe-table 45 <vxe-table
47 show-overflow 46 show-overflow
48 keep-source 47 keep-source
@@ -84,14 +83,14 @@ @@ -84,14 +83,14 @@
84 preIcon="ep:edit" 83 preIcon="ep:edit"
85 :title="t('action.edit')" 84 :title="t('action.edit')"
86 v-hasPermi="['system:menu:update']" 85 v-hasPermi="['system:menu:update']"
87 - @click="handleUpdate(row)" 86 + @click="handleUpdate(row.id)"
88 /> 87 />
89 <!-- 操作:删除 --> 88 <!-- 操作:删除 -->
90 <XTextButton 89 <XTextButton
91 preIcon="ep:delete" 90 preIcon="ep:delete"
92 :title="t('action.del')" 91 :title="t('action.del')"
93 v-hasPermi="['system:menu:delete']" 92 v-hasPermi="['system:menu:delete']"
94 - @click="handleDelete(row)" 93 + @click="handleDelete(row.id)"
95 /> 94 />
96 </template> 95 </template>
97 </vxe-column> 96 </vxe-column>
@@ -102,6 +101,7 @@ @@ -102,6 +101,7 @@
102 <template #default> 101 <template #default>
103 <!-- 对话框(添加 / 修改) --> 102 <!-- 对话框(添加 / 修改) -->
104 <el-form 103 <el-form
  104 + ref="formRef"
105 :model="menuForm" 105 :model="menuForm"
106 :rules="rules" 106 :rules="rules"
107 :inline="true" 107 :inline="true"
@@ -254,7 +254,6 @@ @@ -254,7 +254,6 @@
254 import { onMounted, reactive, ref } from 'vue' 254 import { onMounted, reactive, ref } from 'vue'
255 import { useI18n } from '@/hooks/web/useI18n' 255 import { useI18n } from '@/hooks/web/useI18n'
256 import { useMessage } from '@/hooks/web/useMessage' 256 import { useMessage } from '@/hooks/web/useMessage'
257 -// TODO @星语:是不是 'element-plus' 和 '@/components/Tooltip' 和 '@/components/Icon' 全局直接引入  
258 import { 257 import {
259 ElRow, 258 ElRow,
260 ElCol, 259 ElCol,
@@ -266,14 +265,14 @@ import { @@ -266,14 +265,14 @@ import {
266 ElTreeSelect, 265 ElTreeSelect,
267 ElOption, 266 ElOption,
268 ElRadioGroup, 267 ElRadioGroup,
269 - ElRadioButton 268 + ElRadioButton,
  269 + FormInstance
270 } from 'element-plus' 270 } from 'element-plus'
271 import { Tooltip } from '@/components/Tooltip' 271 import { Tooltip } from '@/components/Tooltip'
272 import { IconSelect } from '@/components/Icon' 272 import { IconSelect } from '@/components/Icon'
273 import { VxeTableInstance } from 'vxe-table' 273 import { VxeTableInstance } from 'vxe-table'
274 // 业务相关的 import 274 // 业务相关的 import
275 import * as MenuApi from '@/api/system/menu' 275 import * as MenuApi from '@/api/system/menu'
276 -import { MenuVO } from '@/api/system/menu/types'  
277 import { required } from '@/utils/formRules.js' 276 import { required } from '@/utils/formRules.js'
278 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' 277 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
279 import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants' 278 import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants'
@@ -291,7 +290,8 @@ const dialogTitle = ref(&#39;edit&#39;) // 弹出层标题 @@ -291,7 +290,8 @@ const dialogTitle = ref(&#39;edit&#39;) // 弹出层标题
291 const actionType = ref('') // 操作按钮的类型 290 const actionType = ref('') // 操作按钮的类型
292 const actionLoading = ref(false) // 遮罩层 291 const actionLoading = ref(false) // 遮罩层
293 // 新增和修改的表单值 292 // 新增和修改的表单值
294 -const menuForm = ref<MenuVO>({ 293 +const formRef = ref<FormInstance>()
  294 +const menuForm = ref<MenuApi.MenuVO>({
295 id: 0, 295 id: 0,
296 name: '', 296 name: '',
297 permission: '', 297 permission: '',
@@ -316,19 +316,12 @@ const rules = reactive({ @@ -316,19 +316,12 @@ const rules = reactive({
316 316
317 // ========== 下拉框[上级菜单] ========== 317 // ========== 下拉框[上级菜单] ==========
318 // 下拉框[上级菜单]的配置项目 318 // 下拉框[上级菜单]的配置项目
319 -// TODO @星语:menuProps 貌似也可以抽到全局?  
320 const menuProps = { 319 const menuProps = {
321 checkStrictly: true, 320 checkStrictly: true,
322 children: 'children', 321 children: 'children',
323 label: 'name', 322 label: 'name',
324 value: 'id' 323 value: 'id'
325 } 324 }
326 -// TODO @星语:Tree 可以是全局的  
327 -interface Tree {  
328 - id: number  
329 - name: string  
330 - children?: Tree[] | any[]  
331 -}  
332 const menuOptions = ref<any[]>([]) // 树形结构 325 const menuOptions = ref<any[]>([]) // 树形结构
333 const getTree = async () => { 326 const getTree = async () => {
334 menuOptions.value = [] 327 menuOptions.value = []
@@ -339,9 +332,9 @@ const getTree = async () =&gt; { @@ -339,9 +332,9 @@ const getTree = async () =&gt; {
339 } 332 }
340 333
341 // ========== 查询 ========== 334 // ========== 查询 ==========
342 -const queryParams = reactive({  
343 - name: null,  
344 - status: null 335 +const queryParams = reactive<MenuApi.MenuPageReqVO>({
  336 + name: undefined,
  337 + status: undefined
345 }) 338 })
346 const getList = async () => { 339 const getList = async () => {
347 tableLoading.value = true 340 tableLoading.value = true
@@ -357,31 +350,47 @@ const handleQuery = async () =&gt; { @@ -357,31 +350,47 @@ const handleQuery = async () =&gt; {
357 350
358 // 重置操作 351 // 重置操作
359 const resetQuery = async () => { 352 const resetQuery = async () => {
360 - queryParams.name = null  
361 - queryParams.status = null 353 + queryParams.name = undefined
  354 + queryParams.status = undefined
362 await getList() 355 await getList()
363 } 356 }
364 357
365 // ========== 新增/修改 ========== 358 // ========== 新增/修改 ==========
366 359
367 // 设置标题 360 // 设置标题
368 -const setDialogTile = (type: string) => { 361 +const setDialogTile = async (type: string) => {
  362 + await getTree()
369 dialogTitle.value = t('action.' + type) 363 dialogTitle.value = t('action.' + type)
370 actionType.value = type 364 actionType.value = type
371 dialogVisible.value = true 365 dialogVisible.value = true
372 } 366 }
373 367
374 -// 新建操作 368 +// 新增操作
375 const handleCreate = () => { 369 const handleCreate = () => {
376 setDialogTile('create') 370 setDialogTile('create')
377 - // TODO @星语:重置表单 371 + formRef.value?.resetFields()
  372 + menuForm.value = {
  373 + id: 0,
  374 + name: '',
  375 + permission: '',
  376 + type: SystemMenuTypeEnum.DIR,
  377 + sort: 1,
  378 + parentId: 0,
  379 + path: '',
  380 + icon: '',
  381 + component: '',
  382 + status: CommonStatusEnum.ENABLE,
  383 + visible: true,
  384 + keepAlive: true,
  385 + createTime: ''
  386 + }
378 } 387 }
379 388
380 // 修改操作 389 // 修改操作
381 -const handleUpdate = async (row: MenuVO) => { 390 +const handleUpdate = async (rowId: number) => {
382 setDialogTile('update') 391 setDialogTile('update')
383 // 设置数据 392 // 设置数据
384 - const res = await MenuApi.getMenuApi(row.id) 393 + const res = await MenuApi.getMenuApi(rowId)
385 menuForm.value = res 394 menuForm.value = res
386 } 395 }
387 396
@@ -411,11 +420,11 @@ const submitForm = async () =&gt; { @@ -411,11 +420,11 @@ const submitForm = async () =&gt; {
411 await MenuApi.updateMenuApi(menuForm.value) 420 await MenuApi.updateMenuApi(menuForm.value)
412 message.success(t('common.updateSuccess')) 421 message.success(t('common.updateSuccess'))
413 } 422 }
414 - // 操作成功,重新加载列表  
415 - dialogVisible.value = false  
416 - await getList()  
417 } finally { 423 } finally {
  424 + dialogVisible.value = false
418 actionLoading.value = false 425 actionLoading.value = false
  426 + // 操作成功,重新加载列表
  427 + await getList()
419 } 428 }
420 } 429 }
421 430
@@ -426,9 +435,9 @@ const isExternal = (path: string) =&gt; { @@ -426,9 +435,9 @@ const isExternal = (path: string) =&gt; {
426 435
427 // ========== 删除 ========== 436 // ========== 删除 ==========
428 // 删除操作 437 // 删除操作
429 -const handleDelete = async (row: MenuVO) => {  
430 - message.confirm(t('common.delDataMessage'), t('common.confirmTitle')).then(async () => {  
431 - await MenuApi.deleteMenuApi(row.id) 438 +const handleDelete = async (rowId: number) => {
  439 + message.delConfirm().then(async () => {
  440 + await MenuApi.deleteMenuApi(rowId)
432 message.success(t('common.delSuccess')) 441 message.success(t('common.delSuccess'))
433 await getList() 442 await getList()
434 }) 443 })
@@ -437,7 +446,5 @@ const handleDelete = async (row: MenuVO) =&gt; { @@ -437,7 +446,5 @@ const handleDelete = async (row: MenuVO) =&gt; {
437 // ========== 初始化 ========== 446 // ========== 初始化 ==========
438 onMounted(async () => { 447 onMounted(async () => {
439 await getList() 448 await getList()
440 - // TODO @星语:这个告警解决下;是不是改成新增和修改点击的时候,去加载下好一点哈?  
441 - getTree()  
442 }) 449 })
443 </script> 450 </script>
yudao-ui-admin-vue3/src/views/system/notice/index.vue
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 preIcon="ep:view" 21 preIcon="ep:view"
22 :title="t('action.detail')" 22 :title="t('action.detail')"
23 v-hasPermi="['system:notice:update']" 23 v-hasPermi="['system:notice:update']"
24 - @click="handleDetail(row)" 24 + @click="handleDetail(row.id)"
25 /> 25 />
26 <XTextButton 26 <XTextButton
27 preIcon="ep:delete" 27 preIcon="ep:delete"
@@ -36,10 +36,10 @@ @@ -36,10 +36,10 @@
36 <template #default> 36 <template #default>
37 <!-- 对话框(添加 / 修改) --> 37 <!-- 对话框(添加 / 修改) -->
38 <Form 38 <Form
  39 + ref="formRef"
39 v-if="['create', 'update'].includes(actionType)" 40 v-if="['create', 'update'].includes(actionType)"
40 :schema="allSchemas.formSchema" 41 :schema="allSchemas.formSchema"
41 :rules="rules" 42 :rules="rules"
42 - ref="formRef"  
43 /> 43 />
44 <!-- 对话框(详情) --> 44 <!-- 对话框(详情) -->
45 <Descriptions 45 <Descriptions
@@ -63,30 +63,31 @@ @@ -63,30 +63,31 @@
63 </template> 63 </template>
64 <script setup lang="ts"> 64 <script setup lang="ts">
65 import { ref, unref } from 'vue' 65 import { ref, unref } from 'vue'
66 -import * as NoticeApi from '@/api/system/notice'  
67 -import { NoticeVO } from '@/api/system/notice/types'  
68 -import { rules, allSchemas } from './notice.data'  
69 import { useI18n } from '@/hooks/web/useI18n' 66 import { useI18n } from '@/hooks/web/useI18n'
70 import { useMessage } from '@/hooks/web/useMessage' 67 import { useMessage } from '@/hooks/web/useMessage'
71 import { useVxeGrid } from '@/hooks/web/useVxeGrid' 68 import { useVxeGrid } from '@/hooks/web/useVxeGrid'
72 import { VxeGridInstance } from 'vxe-table' 69 import { VxeGridInstance } from 'vxe-table'
73 import { FormExpose } from '@/components/Form' 70 import { FormExpose } from '@/components/Form'
74 71
  72 +import * as NoticeApi from '@/api/system/notice'
  73 +import { rules, allSchemas } from './notice.data'
  74 +
75 const { t } = useI18n() // 国际化 75 const { t } = useI18n() // 国际化
76 const message = useMessage() // 消息弹窗 76 const message = useMessage() // 消息弹窗
  77 +
  78 +const xGrid = ref<VxeGridInstance>() // grid Ref
  79 +const { gridOptions } = useVxeGrid<NoticeApi.NoticeVO>({
  80 + allSchemas: allSchemas,
  81 + getListApi: NoticeApi.getNoticePageApi
  82 +})
  83 +
77 const dialogVisible = ref(false) // 是否显示弹出层 84 const dialogVisible = ref(false) // 是否显示弹出层
78 const dialogTitle = ref('edit') // 弹出层标题 85 const dialogTitle = ref('edit') // 弹出层标题
79 const actionType = ref('') // 操作按钮的类型 86 const actionType = ref('') // 操作按钮的类型
80 const actionLoading = ref(false) // 按钮Loading 87 const actionLoading = ref(false) // 按钮Loading
81 -const xGrid = ref<VxeGridInstance>() // grid Ref  
82 const formRef = ref<FormExpose>() // 表单 Ref 88 const formRef = ref<FormExpose>() // 表单 Ref
83 const detailRef = ref() // 详情 Ref 89 const detailRef = ref() // 详情 Ref
84 90
85 -const { gridOptions } = useVxeGrid<NoticeVO>({  
86 - allSchemas: allSchemas,  
87 - getListApi: NoticeApi.getNoticePageApi  
88 -})  
89 -  
90 // 设置标题 91 // 设置标题
91 const setDialogTile = (type: string) => { 92 const setDialogTile = (type: string) => {
92 dialogTitle.value = t('action.' + type) 93 dialogTitle.value = t('action.' + type)
@@ -110,9 +111,11 @@ const handleUpdate = async (rowId: number) =&gt; { @@ -110,9 +111,11 @@ const handleUpdate = async (rowId: number) =&gt; {
110 } 111 }
111 112
112 // 详情操作 113 // 详情操作
113 -const handleDetail = (row: NoticeVO) => { 114 +const handleDetail = async (rowId: number) => {
114 setDialogTile('detail') 115 setDialogTile('detail')
115 - detailRef.value = row 116 + // 设置数据
  117 + const res = await NoticeApi.getNoticeApi(rowId)
  118 + detailRef.value = res
116 } 119 }
117 120
118 // 删除操作 121 // 删除操作
@@ -137,7 +140,7 @@ const submitForm = async () =&gt; { @@ -137,7 +140,7 @@ const submitForm = async () =&gt; {
137 actionLoading.value = true 140 actionLoading.value = true
138 // 提交请求 141 // 提交请求
139 try { 142 try {
140 - const data = unref(formRef)?.formModel as NoticeVO 143 + const data = unref(formRef)?.formModel as NoticeApi.NoticeVO
141 if (actionType.value === 'create') { 144 if (actionType.value === 'create') {
142 await NoticeApi.createNoticeApi(data) 145 await NoticeApi.createNoticeApi(data)
143 message.success(t('common.createSuccess')) 146 message.success(t('common.createSuccess'))
yudao-ui-admin-vue3/src/views/system/notice/notice.data.ts
@@ -25,8 +25,7 @@ const crudSchemas = reactive&lt;VxeCrudSchema&gt;({ @@ -25,8 +25,7 @@ const crudSchemas = reactive&lt;VxeCrudSchema&gt;({
25 { 25 {
26 title: '公告类型', 26 title: '公告类型',
27 field: 'type', 27 field: 'type',
28 - dictType: DICT_TYPE.SYSTEM_NOTICE_TYPE,  
29 - isSearch: true 28 + dictType: DICT_TYPE.SYSTEM_NOTICE_TYPE
30 }, 29 },
31 { 30 {
32 title: t('common.status'), 31 title: t('common.status'),
yudao-ui-admin-vue3/src/views/system/post/index.vue
@@ -11,6 +11,13 @@ @@ -11,6 +11,13 @@
11 v-hasPermi="['system:post:create']" 11 v-hasPermi="['system:post:create']"
12 @click="handleCreate()" 12 @click="handleCreate()"
13 /> 13 />
  14 + <XButton
  15 + type="primary"
  16 + preIcon="ep:download"
  17 + :title="t('action.export')"
  18 + v-hasPermi="['system:post:export']"
  19 + @click="handleExport()"
  20 + />
14 </template> 21 </template>
15 <template #actionbtns_default="{ row }"> 22 <template #actionbtns_default="{ row }">
16 <!-- 操作:修改 --> 23 <!-- 操作:修改 -->
@@ -25,7 +32,7 @@ @@ -25,7 +32,7 @@
25 preIcon="ep:view" 32 preIcon="ep:view"
26 :title="t('action.detail')" 33 :title="t('action.detail')"
27 v-hasPermi="['system:post:update']" 34 v-hasPermi="['system:post:update']"
28 - @click="handleDetail(row)" 35 + @click="handleDetail(row.id)"
29 /> 36 />
30 <!-- 操作:删除 --> 37 <!-- 操作:删除 -->
31 <XTextButton 38 <XTextButton
@@ -42,10 +49,10 @@ @@ -42,10 +49,10 @@
42 <template #default> 49 <template #default>
43 <!-- 表单:添加/修改 --> 50 <!-- 表单:添加/修改 -->
44 <Form 51 <Form
  52 + ref="formRef"
45 v-if="['create', 'update'].includes(actionType)" 53 v-if="['create', 'update'].includes(actionType)"
46 :schema="allSchemas.formSchema" 54 :schema="allSchemas.formSchema"
47 :rules="rules" 55 :rules="rules"
48 - ref="formRef"  
49 /> 56 />
50 <!-- 表单:详情 --> 57 <!-- 表单:详情 -->
51 <Descriptions 58 <Descriptions
@@ -78,14 +85,14 @@ import { VxeGridInstance } from &#39;vxe-table&#39; @@ -78,14 +85,14 @@ import { VxeGridInstance } from &#39;vxe-table&#39;
78 import { FormExpose } from '@/components/Form' 85 import { FormExpose } from '@/components/Form'
79 // 业务相关的 import 86 // 业务相关的 import
80 import * as PostApi from '@/api/system/post' 87 import * as PostApi from '@/api/system/post'
81 -import { PostVO } from '@/api/system/post/types'  
82 import { rules, allSchemas } from './post.data' 88 import { rules, allSchemas } from './post.data'
  89 +import download from '@/utils/download'
83 90
84 const { t } = useI18n() // 国际化 91 const { t } = useI18n() // 国际化
85 const message = useMessage() // 消息弹窗 92 const message = useMessage() // 消息弹窗
86 // 列表相关的变量 93 // 列表相关的变量
87 const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref 94 const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
88 -const { gridOptions } = useVxeGrid<PostVO>({ 95 +const { gridOptions } = useVxeGrid<PostApi.PostVO>({
89 allSchemas: allSchemas, 96 allSchemas: allSchemas,
90 getListApi: PostApi.getPostPageApi 97 getListApi: PostApi.getPostPageApi
91 }) 98 })
@@ -111,6 +118,16 @@ const handleCreate = () =&gt; { @@ -111,6 +118,16 @@ const handleCreate = () =&gt; {
111 unref(formRef)?.getElFormRef()?.resetFields() 118 unref(formRef)?.getElFormRef()?.resetFields()
112 } 119 }
113 120
  121 +// 导出操作
  122 +const handleExport = async () => {
  123 + const queryParams = Object.assign(
  124 + {},
  125 + JSON.parse(JSON.stringify(xGrid.value?.getRefMaps().refForm.value.data))
  126 + )
  127 + const res = await PostApi.exportPostApi(queryParams)
  128 + download.excel(res, '岗位列表.xls')
  129 +}
  130 +
114 // 修改操作 131 // 修改操作
115 const handleUpdate = async (rowId: number) => { 132 const handleUpdate = async (rowId: number) => {
116 setDialogTile('update') 133 setDialogTile('update')
@@ -120,10 +137,10 @@ const handleUpdate = async (rowId: number) =&gt; { @@ -120,10 +137,10 @@ const handleUpdate = async (rowId: number) =&gt; {
120 } 137 }
121 138
122 // 详情操作 139 // 详情操作
123 -const handleDetail = (row: PostVO) => { 140 +const handleDetail = async (rowId: number) => {
124 setDialogTile('detail') 141 setDialogTile('detail')
125 - // TODO @星语:要不读取下后端?  
126 - detailRef.value = row 142 + const res = await PostApi.getPostApi(rowId)
  143 + detailRef.value = res
127 } 144 }
128 145
129 // 删除操作 146 // 删除操作
@@ -144,13 +161,12 @@ const handleDelete = async (rowId: number) =&gt; { @@ -144,13 +161,12 @@ const handleDelete = async (rowId: number) =&gt; {
144 const submitForm = async () => { 161 const submitForm = async () => {
145 const elForm = unref(formRef)?.getElFormRef() 162 const elForm = unref(formRef)?.getElFormRef()
146 if (!elForm) return 163 if (!elForm) return
147 - // TODO @星语:这个告警,要不要解决下?  
148 elForm.validate(async (valid) => { 164 elForm.validate(async (valid) => {
149 if (valid) { 165 if (valid) {
150 actionLoading.value = true 166 actionLoading.value = true
151 // 提交请求 167 // 提交请求
152 try { 168 try {
153 - const data = unref(formRef)?.formModel as PostVO 169 + const data = unref(formRef)?.formModel as PostApi.PostVO
154 if (actionType.value === 'create') { 170 if (actionType.value === 'create') {
155 await PostApi.createPostApi(data) 171 await PostApi.createPostApi(data)
156 message.success(t('common.createSuccess')) 172 message.success(t('common.createSuccess'))
yudao-ui-admin-vue3/types/global.d.ts
@@ -36,4 +36,14 @@ declare global { @@ -36,4 +36,14 @@ declare global {
36 code: string 36 code: string
37 data: T extends any ? T : T & any 37 data: T extends any ? T : T & any
38 } 38 }
  39 +
  40 + declare interface BasePage {
  41 + pageSize?: number
  42 + pageNo?: number
  43 + }
  44 + declare interface Tree {
  45 + id: number
  46 + name: string
  47 + children?: Tree[] | any[]
  48 + }
39 } 49 }