Commit dc84ebde9ddc476c405c4a14f410bcdaf40b5387

Authored by xingyu4j
1 parent 1a45526a

perf: vxe demo

yudao-ui-admin-vue3/src/api/system/post/types.ts
... ... @@ -5,7 +5,7 @@ export type PostVO = {
5 5 sort: number
6 6 status: number
7 7 remark: string
8   - createTime: string
  8 + createTime?: string
9 9 }
10 10  
11 11 export type PostPageReqVO = {
... ...
yudao-ui-admin-vue3/src/hooks/web/useVxeCrudSchemas.ts
... ... @@ -3,6 +3,7 @@ import { getIntDictOptions } from '@/utils/dict'
3 3 import { reactive } from 'vue'
4 4 import {
5 5 FormItemRenderOptions,
  6 + VxeColumnPropTypes,
6 7 VxeFormItemProps,
7 8 VxeGridPropTypes,
8 9 VxeTableDefines
... ... @@ -10,10 +11,13 @@ import {
10 11 import { eachTree } from 'xe-utils'
11 12 import { useI18n } from '@/hooks/web/useI18n'
12 13 import { VxeTableColumn } from '@/types/table'
  14 +import { FormSchema } from '@/types/form'
  15 +import { ComponentOptions } from '@/types/components'
13 16  
14 17 export type VxeCrudSchema = Omit<VxeTableColumn, 'children'> & {
15 18 field: string
16 19 title?: string
  20 + formatter?: VxeColumnPropTypes.Formatter
17 21 search?: CrudSearchParams
18 22 table?: CrudTableParams
19 23 form?: CrudFormParams
... ... @@ -35,7 +39,7 @@ type CrudTableParams = {
35 39 type CrudFormParams = {
36 40 // 是否显示表单项
37 41 show?: boolean
38   -} & Omit<VxeFormItemProps, 'field'>
  42 +} & Omit<FormSchema, 'field'>
39 43  
40 44 type CrudDescriptionsParams = {
41 45 // 是否显示表单项
... ... @@ -47,10 +51,10 @@ type CrudPrintParams = {
47 51 show?: boolean
48 52 } & Omit<VxeTableDefines.ColumnInfo[], 'field'>
49 53  
50   -interface VxeAllSchemas {
  54 +export type VxeAllSchemas = {
51 55 searchSchema: VxeFormItemProps[]
52 56 tableSchema: VxeGridPropTypes.Columns
53   - formSchema: VxeFormItemProps[]
  57 + formSchema: FormSchema[]
54 58 detailSchema: DescriptionsSchema[]
55 59 printSchema: VxeTableDefines.ColumnInfo[]
56 60 }
... ... @@ -160,6 +164,9 @@ const filterTableSchema = (crudSchema: VxeCrudSchema[]): VxeGridPropTypes.Column
160 164 field: schemaItem.field,
161 165 title: schemaItem.table?.title || schemaItem.title
162 166 }
  167 + if (schemaItem?.formatter) {
  168 + tableSchemaItem.formatter = schemaItem.formatter
  169 + }
163 170  
164 171 // 删除不必要的字段
165 172 delete tableSchemaItem.show
... ... @@ -171,32 +178,31 @@ const filterTableSchema = (crudSchema: VxeCrudSchema[]): VxeGridPropTypes.Column
171 178 }
172 179  
173 180 // 过滤 form 结构
174   -const filterFormSchema = (crudSchema: VxeCrudSchema[]): VxeFormItemProps[] => {
175   - const formSchema: VxeFormItemProps[] = []
176   - const { t } = useI18n()
  181 +const filterFormSchema = (crudSchema: VxeCrudSchema[]): FormSchema[] => {
  182 + const formSchema: FormSchema[] = []
  183 +
177 184 eachTree(crudSchema, (schemaItem: VxeCrudSchema) => {
178 185 // 判断是否显示
179 186 if (schemaItem?.form?.show !== false) {
180   - let itemRenderName = schemaItem?.form?.itemRender?.name || '$input'
181   - let itemRender: FormItemRenderOptions = {
182   - name: itemRenderName,
183   - props: { placeholder: t('common.inputText') }
184   - }
  187 + let component = schemaItem?.form?.component || 'Input'
  188 + const options: ComponentOptions[] = []
  189 + let comonentProps = {}
185 190 if (schemaItem.dictType) {
186   - if (!(schemaItem.form && schemaItem.form.itemRender?.name)) itemRenderName = '$select'
187   - itemRender = {
188   - name: itemRenderName,
189   - options: getIntDictOptions(schemaItem.dictType),
190   - props: { placeholder: t('common.selectText') }
  191 + getIntDictOptions(schemaItem.dictType).forEach((dict) => {
  192 + options.push(dict)
  193 + })
  194 + comonentProps = {
  195 + options: options
191 196 }
  197 + if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
192 198 }
193 199 const formSchemaItem = {
194 200 // 默认为 input
195   - itemRender: itemRender,
  201 + component: component,
  202 + componentProps: comonentProps,
196 203 ...schemaItem.form,
197   - span: schemaItem.form?.span || 12,
198 204 field: schemaItem.field,
199   - title: schemaItem.form?.title || schemaItem.title
  205 + label: schemaItem.form?.label || schemaItem.title
200 206 }
201 207  
202 208 // 删除不必要的字段
... ...
yudao-ui-admin-vue3/src/hooks/web/useVxeGrid.ts
1 1 import { computed, reactive } from 'vue'
2 2 import { VxeGridProps } from 'vxe-table'
3 3 import { useAppStore } from '@/store/modules/app'
  4 +import { VxeAllSchemas } from './useVxeCrudSchemas'
  5 +import { useI18n } from '@/hooks/web/useI18n'
  6 +import { useMessage } from '@/hooks/web/useMessage'
  7 +
  8 +const { t } = useI18n()
  9 +const message = useMessage() // 消息弹窗
  10 +
  11 +interface UseVxeGridConfig<T = any> {
  12 + allSchemas: VxeAllSchemas
  13 + getListApi: (option: any) => Promise<T>
  14 + delListApi?: (option: any) => Promise<T>
  15 + exportListApi?: (option: any) => Promise<T>
  16 +}
4 17  
5 18 const appStore = useAppStore()
6 19  
... ... @@ -14,36 +27,40 @@ const currentSize = computed(() =&gt; {
14 27 }
15 28 })
16 29  
17   -export const useVxeGrid = (allSchemas, getPageApi) => {
  30 +export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => {
18 31 const gridOptions = reactive<VxeGridProps>({
19   - loading: false,
  32 + loading: true,
20 33 size: currentSize.value,
21 34 height: 800,
22 35 rowConfig: {
23   - keyField: 'id',
24   - isCurrent: true,
25   - isHover: true
  36 + isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
  37 + isHover: true // 当鼠标移到行时,是否要高亮当前行
  38 + },
  39 + showOverflow: 'tooltip', // 当内容溢出时显示为省略号
  40 + tooltipConfig: {
  41 + showAll: true // 开启全表工具提示
26 42 },
27 43 toolbarConfig: {
28 44 custom: true,
29 45 slots: { buttons: 'toolbar_buttons' }
30 46 },
31 47 printConfig: {
32   - columns: allSchemas.printSchema
  48 + columns: config?.allSchemas.printSchema
33 49 },
34 50 formConfig: {
35 51 titleWidth: 100,
36 52 titleAlign: 'right',
37   - items: allSchemas.searchSchema
  53 + items: config?.allSchemas.searchSchema
38 54 },
39   - columns: allSchemas.tableSchema,
  55 + columns: config?.allSchemas.tableSchema,
40 56 pagerConfig: {
41   - border: false,
42   - background: false,
43   - perfect: true,
44   - pageSize: 10,
45   - pagerCount: 7,
46   - pageSizes: [5, 10, 15, 20, 50, 100, 200, 500],
  57 + border: false, // 带边框
  58 + background: true, // 带背景颜色
  59 + perfect: true, // 配套的样式
  60 + pageSize: 10, // 每页大小
  61 + pagerCount: 7, // 显示页码按钮的数量
  62 + autoHidden: true, // 当只有一页时自动隐藏
  63 + pageSizes: [5, 10, 15, 20, 50, 100, 200, 500], // 每页大小选项列表
47 64 layouts: [
48 65 'PrevJump',
49 66 'PrevPage',
... ... @@ -61,17 +78,25 @@ export const useVxeGrid = (allSchemas, getPageApi) =&gt; {
61 78 props: { result: 'list', total: 'total' },
62 79 ajax: {
63 80 query: ({ page, form }) => {
64   - gridOptions.loading = true
65 81 const queryParams = Object.assign({}, form)
66 82 queryParams.pageSize = page.pageSize
67 83 queryParams.pageNo = page.currentPage
68 84 gridOptions.loading = false
69 85 return new Promise(async (resolve) => {
70   - resolve(await getPageApi(queryParams))
  86 + resolve(await config?.getListApi(queryParams))
71 87 })
72 88 }
73 89 }
74 90 }
75 91 })
76   - return gridOptions
  92 + const delList = (ids: string | number | string[] | number[]) => {
  93 + message.delConfirm().then(() => {
  94 + config?.delListApi && config?.delListApi(ids)
  95 + message.success(t('common.delSuccess'))
  96 + })
  97 + }
  98 + return {
  99 + gridOptions,
  100 + delList
  101 + }
77 102 }
... ...
yudao-ui-admin-vue3/src/views/system/post/index.vue
... ... @@ -44,12 +44,11 @@
44 44 <XModal id="postModel" v-model="dialogVisible" :title="dialogTitle">
45 45 <template #default>
46 46 <!-- 对话框(添加 / 修改) -->
47   - <vxe-form
48   - ref="xForm"
  47 + <Form
49 48 v-if="['create', 'update'].includes(actionType)"
50   - :data="formData"
51   - :items="formItems"
  49 + :schema="allSchemas.formSchema"
52 50 :rules="rules"
  51 + ref="formRef"
53 52 />
54 53 <Descriptions
55 54 v-if="actionType === 'detail'"
... ... @@ -77,7 +76,7 @@
77 76 </XModal>
78 77 </template>
79 78 <script setup lang="ts">
80   -import { ref } from 'vue'
  79 +import { ref, unref } from 'vue'
81 80 import dayjs from 'dayjs'
82 81 import { DICT_TYPE } from '@/utils/dict'
83 82 import * as PostApi from '@/api/system/post'
... ... @@ -86,20 +85,22 @@ import { rules, allSchemas } from &#39;./post.data&#39;
86 85 import { useI18n } from '@/hooks/web/useI18n'
87 86 import { useMessage } from '@/hooks/web/useMessage'
88 87 import { useVxeGrid } from '@/hooks/web/useVxeGrid'
89   -import { VxeFormEvents, VxeFormInstance, VxeFormItemProps, VxeGridInstance } from 'vxe-table'
  88 +import { VxeFormEvents, VxeGridInstance } from 'vxe-table'
  89 +import { FormExpose } from '@/components/Form'
90 90  
91 91 const { t } = useI18n() // 国际化
92 92 const message = useMessage() // 消息弹窗
93 93 const xGrid = ref<VxeGridInstance>()
94   -const xForm = ref<VxeFormInstance>()
  94 +const formRef = ref<FormExpose>() // 表单 Ref
95 95 const dialogVisible = ref(false) // 是否显示弹出层
96 96 const dialogTitle = ref('edit') // 弹出层标题
97 97 const actionType = ref('') // 操作按钮的类型
98 98 const actionLoading = ref(false) // 按钮Loading
99 99  
100   -const gridOptions = useVxeGrid(allSchemas, PostApi.getPostPageApi)
101   -const formData = ref<PostVO>()
102   -const formItems = ref<VxeFormItemProps[]>(allSchemas.formSchema)
  100 +const { gridOptions } = useVxeGrid<PostVO>({
  101 + allSchemas: allSchemas,
  102 + getListApi: PostApi.getPostPageApi
  103 +})
103 104 // 设置标题
104 105 const setDialogTile = (type: string) => {
105 106 dialogTitle.value = t('action.' + type)
... ... @@ -116,7 +117,8 @@ const handleDetail = (row: PostVO) =&gt; {
116 117 // 新增操作
117 118 const handleCreate = () => {
118 119 setDialogTile('create')
119   - formData.value = undefined
  120 + // 重置表单
  121 + unref(formRef)?.getElFormRef()?.resetFields()
120 122 }
121 123  
122 124 // 修改操作
... ... @@ -124,10 +126,10 @@ const handleUpdate = async (rowId: number) =&gt; {
124 126 setDialogTile('update')
125 127 // 设置数据
126 128 const res = await PostApi.getPostApi(rowId)
127   - formData.value = res
  129 + unref(formRef)?.setValues(res)
128 130 }
129 131 // 删除操作
130   -const handleDelete = (rowId: number) => {
  132 +const handleDelete = async (rowId: number) => {
131 133 message
132 134 .delConfirm()
133 135 .then(async () => {
... ... @@ -140,22 +142,28 @@ const handleDelete = (rowId: number) =&gt; {
140 142 }
141 143 // 提交按钮
142 144 const submitForm: VxeFormEvents.Submit = async () => {
143   - actionLoading.value = true
144   - // 提交请求
145   - try {
146   - const data = formData.value as PostVO
147   - if (actionType.value === 'create') {
148   - await PostApi.createPostApi(data)
149   - message.success(t('common.createSuccess'))
150   - } else {
151   - await PostApi.updatePostApi(data)
152   - message.success(t('common.updateSuccess'))
  145 + const elForm = unref(formRef)?.getElFormRef()
  146 + if (!elForm) return
  147 + elForm.validate(async (valid) => {
  148 + if (valid) {
  149 + actionLoading.value = true
  150 + // 提交请求
  151 + try {
  152 + const data = unref(formRef)?.formModel as PostVO
  153 + if (actionType.value === 'create') {
  154 + await PostApi.createPostApi(data)
  155 + message.success(t('common.createSuccess'))
  156 + } else {
  157 + await PostApi.updatePostApi(data)
  158 + message.success(t('common.updateSuccess'))
  159 + }
  160 + // 操作成功,重新加载列表
  161 + dialogVisible.value = false
  162 + } finally {
  163 + actionLoading.value = false
  164 + xGrid.value?.commitProxy('query')
  165 + }
153 166 }
154   - // 操作成功,重新加载列表
155   - dialogVisible.value = false
156   - } finally {
157   - actionLoading.value = false
158   - xGrid.value?.commitProxy('query')
159   - }
  167 + })
160 168 }
161 169 </script>
... ...
yudao-ui-admin-vue3/src/views/system/post/post.data.ts
... ... @@ -57,8 +57,16 @@ const crudSchemas = reactive&lt;VxeCrudSchema[]&gt;([
57 57 }
58 58 },
59 59 {
  60 + title: '备注',
  61 + field: 'remark',
  62 + table: {
  63 + show: false
  64 + }
  65 + },
  66 + {
60 67 title: t('common.createTime'),
61 68 field: 'createTime',
  69 + formatter: 'formatDate',
62 70 form: {
63 71 show: false
64 72 }
... ... @@ -66,10 +74,8 @@ const crudSchemas = reactive&lt;VxeCrudSchema[]&gt;([
66 74 {
67 75 title: t('table.action'),
68 76 field: 'action',
69   - width: '240px',
70 77 table: {
71 78 width: '240px',
72   - showOverflow: true,
73 79 slots: {
74 80 default: 'action_default'
75 81 }
... ...