Commit 120417b792576d87f1b94b27340d351bc47b2c79
1 parent
7cbd6cfb
refactor: vxe crud
Showing
16 changed files
with
190 additions
and
119 deletions
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
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
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 = <T = any>(config?: UseVxeGridConfig<T>) => { | @@ -88,10 +89,29 @@ export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => { | ||
| 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 '../index' | @@ -3,7 +3,7 @@ import { store } from '../index' | ||
| 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) => { | @@ -34,10 +34,10 @@ export const getDictOptions = (dictType: string) => { | ||
| 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('edit') // 弹出层标题 | @@ -291,7 +290,8 @@ const dialogTitle = ref('edit') // 弹出层标题 | ||
| 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 () => { | @@ -339,9 +332,9 @@ const getTree = async () => { | ||
| 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 () => { | @@ -357,31 +350,47 @@ const handleQuery = async () => { | ||
| 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 () => { | @@ -411,11 +420,11 @@ const submitForm = async () => { | ||
| 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) => { | @@ -426,9 +435,9 @@ const isExternal = (path: string) => { | ||
| 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) => { | @@ -437,7 +446,5 @@ const handleDelete = async (row: MenuVO) => { | ||
| 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) => { | @@ -110,9 +111,11 @@ const handleUpdate = async (rowId: number) => { | ||
| 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 () => { | @@ -137,7 +140,7 @@ const submitForm = async () => { | ||
| 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<VxeCrudSchema>({ | @@ -25,8 +25,7 @@ const crudSchemas = reactive<VxeCrudSchema>({ | ||
| 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 'vxe-table' | @@ -78,14 +85,14 @@ import { VxeGridInstance } from 'vxe-table' | ||
| 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 = () => { | @@ -111,6 +118,16 @@ const handleCreate = () => { | ||
| 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) => { | @@ -120,10 +137,10 @@ const handleUpdate = async (rowId: number) => { | ||
| 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) => { | @@ -144,13 +161,12 @@ const handleDelete = async (rowId: number) => { | ||
| 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 | } |