Commit 49237ad9666e2dfe9208abaf338a8dc1fdf466e8
1 parent
e1b4ab2d
feat: add vxe crud schemas
Showing
6 changed files
with
346 additions
and
376 deletions
yudao-ui-admin-vue3/src/hooks/web/useVxeCrudSchemas.ts
0 → 100644
| 1 | +import { DescriptionsSchema } from '@/types/descriptions' | ||
| 2 | +import { getIntDictOptions } from '@/utils/dict' | ||
| 3 | +import { reactive } from 'vue' | ||
| 4 | +import { | ||
| 5 | + FormItemRenderOptions, | ||
| 6 | + VxeFormItemProps, | ||
| 7 | + VxeGridPropTypes, | ||
| 8 | + VxeTableDefines | ||
| 9 | +} from 'vxe-table' | ||
| 10 | +import { eachTree } from 'xe-utils' | ||
| 11 | +import { useI18n } from '@/hooks/web/useI18n' | ||
| 12 | +import { VxeTableColumn } from '@/types/table' | ||
| 13 | + | ||
| 14 | +export type VxeCrudSchema = Omit<VxeTableColumn, 'children'> & { | ||
| 15 | + field: string | ||
| 16 | + title?: string | ||
| 17 | + search?: CrudSearchParams | ||
| 18 | + table?: CrudTableParams | ||
| 19 | + form?: CrudFormParams | ||
| 20 | + detail?: CrudDescriptionsParams | ||
| 21 | + print?: boolean | ||
| 22 | + children?: VxeCrudSchema[] | ||
| 23 | + dictType?: string | ||
| 24 | +} | ||
| 25 | +type CrudSearchParams = { | ||
| 26 | + // 是否显示在查询项 | ||
| 27 | + show?: boolean | ||
| 28 | +} & Omit<VxeFormItemProps, 'field'> | ||
| 29 | + | ||
| 30 | +type CrudTableParams = { | ||
| 31 | + // 是否显示表头 | ||
| 32 | + show?: boolean | ||
| 33 | +} & Omit<VxeTableDefines.ColumnOptions, 'field'> | ||
| 34 | + | ||
| 35 | +type CrudFormParams = { | ||
| 36 | + // 是否显示表单项 | ||
| 37 | + show?: boolean | ||
| 38 | +} & Omit<VxeFormItemProps, 'field'> | ||
| 39 | + | ||
| 40 | +type CrudDescriptionsParams = { | ||
| 41 | + // 是否显示表单项 | ||
| 42 | + show?: boolean | ||
| 43 | +} & Omit<DescriptionsSchema, 'field'> | ||
| 44 | + | ||
| 45 | +interface VxeAllSchemas { | ||
| 46 | + searchSchema: VxeFormItemProps[] | ||
| 47 | + tableSchema: VxeGridPropTypes.Columns | ||
| 48 | + formSchema: VxeFormItemProps[] | ||
| 49 | + detailSchema: DescriptionsSchema[] | ||
| 50 | + printSchema: VxeTableDefines.ColumnInfo[] | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +// 过滤所有结构 | ||
| 54 | +export const useVxeCrudSchemas = ( | ||
| 55 | + crudSchema: VxeCrudSchema[] | ||
| 56 | +): { | ||
| 57 | + allSchemas: VxeAllSchemas | ||
| 58 | +} => { | ||
| 59 | + // 所有结构数据 | ||
| 60 | + const allSchemas = reactive<VxeAllSchemas>({ | ||
| 61 | + searchSchema: [], | ||
| 62 | + tableSchema: [], | ||
| 63 | + formSchema: [], | ||
| 64 | + detailSchema: [], | ||
| 65 | + printSchema: [] | ||
| 66 | + }) | ||
| 67 | + | ||
| 68 | + const searchSchema = filterSearchSchema(crudSchema) | ||
| 69 | + allSchemas.searchSchema = searchSchema || [] | ||
| 70 | + | ||
| 71 | + const tableSchema = filterTableSchema(crudSchema) | ||
| 72 | + allSchemas.tableSchema = tableSchema || [] | ||
| 73 | + | ||
| 74 | + const formSchema = filterFormSchema(crudSchema) | ||
| 75 | + allSchemas.formSchema = formSchema | ||
| 76 | + | ||
| 77 | + const detailSchema = filterDescriptionsSchema(crudSchema) | ||
| 78 | + allSchemas.detailSchema = detailSchema | ||
| 79 | + | ||
| 80 | + const printSchema = filterPrintSchema(crudSchema) | ||
| 81 | + allSchemas.printSchema = printSchema | ||
| 82 | + | ||
| 83 | + return { | ||
| 84 | + allSchemas | ||
| 85 | + } | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +// 过滤 Search 结构 | ||
| 89 | +const filterSearchSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] => { | ||
| 90 | + const searchSchema: VxeFormItemProps[] = [] | ||
| 91 | + const { t } = useI18n() | ||
| 92 | + eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | ||
| 93 | + // 判断是否显示 | ||
| 94 | + if (schemaItem?.search?.show) { | ||
| 95 | + let itemRenderName = schemaItem?.search?.itemRender?.name || '$input' | ||
| 96 | + const options: any[] = [] | ||
| 97 | + let itemRender: FormItemRenderOptions = { | ||
| 98 | + name: itemRenderName, | ||
| 99 | + props: { placeholder: t('common.inputText') } | ||
| 100 | + } | ||
| 101 | + if (schemaItem.dictType) { | ||
| 102 | + const allOptions = { label: '全部', value: '' } | ||
| 103 | + options.push(allOptions) | ||
| 104 | + getIntDictOptions(schemaItem.dictType).forEach((dict) => { | ||
| 105 | + options.push(dict) | ||
| 106 | + }) | ||
| 107 | + itemRender.options = options | ||
| 108 | + if (!schemaItem.search.itemRender?.name) itemRenderName = '$select' | ||
| 109 | + itemRender = { | ||
| 110 | + name: itemRenderName, | ||
| 111 | + options: options, | ||
| 112 | + props: { placeholder: t('common.selectText') } | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + const searchSchemaItem = { | ||
| 117 | + // 默认为 input | ||
| 118 | + span: 6, | ||
| 119 | + itemRender: itemRender, | ||
| 120 | + ...schemaItem.search, | ||
| 121 | + field: schemaItem.field, | ||
| 122 | + title: schemaItem.search?.title || schemaItem.title | ||
| 123 | + } | ||
| 124 | + // 删除不必要的字段 | ||
| 125 | + delete searchSchemaItem.show | ||
| 126 | + | ||
| 127 | + searchSchema.push(searchSchemaItem) | ||
| 128 | + } | ||
| 129 | + }) | ||
| 130 | + // 添加搜索按钮 | ||
| 131 | + const buttons: VxeFormItemProps = { | ||
| 132 | + span: 24, | ||
| 133 | + align: 'center', | ||
| 134 | + collapseNode: true, | ||
| 135 | + itemRender: { | ||
| 136 | + name: '$buttons', | ||
| 137 | + children: [ | ||
| 138 | + { props: { type: 'submit', content: t('common.query'), status: 'primary' } }, | ||
| 139 | + { props: { type: 'reset', content: t('common.reset') } } | ||
| 140 | + ] | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + searchSchema.push(buttons) | ||
| 144 | + return searchSchema | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +// 过滤 table 结构 | ||
| 148 | +const filterTableSchema = (crudSchema: VxeCrudSchema[]): VxeGridPropTypes.Columns => { | ||
| 149 | + const tableSchema: VxeGridPropTypes.Columns = [] | ||
| 150 | + eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | ||
| 151 | + // 判断是否显示 | ||
| 152 | + if (schemaItem?.table?.show !== false) { | ||
| 153 | + const tableSchemaItem = { | ||
| 154 | + ...schemaItem.table, | ||
| 155 | + field: schemaItem.field, | ||
| 156 | + title: schemaItem.table?.title || schemaItem.title | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + // 删除不必要的字段 | ||
| 160 | + delete tableSchemaItem.show | ||
| 161 | + | ||
| 162 | + tableSchema.push(tableSchemaItem) | ||
| 163 | + } | ||
| 164 | + }) | ||
| 165 | + return tableSchema | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +// 过滤 form 结构 | ||
| 169 | +const filterFormSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] => { | ||
| 170 | + const formSchema: VxeFormItemProps[] = [] | ||
| 171 | + const { t } = useI18n() | ||
| 172 | + eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | ||
| 173 | + // 判断是否显示 | ||
| 174 | + if (schemaItem?.form?.show !== false) { | ||
| 175 | + let itemRenderName = schemaItem?.form?.itemRender?.name || '$input' | ||
| 176 | + let itemRender: FormItemRenderOptions = { | ||
| 177 | + name: itemRenderName, | ||
| 178 | + props: { placeholder: t('common.inputText') } | ||
| 179 | + } | ||
| 180 | + if (schemaItem.dictType) { | ||
| 181 | + if (!(schemaItem.form && schemaItem.form.itemRender?.name)) itemRenderName = '$select' | ||
| 182 | + itemRender = { | ||
| 183 | + name: itemRenderName, | ||
| 184 | + options: getIntDictOptions(schemaItem.dictType), | ||
| 185 | + props: { placeholder: t('common.selectText') } | ||
| 186 | + } | ||
| 187 | + } | ||
| 188 | + const formSchemaItem = { | ||
| 189 | + // 默认为 input | ||
| 190 | + itemRender: itemRender, | ||
| 191 | + ...schemaItem.form, | ||
| 192 | + field: schemaItem.field, | ||
| 193 | + title: schemaItem.form?.title || schemaItem.title | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + // 删除不必要的字段 | ||
| 197 | + delete formSchemaItem.show | ||
| 198 | + | ||
| 199 | + formSchema.push(formSchemaItem) | ||
| 200 | + } | ||
| 201 | + }) | ||
| 202 | + | ||
| 203 | + return formSchema | ||
| 204 | +} | ||
| 205 | + | ||
| 206 | +// 过滤 descriptions 结构 | ||
| 207 | +const filterDescriptionsSchema = (crudSchema: VxeCrudSchema[]): DescriptionsSchema[] => { | ||
| 208 | + const descriptionsSchema: DescriptionsSchema[] = [] | ||
| 209 | + | ||
| 210 | + eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | ||
| 211 | + // 判断是否显示 | ||
| 212 | + if (schemaItem?.detail?.show !== false) { | ||
| 213 | + const descriptionsSchemaItem = { | ||
| 214 | + ...schemaItem.detail, | ||
| 215 | + field: schemaItem.field, | ||
| 216 | + label: schemaItem.detail?.label || schemaItem.title | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + // 删除不必要的字段 | ||
| 220 | + delete descriptionsSchemaItem.show | ||
| 221 | + | ||
| 222 | + descriptionsSchema.push(descriptionsSchemaItem) | ||
| 223 | + } | ||
| 224 | + }) | ||
| 225 | + | ||
| 226 | + return descriptionsSchema | ||
| 227 | +} | ||
| 228 | + | ||
| 229 | +// 过滤 打印 结构 | ||
| 230 | +const filterPrintSchema = (crudSchema: VxeCrudSchema[]): any[] => { | ||
| 231 | + const printSchema: any[] = [] | ||
| 232 | + | ||
| 233 | + eachTree(crudSchema, (schemaItem: VxeCrudSchema) => { | ||
| 234 | + // 判断是否显示 | ||
| 235 | + if (schemaItem?.detail?.show !== false) { | ||
| 236 | + const printSchemaItem = { | ||
| 237 | + field: schemaItem.field | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + printSchema.push(printSchemaItem) | ||
| 241 | + } | ||
| 242 | + }) | ||
| 243 | + | ||
| 244 | + return printSchema | ||
| 245 | +} |
yudao-ui-admin-vue3/src/hooks/web/useVxeGrid.ts
0 → 100644
| 1 | +import { reactive } from 'vue' | ||
| 2 | +import { VxeGridProps } from 'vxe-table' | ||
| 3 | + | ||
| 4 | +export const useVxeGrid = (allSchemas, getPageApi) => { | ||
| 5 | + const gridOptions = reactive<VxeGridProps>({ | ||
| 6 | + loading: false, | ||
| 7 | + rowConfig: { | ||
| 8 | + keyField: 'id', | ||
| 9 | + isHover: true | ||
| 10 | + }, | ||
| 11 | + toolbarConfig: { | ||
| 12 | + custom: true, | ||
| 13 | + slots: { buttons: 'toolbar_buttons' } | ||
| 14 | + }, | ||
| 15 | + printConfig: { | ||
| 16 | + columns: allSchemas.printSchema | ||
| 17 | + }, | ||
| 18 | + formConfig: { | ||
| 19 | + titleWidth: 100, | ||
| 20 | + titleAlign: 'right', | ||
| 21 | + items: allSchemas.searchSchema | ||
| 22 | + }, | ||
| 23 | + columns: allSchemas.tableSchema, | ||
| 24 | + pagerConfig: { | ||
| 25 | + border: false, | ||
| 26 | + background: false, | ||
| 27 | + perfect: true, | ||
| 28 | + pageSize: 10, | ||
| 29 | + pagerCount: 7, | ||
| 30 | + pageSizes: [5, 10, 15, 20, 50, 100, 200, 500], | ||
| 31 | + layouts: [ | ||
| 32 | + 'PrevJump', | ||
| 33 | + 'PrevPage', | ||
| 34 | + 'Jump', | ||
| 35 | + 'PageCount', | ||
| 36 | + 'NextPage', | ||
| 37 | + 'NextJump', | ||
| 38 | + 'Sizes', | ||
| 39 | + 'Total' | ||
| 40 | + ] | ||
| 41 | + }, | ||
| 42 | + proxyConfig: { | ||
| 43 | + seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号) | ||
| 44 | + form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为 | ||
| 45 | + props: { result: 'list', total: 'total' }, | ||
| 46 | + ajax: { | ||
| 47 | + query: ({ page, form }) => { | ||
| 48 | + const queryParams = Object.assign({}, form) | ||
| 49 | + queryParams.pageSize = page.pageSize | ||
| 50 | + queryParams.pageNo = page.currentPage | ||
| 51 | + return new Promise(async (resolve) => { | ||
| 52 | + resolve(await getPageApi(queryParams)) | ||
| 53 | + }) | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + }) | ||
| 58 | + return gridOptions | ||
| 59 | +} |
yudao-ui-admin-vue3/src/types/table.d.ts
| @@ -4,6 +4,12 @@ export type TableColumn = { | @@ -4,6 +4,12 @@ export type TableColumn = { | ||
| 4 | children?: TableColumn[] | 4 | children?: TableColumn[] |
| 5 | } & Recordable | 5 | } & Recordable |
| 6 | 6 | ||
| 7 | +export type VxeTableColumn = { | ||
| 8 | + field: string | ||
| 9 | + title?: string | ||
| 10 | + children?: TableColumn[] | ||
| 11 | +} & Recordable | ||
| 12 | + | ||
| 7 | export type TableSlotDefault = { | 13 | export type TableSlotDefault = { |
| 8 | row: Recordable | 14 | row: Recordable |
| 9 | column: TableColumn | 15 | column: TableColumn |
yudao-ui-admin-vue3/src/views/system/post/index.vue
| 1 | <script setup lang="ts"> | 1 | <script setup lang="ts"> |
| 2 | -import { reactive, ref } from 'vue' | 2 | +import { ref } from 'vue' |
| 3 | import dayjs from 'dayjs' | 3 | import dayjs from 'dayjs' |
| 4 | import { useI18n } from '@/hooks/web/useI18n' | 4 | import { useI18n } from '@/hooks/web/useI18n' |
| 5 | -import { | ||
| 6 | - VxeFormEvents, | ||
| 7 | - VxeFormInstance, | ||
| 8 | - VxeFormItemProps, | ||
| 9 | - VxeGrid, | ||
| 10 | - VxeGridInstance, | ||
| 11 | - VxeGridProps | ||
| 12 | -} from 'vxe-table' | 5 | +import { VxeFormEvents, VxeFormInstance, VxeFormItemProps, VxeGridInstance } from 'vxe-table' |
| 13 | import * as PostApi from '@/api/system/post' | 6 | import * as PostApi from '@/api/system/post' |
| 14 | -import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | 7 | +import { DICT_TYPE } from '@/utils/dict' |
| 15 | import { ContentWrap } from '@/components/ContentWrap' | 8 | import { ContentWrap } from '@/components/ContentWrap' |
| 16 | -import { PostPageReqVO, PostVO } from '@/api/system/post/types' | 9 | +import { PostVO } from '@/api/system/post/types' |
| 17 | import { rules, allSchemas } from './post.data' | 10 | import { rules, allSchemas } from './post.data' |
| 18 | -import { ElMessage, ElMessageBox } from 'element-plus' | 11 | +import { useMessage } from '@/hooks/web/useMessage' |
| 12 | +import { useVxeGrid } from '@/hooks/web/useVxeGrid' | ||
| 19 | 13 | ||
| 20 | const { t } = useI18n() // 国际化 | 14 | const { t } = useI18n() // 国际化 |
| 21 | - | 15 | +const message = useMessage() |
| 22 | const xGrid = ref<VxeGridInstance>() | 16 | const xGrid = ref<VxeGridInstance>() |
| 23 | const xForm = ref<VxeFormInstance>() | 17 | const xForm = ref<VxeFormInstance>() |
| 24 | const dialogVisible = ref(false) // 是否显示弹出层 | 18 | const dialogVisible = ref(false) // 是否显示弹出层 |
| @@ -26,158 +20,9 @@ const dialogTitle = ref('edit') // 弹出层标题 | @@ -26,158 +20,9 @@ const dialogTitle = ref('edit') // 弹出层标题 | ||
| 26 | const actionType = ref('') // 操作按钮的类型 | 20 | const actionType = ref('') // 操作按钮的类型 |
| 27 | const actionLoading = ref(false) // 遮罩层 | 21 | const actionLoading = ref(false) // 遮罩层 |
| 28 | 22 | ||
| 29 | -const gridOptions = reactive<VxeGridProps>({ | ||
| 30 | - loading: false, | ||
| 31 | - rowConfig: { | ||
| 32 | - keyField: 'id', | ||
| 33 | - isHover: true | ||
| 34 | - }, | ||
| 35 | - toolbarConfig: { | ||
| 36 | - custom: true, | ||
| 37 | - slots: { buttons: 'toolbar_buttons' } | ||
| 38 | - }, | ||
| 39 | - printConfig: { | ||
| 40 | - columns: [ | ||
| 41 | - { field: 'name' }, | ||
| 42 | - { field: 'code' }, | ||
| 43 | - { field: 'sort' }, | ||
| 44 | - { field: 'status' }, | ||
| 45 | - { field: 'createTime' } | ||
| 46 | - ] | ||
| 47 | - }, | ||
| 48 | - formConfig: { | ||
| 49 | - titleWidth: 100, | ||
| 50 | - titleAlign: 'right', | ||
| 51 | - items: [ | ||
| 52 | - { | ||
| 53 | - field: 'name', | ||
| 54 | - title: '岗位名称', | ||
| 55 | - span: 6, | ||
| 56 | - itemRender: { name: '$input', props: { placeholder: '请输入岗位名称' } } | ||
| 57 | - }, | ||
| 58 | - { | ||
| 59 | - field: 'code', | ||
| 60 | - title: '岗位编码', | ||
| 61 | - span: 6, | ||
| 62 | - itemRender: { name: '$input', props: { placeholder: '请输入岗位编码' } } | ||
| 63 | - }, | ||
| 64 | - { | ||
| 65 | - field: 'status', | ||
| 66 | - title: t('common.status'), | ||
| 67 | - span: 6, | ||
| 68 | - itemRender: { name: '$select', options: getIntDictOptions(DICT_TYPE.COMMON_STATUS) } | ||
| 69 | - }, | ||
| 70 | - { | ||
| 71 | - span: 24, | ||
| 72 | - align: 'center', | ||
| 73 | - collapseNode: true, | ||
| 74 | - itemRender: { | ||
| 75 | - name: '$buttons', | ||
| 76 | - children: [ | ||
| 77 | - { props: { type: 'submit', content: t('common.query'), status: 'primary' } }, | ||
| 78 | - { props: { type: 'reset', content: t('common.reset') } } | ||
| 79 | - ] | ||
| 80 | - } | ||
| 81 | - } | ||
| 82 | - ] | ||
| 83 | - }, | ||
| 84 | - columns: [ | ||
| 85 | - { type: 'seq', title: t('common.index'), width: 100 }, | ||
| 86 | - { field: 'name', title: '岗位名称' }, | ||
| 87 | - { field: 'code', title: '岗位编码' }, | ||
| 88 | - { field: 'sort', title: '岗位顺序' }, | ||
| 89 | - { | ||
| 90 | - field: 'status', | ||
| 91 | - title: t('common.status'), | ||
| 92 | - slots: { | ||
| 93 | - default: 'status_default' | ||
| 94 | - } | ||
| 95 | - }, | ||
| 96 | - { | ||
| 97 | - field: 'createTime', | ||
| 98 | - title: t('common.createTime'), | ||
| 99 | - width: 160, | ||
| 100 | - sortable: true, | ||
| 101 | - formatter: 'formatDate' | ||
| 102 | - }, | ||
| 103 | - { | ||
| 104 | - field: 'action', | ||
| 105 | - title: t('table.action'), | ||
| 106 | - width: '240px', | ||
| 107 | - showOverflow: true, | ||
| 108 | - slots: { | ||
| 109 | - default: 'action_default' | ||
| 110 | - } | ||
| 111 | - } | ||
| 112 | - ], | ||
| 113 | - pagerConfig: { | ||
| 114 | - border: false, | ||
| 115 | - background: false, | ||
| 116 | - perfect: true, | ||
| 117 | - pageSize: 10, | ||
| 118 | - pagerCount: 7, | ||
| 119 | - pageSizes: [5, 10, 15, 20, 50, 100, 200, 500], | ||
| 120 | - layouts: ['PrevJump', 'PrevPage', 'Jump', 'PageCount', 'NextPage', 'NextJump', 'Sizes', 'Total'] | ||
| 121 | - }, | ||
| 122 | - proxyConfig: { | ||
| 123 | - seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号) | ||
| 124 | - form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为 | ||
| 125 | - props: { result: 'list', total: 'total' }, | ||
| 126 | - ajax: { | ||
| 127 | - query: ({ page, form }) => { | ||
| 128 | - const queryParams: PostPageReqVO = Object.assign({}, form) | ||
| 129 | - queryParams.pageSize = page.pageSize | ||
| 130 | - queryParams.pageNo = page.currentPage | ||
| 131 | - return new Promise(async (resolve) => { | ||
| 132 | - resolve(await PostApi.getPostPageApi(queryParams)) | ||
| 133 | - }) | ||
| 134 | - } | ||
| 135 | - } | ||
| 136 | - } | ||
| 137 | -}) | 23 | +const gridOptions = useVxeGrid(allSchemas, PostApi.getPostPageApi) |
| 138 | const formData = ref<PostVO>() | 24 | const formData = ref<PostVO>() |
| 139 | -const formItems = ref<VxeFormItemProps[]>([ | ||
| 140 | - { field: 'id', title: 'id', visible: false }, | ||
| 141 | - { | ||
| 142 | - field: 'name', | ||
| 143 | - title: '岗位名称', | ||
| 144 | - span: 12, | ||
| 145 | - itemRender: { name: '$input', props: { placeholder: '请输入岗位名称' } } | ||
| 146 | - }, | ||
| 147 | - { | ||
| 148 | - field: 'code', | ||
| 149 | - title: '岗位编码', | ||
| 150 | - span: 12, | ||
| 151 | - itemRender: { name: '$input', props: { placeholder: '请输入岗位编码' } } | ||
| 152 | - }, | ||
| 153 | - { | ||
| 154 | - field: 'sort', | ||
| 155 | - title: '岗位顺序', | ||
| 156 | - span: 12, | ||
| 157 | - itemRender: { name: '$input', props: { type: 'number', placeholder: '请输入岗位顺序' } } | ||
| 158 | - }, | ||
| 159 | - { | ||
| 160 | - field: 'status', | ||
| 161 | - title: t('common.status'), | ||
| 162 | - span: 12, | ||
| 163 | - itemRender: { | ||
| 164 | - name: '$select', | ||
| 165 | - options: getIntDictOptions(DICT_TYPE.COMMON_STATUS), | ||
| 166 | - props: { placeholder: '请选择' } | ||
| 167 | - } | ||
| 168 | - }, | ||
| 169 | - { | ||
| 170 | - align: 'center', | ||
| 171 | - span: 24, | ||
| 172 | - itemRender: { | ||
| 173 | - name: '$buttons', | ||
| 174 | - children: [ | ||
| 175 | - { props: { type: 'submit', content: t('action.save'), status: 'primary' } }, | ||
| 176 | - { props: { type: 'reset', content: t('common.reset') } } | ||
| 177 | - ] | ||
| 178 | - } | ||
| 179 | - } | ||
| 180 | -]) | 25 | +const formItems = ref<VxeFormItemProps[]>(allSchemas.formSchema) |
| 181 | // 设置标题 | 26 | // 设置标题 |
| 182 | const setDialogTile = (type: string) => { | 27 | const setDialogTile = (type: string) => { |
| 183 | dialogTitle.value = t('action.' + type) | 28 | dialogTitle.value = t('action.' + type) |
| @@ -206,16 +51,13 @@ const handleUpdate = async (rowId: number) => { | @@ -206,16 +51,13 @@ const handleUpdate = async (rowId: number) => { | ||
| 206 | } | 51 | } |
| 207 | // 删除操作 | 52 | // 删除操作 |
| 208 | const handleDelete = (rowId: number) => { | 53 | const handleDelete = (rowId: number) => { |
| 209 | - ElMessageBox.confirm(t('common.delMessage'), t('common.confirmTitle'), { | ||
| 210 | - confirmButtonText: t('common.ok'), | ||
| 211 | - cancelButtonText: t('common.cancel'), | ||
| 212 | - type: 'warning' | ||
| 213 | - }) | 54 | + message |
| 55 | + .confirm(t('common.delMessage'), t('common.confirmTitle')) | ||
| 214 | .then(async () => { | 56 | .then(async () => { |
| 215 | await PostApi.deletePostApi(rowId) | 57 | await PostApi.deletePostApi(rowId) |
| 58 | + message.success(t('common.delSuccess')) | ||
| 216 | }) | 59 | }) |
| 217 | .finally(() => { | 60 | .finally(() => { |
| 218 | - ElMessage.success(t('common.delSuccess')) | ||
| 219 | xGrid.value?.commitProxy('query') | 61 | xGrid.value?.commitProxy('query') |
| 220 | }) | 62 | }) |
| 221 | } | 63 | } |
| @@ -227,10 +69,10 @@ const submitForm: VxeFormEvents.Submit = async () => { | @@ -227,10 +69,10 @@ const submitForm: VxeFormEvents.Submit = async () => { | ||
| 227 | const data = formData.value as PostVO | 69 | const data = formData.value as PostVO |
| 228 | if (actionType.value === 'create') { | 70 | if (actionType.value === 'create') { |
| 229 | await PostApi.createPostApi(data) | 71 | await PostApi.createPostApi(data) |
| 230 | - ElMessage.success(t('common.createSuccess')) | 72 | + message.success(t('common.createSuccess')) |
| 231 | } else { | 73 | } else { |
| 232 | await PostApi.updatePostApi(data) | 74 | await PostApi.updatePostApi(data) |
| 233 | - ElMessage.success(t('common.updateSuccess')) | 75 | + message.success(t('common.updateSuccess')) |
| 234 | } | 76 | } |
| 235 | // 操作成功,重新加载列表 | 77 | // 操作成功,重新加载列表 |
| 236 | dialogVisible.value = false | 78 | dialogVisible.value = false |
yudao-ui-admin-vue3/src/views/system/post/indexd.vue deleted
| 1 | -<script setup lang="ts"> | ||
| 2 | -import { ref, unref } from 'vue' | ||
| 3 | -import dayjs from 'dayjs' | ||
| 4 | -import { ElMessage } from 'element-plus' | ||
| 5 | -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 | -import type { PostVO } from '@/api/system/post/types' | ||
| 10 | -import { rules, allSchemas } from './post.data' | ||
| 11 | -import * as PostApi from '@/api/system/post' | ||
| 12 | -const { t } = useI18n() // 国际化 | ||
| 13 | - | ||
| 14 | -// ========== 列表相关 ========== | ||
| 15 | -const { register, tableObject, methods } = useTable<PostVO>({ | ||
| 16 | - getListApi: PostApi.getPostPageApi, | ||
| 17 | - delListApi: PostApi.deletePostApi, | ||
| 18 | - exportListApi: PostApi.exportPostApi | ||
| 19 | -}) | ||
| 20 | -const { getList, setSearchParams, delList, exportList } = methods | ||
| 21 | - | ||
| 22 | -// ========== CRUD 相关 ========== | ||
| 23 | -const actionLoading = ref(false) // 遮罩层 | ||
| 24 | -const actionType = ref('') // 操作按钮的类型 | ||
| 25 | -const dialogVisible = ref(false) // 是否显示弹出层 | ||
| 26 | -const dialogTitle = ref('edit') // 弹出层标题 | ||
| 27 | -const formRef = ref<FormExpose>() // 表单 Ref | ||
| 28 | - | ||
| 29 | -// 设置标题 | ||
| 30 | -const setDialogTile = (type: string) => { | ||
| 31 | - dialogTitle.value = t('action.' + type) | ||
| 32 | - actionType.value = type | ||
| 33 | - dialogVisible.value = true | ||
| 34 | -} | ||
| 35 | - | ||
| 36 | -// 新增操作 | ||
| 37 | -const handleCreate = () => { | ||
| 38 | - setDialogTile('create') | ||
| 39 | - // 重置表单 | ||
| 40 | - unref(formRef)?.getElFormRef()?.resetFields() | ||
| 41 | -} | ||
| 42 | - | ||
| 43 | -// 修改操作 | ||
| 44 | -const handleUpdate = async (rowId: number) => { | ||
| 45 | - setDialogTile('update') | ||
| 46 | - // 设置数据 | ||
| 47 | - const res = await PostApi.getPostApi(rowId) | ||
| 48 | - unref(formRef)?.setValues(res) | ||
| 49 | -} | ||
| 50 | - | ||
| 51 | -// 提交按钮 | ||
| 52 | -const submitForm = async () => { | ||
| 53 | - const elForm = unref(formRef)?.getElFormRef() | ||
| 54 | - if (!elForm) return | ||
| 55 | - elForm.validate(async (valid) => { | ||
| 56 | - if (valid) { | ||
| 57 | - actionLoading.value = true | ||
| 58 | - // 提交请求 | ||
| 59 | - try { | ||
| 60 | - const data = unref(formRef)?.formModel as PostVO | ||
| 61 | - if (actionType.value === 'create') { | ||
| 62 | - await PostApi.createPostApi(data) | ||
| 63 | - ElMessage.success(t('common.createSuccess')) | ||
| 64 | - } else { | ||
| 65 | - await PostApi.updatePostApi(data) | ||
| 66 | - ElMessage.success(t('common.updateSuccess')) | ||
| 67 | - } | ||
| 68 | - // 操作成功,重新加载列表 | ||
| 69 | - dialogVisible.value = false | ||
| 70 | - await getList() | ||
| 71 | - } finally { | ||
| 72 | - actionLoading.value = false | ||
| 73 | - } | ||
| 74 | - } | ||
| 75 | - }) | ||
| 76 | -} | ||
| 77 | - | ||
| 78 | -// ========== 详情相关 ========== | ||
| 79 | -const detailRef = ref() // 详情 Ref | ||
| 80 | - | ||
| 81 | -// 详情操作 | ||
| 82 | -const handleDetail = async (row: PostVO) => { | ||
| 83 | - // 设置数据 | ||
| 84 | - detailRef.value = row | ||
| 85 | - setDialogTile('detail') | ||
| 86 | -} | ||
| 87 | - | ||
| 88 | -// ========== 初始化 ========== | ||
| 89 | -getList() | ||
| 90 | -</script> | ||
| 91 | - | ||
| 92 | -<template> | ||
| 93 | - <!-- 搜索工作区 --> | ||
| 94 | - <ContentWrap> | ||
| 95 | - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" /> | ||
| 96 | - </ContentWrap> | ||
| 97 | - <ContentWrap> | ||
| 98 | - <!-- 操作工具栏 --> | ||
| 99 | - <div class="mb-10px"> | ||
| 100 | - <el-button type="primary" v-hasPermi="['system:post:create']" @click="handleCreate"> | ||
| 101 | - <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }} | ||
| 102 | - </el-button> | ||
| 103 | - <el-button | ||
| 104 | - type="warning" | ||
| 105 | - v-hasPermi="['system:post:export']" | ||
| 106 | - :loading="tableObject.exportLoading" | ||
| 107 | - @click="exportList('岗位数据.xls')" | ||
| 108 | - > | ||
| 109 | - <Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }} | ||
| 110 | - </el-button> | ||
| 111 | - </div> | ||
| 112 | - <!-- 列表 --> | ||
| 113 | - <Table | ||
| 114 | - :columns="allSchemas.tableColumns" | ||
| 115 | - :selection="false" | ||
| 116 | - :data="tableObject.tableList" | ||
| 117 | - :loading="tableObject.loading" | ||
| 118 | - :pagination="{ | ||
| 119 | - total: tableObject.total | ||
| 120 | - }" | ||
| 121 | - v-model:pageSize="tableObject.pageSize" | ||
| 122 | - v-model:currentPage="tableObject.currentPage" | ||
| 123 | - @register="register" | ||
| 124 | - > | ||
| 125 | - <template #status="{ row }"> | ||
| 126 | - <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> | ||
| 127 | - </template> | ||
| 128 | - <template #createTime="{ row }"> | ||
| 129 | - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | ||
| 130 | - </template> | ||
| 131 | - <template #action="{ row }"> | ||
| 132 | - <el-button | ||
| 133 | - link | ||
| 134 | - type="primary" | ||
| 135 | - v-hasPermi="['system:post:update']" | ||
| 136 | - @click="handleUpdate(row.id)" | ||
| 137 | - > | ||
| 138 | - <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }} | ||
| 139 | - </el-button> | ||
| 140 | - <el-button | ||
| 141 | - link | ||
| 142 | - type="primary" | ||
| 143 | - v-hasPermi="['system:post:update']" | ||
| 144 | - @click="handleDetail(row)" | ||
| 145 | - > | ||
| 146 | - <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }} | ||
| 147 | - </el-button> | ||
| 148 | - <el-button | ||
| 149 | - link | ||
| 150 | - type="primary" | ||
| 151 | - v-hasPermi="['system:post:delete']" | ||
| 152 | - @click="delList(row.id, false)" | ||
| 153 | - > | ||
| 154 | - <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }} | ||
| 155 | - </el-button> | ||
| 156 | - </template> | ||
| 157 | - </Table> | ||
| 158 | - </ContentWrap> | ||
| 159 | - | ||
| 160 | - <Dialog v-model="dialogVisible" :title="dialogTitle"> | ||
| 161 | - <!-- 对话框(添加 / 修改) --> | ||
| 162 | - <Form | ||
| 163 | - v-if="['create', 'update'].includes(actionType)" | ||
| 164 | - :schema="allSchemas.formSchema" | ||
| 165 | - :rules="rules" | ||
| 166 | - ref="formRef" | ||
| 167 | - /> | ||
| 168 | - <!-- 对话框(详情) --> | ||
| 169 | - <Descriptions | ||
| 170 | - v-if="actionType === 'detail'" | ||
| 171 | - :schema="allSchemas.detailSchema" | ||
| 172 | - :data="detailRef" | ||
| 173 | - > | ||
| 174 | - <template #status="{ row }"> | ||
| 175 | - <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> | ||
| 176 | - </template> | ||
| 177 | - <template #createTime="{ row }"> | ||
| 178 | - <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span> | ||
| 179 | - </template> | ||
| 180 | - </Descriptions> | ||
| 181 | - <!-- 操作按钮 --> | ||
| 182 | - <template #footer> | ||
| 183 | - <el-button | ||
| 184 | - v-if="['create', 'update'].includes(actionType)" | ||
| 185 | - type="primary" | ||
| 186 | - :loading="actionLoading" | ||
| 187 | - @click="submitForm" | ||
| 188 | - > | ||
| 189 | - {{ t('action.save') }} | ||
| 190 | - </el-button> | ||
| 191 | - <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button> | ||
| 192 | - </template> | ||
| 193 | - </Dialog> | ||
| 194 | -</template> |
yudao-ui-admin-vue3/src/views/system/post/post.data.ts
| 1 | import { reactive } from 'vue' | 1 | import { reactive } from 'vue' |
| 2 | import { useI18n } from '@/hooks/web/useI18n' | 2 | import { useI18n } from '@/hooks/web/useI18n' |
| 3 | import { required } from '@/utils/formRules' | 3 | import { required } from '@/utils/formRules' |
| 4 | -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' | 4 | +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas' |
| 5 | import { DICT_TYPE } from '@/utils/dict' | 5 | import { DICT_TYPE } from '@/utils/dict' |
| 6 | const { t } = useI18n() // 国际化 | 6 | const { t } = useI18n() // 国际化 |
| 7 | 7 | ||
| @@ -13,9 +13,9 @@ export const rules = reactive({ | @@ -13,9 +13,9 @@ export const rules = reactive({ | ||
| 13 | }) | 13 | }) |
| 14 | 14 | ||
| 15 | // CrudSchema | 15 | // CrudSchema |
| 16 | -const crudSchemas = reactive<CrudSchema[]>([ | 16 | +const crudSchemas = reactive<VxeCrudSchema[]>([ |
| 17 | { | 17 | { |
| 18 | - label: t('common.index'), | 18 | + title: t('common.index'), |
| 19 | field: 'id', | 19 | field: 'id', |
| 20 | type: 'index', | 20 | type: 'index', |
| 21 | form: { | 21 | form: { |
| @@ -26,42 +26,54 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -26,42 +26,54 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 26 | } | 26 | } |
| 27 | }, | 27 | }, |
| 28 | { | 28 | { |
| 29 | - label: '岗位名称', | 29 | + title: '岗位名称', |
| 30 | field: 'name', | 30 | field: 'name', |
| 31 | search: { | 31 | search: { |
| 32 | show: true | 32 | show: true |
| 33 | } | 33 | } |
| 34 | }, | 34 | }, |
| 35 | { | 35 | { |
| 36 | - label: '岗位编码', | 36 | + title: '岗位编码', |
| 37 | field: 'code', | 37 | field: 'code', |
| 38 | search: { | 38 | search: { |
| 39 | show: true | 39 | show: true |
| 40 | } | 40 | } |
| 41 | }, | 41 | }, |
| 42 | { | 42 | { |
| 43 | - label: '岗位顺序', | 43 | + title: '岗位顺序', |
| 44 | field: 'sort' | 44 | field: 'sort' |
| 45 | }, | 45 | }, |
| 46 | { | 46 | { |
| 47 | - label: t('common.status'), | 47 | + title: t('common.status'), |
| 48 | field: 'status', | 48 | field: 'status', |
| 49 | dictType: DICT_TYPE.COMMON_STATUS, | 49 | dictType: DICT_TYPE.COMMON_STATUS, |
| 50 | + table: { | ||
| 51 | + slots: { | ||
| 52 | + default: 'status_default' | ||
| 53 | + } | ||
| 54 | + }, | ||
| 50 | search: { | 55 | search: { |
| 51 | show: true | 56 | show: true |
| 52 | } | 57 | } |
| 53 | }, | 58 | }, |
| 54 | { | 59 | { |
| 55 | - label: t('common.createTime'), | 60 | + title: t('common.createTime'), |
| 56 | field: 'createTime', | 61 | field: 'createTime', |
| 57 | form: { | 62 | form: { |
| 58 | show: false | 63 | show: false |
| 59 | } | 64 | } |
| 60 | }, | 65 | }, |
| 61 | { | 66 | { |
| 62 | - label: t('table.action'), | 67 | + title: t('table.action'), |
| 63 | field: 'action', | 68 | field: 'action', |
| 64 | width: '240px', | 69 | width: '240px', |
| 70 | + table: { | ||
| 71 | + width: '240px', | ||
| 72 | + showOverflow: true, | ||
| 73 | + slots: { | ||
| 74 | + default: 'action_default' | ||
| 75 | + } | ||
| 76 | + }, | ||
| 65 | form: { | 77 | form: { |
| 66 | show: false | 78 | show: false |
| 67 | }, | 79 | }, |
| @@ -70,4 +82,4 @@ const crudSchemas = reactive<CrudSchema[]>([ | @@ -70,4 +82,4 @@ const crudSchemas = reactive<CrudSchema[]>([ | ||
| 70 | } | 82 | } |
| 71 | } | 83 | } |
| 72 | ]) | 84 | ]) |
| 73 | -export const { allSchemas } = useCrudSchemas(crudSchemas) | 85 | +export const { allSchemas } = useVxeCrudSchemas(crudSchemas) |