Pre Merge pull request !184 from 陈賝/dev
						commit
						4fabba27ae
					
				|  | @ -225,6 +225,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { | |||
|     { | ||||
|       field: 'actions', | ||||
|       title: '操作', | ||||
|       fixed: 'right', | ||||
|       width: 160, | ||||
|       slots: { default: 'actions' }, | ||||
|     }, | ||||
|  |  | |||
|  | @ -77,9 +77,6 @@ const [Modal, modalApi] = useVbenModal({ | |||
|         // 编辑模式,加载数据 | ||||
|         const supplierData = await getSupplier(data.id); | ||||
|         await formApi.setValues(supplierData); | ||||
|       } else { | ||||
|         // 新增模式,重置表单 | ||||
|         await formApi.resetFields(); | ||||
|       } | ||||
|     } finally { | ||||
|       modalApi.unlock(); | ||||
|  |  | |||
|  | @ -0,0 +1,214 @@ | |||
| import type { VbenFormSchema } from '#/adapter/form'; | ||||
| import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { ErpWarehouseApi } from '#/api/erp/stock/warehouse'; | ||||
| 
 | ||||
| import { DICT_TYPE, getDictOptions } from '#/utils'; | ||||
| 
 | ||||
| /** 新增/修改的表单 */ | ||||
| export function useFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       component: 'Input', | ||||
|       fieldName: 'id', | ||||
|       dependencies: { | ||||
|         triggerFields: [''], | ||||
|         show: () => false, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '仓库名称', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入仓库名称', | ||||
|       }, | ||||
|       rules: 'required', | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'address', | ||||
|       label: '仓库地址', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入仓库地址', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'status', | ||||
|       label: '开启状态', | ||||
|       component: 'RadioGroup', | ||||
|       componentProps: { | ||||
|         options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), | ||||
|       }, | ||||
|       rules: 'required', | ||||
|       defaultValue: 0, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'warehousePrice', | ||||
|       label: '仓储费(元)', | ||||
|       component: 'InputNumber', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入仓储费,单位:元/天/KG', | ||||
|         min: 0, | ||||
|         precision: 2, | ||||
|         class: 'w-full', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'truckagePrice', | ||||
|       label: '搬运费(元)', | ||||
|       component: 'InputNumber', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入搬运费,单位:元', | ||||
|         min: 0, | ||||
|         precision: 2, | ||||
|         class: 'w-full', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'principal', | ||||
|       label: '负责人', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入负责人', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'sort', | ||||
|       label: '排序', | ||||
|       component: 'InputNumber', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入排序', | ||||
|         precision: 0, | ||||
|         class: 'w-full', | ||||
|       }, | ||||
|       rules: 'required', | ||||
|       defaultValue: 0, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'remark', | ||||
|       label: '备注', | ||||
|       component: 'Textarea', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入备注', | ||||
|         rows: 3, | ||||
|       }, | ||||
|       formItemClass: 'col-span-2', | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 搜索表单 */ | ||||
| export function useGridFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '仓库名称', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入仓库名称', | ||||
|         allowClear: true, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'status', | ||||
|       label: '仓库状态', | ||||
|       component: 'Select', | ||||
|       componentProps: { | ||||
|         placeholder: '请选择仓库状态', | ||||
|         allowClear: true, | ||||
|         options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), | ||||
|       }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 列表的字段 */ | ||||
| export function useGridColumns<T = ErpWarehouseApi.Warehouse>( | ||||
|   onDefaultStatusChange?: ( | ||||
|     newStatus: boolean, | ||||
|     row: T, | ||||
|   ) => PromiseLike<boolean | undefined>, | ||||
| ): VxeTableGridOptions['columns'] { | ||||
|   return [ | ||||
|     { | ||||
|       field: 'name', | ||||
|       title: '仓库名称', | ||||
|       minWidth: 150, | ||||
|     }, | ||||
|     { | ||||
|       field: 'address', | ||||
|       title: '仓库地址', | ||||
|       minWidth: 200, | ||||
|       showOverflow: 'tooltip', | ||||
|     }, | ||||
|     { | ||||
|       field: 'warehousePrice', | ||||
|       title: '仓储费(元)', | ||||
|       width: 120, | ||||
|       cellRender: { | ||||
|         name: 'CellMoney', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'truckagePrice', | ||||
|       title: '搬运费(元)', | ||||
|       width: 120, | ||||
|       cellRender: { | ||||
|         name: 'CellMoney', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'principal', | ||||
|       title: '负责人', | ||||
|       width: 100, | ||||
|     }, | ||||
|     { | ||||
|       field: 'sort', | ||||
|       title: '排序', | ||||
|       width: 80, | ||||
|     }, | ||||
|     { | ||||
|       field: 'status', | ||||
|       title: '状态', | ||||
|       width: 100, | ||||
|       cellRender: { | ||||
|         name: 'CellDict', | ||||
|         props: { type: DICT_TYPE.COMMON_STATUS }, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'defaultStatus', | ||||
|       title: '是否默认', | ||||
|       width: 100, | ||||
|       cellRender: { | ||||
|         attrs: { beforeChange: onDefaultStatusChange }, | ||||
|         name: 'CellSwitch', | ||||
|         props: { | ||||
|           checkedValue: true, | ||||
|           unCheckedValue: false, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'remark', | ||||
|       title: '备注', | ||||
|       minWidth: 150, | ||||
|       showOverflow: 'tooltip', | ||||
|     }, | ||||
|     { | ||||
|       field: 'createTime', | ||||
|       title: '创建时间', | ||||
|       width: 180, | ||||
|       cellRender: { | ||||
|         name: 'CellDateTime', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'actions', | ||||
|       title: '操作', | ||||
|       width: 160, | ||||
|       fixed: 'right', | ||||
|       slots: { default: 'actions' }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
|  | @ -1,32 +1,180 @@ | |||
| <script lang="ts" setup> | ||||
| import { DocAlert, Page } from '@vben/common-ui'; | ||||
| import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { ErpWarehouseApi } from '#/api/erp/stock/warehouse'; | ||||
| 
 | ||||
| import { Button } from 'ant-design-vue'; | ||||
| import { confirm, DocAlert, Page, useVbenModal } from '@vben/common-ui'; | ||||
| import { downloadFileFromBlobPart } from '@vben/utils'; | ||||
| 
 | ||||
| import { message } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||
| import { | ||||
|   deleteWarehouse, | ||||
|   exportWarehouse, | ||||
|   getWarehousePage, | ||||
|   updateWarehouseDefaultStatus, | ||||
| } from '#/api/erp/stock/warehouse'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| import { useGridColumns, useGridFormSchema } from './data'; | ||||
| import WarehouseForm from './modules/form.vue'; | ||||
| 
 | ||||
| /** 仓库管理 */ | ||||
| defineOptions({ name: 'ErpWarehouse' }); | ||||
| 
 | ||||
| /** 刷新表格 */ | ||||
| function onRefresh() { | ||||
|   gridApi.query(); | ||||
| } | ||||
| 
 | ||||
| /** 添加仓库 */ | ||||
| function handleCreate() { | ||||
|   formModalApi.setData({ type: 'create' }).open(); | ||||
| } | ||||
| 
 | ||||
| /** 编辑仓库 */ | ||||
| function handleEdit(row: ErpWarehouseApi.Warehouse) { | ||||
|   formModalApi.setData({ type: 'update', id: row.id }).open(); | ||||
| } | ||||
| 
 | ||||
| /** 删除仓库 */ | ||||
| async function handleDelete(row: ErpWarehouseApi.Warehouse) { | ||||
|   const hideLoading = message.loading({ | ||||
|     content: $t('ui.actionMessage.deleting', [row.name]), | ||||
|     key: 'action_key_msg', | ||||
|   }); | ||||
|   try { | ||||
|     await deleteWarehouse(row.id!); | ||||
|     message.success({ | ||||
|       content: $t('ui.actionMessage.deleteSuccess', [row.name]), | ||||
|       key: 'action_key_msg', | ||||
|     }); | ||||
|     onRefresh(); | ||||
|   } catch { | ||||
|     hideLoading(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 修改默认状态 */ | ||||
| async function handleDefaultStatusChange( | ||||
|   newStatus: boolean, | ||||
|   row: ErpWarehouseApi.Warehouse, | ||||
| ): Promise<boolean | undefined> { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     const text = newStatus ? '开启' : '取消'; | ||||
| 
 | ||||
|     confirm({ | ||||
|       content: `确认要${text}"${row.name}"默认吗?`, | ||||
|     }) | ||||
|       .then(async () => { | ||||
|         // 更新默认状态 | ||||
|         await updateWarehouseDefaultStatus(row.id!, newStatus); | ||||
|         message.success(`${text}默认状态成功`); | ||||
|         resolve(true); | ||||
|       }) | ||||
|       .catch(() => { | ||||
|         reject(new Error('取消操作')); | ||||
|       }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| /** 导出仓库 */ | ||||
| async function handleExport() { | ||||
|   const data = await exportWarehouse(await gridApi.formApi.getValues()); | ||||
|   downloadFileFromBlobPart({ fileName: '仓库.xls', source: data }); | ||||
| } | ||||
| 
 | ||||
| const [FormModal, formModalApi] = useVbenModal({ | ||||
|   connectedComponent: WarehouseForm, | ||||
|   destroyOnClose: true, | ||||
| }); | ||||
| 
 | ||||
| const [Grid, gridApi] = useVbenVxeGrid({ | ||||
|   formOptions: { | ||||
|     schema: useGridFormSchema(), | ||||
|   }, | ||||
|   gridOptions: { | ||||
|     columns: useGridColumns(handleDefaultStatusChange), | ||||
|     height: 'auto', | ||||
|     keepSource: true, | ||||
|     proxyConfig: { | ||||
|       ajax: { | ||||
|         query: async ({ page }, formValues) => { | ||||
|           return await getWarehousePage({ | ||||
|             pageNo: page.currentPage, | ||||
|             pageSize: page.pageSize, | ||||
|             ...formValues, | ||||
|           }); | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     rowConfig: { | ||||
|       keyField: 'id', | ||||
|     }, | ||||
|     toolbarConfig: { | ||||
|       refresh: true, | ||||
|       search: true, | ||||
|     }, | ||||
|   } as VxeTableGridOptions<ErpWarehouseApi.Warehouse>, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Page> | ||||
|   <Page auto-content-height> | ||||
|     <template #doc> | ||||
|       <DocAlert | ||||
|         title="【库存】产品库存、库存明细" | ||||
|         url="https://doc.iocoder.cn/erp/stock/" | ||||
|       /> | ||||
|     <Button | ||||
|       danger | ||||
|       type="link" | ||||
|       target="_blank" | ||||
|       href="https://github.com/yudaocode/yudao-ui-admin-vue3" | ||||
|     > | ||||
|       该功能支持 Vue3 + element-plus 版本! | ||||
|     </Button> | ||||
|     <br /> | ||||
|     <Button | ||||
|       type="link" | ||||
|       target="_blank" | ||||
|       href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/erp/stock/warehouse/index" | ||||
|     > | ||||
|       可参考 | ||||
|       https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/erp/stock/warehouse/index | ||||
|       代码,pull request 贡献给我们! | ||||
|     </Button> | ||||
|     </template> | ||||
| 
 | ||||
|     <FormModal @success="onRefresh" /> | ||||
|     <Grid table-title="仓库列表"> | ||||
|       <template #toolbar-tools> | ||||
|         <TableAction | ||||
|           :actions="[ | ||||
|             { | ||||
|               label: $t('ui.actionTitle.create', ['仓库']), | ||||
|               type: 'primary', | ||||
|               icon: ACTION_ICON.ADD, | ||||
|               auth: ['erp:warehouse:create'], | ||||
|               onClick: handleCreate, | ||||
|             }, | ||||
|             { | ||||
|               label: $t('ui.actionTitle.export'), | ||||
|               type: 'primary', | ||||
|               icon: ACTION_ICON.DOWNLOAD, | ||||
|               auth: ['erp:warehouse:export'], | ||||
|               onClick: handleExport, | ||||
|             }, | ||||
|           ]" | ||||
|         /> | ||||
|       </template> | ||||
| 
 | ||||
|       <template #actions="{ row }"> | ||||
|         <TableAction | ||||
|           :actions="[ | ||||
|             { | ||||
|               label: '编辑', | ||||
|               type: 'link', | ||||
|               icon: ACTION_ICON.EDIT, | ||||
|               auth: ['erp:warehouse:update'], | ||||
|               onClick: handleEdit.bind(null, row), | ||||
|             }, | ||||
|             { | ||||
|               label: '删除', | ||||
|               type: 'link', | ||||
|               danger: true, | ||||
|               icon: ACTION_ICON.DELETE, | ||||
|               auth: ['erp:warehouse:delete'], | ||||
|               popConfirm: { | ||||
|                 title: $t('ui.actionMessage.deleteConfirm', [row.name]), | ||||
|                 confirm: handleDelete.bind(null, row), | ||||
|               }, | ||||
|             }, | ||||
|           ]" | ||||
|         /> | ||||
|       </template> | ||||
|     </Grid> | ||||
|   </Page> | ||||
| </template> | ||||
|  |  | |||
|  | @ -0,0 +1,95 @@ | |||
| <script lang="ts" setup> | ||||
| import type { ErpWarehouseApi } from '#/api/erp/stock/warehouse'; | ||||
| 
 | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| import { useVbenModal } from '@vben/common-ui'; | ||||
| 
 | ||||
| import { message } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { useVbenForm } from '#/adapter/form'; | ||||
| import { | ||||
|   createWarehouse, | ||||
|   getWarehouse, | ||||
|   updateWarehouse, | ||||
| } from '#/api/erp/stock/warehouse'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| import { useFormSchema } from '../data'; | ||||
| 
 | ||||
| const emit = defineEmits(['success']); | ||||
| 
 | ||||
| const formType = ref<'create' | 'update'>('create'); | ||||
| const warehouseId = ref<number>(); | ||||
| 
 | ||||
| const [Form, formApi] = useVbenForm({ | ||||
|   commonConfig: { | ||||
|     componentProps: { | ||||
|       class: 'w-full', | ||||
|     }, | ||||
|     labelWidth: 100, | ||||
|   }, | ||||
|   wrapperClass: 'grid-cols-2', | ||||
|   layout: 'horizontal', | ||||
|   schema: useFormSchema(), | ||||
|   showDefaultActions: false, | ||||
| }); | ||||
| 
 | ||||
| const [Modal, modalApi] = useVbenModal({ | ||||
|   async onConfirm() { | ||||
|     const { valid } = await formApi.validate(); | ||||
|     if (!valid) { | ||||
|       return; | ||||
|     } | ||||
|     modalApi.lock(); | ||||
|     // 提交表单 | ||||
|     const data = (await formApi.getValues()) as ErpWarehouseApi.Warehouse; | ||||
|     try { | ||||
|       if (formType.value === 'create') { | ||||
|         await createWarehouse(data); | ||||
|         message.success($t('ui.actionMessage.createSuccess')); | ||||
|       } else { | ||||
|         await updateWarehouse(data); | ||||
|         message.success($t('ui.actionMessage.updateSuccess')); | ||||
|       } | ||||
|       // 关闭并提示 | ||||
|       await modalApi.close(); | ||||
|       emit('success'); | ||||
|     } finally { | ||||
|       modalApi.unlock(); | ||||
|     } | ||||
|   }, | ||||
|   async onOpenChange(isOpen: boolean) { | ||||
|     if (!isOpen) { | ||||
|       return; | ||||
|     } | ||||
|     // 加载数据 | ||||
|     const data = modalApi.getData<{ id?: number; type: 'create' | 'update' }>(); | ||||
|     if (!data) { | ||||
|       return; | ||||
|     } | ||||
|     formType.value = data.type; | ||||
|     warehouseId.value = data.id; | ||||
| 
 | ||||
|     modalApi.lock(); | ||||
|     try { | ||||
|       if (data.type === 'update' && data.id) { | ||||
|         const warehouseData = await getWarehouse(data.id); | ||||
|         await formApi.setValues(warehouseData); | ||||
|       } | ||||
|     } finally { | ||||
|       modalApi.unlock(); | ||||
|     } | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| defineExpose({ | ||||
|   modalApi, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Modal :title="formType === 'create' ? '新增仓库' : '编辑仓库'" class="w-3/5"> | ||||
|     <Form class="mx-4" /> | ||||
|   </Modal> | ||||
| </template> | ||||
		Loading…
	
		Reference in New Issue
	
	 陈賝
						陈賝