feat: 新增单表代码生成示例
							parent
							
								
									17734ab040
								
							
						
					
					
						commit
						565caecb26
					
				|  | @ -0,0 +1,45 @@ | |||
| import type { PageParam, PageResult } from '@vben/request'; | ||||
| 
 | ||||
| import { requestClient } from '#/api/request'; | ||||
| 
 | ||||
| export namespace Demo01ContactApi { | ||||
|   /** 示例联系人信息 */ | ||||
|   export interface Demo01Contact { | ||||
|     id: number; // 编号
 | ||||
|     name?: string; // 名字
 | ||||
|     sex?: number; // 性别
 | ||||
|     birthday?: Date; // 出生年
 | ||||
|     description?: string; // 简介
 | ||||
|     avatar: string; // 头像
 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 查询示例联系人分页 */ | ||||
| export function getDemo01ContactPage(params: PageParam) { | ||||
|   return requestClient.get<PageResult<Demo01ContactApi.Demo01Contact>>('/infra/demo01-contact/page', { params }); | ||||
| } | ||||
| 
 | ||||
| /** 查询示例联系人详情 */ | ||||
| export function getDemo01Contact(id: number) { | ||||
|   return requestClient.get<Demo01ContactApi.Demo01Contact>(`/infra/demo01-contact/get?id=${id}`); | ||||
| } | ||||
| 
 | ||||
| /** 新增示例联系人 */ | ||||
| export function createDemo01Contact(data: Demo01ContactApi.Demo01Contact) { | ||||
|   return requestClient.post('/infra/demo01-contact/create', data); | ||||
| } | ||||
| 
 | ||||
| /** 修改示例联系人 */ | ||||
| export function updateDemo01Contact(data: Demo01ContactApi.Demo01Contact) { | ||||
|   return requestClient.put('/infra/demo01-contact/update', data); | ||||
| } | ||||
| 
 | ||||
| /** 删除示例联系人 */ | ||||
| export function deleteDemo01Contact(id: number) { | ||||
|   return requestClient.delete(`/infra/demo01-contact/delete?id=${id}`); | ||||
| } | ||||
| 
 | ||||
| /** 导出示例联系人 */ | ||||
| export function exportDemo01Contact(params: any) { | ||||
|   return requestClient.download('/infra/demo01-contact/export-excel', params); | ||||
| } | ||||
|  | @ -0,0 +1,177 @@ | |||
| import type { VbenFormSchema } from '#/adapter/form'; | ||||
| import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { Demo01ContactApi } from '#/api/infra/demo/demo01'; | ||||
| 
 | ||||
| import { getRangePickerDefaultProps } from '#/utils/date'; | ||||
| import { DICT_TYPE, getDictOptions } from '#/utils/dict'; | ||||
| 
 | ||||
| import { useAccess } from '@vben/access'; | ||||
| 
 | ||||
| const { hasAccessByCodes } = useAccess(); | ||||
| 
 | ||||
| /** 新增/修改的表单 */ | ||||
| export function useFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       fieldName: 'id', | ||||
|       component: 'Input', | ||||
|       dependencies: { | ||||
|         triggerFields: [''], | ||||
|         show: () => false, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '名字', | ||||
|       rules: 'required', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入名字', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'sex', | ||||
|       label: '性别', | ||||
|       rules: 'required', | ||||
|       component: 'RadioGroup', | ||||
|       componentProps: { | ||||
|         options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | ||||
|         buttonStyle: 'solid', | ||||
|         optionType: 'button', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'birthday', | ||||
|       label: '出生年', | ||||
|       rules: 'required', | ||||
|       component: 'DatePicker', | ||||
|       componentProps: { | ||||
|         showTime: true, | ||||
|         format: 'YYYY-MM-DD HH:mm:ss', | ||||
|         valueFormat: 'x', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'description', | ||||
|       label: '简介', | ||||
|       rules: 'required', | ||||
|       component: 'Editor', | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'avatar', | ||||
|       label: '头像', | ||||
|       component: 'FileUpload', | ||||
|       componentProps: { | ||||
|         fileType: 'image', | ||||
|         maxCount: 1, | ||||
|       }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 列表的搜索表单 */ | ||||
| export function useGridFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '名字', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         allowClear: true, | ||||
|         placeholder: '请输入名字', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'sex', | ||||
|       label: '性别', | ||||
|       component: 'Select', | ||||
|       componentProps: { | ||||
|         allowClear: true, | ||||
|         options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'createTime', | ||||
|       label: '创建时间', | ||||
|       component: 'RangePicker', | ||||
|       componentProps: { | ||||
|         ...getRangePickerDefaultProps(), | ||||
|         allowClear: true, | ||||
|       }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 列表的字段 */ | ||||
| export function useGridColumns<T = Demo01ContactApi.Demo01Contact>( | ||||
|   onActionClick: OnActionClickFn<T>, | ||||
| ): VxeTableGridOptions['columns'] { | ||||
|   return [ | ||||
|     { | ||||
|       field: 'id', | ||||
|       title: '编号', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'name', | ||||
|       title: '名字', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'sex', | ||||
|       title: '性别', | ||||
|       minWidth: 120, | ||||
|       cellRender: { | ||||
|         name: 'CellDict', | ||||
|         props: { type: DICT_TYPE.SYSTEM_USER_SEX }, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'birthday', | ||||
|       title: '出生年', | ||||
|       minWidth: 120, | ||||
|       formatter: 'formatDateTime', | ||||
|     }, | ||||
|     { | ||||
|       field: 'description', | ||||
|       title: '简介', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'avatar', | ||||
|       title: '头像', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'createTime', | ||||
|       title: '创建时间', | ||||
|       minWidth: 120, | ||||
|       formatter: 'formatDateTime', | ||||
|     }, | ||||
|     { | ||||
|       field: 'operation', | ||||
|       title: '操作', | ||||
|       minWidth: 180, | ||||
|       align: 'center', | ||||
|       fixed: 'right', | ||||
|       cellRender: { | ||||
|         attrs: { | ||||
|           nameField: 'id', | ||||
|           nameTitle: '示例联系人', | ||||
|           onClick: onActionClick, | ||||
|         }, | ||||
|         name: 'CellOperation', | ||||
|         options: [ | ||||
|           { | ||||
|             code: 'edit', | ||||
|             show: hasAccessByCodes(['infra:demo01-contact:update']), | ||||
|           }, | ||||
|           { | ||||
|             code: 'delete', | ||||
|             show: hasAccessByCodes(['infra:demo01-contact:delete']), | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
|  | @ -0,0 +1,125 @@ | |||
| <script lang="ts" setup> | ||||
| import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { Demo01ContactApi } from '#/api/infra/demo/demo01'; | ||||
| 
 | ||||
| import { DocAlert } from '#/components/doc-alert'; | ||||
| import Form from './modules/form.vue'; | ||||
| import { Page, useVbenModal } from '@vben/common-ui'; | ||||
| import { Download, Plus } from '@vben/icons'; | ||||
| import { Button, message } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||
| import { deleteDemo01Contact, exportDemo01Contact, getDemo01ContactPage } from '#/api/infra/demo/demo01'; | ||||
| import { $t } from '#/locales'; | ||||
| import { downloadByData } from '#/utils/download'; | ||||
| 
 | ||||
| import { useGridColumns, useGridFormSchema } from './data'; | ||||
| 
 | ||||
| const [FormModal, formModalApi] = useVbenModal({ | ||||
|   connectedComponent: Form, | ||||
|   destroyOnClose: true, | ||||
| }); | ||||
| 
 | ||||
| /** 刷新表格 */ | ||||
| function onRefresh() { | ||||
|   gridApi.query(); | ||||
| } | ||||
| 
 | ||||
| /** 导出表格 */ | ||||
| async function onExport() { | ||||
|   const data = await exportDemo01Contact(await gridApi.formApi.getValues()); | ||||
|   downloadByData(data, '示例联系人.xls'); | ||||
| } | ||||
| 
 | ||||
| /** 创建示例联系人 */ | ||||
| function onCreate() { | ||||
|   formModalApi.setData(null).open(); | ||||
| } | ||||
| 
 | ||||
| /** 编辑示例联系人 */ | ||||
| function onEdit(row: Demo01ContactApi.Demo01Contact) { | ||||
|   formModalApi.setData(row).open(); | ||||
| } | ||||
| 
 | ||||
| /** 删除示例联系人 */ | ||||
| async function onDelete(row: Demo01ContactApi.Demo01Contact) { | ||||
|   const hideLoading = message.loading({ | ||||
|     content: $t('ui.actionMessage.deleting', [row.id]), | ||||
|     duration: 0, | ||||
|     key: 'action_process_msg', | ||||
|   }); | ||||
|   try { | ||||
|     await deleteDemo01Contact(row.id as number); | ||||
|     message.success({ | ||||
|       content: $t('ui.actionMessage.deleteSuccess', [row.id]), | ||||
|       key: 'action_process_msg', | ||||
|     }); | ||||
|     onRefresh(); | ||||
|   } catch { | ||||
|     hideLoading(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 表格操作按钮的回调函数 */ | ||||
| function onActionClick({ code, row }: OnActionClickParams<Demo01ContactApi.Demo01Contact>) { | ||||
|   switch (code) { | ||||
|     case 'delete': { | ||||
|       onDelete(row); | ||||
|       break; | ||||
|     } | ||||
|     case 'edit': { | ||||
|       onEdit(row); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const [Grid, gridApi] = useVbenVxeGrid({ | ||||
|   formOptions: { | ||||
|     schema: useGridFormSchema(), | ||||
|   }, | ||||
|   gridOptions: { | ||||
|     columns: useGridColumns(onActionClick), | ||||
|     height: 'auto', | ||||
|     keepSource: true, | ||||
|     proxyConfig: { | ||||
|       ajax: { | ||||
|         query: async ({ page }, formValues) => { | ||||
|           return await getDemo01ContactPage({ | ||||
|             pageNo: page.currentPage, | ||||
|             pageSize: page.pageSize, | ||||
|             ...formValues, | ||||
|           }); | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     rowConfig: { | ||||
|       keyField: 'id', | ||||
|     }, | ||||
|     toolbarConfig: { | ||||
|       refresh: { code: 'query' }, | ||||
|       search: true, | ||||
|     }, | ||||
|   } as VxeTableGridOptions<Demo01ContactApi.Demo01Contact>, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Page auto-content-height> | ||||
|     <DocAlert title="示例联系人" url="https://doc.iocoder.cn/infra/" /> | ||||
| 
 | ||||
|     <FormModal @success="onRefresh" /> | ||||
|     <Grid table-title="示例联系人列表"> | ||||
|       <template #toolbar-tools> | ||||
|         <Button type="primary" @click="onCreate" v-access:code="['infra:demo01-contact:create']"> | ||||
|           <Plus class="size-5" /> | ||||
|           {{ $t('ui.actionTitle.create', ['示例联系人']) }} | ||||
|         </Button> | ||||
|         <Button type="primary" class="ml-2" @click="onExport" v-access:code="['infra:demo01-contact:export']"> | ||||
|           <Download class="size-5" /> | ||||
|           {{ $t('ui.actionTitle.export') }} | ||||
|         </Button> | ||||
|       </template> | ||||
|     </Grid> | ||||
|   </Page> | ||||
| </template> | ||||
|  | @ -0,0 +1,76 @@ | |||
| <script lang="ts" setup> | ||||
| import type { Demo01ContactApi } from '#/api/infra/demo/demo01'; | ||||
| 
 | ||||
| import { useVbenModal } from '@vben/common-ui'; | ||||
| import { message } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { useVbenForm } from '#/adapter/form'; | ||||
| import { createDemo01Contact, getDemo01Contact, updateDemo01Contact } from '#/api/infra/demo/demo01'; | ||||
| import { $t } from '#/locales'; | ||||
| import { computed, ref } from 'vue'; | ||||
| 
 | ||||
| import { useFormSchema } from '../data'; | ||||
| 
 | ||||
| const emit = defineEmits(['success']); | ||||
| const formData = ref<Demo01ContactApi.Demo01Contact>(); | ||||
| const getTitle = computed(() => { | ||||
|   return formData.value?.id ? $t('ui.actionTitle.edit', ['示例联系人']) : $t('ui.actionTitle.create', ['示例联系人']); | ||||
| }); | ||||
| 
 | ||||
| const [Form, formApi] = useVbenForm({ | ||||
|   layout: 'horizontal', | ||||
|   schema: useFormSchema(), | ||||
|   showDefaultActions: false, | ||||
|   commonConfig: { | ||||
|     labelWidth: 120, | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| const [Modal, modalApi] = useVbenModal({ | ||||
|   async onConfirm() { | ||||
|     const { valid } = await formApi.validate(); | ||||
|     if (!valid) { | ||||
|       return; | ||||
|     } | ||||
|     modalApi.lock(); | ||||
|     // 提交表单 | ||||
|     const data = (await formApi.getValues()) as Demo01ContactApi.Demo01Contact; | ||||
|     try { | ||||
|       await (formData.value?.id ? updateDemo01Contact(data) : createDemo01Contact(data)); | ||||
|       // 关闭并提示 | ||||
|       await modalApi.close(); | ||||
|       emit('success'); | ||||
|       message.success({ | ||||
|         content: $t('ui.actionMessage.operationSuccess'), | ||||
|         key: 'action_process_msg', | ||||
|       }); | ||||
|     } finally { | ||||
|       modalApi.lock(false); | ||||
|     } | ||||
|   }, | ||||
|   async onOpenChange(isOpen: boolean) { | ||||
|     if (!isOpen) { | ||||
|       return; | ||||
|     } | ||||
|     // 加载数据 | ||||
|     const data = modalApi.getData<Demo01ContactApi.Demo01Contact>(); | ||||
|     if (!data || !data.id) { | ||||
|       return; | ||||
|     } | ||||
|     modalApi.lock(); | ||||
|     try { | ||||
|       formData.value = await getDemo01Contact(data.id as number); | ||||
|       // 设置到 values | ||||
|       await formApi.setValues(formData.value); | ||||
|     } finally { | ||||
|       modalApi.lock(false); | ||||
|     } | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Modal :title="getTitle"> | ||||
|     <Form class="mx-4" /> | ||||
|   </Modal> | ||||
| </template> | ||||
		Loading…
	
		Reference in New Issue
	
	 puhui999
						puhui999