fix: 修复表单布局、日期默认值、子弹窗打开/关闭问题

- 业务日期默认当天(dayjs)
- 表单 col-span-1 多列布局
- 子弹窗改为 ref + defineExpose 调用,解决 connectedComponent 冲突
- 物料选择弹窗路径修正
This commit is contained in:
zhouz
2026-07-22 10:35:46 +08:00
parent ea9ae91089
commit 31a3906e24
3 changed files with 57 additions and 34 deletions

View File

@@ -5,10 +5,10 @@ import { computed, ref, watch } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import dayjs from 'dayjs';
import { message } from 'antdv-next';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
type OutboundCreateReq,
type OutboundDetail,
@@ -18,11 +18,10 @@ import { getBsrealStorAttrSimpleList } from '#/api/wms/bsrealstorattr';
import { getSimpleDictDataList } from '#/api/system/dict/data';
import { $t } from '#/locales';
import InventorySelect from './inventory-select.vue';
import ManualDetail from './manual-detail.vue';
import InventorySelectModalComponent from './inventory-select.vue';
import ManualDetailModalComponent from './manual-detail.vue';
const emit = defineEmits(['success']);
const formData = ref<WmsIostorInvApi.IostorInv>();
// ========== 仓库选项 ==========
const storOptions = ref<
@@ -51,7 +50,7 @@ async function loadBillTypeOptions() {
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: { class: 'w-full' },
formItemClass: 'col-span-2',
formItemClass: 'col-span-1',
labelWidth: 80,
},
layout: 'horizontal',
@@ -87,7 +86,6 @@ const [Form, formApi] = useVbenForm({
fieldName: 'bizDate',
label: '业务日期',
rules: 'required',
defaultValue: new Date(),
component: 'DatePicker',
componentProps: {
showTime: true,
@@ -127,7 +125,8 @@ const [Form, formApi] = useVbenForm({
});
// ========== 明细数据 ==========
const detailList = ref<(OutboundDetail & { vehicleCode?: string; materialName?: string })[]>([]);
type DetailRow = OutboundDetail & { vehicleCode?: string; materialName?: string };
const detailList = ref<DetailRow[]>([]);
function updateSummary() {
const totalWeight = detailList.value
@@ -149,6 +148,7 @@ watch(
);
// ========== 明细表格 ==========
const vxeGridRef = ref();
const gridOptions = computed(() => ({
columns: [
{ type: 'seq', title: '序号', width: 50 },
@@ -164,6 +164,8 @@ const gridOptions = computed(() => ({
data: detailList.value,
height: 'auto',
rowConfig: { keyField: 'materialCode', isHover: true },
toolbarConfig: false,
pagerConfig: false,
}));
function handleDeleteDetail(index: number) {
@@ -171,11 +173,8 @@ function handleDeleteDetail(index: number) {
updateSummary();
}
// ========== 库存选择弹窗 ==========
const [InventorySelectModal, inventorySelectModalApi] = useVbenModal({
connectedComponent: InventorySelect,
destroyOnClose: true,
});
// ========== 库存选择弹窗(子组件自带 Modal用 ref 调用 open ==========
const inventorySelectRef = ref<InstanceType<typeof InventorySelectModalComponent>>();
function handleSelectFromInventory() {
const storId = formApi.getValues().storId;
@@ -183,7 +182,7 @@ function handleSelectFromInventory() {
message.warning('请先选择仓库');
return;
}
inventorySelectModalApi.setData({ storId }).open();
inventorySelectRef.value?.open({ storId });
}
function onInventorySelected(rows: any[]) {
@@ -205,18 +204,24 @@ function onInventorySelected(rows: any[]) {
updateSummary();
}
// ========== 手动新增弹窗 ==========
const [ManualDetailModal, manualDetailModalApi] = useVbenModal({
connectedComponent: ManualDetail,
destroyOnClose: true,
});
// ========== 手动新增弹窗(子组件自带 Modal用 ref 调用 open ==========
const manualDetailRef = ref<InstanceType<typeof ManualDetailModalComponent>>();
function handleManualAdd() {
manualDetailModalApi.setData({}).open();
manualDetailRef.value?.open();
}
function onManualAdded(detail: any) {
detailList.value.push(detail);
detailList.value.push({
materialCode: detail.materialCode,
materialId: String(detail.materialId ?? ''),
materialName: detail.materialName,
planQty: detail.planQty,
qtyUnitId: String(detail.qtyUnitId ?? ''),
qtyUnitName: detail.qtyUnitName,
pcsn: detail.pcsn,
remark: detail.remark,
});
updateSummary();
}
@@ -269,6 +274,10 @@ const [Modal, modalApi] = useVbenModal({
if (isOpen) {
await loadStorOptions();
await loadBillTypeOptions();
// 业务日期默认当天
formApi.setValues({
bizDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
});
}
if (!isOpen) {
detailList.value = [];
@@ -294,7 +303,7 @@ const [Modal, modalApi] = useVbenModal({
</div>
</div>
<vxe-grid v-bind="gridOptions">
<vxe-grid ref="vxeGridRef" v-bind="gridOptions">
<template #actions="{ rowIndex }">
<a-button type="link" danger @click="handleDeleteDetail(rowIndex)">
删除
@@ -304,7 +313,14 @@ const [Modal, modalApi] = useVbenModal({
</div>
</div>
<InventorySelectModal @select="onInventorySelected" />
<ManualDetailModal @confirm="onManualAdded" />
<!-- 子弹窗不通过 connectedComponent而是通过 ref 调用 -->
<InventorySelectModalComponent
ref="inventorySelectRef"
@select="onInventorySelected"
/>
<ManualDetailModalComponent
ref="manualDetailRef"
@confirm="onManualAdded"
/>
</Modal>
</template>

View File

@@ -101,6 +101,12 @@ const [Modal, modalApi] = useVbenModal({
}
},
});
/** 暴露给父组件调用 */
function open(data: { storId: string }) {
modalApi.setData(data).open();
}
defineExpose({ open });
</script>
<template>

View File

@@ -5,7 +5,7 @@ import { useVbenModal } from '@vben/common-ui';
import { useVbenForm } from '#/adapter/form';
import MaterialSelectModalComponent from '../../../base/materialbase/components/MaterialSelectModal.vue';
import MaterialSelectModalComponent from '../../base/materialbase/components/MaterialSelectModal.vue';
const emit = defineEmits(['confirm']);
@@ -14,7 +14,7 @@ const [MaterialSelectModal, materialSelectModalApi] = useVbenModal({
connectedComponent: MaterialSelectModalComponent,
});
/** 已选物料信息(不在表单中展示的额外字段) */
/** 已选物料信息 */
const selectedMaterial = ref<{
materialId: number;
materialName: string;
@@ -44,9 +44,7 @@ function handleMaterialSelect(rows: any[]) {
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
componentProps: { class: 'w-full' },
formItemClass: 'col-span-2',
labelWidth: 80,
},
@@ -111,9 +109,7 @@ const [Modal, modalApi] = useVbenModal({
width: 500,
async onConfirm() {
const { valid } = await formApi.validate();
if (!valid) {
return;
}
if (!valid) return;
if (!selectedMaterial.value) {
return;
}
@@ -125,8 +121,8 @@ const [Modal, modalApi] = useVbenModal({
planQty: values.planQty,
qtyUnitId: selectedMaterial.value.qtyUnitId,
qtyUnitName: selectedMaterial.value.qtyUnitName,
pcsn: values.pcsn,
remark: values.remark,
pcsn: values.pcsn || '',
remark: values.remark || '',
});
modalApi.close();
},
@@ -135,11 +131,16 @@ const [Modal, modalApi] = useVbenModal({
selectedMaterial.value = null;
return;
}
// 弹窗打开时重置表单
selectedMaterial.value = null;
await formApi.resetForm();
},
});
/** 暴露给父组件调用 */
function open() {
modalApi.open();
}
defineExpose({ open });
</script>
<template>