feat(wms):优化 antd、ele 的 order receipt 迁移

pull/345/head
YunaiV 2026-05-17 23:56:05 +08:00
parent 41d5aa93d6
commit f8c2d4b1ff
7 changed files with 51 additions and 31 deletions

View File

@ -397,13 +397,17 @@ interface ReceiptOrderDetailFooterRow {
quantity?: number; quantity?: number;
totalPrice?: number; totalPrice?: number;
} }
type ReceiptOrderDetailFooterColumn = Pick<
NonNullable<NonNullable<VxeTableGridOptions['columns']>[number]>,
'field'
>;
/** 明细表格的合计行 */ /** 明细表格的合计行 */
export function getDetailFooter({ export function getDetailFooter({
columns, columns,
data, data,
}: { }: {
columns: Array<{ field?: string }>; columns: ReceiptOrderDetailFooterColumn[];
data: ReceiptOrderDetailFooterRow[]; data: ReceiptOrderDetailFooterRow[];
}) { }) {
return [ return [

View File

@ -53,8 +53,16 @@ const [DetailModal, detailModalApi] = useVbenModal({
destroyOnClose: true, destroyOnClose: true,
}); });
/** 清空展开明细缓存 */
function clearDetailMap() {
for (const id of Object.keys(detailMap)) {
delete detailMap[Number(id)];
}
}
/** 刷新表格 */ /** 刷新表格 */
function handleRefresh() { function handleRefresh() {
clearDetailMap();
gridApi.query(); gridApi.query();
} }
@ -162,7 +170,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
columns: useGridColumns(), columns: useGridColumns(),
expandConfig: { expandConfig: {
padding: true, padding: true,
trigger: 'default',
}, },
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,

View File

@ -15,12 +15,10 @@ import { useDescription } from '#/components/description';
import { import {
formatPrice, formatPrice,
formatQuantity, formatQuantity,
formatSumPrice,
formatSumQuantity,
multiplyPrice, multiplyPrice,
} from '#/views/wms/utils/format'; } from '#/views/wms/utils/format';
import { useDetailSchema } from '../data'; import { getDetailFooter, useDetailSchema } from '../data';
interface DetailRow extends WmsReceiptOrderDetailApi.ReceiptOrderDetail { interface DetailRow extends WmsReceiptOrderDetailApi.ReceiptOrderDetail {
totalPrice?: number; totalPrice?: number;
@ -80,7 +78,9 @@ const [Modal, modalApi] = useVbenModal({
:data="detailRows" :data="detailRows"
border border
empty-text="暂无商品明细" empty-text="暂无商品明细"
:footer-method="getDetailFooter"
:show-overflow="true" :show-overflow="true"
show-footer
size="small" size="small"
> >
<VxeColumn title="商品信息" min-width="220"> <VxeColumn title="商品信息" min-width="220">
@ -99,7 +99,7 @@ const [Modal, modalApi] = useVbenModal({
</div> </div>
</template> </template>
</VxeColumn> </VxeColumn>
<VxeColumn title="数量" align="right" width="120"> <VxeColumn field="quantity" title="数量" align="right" width="120">
<template #default="{ row }"> <template #default="{ row }">
{{ formatQuantity(row.quantity) || '-' }} {{ formatQuantity(row.quantity) || '-' }}
</template> </template>
@ -110,16 +110,12 @@ const [Modal, modalApi] = useVbenModal({
{{ formatPrice(row.price) || '-' }} {{ formatPrice(row.price) || '-' }}
</template> </template>
</VxeColumn> </VxeColumn>
<VxeColumn title="总价" align="right" width="140"> <VxeColumn field="totalPrice" title="总价" align="right" width="140">
<template #default="{ row }"> <template #default="{ row }">
{{ formatPrice(row.totalPrice) || '-' }} {{ formatPrice(row.totalPrice) || '-' }}
</template> </template>
</VxeColumn> </VxeColumn>
</VxeTable> </VxeTable>
<div class="flex justify-end gap-6 text-sm">
<span>合计数量{{ formatSumQuantity(detailRows, (detail) => detail.quantity) }}</span>
<span>合计金额{{ formatSumPrice(detailRows, (detail) => detail.totalPrice) }}</span>
</div>
</div> </div>
</Modal> </Modal>
</template> </template>

View File

@ -7,6 +7,7 @@ import type { WmsReceiptOrderDetailApi } from '#/api/wms/order/receipt/detail';
import { computed, nextTick, ref } from 'vue'; import { computed, nextTick, ref } from 'vue';
import { confirm, useVbenModal } from '@vben/common-ui'; import { confirm, useVbenModal } from '@vben/common-ui';
import { isEqual } from '@vben/utils';
import { InputNumber, message } from 'ant-design-vue'; import { InputNumber, message } from 'ant-design-vue';
@ -46,9 +47,9 @@ defineOptions({ name: 'WmsReceiptOrderForm' });
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const formData = ref<WmsReceiptOrderApi.ReceiptOrder>(); const formData = ref<WmsReceiptOrderApi.ReceiptOrder>({});
const formMode = ref<FormMode>('create'); const formMode = ref<FormMode>('create');
const originalSubmitData = ref(''); const originalSubmitData = ref<WmsReceiptOrderApi.ReceiptOrder>();
const details = ref<DetailRow[]>([]); const details = ref<DetailRow[]>([]);
const detailTableRef = ref<VxeTableInstance>(); const detailTableRef = ref<VxeTableInstance>();
const skuSelectRef = ref<InstanceType<typeof WmsItemSkuSelect>>(); const skuSelectRef = ref<InstanceType<typeof WmsItemSkuSelect>>();
@ -237,7 +238,7 @@ async function buildSubmitData(): Promise<WmsReceiptOrderApi.ReceiptOrder> {
totalPrice: _totalPrice, totalPrice: _totalPrice,
totalQuantity: _totalQuantity, totalQuantity: _totalQuantity,
...order ...order
} = formData.value || {}; } = formData.value;
return { return {
...order, ...order,
...values, ...values,
@ -255,7 +256,7 @@ async function handleFormComplete() {
modalApi.lock(); modalApi.lock();
try { try {
const data = await buildSubmitData(); const data = await buildSubmitData();
if (JSON.stringify(data) !== originalSubmitData.value) { if (!isEqual(data, originalSubmitData.value)) {
await updateReceiptOrder(data); await updateReceiptOrder(data);
} }
await completeReceiptOrder(formData.value.id); await completeReceiptOrder(formData.value.id);
@ -307,8 +308,8 @@ const [Modal, modalApi] = useVbenModal({
}, },
async onOpenChange(isOpen: boolean) { async onOpenChange(isOpen: boolean) {
if (!isOpen) { if (!isOpen) {
formData.value = undefined; formData.value = {};
originalSubmitData.value = ''; originalSubmitData.value = undefined;
setDetails([]); setDetails([]);
return; return;
} }
@ -329,7 +330,7 @@ const [Modal, modalApi] = useVbenModal({
setDetails(orderDetails); setDetails(orderDetails);
// values // values
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
originalSubmitData.value = JSON.stringify(await buildSubmitData()); originalSubmitData.value = await buildSubmitData();
} finally { } finally {
modalApi.unlock(); modalApi.unlock();
} }
@ -343,14 +344,18 @@ const [Modal, modalApi] = useVbenModal({
}; };
setDetails([]); setDetails([]);
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
originalSubmitData.value = JSON.stringify(await buildSubmitData()); originalSubmitData.value = await buildSubmitData();
await nextTick(); await nextTick();
}, },
}); });
</script> </script>
<template> <template>
<Modal :title="getTitle" class="w-3/4"> <Modal
:title="getTitle"
class="w-3/4"
:show-confirm-button="isPrepareOrder"
>
<div class="mx-4"> <div class="mx-4">
<Form /> <Form />
<div class="mt-4"> <div class="mt-4">

View File

@ -397,13 +397,17 @@ interface ReceiptOrderDetailFooterRow {
quantity?: number; quantity?: number;
totalPrice?: number; totalPrice?: number;
} }
type ReceiptOrderDetailFooterColumn = Pick<
NonNullable<NonNullable<VxeTableGridOptions['columns']>[number]>,
'field'
>;
/** 明细表格的合计行 */ /** 明细表格的合计行 */
export function getDetailFooter({ export function getDetailFooter({
columns, columns,
data, data,
}: { }: {
columns: Array<{ field?: string }>; columns: ReceiptOrderDetailFooterColumn[];
data: ReceiptOrderDetailFooterRow[]; data: ReceiptOrderDetailFooterRow[];
}) { }) {
return [ return [

View File

@ -169,7 +169,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
columns: useGridColumns(), columns: useGridColumns(),
expandConfig: { expandConfig: {
padding: true, padding: true,
trigger: 'default',
}, },
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,

View File

@ -7,6 +7,7 @@ import type { WmsReceiptOrderDetailApi } from '#/api/wms/order/receipt/detail';
import { computed, nextTick, ref } from 'vue'; import { computed, nextTick, ref } from 'vue';
import { confirm, useVbenModal } from '@vben/common-ui'; import { confirm, useVbenModal } from '@vben/common-ui';
import { isEqual } from '@vben/utils';
import { ElInputNumber, ElMessage } from 'element-plus'; import { ElInputNumber, ElMessage } from 'element-plus';
@ -46,9 +47,9 @@ defineOptions({ name: 'WmsReceiptOrderForm' });
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const formData = ref<WmsReceiptOrderApi.ReceiptOrder>(); const formData = ref<WmsReceiptOrderApi.ReceiptOrder>({});
const formMode = ref<FormMode>('create'); const formMode = ref<FormMode>('create');
const originalSubmitData = ref(''); const originalSubmitData = ref<WmsReceiptOrderApi.ReceiptOrder>();
const details = ref<DetailRow[]>([]); const details = ref<DetailRow[]>([]);
const detailTableRef = ref<VxeTableInstance>(); const detailTableRef = ref<VxeTableInstance>();
const skuSelectRef = ref<InstanceType<typeof WmsItemSkuSelect>>(); const skuSelectRef = ref<InstanceType<typeof WmsItemSkuSelect>>();
@ -237,7 +238,7 @@ async function buildSubmitData(): Promise<WmsReceiptOrderApi.ReceiptOrder> {
totalPrice: _totalPrice, totalPrice: _totalPrice,
totalQuantity: _totalQuantity, totalQuantity: _totalQuantity,
...order ...order
} = formData.value || {}; } = formData.value;
return { return {
...order, ...order,
...values, ...values,
@ -255,7 +256,7 @@ async function handleFormComplete() {
modalApi.lock(); modalApi.lock();
try { try {
const data = await buildSubmitData(); const data = await buildSubmitData();
if (JSON.stringify(data) !== originalSubmitData.value) { if (!isEqual(data, originalSubmitData.value)) {
await updateReceiptOrder(data); await updateReceiptOrder(data);
} }
await completeReceiptOrder(formData.value.id); await completeReceiptOrder(formData.value.id);
@ -307,8 +308,8 @@ const [Modal, modalApi] = useVbenModal({
}, },
async onOpenChange(isOpen: boolean) { async onOpenChange(isOpen: boolean) {
if (!isOpen) { if (!isOpen) {
formData.value = undefined; formData.value = {};
originalSubmitData.value = ''; originalSubmitData.value = undefined;
setDetails([]); setDetails([]);
return; return;
} }
@ -329,7 +330,7 @@ const [Modal, modalApi] = useVbenModal({
setDetails(orderDetails); setDetails(orderDetails);
// values // values
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
originalSubmitData.value = JSON.stringify(await buildSubmitData()); originalSubmitData.value = await buildSubmitData();
} finally { } finally {
modalApi.unlock(); modalApi.unlock();
} }
@ -343,14 +344,18 @@ const [Modal, modalApi] = useVbenModal({
}; };
setDetails([]); setDetails([]);
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
originalSubmitData.value = JSON.stringify(await buildSubmitData()); originalSubmitData.value = await buildSubmitData();
await nextTick(); await nextTick();
}, },
}); });
</script> </script>
<template> <template>
<Modal :title="getTitle" class="w-3/4"> <Modal
:title="getTitle"
class="w-3/4"
:show-confirm-button="isPrepareOrder"
>
<div class="mx-4"> <div class="mx-4">
<Form /> <Form />
<div class="mt-4"> <div class="mt-4">