| | |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { Divider, message } from 'ant-design-vue'; |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { |
| | |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useRouteProductFormSchema } from '../data'; |
| | | import ProductBomList from './product-bom-list.vue'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref<MesProRouteProductApi.RouteProduct>(); |
| | | const boundItemIds = ref<number[]>([]); // 已绑定本路线的产品物料编号(新增多选时跳过) |
| | | const getTitle = computed(() => |
| | | formData.value?.id |
| | | ? $t('ui.actionTitle.edit', ['工艺路线产品']) |
| | | : $t('ui.actionTitle.create', ['工艺路线产品']), |
| | | ); |
| | | |
| | | /** MdItemSelect change 回调:把物料编码/名称/规格/单位回填到 form */ |
| | | /** MdItemSelect 单选 change 回调:把物料编码/名称/规格/单位回填到 form */ |
| | | async function handleItemChange(item?: any) { |
| | | if (!item) { |
| | | return; |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // 提交表单 |
| | | const data = |
| | | (await formApi.getValues()) as MesProRouteProductApi.RouteProduct; |
| | | const data = (await formApi.getValues()) as MesProRouteProductApi.RouteProduct & { |
| | | itemIds?: number[]; |
| | | }; |
| | | try { |
| | | // 编辑模式:更新单个产品 |
| | | if (formData.value?.id) { |
| | | await updateRouteProduct(data); |
| | | // 用最新表单值同步 formData,确保产品 BOM 子表绑定的 itemId 与表单一致 |
| | | formData.value = { ...formData.value, ...data }; |
| | | } else { |
| | | // 新增成功后切换到编辑模式,方便继续维护产品 BOM |
| | | const id = await createRouteProduct(data); |
| | | formData.value = { ...data, id }; |
| | | await formApi.setFieldValue('id', id); |
| | | await modalApi.close(); |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | return; |
| | | } |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | // 新增模式:多选产品一次性绑定,跳过已在路线中的产品 |
| | | const itemIds = Array.isArray(data.itemIds) ? data.itemIds : []; |
| | | if (itemIds.length === 0) { |
| | | message.warning('请至少选择一个产品'); |
| | | return; |
| | | } |
| | | let created = 0; |
| | | let skipped = 0; |
| | | const failedIds: number[] = []; |
| | | for (const itemId of itemIds) { |
| | | if (itemId == null) { |
| | | continue; |
| | | } |
| | | if (boundItemIds.value.includes(itemId)) { |
| | | skipped++; |
| | | continue; |
| | | } |
| | | try { |
| | | await createRouteProduct({ |
| | | routeId: data.routeId, |
| | | itemId, |
| | | quantity: data.quantity, |
| | | productionTime: data.productionTime, |
| | | timeUnitType: data.timeUnitType, |
| | | remark: data.remark, |
| | | }); |
| | | created++; |
| | | } catch { |
| | | failedIds.push(itemId); |
| | | } |
| | | } |
| | | if (skipped > 0) { |
| | | message.warning(`已跳过 ${skipped} 个已绑定的产品`); |
| | | } |
| | | if (failedIds.length > 0) { |
| | | message.error( |
| | | `有 ${failedIds.length} 个产品绑定失败(可能已被其它工艺路线占用)`, |
| | | ); |
| | | } |
| | | if (created > 0) { |
| | | message.success(`成功绑定 ${created} 个产品`); |
| | | await modalApi.close(); |
| | | emit('success'); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = undefined; |
| | | boundItemIds.value = []; |
| | | return; |
| | | } |
| | | // 加载数据 |
| | | const data = modalApi.getData<{ |
| | | id?: number; |
| | | routeId: number; |
| | | boundItemIds?: number[]; |
| | | }>(); |
| | | if (!data) { |
| | | return; |
| | | } |
| | | boundItemIds.value = data.boundItemIds || []; |
| | | if (!data.id) { |
| | | await formApi.setValues({ routeId: data.routeId }); |
| | | // 新增模式:多选产品绑定 |
| | | formData.value = undefined; |
| | | await formApi.setState({ |
| | | schema: useRouteProductFormSchema(handleItemChange, true), |
| | | }); |
| | | await formApi.setValues({ |
| | | routeId: data.routeId, |
| | | itemIds: [], |
| | | quantity: 1, |
| | | productionTime: 1, |
| | | timeUnitType: 'MINUTE', |
| | | remark: undefined, |
| | | }); |
| | | return; |
| | | } |
| | | // 编辑模式:加载单个产品回填 |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getRouteProduct(data.id); |
| | | // 设置到 values |
| | | await formApi.setState({ |
| | | schema: useRouteProductFormSchema(handleItemChange, false), |
| | | }); |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal :title="getTitle" class="w-3/5"> |
| | | <Modal :title="getTitle" class="w-2/5"> |
| | | <Form class="mx-4" /> |
| | | <!-- 编辑模式下展示产品 BOM 子表,新增模式下隐藏 --> |
| | | <template v-if="formData?.id && formData?.itemId"> |
| | | <Divider class="!my-3" orientation="left">产品 BOM 配置</Divider> |
| | | <div class="mx-4"> |
| | | <ProductBomList |
| | | :route-id="formData.routeId!" |
| | | :product-id="formData.itemId" |
| | | :product-name="formData.itemName" |
| | | /> |
| | | </div> |
| | | </template> |
| | | </Modal> |
| | | </template> |
| | | </template> |