| | |
| | | stockCount?: number; // 库存数量(显示字段) |
| | | needProduction?: number; // 是否需要生产:0-不需要,1-需要 |
| | | mpsId?: number; // MPS编号 |
| | | batchCode?: string; // 批次号 |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | const open = ref(false); |
| | | const multiple = ref(true); |
| | | const outStatus = ref<number | undefined>(undefined); |
| | | const status = ref<number | undefined>(undefined); |
| | | const selectedRows = ref<ErpSaleOrderApi.SaleOrder[]>([]); |
| | | const preSelectedIds = ref<number[]>([]); |
| | |
| | | return await getSaleOrderPage({ |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | outStatus: outStatus.value, |
| | | status: status.value, |
| | | ...formValues, |
| | | }); |
| | |
| | | /** 打开销售订单选择弹窗 */ |
| | | async function openModal( |
| | | selectedIds?: number[], |
| | | options?: { multiple?: boolean; status?: number }, |
| | | options?: { multiple?: boolean; outStatus?: number; status?: number }, |
| | | ) { |
| | | open.value = true; |
| | | multiple.value = options?.multiple ?? true; |
| | | outStatus.value = options?.outStatus; |
| | | status.value = options?.status; |
| | | preSelectedIds.value = selectedIds || []; |
| | | await nextTick(); |
| | |
| | | allowClear?: boolean; |
| | | disabled?: boolean; |
| | | modelValue?: number; |
| | | outStatus?: number; |
| | | placeholder?: string; |
| | | status?: number; |
| | | }>(), |
| | |
| | | allowClear: true, |
| | | disabled: false, |
| | | modelValue: undefined, |
| | | outStatus: undefined, |
| | | placeholder: '请选择销售订单', |
| | | status: undefined, |
| | | }, |
| | |
| | | const selectedIds = ( |
| | | props.modelValue === null ? [] : [props.modelValue] |
| | | ) as number[]; |
| | | dialogRef.value?.open(selectedIds, { multiple: false, status: props.status }); |
| | | dialogRef.value?.open(selectedIds, { |
| | | multiple: false, |
| | | outStatus: props.outStatus, |
| | | status: props.status, |
| | | }); |
| | | } |
| | | |
| | | function handleSelected(rows: ErpSaleOrderApi.SaleOrder[]) { |
| | |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { getAccountSimpleList } from '#/api/erp/finance/account'; |
| | | import { getSaleOrderItemListByOrderId, getSaleOrderPage } from '#/api/erp/sale/order'; |
| | | import { |
| | | createSaleReturn, |
| | | getSaleReturn, |
| | |
| | | }); |
| | | const formType = ref<FormType>('create'); // 表单类型:'create' | 'edit' | 'detail' |
| | | const itemFormRef = ref<InstanceType<typeof ItemForm>>(); |
| | | const orderItems = ref<ErpSaleOrderApi.SaleOrderItem[]>([]); |
| | | |
| | | const getTitle = computed(() => { |
| | | if (formType.value === 'create') { |
| | |
| | | } |
| | | |
| | | /** 选择销售订单 */ |
| | | function handleUpdateOrder(order: ErpSaleOrderApi.SaleOrder) { |
| | | async function handleUpdateOrder(order: ErpSaleOrderApi.SaleOrder) { |
| | | formData.value = { |
| | | ...formData.value, |
| | | orderId: order.id, |
| | |
| | | remark: order.remark!, |
| | | discountPercent: order.discountPercent!, |
| | | }; |
| | | // 将订单项设置到退货单项 |
| | | order.items!.forEach((item: any) => { |
| | | item.totalCount = item.count; |
| | | item.count = item.totalCount - item.returnCount; |
| | | item.orderItemId = item.id; |
| | | item.id = undefined; |
| | | // 加载关联销售订单的物料列表 |
| | | const items = await getSaleOrderItemListByOrderId(order.id!); |
| | | orderItems.value = items; |
| | | // 将订单项转换为退货单项(仅保留可退货数量 > 0 的项) |
| | | const returnItems: ErpSaleReturnApi.SaleReturnItem[] = []; |
| | | for (const item of items) { |
| | | const returnCount = (item as { returnCount?: number }).returnCount ?? 0; |
| | | const remainingCount = (item.count ?? 0) - returnCount; |
| | | if (remainingCount <= 0) continue; |
| | | |
| | | returnItems.push({ |
| | | orderItemId: item.id, |
| | | productId: item.productId, |
| | | productName: item.productName || '', |
| | | productPrice: item.productPrice || 0, |
| | | productUnitId: item.productUnitId, |
| | | productUnitName: item.productUnitName, |
| | | productBarCode: item.productBarCode, |
| | | totalCount: item.count, |
| | | count: remainingCount, |
| | | taxPercent: item.taxPercent || 0, |
| | | remark: item.remark || '', |
| | | totalProductPrice: 0, |
| | | taxPrice: 0, |
| | | totalPrice: 0, |
| | | }); |
| | | formData.value.items = order.items!.filter( |
| | | (item) => item.count && item.count > 0, |
| | | ) as ErpSaleReturnApi.SaleReturnItem[]; |
| | | } |
| | | formData.value.items = returnItems; |
| | | formApi.setValues(formData.value, false); |
| | | } |
| | | |
| | |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = {} as ErpSaleReturnApi.SaleReturn; |
| | | orderItems.value = []; |
| | | return; |
| | | } |
| | | // 加载数据 |
| | | const data = modalApi.getData<{ formType: FormType; id?: number }>(); |
| | | formType.value = data.formType; |
| | | const modalData = modalApi.getData<{ formType: FormType; id?: number }>(); |
| | | formType.value = modalData.formType; |
| | | |
| | | // 编辑/详情模式:先加载数据,再更新 schema,确保渲染时 orderNo 已就绪 |
| | | if (modalData?.id) { |
| | | modalApi.lock(); |
| | | try { |
| | | const apiData = await getSaleReturn(modalData.id); |
| | | const raw = apiData as Record<string, unknown>; |
| | | |
| | | // 提取订单号(尝试多种可能的字段名 / 嵌套结构) |
| | | const getOrderNo = (): string => { |
| | | if (raw.orderNo) return raw.orderNo as string; |
| | | if (raw.salesOrderCode) return raw.salesOrderCode as string; |
| | | if (raw.salesOrderNo) return raw.salesOrderNo as string; |
| | | const so = raw.salesOrder as Record<string, unknown> | undefined; |
| | | if (so?.no) return so.no as string; |
| | | const o = raw.order as Record<string, unknown> | undefined; |
| | | if (o?.no) return o.no as string; |
| | | return ''; |
| | | }; |
| | | |
| | | // 提取订单ID(尝试多种可能的字段名 / 嵌套结构) |
| | | const getOrderId = (): number | undefined => { |
| | | if (raw.orderId) return raw.orderId as number; |
| | | if (raw.salesOrderId) return raw.salesOrderId as number; |
| | | const so = raw.salesOrder as Record<string, unknown> | undefined; |
| | | if (so?.id) return so.id as number; |
| | | const o = raw.order as Record<string, unknown> | undefined; |
| | | if (o?.id) return o.id as number; |
| | | return undefined; |
| | | }; |
| | | |
| | | let orderNo = getOrderNo(); |
| | | let orderId = getOrderId(); |
| | | |
| | | // 如果有订单号但没有订单ID,通过订单号反查订单ID |
| | | if (orderNo && !orderId) { |
| | | const orderPage = await getSaleOrderPage({ |
| | | pageNo: 1, |
| | | pageSize: 1, |
| | | no: orderNo, |
| | | } as Record<string, unknown> as never); |
| | | const list = (orderPage as Record<string, unknown>)?.list as Array<Record<string, unknown>> | undefined; |
| | | if (list?.length) { |
| | | orderId = list[0].id as number; |
| | | } |
| | | } |
| | | |
| | | formData.value = { ...apiData, orderNo, orderId }; |
| | | if (orderId) { |
| | | orderItems.value = await getSaleOrderItemListByOrderId(orderId); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | } |
| | | |
| | | // 数据就绪后再更新 schema 和设置表单值 |
| | | formApi.setDisabled(formType.value === 'detail'); |
| | | formApi.updateSchema(useFormSchema(formType.value)); |
| | | if (!data || !data.id) { |
| | | |
| | | if (!modalData?.id) { |
| | | // 新增时,默认选中账户 |
| | | const accountList = await getAccountSimpleList(); |
| | | const defaultAccount = accountList.find((item) => item.defaultStatus); |
| | |
| | | } |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getSaleReturn(data.id); |
| | | // 设置到 values |
| | | |
| | | await formApi.setValues(formData.value, false); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | |
| | | id: item.id, |
| | | })); |
| | | await formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | }); |
| | |
| | | :disabled="formType === 'detail'" |
| | | :discount-percent="formData?.discountPercent ?? 0" |
| | | :other-price="formData?.otherPrice ?? 0" |
| | | :order-items="orderItems" |
| | | @update:items="handleUpdateItems" |
| | | @update:discount-price="handleUpdateDiscountPrice" |
| | | @update:other-price="handleUpdateOtherPrice" |
| | |
| | | </template> |
| | | <template #orderNo> |
| | | <SaleOrderSelect |
| | | :key="formData?.orderNo ?? 'empty'" |
| | | :order-no="formData?.orderNo" |
| | | @update:order="handleUpdateOrder" |
| | | /> |
| | |
| | | <script lang="ts" setup> |
| | | import type { MdmItemApi } from '#/api/mdm/item'; |
| | | import type { ErpSaleOrderApi } from '#/api/erp/sale/order'; |
| | | import type { ErpSaleReturnApi } from '#/api/erp/sale/return'; |
| | | |
| | | import { computed, nextTick, onMounted, ref, watch } from 'vue'; |
| | |
| | | disabled?: boolean; |
| | | discountPercent?: number; |
| | | otherPrice?: number; |
| | | orderItems?: ErpSaleOrderApi.SaleOrderItem[]; |
| | | } |
| | | |
| | | const props = withDefaults(defineProps<Props>(), { |
| | |
| | | disabled: false, |
| | | discountPercent: 0, |
| | | otherPrice: 0, |
| | | orderItems: () => [], |
| | | }); |
| | | |
| | | const emit = defineEmits([ |
| | |
| | | emit('update:items', [...tableData.value]); |
| | | } |
| | | |
| | | /** 处理新增物料行 */ |
| | | function handleAdd() { |
| | | const newRow: ErpSaleReturnApi.SaleReturnItem = { |
| | | seq: Date.now(), |
| | | productId: undefined, |
| | | productName: '', |
| | | productPrice: 0, |
| | | productUnitId: undefined, |
| | | productUnitName: '', |
| | | count: 0, |
| | | totalProductPrice: 0, |
| | | taxPercent: 0, |
| | | taxPrice: 0, |
| | | totalPrice: 0, |
| | | remark: '', |
| | | }; |
| | | tableData.value.push(newRow); |
| | | emit('update:items', [...tableData.value]); |
| | | } |
| | | |
| | | /** 处理产品变更:优先从关联订单物料中填充,兜底从全部物料中查找 */ |
| | | function handleProductChange(row: ErpSaleReturnApi.SaleReturnItem) { |
| | | // 优先从关联订单的物料中查找 |
| | | const orderItem = props.orderItems.find( |
| | | (item) => item.productId === row.productId, |
| | | ); |
| | | if (orderItem) { |
| | | row.productName = orderItem.productName; |
| | | row.productPrice = orderItem.productPrice ?? 0; |
| | | row.productUnitId = orderItem.productUnitId; |
| | | row.productUnitName = orderItem.productUnitName; |
| | | row.productBarCode = orderItem.productBarCode; |
| | | row.taxPercent = orderItem.taxPercent ?? 0; |
| | | row.count = row.count || 1; |
| | | handleRowChange(row); |
| | | return; |
| | | } |
| | | // 兜底:从全部物料中查找 |
| | | const product = productOptions.value.find((item) => item.id === row.productId); |
| | | if (product) { |
| | | row.productName = product.name || ''; |
| | | row.productPrice = product.salesPrice ?? 0; |
| | | row.productUnitId = product.unitMeasureId; |
| | | row.productUnitName = product.unitMeasureName; |
| | | row.productBarCode = product.barCode; |
| | | row.taxPercent = 0; |
| | | row.count = row.count || 1; |
| | | handleRowChange(row); |
| | | } |
| | | } |
| | | |
| | | /** 处理仓库变更 */ |
| | | async function handleWarehouseChange(row: ErpSaleReturnApi.SaleReturnItem) { |
| | | const stockCount = await getWarehouseStockCount({ |
| | |
| | | for (let i = 0; i < tableData.value.length; i++) { |
| | | const item = tableData.value[i]; |
| | | if (item) { |
| | | if (!item.productId) { |
| | | throw new Error(`第 ${i + 1} 行:产品不能为空`); |
| | | } |
| | | if (!item.warehouseId) { |
| | | throw new Error(`第 ${i + 1} 行:仓库不能为空`); |
| | | } |
| | |
| | | </template> |
| | | <template #productId="{ row }"> |
| | | <Select |
| | | disabled |
| | | :disabled="disabled" |
| | | v-model:value="row.productId" |
| | | :options="productOptions" |
| | | :field-names="{ label: 'name', value: 'id' }" |
| | | :options="orderItems?.length ? orderItems : productOptions" |
| | | :field-names="orderItems?.length ? { label: 'productName', value: 'productId' } : { label: 'name', value: 'id' }" |
| | | class="w-full" |
| | | placeholder="请选择产品" |
| | | show-search |
| | | @change="handleProductChange(row)" |
| | | /> |
| | | </template> |
| | | <template #count="{ row }"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <TableAction |
| | | v-if="!disabled" |
| | | class="mt-2 flex justify-center" |
| | | :actions="[ |
| | | { |
| | | label: '添加退货产品', |
| | | type: 'default', |
| | | onClick: handleAdd, |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | </Grid> |
| | | </template> |
| | |
| | | const selectedRows = ref<MesMdItemApi.Item[]>([]); // 已选物料列表 |
| | | const selectedItemTypeId = ref<number>(); // 当前筛选分类编号 |
| | | const preSelectedIds = ref<number[]>([]); // 预选物料编号列表 |
| | | const productIds = ref<number[]>([]); // 限定可选的物料编号列表(为空则不限制) |
| | | const typeTreeRef = ref<InstanceType<typeof MdItemTypeTree>>(); // 物料分类树 |
| | | |
| | | /** 获取当前表格数据 */ |
| | |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues) => { |
| | | return await getItemPage({ |
| | | const params: Record<string, unknown> = { |
| | | pageNo: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | itemTypeId: selectedItemTypeId.value, |
| | | status: CommonStatusEnum.ENABLE, |
| | | }); |
| | | }; |
| | | // 限定可选物料范围 |
| | | if (productIds.value.length > 0) { |
| | | params.pageSize = 1000; |
| | | params.ids = productIds.value.join(','); |
| | | } |
| | | const result = await getItemPage(params as never); |
| | | return result; |
| | | }, |
| | | }, |
| | | }, |
| | |
| | | /** 打开物料选择弹窗 */ |
| | | async function openModal( |
| | | selectedIds?: number[], |
| | | options?: { multiple?: boolean } |
| | | options?: { multiple?: boolean; productIds?: number[] } |
| | | ) { |
| | | open.value = true; |
| | | multiple.value = options?.multiple ?? true; |
| | | preSelectedIds.value = selectedIds || []; |
| | | productIds.value = options?.productIds || []; |
| | | await nextTick(); |
| | | gridApi.setGridOptions({ |
| | | columns: useItemSelectGridColumns(multiple.value), |
| | |
| | | disabled?: boolean; |
| | | modelValue?: number; |
| | | placeholder?: string; |
| | | productIds?: number[]; |
| | | }>(), |
| | | { |
| | | allowClear: true, |
| | | disabled: false, |
| | | modelValue: undefined, |
| | | placeholder: '请选择产品物料', |
| | | productIds: () => [], |
| | | }, |
| | | ); |
| | | const emit = defineEmits<{ |
| | |
| | | const selectedIds = ( |
| | | props.modelValue === null ? [] : [props.modelValue] |
| | | ) as number[]; |
| | | dialogRef.value?.open(selectedIds, { multiple: false }); |
| | | dialogRef.value?.open(selectedIds, { |
| | | multiple: false, |
| | | productIds: props.productIds, |
| | | }); |
| | | } |
| | | |
| | | /** 回填选中的物料 */ |
| | |
| | | }); |
| | | |
| | | /** 重新挂载 schema 并按表单态控制底部按钮 */ |
| | | const mainActionText = computed(() => { |
| | | if (isConfirm.value) return '确认'; |
| | | if (isFinish.value) return '完成'; |
| | | return '提交'; |
| | | }); |
| | | |
| | | const showMainBtn = computed(() => isEditable.value || isConfirm.value || isFinish.value); |
| | | |
| | | function applySchema() { |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi) }); |
| | | const showBtn = isEditable.value || isConfirm.value || isFinish.value; |
| | | modalApi.setState({ |
| | | showConfirmButton: showBtn, |
| | | confirmText: isConfirm.value || canConfirm.value |
| | | ? '确认' |
| | | : isFinish.value |
| | | ? '完成' |
| | | : isCreateMode.value |
| | | ? '新增' |
| | | : '保存', |
| | | }); |
| | | modalApi.setState({ showCancelButton: false, showConfirmButton: false }); |
| | | } |
| | | |
| | | /** 仅保存(不改变状态) */ |
| | |
| | | </Tabs> |
| | | </template> |
| | | <template #prepend-footer> |
| | | <div class="flex flex-auto items-center"> |
| | | <Button v-if="showMainBtn" |
| | | type="primary" |
| | | @click="modalApi.onConfirm()"> |
| | | {{ mainActionText }} |
| | | </Button> |
| | | </div> |
| | | </template> |
| | | <template #append-footer> |
| | | <div class="flex gap-2"> |
| | | <Button v-if="canConfirm" |
| | | @click="handleSave"> |
| | | 保存 |
| | | 保存修改 |
| | | </Button> |
| | | <Button v-if="formType === 'detail' && formData?.id" |
| | | @click="handleBarcode"> |
| | | 查看条码 |
| | | </Button> |
| | | <Button @click="modalApi.close()">取消</Button> |
| | | </div> |
| | | </template> |
| | | </Modal> |
| | | <BarcodeDetail ref="barcodeDetailRef" /> |
| | |
| | | import type { ErpSaleOrderApi } from '#/api/erp/sale/order'; |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesWmReturnSalesApi } from '#/api/mes/wm/returnsales'; |
| | |
| | | export function useFormSchema( |
| | | formType: FormType, |
| | | formApi?: VbenFormApi, |
| | | onOrderChange?: (item: Record<string, unknown> | undefined) => void, |
| | | ): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | |
| | | label: '销售订单号', |
| | | component: markRaw(ErpSaleOrderSelect), |
| | | componentProps: { |
| | | outStatus: 3, |
| | | placeholder: '请选择销售订单', |
| | | onChange: (item: any) => { |
| | | if (formApi) { |
| | |
| | | formApi.setFieldValue('clientId', item.customerId); |
| | | } |
| | | } |
| | | onOrderChange?.(item); |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | |
| | | export function useLineFormSchema( |
| | | clientId?: number, |
| | | salesOrderCode?: string, |
| | | items?: ErpSaleOrderApi.SaleOrderItem[], |
| | | onItemChange?: (item: ErpSaleOrderApi.SaleOrderItem | undefined) => void, |
| | | ): VbenFormSchema[] { |
| | | const hasItems = items && items.length > 0; |
| | | return [ |
| | | { |
| | | fieldName: 'itemId', |
| | | label: '物料', |
| | | component: markRaw(MdItemSelect), |
| | | componentProps: { |
| | | component: hasItems ? 'Select' : markRaw(MdItemSelect), |
| | | componentProps: hasItems |
| | | ? { |
| | | placeholder: '请选择物料', |
| | | options: items.map((item) => ({ |
| | | label: `${item.productName || ''}(${item.productBarCode || ''})`, |
| | | value: item.productId, |
| | | })), |
| | | onChange: (value: number | undefined) => { |
| | | const selected = items.find((i) => i.productId === value); |
| | | onItemChange?.(selected); |
| | | }, |
| | | } |
| | | : { |
| | | placeholder: '请选择物料', |
| | | productIds: [], |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | |
| | | placeholder: '请输入退货数量', |
| | | precision: 2, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['itemId'], |
| | | componentProps: (values) => { |
| | | const selected = items?.find((i) => i.productId === values.itemId); |
| | | return { |
| | | class: '!w-full', |
| | | max: selected?.count ?? undefined, |
| | | min: 0, |
| | | placeholder: '请输入退货数量', |
| | | precision: 2, |
| | | }; |
| | | }, |
| | | rules: (values) => { |
| | | const selected = items?.find((i) => i.productId === values.itemId); |
| | | const max = selected?.count; |
| | | if (max !== undefined && max !== null) { |
| | | return z |
| | | .number({ message: '请输入退货数量' }) |
| | | .min(0) |
| | | .max(max, `可退货数量不能超过 ${max}`); |
| | | } |
| | | return z.number({ message: '请输入退货数量' }).min(0); |
| | | }, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | |
| | | component: markRaw(WmBatchSelect), |
| | | componentProps: { |
| | | clientId, |
| | | disabled: true, |
| | | placeholder: '请选择批次', |
| | | salesOrderCode, |
| | | }, |
| | |
| | | triggerFields: ['itemId'], |
| | | componentProps: (values) => ({ |
| | | clientId, |
| | | disabled: true, |
| | | itemId: values.itemId, |
| | | placeholder: '请选择批次', |
| | | salesOrderCode, |
| | |
| | | submitReturnSales, |
| | | updateReturnSales, |
| | | } from '#/api/mes/wm/returnsales'; |
| | | import type { ErpSaleOrderApi } from '#/api/erp/sale/order'; |
| | | |
| | | import { getSaleOrder, getSaleOrderPage } from '#/api/erp/sale/order'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../data'; |
| | |
| | | const formType = ref<FormType>('create'); |
| | | const formData = ref<MesWmReturnSalesApi.ReturnSales>(); |
| | | const originalSnapshot = ref(''); // 表单原始数据快照,用于提交时跳过未变更的保存请求 |
| | | const saleOrderItems = ref<ErpSaleOrderApi.SaleOrderItem[]>([]); // 当前销售订单的物料行 |
| | | const isEditable = computed(() => |
| | | // 是否为编辑模式(可保存) |
| | | ['create', 'update'].includes(formType.value), |
| | |
| | | // 加载数据 |
| | | const data = modalApi.getData<{ formType: FormType; id?: number }>(); |
| | | formType.value = data.formType; |
| | | formApi.setState({ schema: useFormSchema(formType.value, formApi) }); |
| | | formApi.setState({ |
| | | schema: useFormSchema(formType.value, formApi, (item) => { |
| | | if (item?.id) { |
| | | getSaleOrder(item.id as number).then((order) => { |
| | | saleOrderItems.value = (order as ErpSaleOrderApi.SaleOrder)?.items || []; |
| | | }); |
| | | } else { |
| | | saleOrderItems.value = []; |
| | | } |
| | | }), |
| | | }); |
| | | formApi.setDisabled(!isEditable.value); |
| | | modalApi.setState({ showConfirmButton: isEditable.value }); |
| | | if (data?.id) { |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getReturnSales(data.id); |
| | | // 通过销售订单号反查订单ID,确保 ErpSaleOrderSelect 能正确回显 |
| | | if (formData.value?.salesOrderCode && !formData.value.saleOrderId) { |
| | | const orderPage = await getSaleOrderPage({ |
| | | pageNo: 1, |
| | | pageSize: 1, |
| | | no: formData.value.salesOrderCode, |
| | | } as Record<string, unknown> as never); |
| | | const list = (orderPage as Record<string, unknown>)?.list as Array<Record<string, unknown>> | undefined; |
| | | if (list?.length) { |
| | | const orderId = list[0].id as number; |
| | | (formData.value as Record<string, unknown>).saleOrderId = orderId; |
| | | const order = await getSaleOrder(orderId); |
| | | saleOrderItems.value = order?.items || []; |
| | | } |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | |
| | | :client-id="formData.clientId" |
| | | :form-type="formType" |
| | | :return-id="formData.id" |
| | | :sale-order-items="saleOrderItems" |
| | | :sales-order-code="formData.salesOrderCode" |
| | | /> |
| | | </div> |
| | |
| | | <script lang="ts" setup> |
| | | import type { ErpSaleOrderApi } from '#/api/erp/sale/order'; |
| | | import type { MesWmReturnSalesLineApi } from '#/api/mes/wm/returnsales/line'; |
| | | |
| | | import { computed, ref } from 'vue'; |
| | |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { getBatchPage } from '#/api/mes/wm/batch'; |
| | | import { |
| | | createReturnSalesLine, |
| | | getReturnSalesLine, |
| | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref<MesWmReturnSalesLineApi.ReturnSalesLine>(); |
| | | const returnId = ref<number>(); // 所属退货单编号 |
| | | const maxQuantity = ref<number>(); // 当前选中物料可退货的最大数量 |
| | | |
| | | const getTitle = computed(() => { |
| | | return formData.value?.id |
| | |
| | | const data = modalApi.getData<{ |
| | | clientId?: number; |
| | | id?: number; |
| | | items?: ErpSaleOrderApi.SaleOrderItem[]; |
| | | returnId: number; |
| | | salesOrderCode?: string; |
| | | }>(); |
| | | returnId.value = data.returnId; |
| | | maxQuantity.value = undefined; |
| | | formApi.setState({ |
| | | schema: useLineFormSchema(data.clientId, data.salesOrderCode), |
| | | schema: useLineFormSchema( |
| | | data.clientId, |
| | | data.salesOrderCode, |
| | | data.items || [], |
| | | async (item) => { |
| | | maxQuantity.value = item?.count; |
| | | // 重置批次 |
| | | await formApi.setFieldValue('batchId', undefined); |
| | | if (item?.batchCode) { |
| | | try { |
| | | const batchPage = await getBatchPage({ |
| | | code: item.batchCode, |
| | | pageNo: 1, |
| | | pageSize: 1, |
| | | }); |
| | | const batchList = batchPage?.list; |
| | | if (batchList?.length) { |
| | | await formApi.setFieldValue('batchId', batchList[0].id); |
| | | } |
| | | } catch { |
| | | // 查询失败时忽略 |
| | | } |
| | | } |
| | | }, |
| | | ), |
| | | }); |
| | | if (!data.id) { |
| | | return; |
| | |
| | | <template> |
| | | <Modal :title="getTitle" class="w-3/5"> |
| | | <Form class="mx-4" /> |
| | | <div |
| | | v-if="maxQuantity !== undefined" |
| | | class="mx-4 mt-2 text-sm text-blue-600" |
| | | > |
| | | 当前物料可退货数量:<span class="font-bold">{{ maxQuantity }}</span> |
| | | </div> |
| | | </Modal> |
| | | </template> |
| | |
| | | <script lang="ts" setup> |
| | | import type { FormType } from '../data'; |
| | | |
| | | import type { ErpSaleOrderApi } from '#/api/erp/sale/order'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesWmReturnSalesDetailApi } from '#/api/mes/wm/returnsales/detail'; |
| | | import type { MesWmReturnSalesLineApi } from '#/api/mes/wm/returnsales/line'; |
| | |
| | | clientId?: number; |
| | | formType: FormType; |
| | | returnId: number; |
| | | saleOrderItems?: ErpSaleOrderApi.SaleOrderItem[]; |
| | | salesOrderCode?: string; |
| | | }>(); |
| | | |
| | |
| | | lineFormModalApi |
| | | .setData({ |
| | | clientId: props.clientId, |
| | | items: props.saleOrderItems, |
| | | returnId: props.returnId, |
| | | salesOrderCode: props.salesOrderCode, |
| | | }) |
| | |
| | | .setData({ |
| | | clientId: props.clientId, |
| | | id: row.id, |
| | | items: props.saleOrderItems, |
| | | returnId: props.returnId, |
| | | salesOrderCode: props.salesOrderCode, |
| | | }) |