Commit 725cc4e41b2879862a3c2d3cca3490197d4a62a3
1 parent
94527ae9
perf: vxe
Showing
9 changed files
with
302 additions
and
297 deletions
yudao-ui-admin-vue3/src/config/axios/service.ts
| ... | ... | @@ -5,7 +5,7 @@ import axios, { |
| 5 | 5 | AxiosResponse, |
| 6 | 6 | AxiosError |
| 7 | 7 | } from 'axios' |
| 8 | -import { useMessage } from '@/hooks/web/useMessage' | |
| 8 | +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' | |
| 9 | 9 | import qs from 'qs' |
| 10 | 10 | import { config } from '@/config/axios/config' |
| 11 | 11 | import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth' |
| ... | ... | @@ -17,7 +17,6 @@ import { useCache } from '@/hooks/web/useCache' |
| 17 | 17 | const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE |
| 18 | 18 | const { result_code, base_url, request_timeout } = config |
| 19 | 19 | |
| 20 | -const message = useMessage() | |
| 21 | 20 | // 需要忽略的提示。忽略后,自动 Promise.reject('error') |
| 22 | 21 | const ignoreMsgs = [ |
| 23 | 22 | '无效的刷新令牌', // 刷新令牌被删除时,不用提示 |
| ... | ... | @@ -30,6 +29,8 @@ export const isRelogin = { show: false } |
| 30 | 29 | let requestList: any[] = [] |
| 31 | 30 | // 是否正在刷新中 |
| 32 | 31 | let isRefreshToken = false |
| 32 | +// 请求白名单,无须token的接口 | |
| 33 | +const whiteList: string[] = ['/login', '/refresh-token'] | |
| 33 | 34 | |
| 34 | 35 | // 创建axios实例 |
| 35 | 36 | const service: AxiosInstance = axios.create({ |
| ... | ... | @@ -42,14 +43,20 @@ const service: AxiosInstance = axios.create({ |
| 42 | 43 | service.interceptors.request.use( |
| 43 | 44 | (config: AxiosRequestConfig) => { |
| 44 | 45 | // 是否需要设置 token |
| 45 | - const isToken = (config!.headers || {}).isToken === false | |
| 46 | + let isToken = (config!.headers || {}).isToken === false | |
| 47 | + whiteList.some((v) => { | |
| 48 | + if (config.url) { | |
| 49 | + config.url.indexOf(v) > -1 | |
| 50 | + return (isToken = false) | |
| 51 | + } | |
| 52 | + }) | |
| 46 | 53 | if (getAccessToken() && !isToken) { |
| 47 | 54 | ;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token |
| 48 | 55 | } |
| 49 | 56 | // 设置租户 |
| 50 | 57 | if (tenantEnable && tenantEnable === 'true') { |
| 51 | 58 | const tenantId = getTenantId() |
| 52 | - if (tenantId) (config as Recordable).headers.common['tenant-id'] = tenantId | |
| 59 | + if (tenantId) (config as Recordable).headers['tenant-id'] = tenantId | |
| 53 | 60 | } |
| 54 | 61 | const params = config.params || {} |
| 55 | 62 | const data = config.data || false |
| ... | ... | @@ -157,10 +164,10 @@ service.interceptors.response.use( |
| 157 | 164 | }) |
| 158 | 165 | } |
| 159 | 166 | } else if (code === 500) { |
| 160 | - message.error(t('sys.api.errMsg500')) | |
| 167 | + ElMessage.error(t('sys.api.errMsg500')) | |
| 161 | 168 | return Promise.reject(new Error(msg)) |
| 162 | 169 | } else if (code === 901) { |
| 163 | - message.error( | |
| 170 | + ElMessage.error( | |
| 164 | 171 | '<div>' + |
| 165 | 172 | t('sys.api.errMsg901') + |
| 166 | 173 | '</div>' + |
| ... | ... | @@ -175,7 +182,7 @@ service.interceptors.response.use( |
| 175 | 182 | // hard coding:忽略这个提示,直接登出 |
| 176 | 183 | console.log(msg) |
| 177 | 184 | } else { |
| 178 | - message.notifyError(msg) | |
| 185 | + ElNotification.error({ title: msg }) | |
| 179 | 186 | } |
| 180 | 187 | return Promise.reject('error') |
| 181 | 188 | } else { |
| ... | ... | @@ -184,16 +191,16 @@ service.interceptors.response.use( |
| 184 | 191 | }, |
| 185 | 192 | (error: AxiosError) => { |
| 186 | 193 | console.log('err' + error) // for debug |
| 187 | - let { message: msg } = error | |
| 194 | + let { message } = error | |
| 188 | 195 | const { t } = useI18n() |
| 189 | - if (msg === 'Network Error') { | |
| 190 | - msg = t('sys.api.errorMessage') | |
| 191 | - } else if (msg.includes('timeout')) { | |
| 192 | - msg = t('sys.api.apiTimeoutMessage') | |
| 193 | - } else if (msg.includes('Request failed with status code')) { | |
| 194 | - msg = t('sys.api.apiRequestFailed') + msg.substr(msg.length - 3) | |
| 196 | + if (message === 'Network Error') { | |
| 197 | + message = t('sys.api.errorMessage') | |
| 198 | + } else if (message.includes('timeout')) { | |
| 199 | + message = t('sys.api.apiTimeoutMessage') | |
| 200 | + } else if (message.includes('Request failed with status code')) { | |
| 201 | + message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3) | |
| 195 | 202 | } |
| 196 | - message.error(msg) | |
| 203 | + ElMessage.error(message) | |
| 197 | 204 | return Promise.reject(error) |
| 198 | 205 | } |
| 199 | 206 | ) |
| ... | ... | @@ -205,8 +212,11 @@ const handleAuthorized = () => { |
| 205 | 212 | const { t } = useI18n() |
| 206 | 213 | if (!isRelogin.show) { |
| 207 | 214 | isRelogin.show = true |
| 208 | - message | |
| 209 | - .confirm(t('sys.api.timeoutMessage')) | |
| 215 | + ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), { | |
| 216 | + confirmButtonText: t('login.relogin'), | |
| 217 | + cancelButtonText: t('common.cancel'), | |
| 218 | + type: 'warning' | |
| 219 | + }) | |
| 210 | 220 | .then(() => { |
| 211 | 221 | const { wsCache } = useCache() |
| 212 | 222 | resetRouter() // 重置静态路由表 | ... | ... |
yudao-ui-admin-vue3/src/hooks/web/useVxeCrudSchemas.ts
| ... | ... | @@ -14,7 +14,15 @@ import { VxeTableColumn } from '@/types/table' |
| 14 | 14 | import { FormSchema } from '@/types/form' |
| 15 | 15 | import { ComponentOptions } from '@/types/components' |
| 16 | 16 | |
| 17 | -export type VxeCrudSchema = Omit<VxeTableColumn, 'children'> & { | |
| 17 | +export type VxeCrudSchema = { | |
| 18 | + // 主键ID | |
| 19 | + primaryKey?: string | |
| 20 | + primaryType?: VxeColumnPropTypes.Type | |
| 21 | + // 是否开启操作栏插槽 | |
| 22 | + action?: boolean | |
| 23 | + columns: VxeCrudColumns[] | |
| 24 | +} | |
| 25 | +type VxeCrudColumns = Omit<VxeTableColumn, 'children'> & { | |
| 18 | 26 | field: string |
| 19 | 27 | title?: string |
| 20 | 28 | formatter?: VxeColumnPropTypes.Formatter |
| ... | ... | @@ -23,7 +31,7 @@ export type VxeCrudSchema = Omit<VxeTableColumn, 'children'> & { |
| 23 | 31 | form?: CrudFormParams |
| 24 | 32 | detail?: CrudDescriptionsParams |
| 25 | 33 | print?: CrudPrintParams |
| 26 | - children?: VxeCrudSchema[] | |
| 34 | + children?: VxeCrudColumns[] | |
| 27 | 35 | dictType?: string |
| 28 | 36 | } |
| 29 | 37 | type CrudSearchParams = { |
| ... | ... | @@ -61,7 +69,7 @@ export type VxeAllSchemas = { |
| 61 | 69 | |
| 62 | 70 | // 过滤所有结构 |
| 63 | 71 | export const useVxeCrudSchemas = ( |
| 64 | - crudSchema: VxeCrudSchema[] | |
| 72 | + crudSchema: VxeCrudSchema | |
| 65 | 73 | ): { |
| 66 | 74 | allSchemas: VxeAllSchemas |
| 67 | 75 | } => { |
| ... | ... | @@ -95,10 +103,10 @@ export const useVxeCrudSchemas = ( |
| 95 | 103 | } |
| 96 | 104 | |
| 97 | 105 | // 过滤 Search 结构 |
| 98 | -const filterSearchSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] => { | |
| 106 | +const filterSearchSchema = (crudSchema: VxeCrudSchema): VxeFormItemProps[] => { | |
| 99 | 107 | const searchSchema: VxeFormItemProps[] = [] |
| 100 | 108 | const { t } = useI18n() |
| 101 | - eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | |
| 109 | + eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => { | |
| 102 | 110 | // 判断是否显示 |
| 103 | 111 | if (schemaItem?.search?.show) { |
| 104 | 112 | let itemRenderName = schemaItem?.search?.itemRender?.name || '$input' |
| ... | ... | @@ -154,9 +162,20 @@ const filterSearchSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] => |
| 154 | 162 | } |
| 155 | 163 | |
| 156 | 164 | // 过滤 table 结构 |
| 157 | -const filterTableSchema = (crudSchema: VxeCrudSchema[]): VxeGridPropTypes.Columns => { | |
| 165 | +const filterTableSchema = (crudSchema: VxeCrudSchema): VxeGridPropTypes.Columns => { | |
| 166 | + const { t } = useI18n() | |
| 158 | 167 | const tableSchema: VxeGridPropTypes.Columns = [] |
| 159 | - eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | |
| 168 | + // 主键ID | |
| 169 | + if (crudSchema.primaryKey) { | |
| 170 | + const tableSchemaItem = { | |
| 171 | + title: t('common.index'), | |
| 172 | + field: crudSchema.primaryKey, | |
| 173 | + type: crudSchema.primaryType ? crudSchema.primaryType : 'seq', | |
| 174 | + width: '50px' | |
| 175 | + } | |
| 176 | + tableSchema.push(tableSchemaItem) | |
| 177 | + } | |
| 178 | + eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => { | |
| 160 | 179 | // 判断是否显示 |
| 161 | 180 | if (schemaItem?.table?.show !== false) { |
| 162 | 181 | const tableSchemaItem = { |
| ... | ... | @@ -167,6 +186,12 @@ const filterTableSchema = (crudSchema: VxeCrudSchema[]): VxeGridPropTypes.Column |
| 167 | 186 | if (schemaItem?.formatter) { |
| 168 | 187 | tableSchemaItem.formatter = schemaItem.formatter |
| 169 | 188 | } |
| 189 | + if (schemaItem?.dictType) { | |
| 190 | + tableSchemaItem.cellRender = { | |
| 191 | + name: 'XDict', | |
| 192 | + content: schemaItem.dictType | |
| 193 | + } | |
| 194 | + } | |
| 170 | 195 | |
| 171 | 196 | // 删除不必要的字段 |
| 172 | 197 | delete tableSchemaItem.show |
| ... | ... | @@ -174,14 +199,26 @@ const filterTableSchema = (crudSchema: VxeCrudSchema[]): VxeGridPropTypes.Column |
| 174 | 199 | tableSchema.push(tableSchemaItem) |
| 175 | 200 | } |
| 176 | 201 | }) |
| 202 | + // 操作栏插槽 | |
| 203 | + if (crudSchema.action && crudSchema.action == true) { | |
| 204 | + const tableSchemaItem = { | |
| 205 | + title: t('table.action'), | |
| 206 | + field: 'actionbtns', | |
| 207 | + width: '240px', | |
| 208 | + slots: { | |
| 209 | + default: 'actionbtns_default' | |
| 210 | + } | |
| 211 | + } | |
| 212 | + tableSchema.push(tableSchemaItem) | |
| 213 | + } | |
| 177 | 214 | return tableSchema |
| 178 | 215 | } |
| 179 | 216 | |
| 180 | 217 | // 过滤 form 结构 |
| 181 | -const filterFormSchema = (crudSchema: VxeCrudSchema[]): FormSchema[] => { | |
| 218 | +const filterFormSchema = (crudSchema: VxeCrudSchema): FormSchema[] => { | |
| 182 | 219 | const formSchema: FormSchema[] = [] |
| 183 | 220 | |
| 184 | - eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | |
| 221 | + eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => { | |
| 185 | 222 | // 判断是否显示 |
| 186 | 223 | if (schemaItem?.form?.show !== false) { |
| 187 | 224 | let component = schemaItem?.form?.component || 'Input' |
| ... | ... | @@ -216,10 +253,10 @@ const filterFormSchema = (crudSchema: VxeCrudSchema[]): FormSchema[] => { |
| 216 | 253 | } |
| 217 | 254 | |
| 218 | 255 | // 过滤 descriptions 结构 |
| 219 | -const filterDescriptionsSchema = (crudSchema: VxeCrudSchema[]): DescriptionsSchema[] => { | |
| 256 | +const filterDescriptionsSchema = (crudSchema: VxeCrudSchema): DescriptionsSchema[] => { | |
| 220 | 257 | const descriptionsSchema: DescriptionsSchema[] = [] |
| 221 | 258 | |
| 222 | - eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | |
| 259 | + eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => { | |
| 223 | 260 | // 判断是否显示 |
| 224 | 261 | if (schemaItem?.detail?.show !== false) { |
| 225 | 262 | const descriptionsSchemaItem = { |
| ... | ... | @@ -239,10 +276,10 @@ const filterDescriptionsSchema = (crudSchema: VxeCrudSchema[]): DescriptionsSche |
| 239 | 276 | } |
| 240 | 277 | |
| 241 | 278 | // 过滤 打印 结构 |
| 242 | -const filterPrintSchema = (crudSchema: VxeCrudSchema[]): any[] => { | |
| 279 | +const filterPrintSchema = (crudSchema: VxeCrudSchema): any[] => { | |
| 243 | 280 | const printSchema: any[] = [] |
| 244 | 281 | |
| 245 | - eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | |
| 282 | + eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => { | |
| 246 | 283 | // 判断是否显示 |
| 247 | 284 | if (schemaItem?.print?.show !== false) { |
| 248 | 285 | const printSchemaItem = { | ... | ... |
yudao-ui-admin-vue3/src/plugins/vxeTable/index.ts
| 1 | 1 | import { App, unref } from 'vue' |
| 2 | 2 | import 'xe-utils' |
| 3 | 3 | import XEUtils from 'xe-utils' |
| 4 | +import './renderer' | |
| 4 | 5 | import { i18n } from '@/plugins/vueI18n' |
| 5 | 6 | import zhCN from 'vxe-table/es/locale/lang/zh-CN' |
| 6 | 7 | import enUS from 'vxe-table/lib/locale/lang/en-US' |
| ... | ... | @@ -138,6 +139,10 @@ VXETable.formats.mixin({ |
| 138 | 139 | formatDate({ cellValue }, format) { |
| 139 | 140 | return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd HH:mm:ss') |
| 140 | 141 | }, |
| 142 | + // 格式字典 | |
| 143 | + formatDict() { | |
| 144 | + return 'cellValue 123' | |
| 145 | + }, | |
| 141 | 146 | // 四舍五入金额,每隔3位逗号分隔,默认2位数 |
| 142 | 147 | formatAmount({ cellValue }, digits = 2) { |
| 143 | 148 | return XEUtils.commafy(Number(cellValue), { digits }) | ... | ... |
yudao-ui-admin-vue3/src/plugins/vxeTable/renderer/dict.tsx
0 → 100644
| 1 | +import { DictTag } from '@/components/DictTag' | |
| 2 | +import { VXETable } from 'vxe-table' | |
| 3 | + | |
| 4 | +// 创建一个简单的超链接渲染 | |
| 5 | +VXETable.renderer.add('XDict', { | |
| 6 | + // 默认显示模板 | |
| 7 | + renderDefault(renderOpts, params) { | |
| 8 | + const { row, column } = params | |
| 9 | + const { content } = renderOpts | |
| 10 | + return <DictTag type={content as unknown as string} value={row[column.field]}></DictTag> | |
| 11 | + } | |
| 12 | +}) | ... | ... |
yudao-ui-admin-vue3/src/plugins/vxeTable/renderer/index.tsx
0 → 100644
| 1 | +import './dict' | ... | ... |
yudao-ui-admin-vue3/src/views/system/errorCode/errorCode.data.ts
| ... | ... | @@ -2,9 +2,8 @@ import { reactive } from 'vue' |
| 2 | 2 | import { required } from '@/utils/formRules' |
| 3 | 3 | import { useI18n } from '@/hooks/web/useI18n' |
| 4 | 4 | import { DICT_TYPE } from '@/utils/dict' |
| 5 | -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | |
| 6 | -// 国际化 | |
| 7 | -const { t } = useI18n() | |
| 5 | +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas' | |
| 6 | +const { t } = useI18n() // 国际化 | |
| 8 | 7 | // 表单校验 |
| 9 | 8 | export const rules = reactive({ |
| 10 | 9 | applicationName: [required], |
| ... | ... | @@ -12,71 +11,45 @@ export const rules = reactive({ |
| 12 | 11 | message: [required] |
| 13 | 12 | }) |
| 14 | 13 | // 新增 + 修改 |
| 15 | -const crudSchemas = reactive<CrudSchema[]>([ | |
| 16 | - { | |
| 17 | - label: t('common.index'), | |
| 18 | - field: 'id', | |
| 19 | - type: 'index', | |
| 20 | - form: { | |
| 21 | - show: false | |
| 14 | +const crudSchemas = reactive<VxeCrudSchema>({ | |
| 15 | + primaryKey: 'id', | |
| 16 | + primaryType: 'seq', | |
| 17 | + action: true, | |
| 18 | + columns: [ | |
| 19 | + { | |
| 20 | + title: '错误码类型', | |
| 21 | + field: 'type', | |
| 22 | + dictType: DICT_TYPE.SYSTEM_ERROR_CODE_TYPE, | |
| 23 | + search: { | |
| 24 | + show: true | |
| 25 | + } | |
| 22 | 26 | }, |
| 23 | - detail: { | |
| 24 | - show: false | |
| 25 | - } | |
| 26 | - }, | |
| 27 | - { | |
| 28 | - label: '错误码类型', | |
| 29 | - field: 'type', | |
| 30 | - component: 'InputNumber', | |
| 31 | - dictType: DICT_TYPE.SYSTEM_ERROR_CODE_TYPE, | |
| 32 | - search: { | |
| 33 | - show: true | |
| 34 | - } | |
| 35 | - }, | |
| 36 | - { | |
| 37 | - label: '应用名', | |
| 38 | - field: 'applicationName', | |
| 39 | - search: { | |
| 40 | - show: true | |
| 41 | - } | |
| 42 | - }, | |
| 43 | - { | |
| 44 | - label: '错误码编码', | |
| 45 | - field: 'code', | |
| 46 | - search: { | |
| 47 | - show: true | |
| 48 | - } | |
| 49 | - }, | |
| 50 | - { | |
| 51 | - label: '错误码错误提示', | |
| 52 | - field: 'message' | |
| 53 | - }, | |
| 54 | - { | |
| 55 | - label: t('common.createTime'), | |
| 56 | - field: 'createTime', | |
| 57 | - form: { | |
| 58 | - show: false | |
| 27 | + { | |
| 28 | + title: '应用名', | |
| 29 | + field: 'applicationName', | |
| 30 | + search: { | |
| 31 | + show: true | |
| 32 | + } | |
| 59 | 33 | }, |
| 60 | - search: { | |
| 61 | - show: true, | |
| 62 | - component: 'DatePicker', | |
| 63 | - componentProps: { | |
| 64 | - type: 'daterange', | |
| 65 | - valueFormat: 'YYYY-MM-DD HH:mm:ss', | |
| 66 | - defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] | |
| 34 | + { | |
| 35 | + title: '错误码编码', | |
| 36 | + field: 'code', | |
| 37 | + search: { | |
| 38 | + show: true | |
| 67 | 39 | } |
| 68 | - } | |
| 69 | - }, | |
| 70 | - { | |
| 71 | - field: 'action', | |
| 72 | - width: '240px', | |
| 73 | - label: t('table.action'), | |
| 74 | - form: { | |
| 75 | - show: false | |
| 76 | 40 | }, |
| 77 | - detail: { | |
| 78 | - show: false | |
| 41 | + { | |
| 42 | + title: '错误码错误提示', | |
| 43 | + field: 'message' | |
| 44 | + }, | |
| 45 | + { | |
| 46 | + title: t('common.createTime'), | |
| 47 | + field: 'createTime', | |
| 48 | + formatter: 'formatDate', | |
| 49 | + form: { | |
| 50 | + show: false | |
| 51 | + } | |
| 79 | 52 | } |
| 80 | - } | |
| 81 | -]) | |
| 82 | -export const { allSchemas } = useCrudSchemas(crudSchemas) | |
| 53 | + ] | |
| 54 | +}) | |
| 55 | +export const { allSchemas } = useVxeCrudSchemas(crudSchemas) | ... | ... |
yudao-ui-admin-vue3/src/views/system/errorCode/index.vue
| 1 | +<template> | |
| 2 | + <ContentWrap> | |
| 3 | + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar"> | |
| 4 | + <template #toolbar_buttons> | |
| 5 | + <XButton | |
| 6 | + type="primary" | |
| 7 | + preIcon="ep:zoom-in" | |
| 8 | + :title="t('action.add')" | |
| 9 | + v-hasPermi="['system:error-code:create']" | |
| 10 | + @click="handleCreate()" | |
| 11 | + /> | |
| 12 | + </template> | |
| 13 | + <template #createTime_item="{ data }"> | |
| 14 | + <el-date-picker | |
| 15 | + v-model="data.createTime" | |
| 16 | + type="datetimerange" | |
| 17 | + range-separator="-" | |
| 18 | + :start-placeholder="t('common.startTimeText')" | |
| 19 | + :end-placeholder="t('common.endTimeText')" | |
| 20 | + /> | |
| 21 | + </template> | |
| 22 | + <template #type_default="{ row }"> | |
| 23 | + <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> | |
| 24 | + </template> | |
| 25 | + <template #actionbtns_default="{ row }"> | |
| 26 | + <XTextButton | |
| 27 | + preIcon="ep:edit" | |
| 28 | + :title="t('action.edit')" | |
| 29 | + v-hasPermi="['system:error-code:update']" | |
| 30 | + @click="handleUpdate(row.id)" | |
| 31 | + /> | |
| 32 | + <XTextButton | |
| 33 | + preIcon="ep:view" | |
| 34 | + :title="t('action.detail')" | |
| 35 | + v-hasPermi="['system:error-code:update']" | |
| 36 | + @click="handleDetail(row)" | |
| 37 | + /> | |
| 38 | + <XTextButton | |
| 39 | + preIcon="ep:delete" | |
| 40 | + :title="t('action.del')" | |
| 41 | + v-hasPermi="['system:error-code:delete']" | |
| 42 | + @click="handleDelete(row.id)" | |
| 43 | + /> | |
| 44 | + </template> | |
| 45 | + </vxe-grid> | |
| 46 | + </ContentWrap> | |
| 47 | + <XModal id="errorCodeModel" v-model="dialogVisible" :title="dialogTitle"> | |
| 48 | + <template #default> | |
| 49 | + <!-- 对话框(添加 / 修改) --> | |
| 50 | + <Form | |
| 51 | + v-if="['create', 'update'].includes(actionType)" | |
| 52 | + :schema="allSchemas.formSchema" | |
| 53 | + :rules="rules" | |
| 54 | + ref="formRef" | |
| 55 | + /> | |
| 56 | + <!-- 对话框(详情) --> | |
| 57 | + <Descriptions | |
| 58 | + v-if="actionType === 'detail'" | |
| 59 | + :schema="allSchemas.detailSchema" | |
| 60 | + :data="detailRef" | |
| 61 | + > | |
| 62 | + <template #type="{ row }"> | |
| 63 | + <DictTag :type="DICT_TYPE.SYSTEM_ERROR_CODE_TYPE" :value="row.type" /> | |
| 64 | + </template> | |
| 65 | + <template #createTime="{ row }"> | |
| 66 | + <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | |
| 67 | + </template> | |
| 68 | + </Descriptions> | |
| 69 | + </template> | |
| 70 | + <!-- 操作按钮 --> | |
| 71 | + <template #footer> | |
| 72 | + <XButton | |
| 73 | + v-if="['create', 'update'].includes(actionType)" | |
| 74 | + type="primary" | |
| 75 | + :title="t('action.save')" | |
| 76 | + :loading="actionLoading" | |
| 77 | + @click="submitForm" | |
| 78 | + /> | |
| 79 | + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" /> | |
| 80 | + </template> | |
| 81 | + </XModal> | |
| 82 | +</template> | |
| 83 | + | |
| 1 | 84 | <script setup lang="ts"> |
| 2 | 85 | import { ref, unref } from 'vue' |
| 3 | 86 | import dayjs from 'dayjs' |
| 4 | -import { ElMessage } from 'element-plus' | |
| 5 | 87 | import { DICT_TYPE } from '@/utils/dict' |
| 6 | -import { useTable } from '@/hooks/web/useTable' | |
| 7 | -import { useI18n } from '@/hooks/web/useI18n' | |
| 8 | -import { FormExpose } from '@/components/Form' | |
| 9 | 88 | import type { ErrorCodeVO } from '@/api/system/errorCode/types' |
| 10 | 89 | import { rules, allSchemas } from './errorCode.data' |
| 11 | 90 | import * as ErrorCodeApi from '@/api/system/errorCode' |
| 12 | -const { t } = useI18n() // 国际化 | |
| 13 | - | |
| 14 | -// ========== 列表相关 ========== | |
| 15 | -const { register, tableObject, methods } = useTable<ErrorCodeVO>({ | |
| 16 | - getListApi: ErrorCodeApi.getErrorCodePageApi, | |
| 17 | - delListApi: ErrorCodeApi.deleteErrorCodeApi | |
| 18 | -}) | |
| 19 | -const { getList, setSearchParams, delList } = methods | |
| 91 | +import { useI18n } from '@/hooks/web/useI18n' | |
| 92 | +import { useMessage } from '@/hooks/web/useMessage' | |
| 93 | +import { useVxeGrid } from '@/hooks/web/useVxeGrid' | |
| 94 | +import { VxeGridInstance } from 'vxe-table' | |
| 95 | +import { FormExpose } from '@/components/Form' | |
| 96 | +import { ElDatePicker } from 'element-plus' | |
| 20 | 97 | |
| 21 | -// ========== CRUD 相关 ========== | |
| 22 | -const loading = ref(false) // 遮罩层 | |
| 23 | -const actionType = ref('') // 操作按钮的类型 | |
| 98 | +const { t } = useI18n() // 国际化 | |
| 99 | +const message = useMessage() // 消息弹窗 | |
| 24 | 100 | const dialogVisible = ref(false) // 是否显示弹出层 |
| 25 | 101 | const dialogTitle = ref('edit') // 弹出层标题 |
| 102 | +const actionType = ref('') // 操作按钮的类型 | |
| 103 | +const actionLoading = ref(false) // 按钮Loading | |
| 104 | +const xGrid = ref<VxeGridInstance>() // grid Ref | |
| 26 | 105 | const formRef = ref<FormExpose>() // 表单 Ref |
| 106 | +const detailRef = ref() // 详情 Ref | |
| 27 | 107 | |
| 108 | +const { gridOptions } = useVxeGrid<ErrorCodeVO>({ | |
| 109 | + allSchemas: allSchemas, | |
| 110 | + getListApi: ErrorCodeApi.getErrorCodePageApi | |
| 111 | +}) | |
| 28 | 112 | // 设置标题 |
| 29 | 113 | const setDialogTile = (type: string) => { |
| 30 | 114 | dialogTitle.value = t('action.' + type) |
| ... | ... | @@ -39,147 +123,57 @@ const handleCreate = () => { |
| 39 | 123 | unref(formRef)?.getElFormRef()?.resetFields() |
| 40 | 124 | } |
| 41 | 125 | |
| 126 | +// 详情操作 | |
| 127 | +const handleDetail = async (row: ErrorCodeVO) => { | |
| 128 | + // 设置数据 | |
| 129 | + detailRef.value = row | |
| 130 | + setDialogTile('detail') | |
| 131 | +} | |
| 132 | + | |
| 42 | 133 | // 修改操作 |
| 43 | -const handleUpdate = async (row: ErrorCodeVO) => { | |
| 134 | +const handleUpdate = async (rowId: number) => { | |
| 44 | 135 | setDialogTile('update') |
| 45 | 136 | // 设置数据 |
| 46 | - const res = await ErrorCodeApi.getErrorCodeApi(row.id) | |
| 137 | + const res = await ErrorCodeApi.getErrorCodeApi(rowId) | |
| 47 | 138 | unref(formRef)?.setValues(res) |
| 48 | 139 | } |
| 49 | 140 | |
| 141 | +// 删除操作 | |
| 142 | +const handleDelete = async (rowId: number) => { | |
| 143 | + message | |
| 144 | + .delConfirm() | |
| 145 | + .then(async () => { | |
| 146 | + await ErrorCodeApi.deleteErrorCodeApi(rowId) | |
| 147 | + message.success(t('common.delSuccess')) | |
| 148 | + }) | |
| 149 | + .finally(() => { | |
| 150 | + xGrid.value?.commitProxy('query') | |
| 151 | + }) | |
| 152 | +} | |
| 153 | + | |
| 50 | 154 | // 提交按钮 |
| 51 | 155 | const submitForm = async () => { |
| 52 | 156 | const elForm = unref(formRef)?.getElFormRef() |
| 53 | 157 | if (!elForm) return |
| 54 | 158 | elForm.validate(async (valid) => { |
| 55 | 159 | if (valid) { |
| 56 | - loading.value = true | |
| 160 | + actionLoading.value = true | |
| 57 | 161 | // 提交请求 |
| 58 | 162 | try { |
| 59 | 163 | const data = unref(formRef)?.formModel as ErrorCodeVO |
| 60 | 164 | if (actionType.value === 'create') { |
| 61 | 165 | await ErrorCodeApi.createErrorCodeApi(data) |
| 62 | - ElMessage.success(t('common.createSuccess')) | |
| 166 | + message.success(t('common.createSuccess')) | |
| 63 | 167 | } else { |
| 64 | 168 | await ErrorCodeApi.updateErrorCodeApi(data) |
| 65 | - ElMessage.success(t('common.updateSuccess')) | |
| 169 | + message.success(t('common.updateSuccess')) | |
| 66 | 170 | } |
| 67 | - // 操作成功,重新加载列表 | |
| 68 | 171 | dialogVisible.value = false |
| 69 | - await getList() | |
| 70 | 172 | } finally { |
| 71 | - loading.value = false | |
| 173 | + actionLoading.value = false | |
| 174 | + xGrid.value?.commitProxy('query') | |
| 72 | 175 | } |
| 73 | 176 | } |
| 74 | 177 | }) |
| 75 | 178 | } |
| 76 | - | |
| 77 | -// ========== 详情相关 ========== | |
| 78 | -const detailRef = ref() // 详情 Ref | |
| 79 | - | |
| 80 | -// 详情操作 | |
| 81 | -const handleDetail = async (row: ErrorCodeVO) => { | |
| 82 | - // 设置数据 | |
| 83 | - detailRef.value = row | |
| 84 | - setDialogTile('detail') | |
| 85 | -} | |
| 86 | - | |
| 87 | -// ========== 初始化 ========== | |
| 88 | -getList() | |
| 89 | 179 | </script> |
| 90 | - | |
| 91 | -<template> | |
| 92 | - <!-- 搜索工作区 --> | |
| 93 | - <ContentWrap> | |
| 94 | - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" /> | |
| 95 | - </ContentWrap> | |
| 96 | - <ContentWrap> | |
| 97 | - <!-- 操作工具栏 --> | |
| 98 | - <div class="mb-10px"> | |
| 99 | - <el-button v-hasPermi="['system:error-code:create']" type="primary" @click="handleCreate"> | |
| 100 | - <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }} | |
| 101 | - </el-button> | |
| 102 | - </div> | |
| 103 | - <!-- 列表 --> | |
| 104 | - <Table | |
| 105 | - :columns="allSchemas.tableColumns" | |
| 106 | - :selection="false" | |
| 107 | - :data="tableObject.tableList" | |
| 108 | - :loading="tableObject.loading" | |
| 109 | - :pagination="{ | |
| 110 | - total: tableObject.total | |
| 111 | - }" | |
| 112 | - v-model:pageSize="tableObject.pageSize" | |
| 113 | - v-model:currentPage="tableObject.currentPage" | |
| 114 | - @register="register" | |
| 115 | - > | |
| 116 | - <template #type="{ row }"> | |
| 117 | - <DictTag :type="DICT_TYPE.SYSTEM_ERROR_CODE_TYPE" :value="row.type" /> | |
| 118 | - </template> | |
| 119 | - <template #createTime="{ row }"> | |
| 120 | - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | |
| 121 | - </template> | |
| 122 | - <template #action="{ row }"> | |
| 123 | - <el-button | |
| 124 | - link | |
| 125 | - type="primary" | |
| 126 | - v-hasPermi="['system:error-code:update']" | |
| 127 | - @click="handleUpdate(row)" | |
| 128 | - > | |
| 129 | - <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }} | |
| 130 | - </el-button> | |
| 131 | - <el-button | |
| 132 | - link | |
| 133 | - type="primary" | |
| 134 | - v-hasPermi="['system:error-code:update']" | |
| 135 | - @click="handleDetail(row)" | |
| 136 | - > | |
| 137 | - <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }} | |
| 138 | - </el-button> | |
| 139 | - <el-button | |
| 140 | - link | |
| 141 | - type="primary" | |
| 142 | - v-hasPermi="['system:error-code:delete']" | |
| 143 | - @click="delList(row.id, false)" | |
| 144 | - > | |
| 145 | - <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }} | |
| 146 | - </el-button> | |
| 147 | - </template> | |
| 148 | - </Table> | |
| 149 | - </ContentWrap> | |
| 150 | - | |
| 151 | - <Dialog v-model="dialogVisible" :title="dialogTitle"> | |
| 152 | - <!-- 对话框(添加 / 修改) --> | |
| 153 | - <Form | |
| 154 | - v-if="['create', 'update'].includes(actionType)" | |
| 155 | - :schema="allSchemas.formSchema" | |
| 156 | - :rules="rules" | |
| 157 | - ref="formRef" | |
| 158 | - /> | |
| 159 | - <!-- 对话框(详情) --> | |
| 160 | - <Descriptions | |
| 161 | - v-if="actionType === 'detail'" | |
| 162 | - :schema="allSchemas.detailSchema" | |
| 163 | - :data="detailRef" | |
| 164 | - > | |
| 165 | - <template #type="{ row }"> | |
| 166 | - <DictTag :type="DICT_TYPE.SYSTEM_ERROR_CODE_TYPE" :value="row.type" /> | |
| 167 | - </template> | |
| 168 | - <template #createTime="{ row }"> | |
| 169 | - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | |
| 170 | - </template> | |
| 171 | - </Descriptions> | |
| 172 | - <!-- 操作按钮 --> | |
| 173 | - <template #footer> | |
| 174 | - <el-button | |
| 175 | - v-if="['create', 'update'].includes(actionType)" | |
| 176 | - type="primary" | |
| 177 | - :loading="loading" | |
| 178 | - @click="submitForm" | |
| 179 | - > | |
| 180 | - {{ t('action.save') }} | |
| 181 | - </el-button> | |
| 182 | - <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button> | |
| 183 | - </template> | |
| 184 | - </Dialog> | |
| 185 | -</template> | ... | ... |
yudao-ui-admin-vue3/src/views/system/post/index.vue
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | <template #status_default="{ row }"> |
| 14 | 14 | <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> |
| 15 | 15 | </template> |
| 16 | - <template #action_default="{ row }"> | |
| 16 | + <template #actionbtns_default="{ row }"> | |
| 17 | 17 | <XTextButton |
| 18 | 18 | preIcon="ep:edit" |
| 19 | 19 | :title="t('action.edit')" | ... | ... |
yudao-ui-admin-vue3/src/views/system/post/post.data.ts
| ... | ... | @@ -13,79 +13,52 @@ export const rules = reactive({ |
| 13 | 13 | }) |
| 14 | 14 | |
| 15 | 15 | // CrudSchema |
| 16 | -const crudSchemas = reactive<VxeCrudSchema[]>([ | |
| 17 | - { | |
| 18 | - title: t('common.index'), | |
| 19 | - field: 'id', | |
| 20 | - type: 'seq', | |
| 21 | - form: { | |
| 22 | - show: false | |
| 16 | +const crudSchemas = reactive<VxeCrudSchema>({ | |
| 17 | + primaryKey: 'id', | |
| 18 | + primaryType: 'seq', | |
| 19 | + action: true, | |
| 20 | + columns: [ | |
| 21 | + { | |
| 22 | + title: '岗位名称', | |
| 23 | + field: 'name', | |
| 24 | + search: { | |
| 25 | + show: true | |
| 26 | + } | |
| 23 | 27 | }, |
| 24 | - detail: { | |
| 25 | - show: false | |
| 26 | - } | |
| 27 | - }, | |
| 28 | - { | |
| 29 | - title: '岗位名称', | |
| 30 | - field: 'name', | |
| 31 | - search: { | |
| 32 | - show: true | |
| 33 | - } | |
| 34 | - }, | |
| 35 | - { | |
| 36 | - title: '岗位编码', | |
| 37 | - field: 'code', | |
| 38 | - search: { | |
| 39 | - show: true | |
| 40 | - } | |
| 41 | - }, | |
| 42 | - { | |
| 43 | - title: '岗位顺序', | |
| 44 | - field: 'sort' | |
| 45 | - }, | |
| 46 | - { | |
| 47 | - title: t('common.status'), | |
| 48 | - field: 'status', | |
| 49 | - dictType: DICT_TYPE.COMMON_STATUS, | |
| 50 | - table: { | |
| 51 | - slots: { | |
| 52 | - default: 'status_default' | |
| 28 | + { | |
| 29 | + title: '岗位编码', | |
| 30 | + field: 'code', | |
| 31 | + search: { | |
| 32 | + show: true | |
| 53 | 33 | } |
| 54 | 34 | }, |
| 55 | - search: { | |
| 56 | - show: true | |
| 57 | - } | |
| 58 | - }, | |
| 59 | - { | |
| 60 | - title: '备注', | |
| 61 | - field: 'remark', | |
| 62 | - table: { | |
| 63 | - show: false | |
| 64 | - } | |
| 65 | - }, | |
| 66 | - { | |
| 67 | - title: t('common.createTime'), | |
| 68 | - field: 'createTime', | |
| 69 | - formatter: 'formatDate', | |
| 70 | - form: { | |
| 71 | - show: false | |
| 72 | - } | |
| 73 | - }, | |
| 74 | - { | |
| 75 | - title: t('table.action'), | |
| 76 | - field: 'action', | |
| 77 | - table: { | |
| 78 | - width: '240px', | |
| 79 | - slots: { | |
| 80 | - default: 'action_default' | |
| 35 | + { | |
| 36 | + title: '岗位顺序', | |
| 37 | + field: 'sort' | |
| 38 | + }, | |
| 39 | + { | |
| 40 | + title: t('common.status'), | |
| 41 | + field: 'status', | |
| 42 | + dictType: DICT_TYPE.COMMON_STATUS, | |
| 43 | + search: { | |
| 44 | + show: true | |
| 81 | 45 | } |
| 82 | 46 | }, |
| 83 | - form: { | |
| 84 | - show: false | |
| 47 | + { | |
| 48 | + title: '备注', | |
| 49 | + field: 'remark', | |
| 50 | + table: { | |
| 51 | + show: false | |
| 52 | + } | |
| 85 | 53 | }, |
| 86 | - detail: { | |
| 87 | - show: false | |
| 54 | + { | |
| 55 | + title: t('common.createTime'), | |
| 56 | + field: 'createTime', | |
| 57 | + formatter: 'formatDate', | |
| 58 | + form: { | |
| 59 | + show: false | |
| 60 | + } | |
| 88 | 61 | } |
| 89 | - } | |
| 90 | -]) | |
| 62 | + ] | |
| 63 | +}) | |
| 91 | 64 | export const { allSchemas } = useVxeCrudSchemas(crudSchemas) | ... | ... |