| | |
| | | <script lang="ts" setup> |
| | | import type { VbenFormSchema } from "#/adapter/form"; |
| | | import type { MdmItemApi } from "#/api/mdm/item"; |
| | | import type { MesProBagCodeApi } from "#/api/mes/pro/bagCode"; |
| | | |
| | | import { computed, markRaw, ref } from "vue"; |
| | | |
| | | import { useVbenModal } from "@vben/common-ui"; |
| | | |
| | |
| | | |
| | | import { useVbenForm } from "#/adapter/form"; |
| | | import { generateBagCodes } from "#/api/mes/pro/bagCode"; |
| | | import { getUnit } from "#/api/mdm/unit"; |
| | | import { MdmItemSelect } from "#/views/basicData/mdm/components"; |
| | | |
| | | defineOptions({ name: "MesProBagCodeGenerateForm" }); |
| | | |
| | | const emit = defineEmits(["success"]); |
| | | |
| | | // 所选品种主计量单位类型:48千克/100千克 -> 每托 N 袋;吨 -> 无托盘直接输袋码数 |
| | | const unitType = ref(""); |
| | | const kgPerPallet = ref<number | null>(null); |
| | | const isTon = ref(false); |
| | | const unitTypeError = ref(false); |
| | | const palletCountVal = ref<number | null>(null); |
| | | const bagCountVal = ref<number | null>(null); |
| | | |
| | | /** 换算/配置提示文案 */ |
| | | const tipText = computed(() => { |
| | | if (unitTypeError.value) { |
| | | return "该品种主计量单位未配置类型(仅支持 48千克/100千克/吨),请先前往「计量单位」维护后重试"; |
| | | } |
| | | if (!unitType.value) { |
| | | return ""; |
| | | } |
| | | if (isTon.value) { |
| | | return `计量单位类型为「吨」:不生成托盘,袋码仅绑定生产批次${ |
| | | bagCountVal.value ? `,将生成 ${bagCountVal.value} 个袋码` : "" |
| | | }`; |
| | | } |
| | | const per = kgPerPallet.value ?? 0; |
| | | const count = palletCountVal.value ?? 0; |
| | | return `计量单位类型为「${unitType.value}」:每托 ${per} 袋${ |
| | | count > 0 |
| | | ? ` × ${count} 托 = ${per * count} 个袋码,将自动生成 ${count} 个托盘并绑定` |
| | | : ",请输入托盘数" |
| | | }`; |
| | | }); |
| | | |
| | | function buildSchema(): VbenFormSchema[] { |
| | | return [ |
| | | const schema: VbenFormSchema[] = [ |
| | | { |
| | | fieldName: "count", |
| | | label: "生成袋数", |
| | | fieldName: "itemId", |
| | | label: "品种", |
| | | component: markRaw(MdmItemSelect), |
| | | componentProps: { |
| | | placeholder: "请选择品种(产品品种)", |
| | | onChange: handleItemChange, |
| | | }, |
| | | rules: "selectRequired", |
| | | }, |
| | | ]; |
| | | if (kgPerPallet.value) { |
| | | schema.push({ |
| | | fieldName: "palletCount", |
| | | label: "托盘数", |
| | | component: "InputNumber", |
| | | componentProps: { |
| | | class: "!w-full", |
| | | min: 1, |
| | | placeholder: "请输入需要生成的袋码数量", |
| | | placeholder: "请输入托盘数(系统自动生成托盘并均分绑定袋码)", |
| | | precision: 0, |
| | | onChange: (value: number | string) => { |
| | | palletCountVal.value = Number(value) || null; |
| | | }, |
| | | }, |
| | | rules: "required", |
| | | }, |
| | | { |
| | | fieldName: "remark", |
| | | label: "备注", |
| | | component: "Textarea", |
| | | }); |
| | | } |
| | | if (isTon.value) { |
| | | schema.push({ |
| | | fieldName: "bagCount", |
| | | label: "袋码数", |
| | | component: "InputNumber", |
| | | componentProps: { |
| | | placeholder: "请输入备注", |
| | | rows: 2, |
| | | class: "!w-full", |
| | | min: 1, |
| | | placeholder: "请输入袋码数(吨品种无托盘,袋码仅绑定批次)", |
| | | precision: 0, |
| | | onChange: (value: number | string) => { |
| | | bagCountVal.value = Number(value) || null; |
| | | }, |
| | | }, |
| | | rules: "required", |
| | | }); |
| | | } |
| | | schema.push({ |
| | | fieldName: "remark", |
| | | label: "备注", |
| | | component: "Textarea", |
| | | componentProps: { |
| | | placeholder: "请输入备注", |
| | | rows: 2, |
| | | }, |
| | | ]; |
| | | }); |
| | | return schema; |
| | | } |
| | | |
| | | /** 选择品种后读取主计量单位类型,动态切换托盘数/袋码数输入 */ |
| | | async function handleItemChange(item?: MdmItemApi.Item) { |
| | | unitType.value = ""; |
| | | kgPerPallet.value = null; |
| | | isTon.value = false; |
| | | unitTypeError.value = false; |
| | | palletCountVal.value = null; |
| | | bagCountVal.value = null; |
| | | if (item?.unitMeasureId) { |
| | | try { |
| | | const unit = await getUnit(item.unitMeasureId); |
| | | const type = (unit?.type ?? "").trim(); |
| | | unitType.value = type; |
| | | if (type === "吨") { |
| | | isTon.value = true; |
| | | } else { |
| | | const matcher = /^(\d{1,5})千克$/.exec(type); |
| | | if (matcher) { |
| | | kgPerPallet.value = Number(matcher[1]); |
| | | } else { |
| | | unitTypeError.value = true; |
| | | } |
| | | } |
| | | } catch { |
| | | unitTypeError.value = true; |
| | | } |
| | | } else if (item) { |
| | | unitTypeError.value = true; |
| | | } |
| | | await formApi.setState({ schema: buildSchema() }); |
| | | } |
| | | |
| | | const [Form, formApi] = useVbenForm({ |
| | |
| | | async onConfirm() { |
| | | const { valid } = await formApi.validate(); |
| | | if (!valid) return; |
| | | if (unitTypeError.value) { |
| | | message.warning(tipText.value); |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | const values = |
| | | (await formApi.getValues()) as MesProBagCodeApi.GenerateParams; |
| | | await generateBagCodes(values); |
| | | message.success(`已成功生成 ${values.count} 条袋码`); |
| | | const data: MesProBagCodeApi.GenerateParams = { |
| | | itemId: values.itemId, |
| | | remark: values.remark, |
| | | }; |
| | | if (isTon.value) { |
| | | data.bagCount = values.bagCount; |
| | | } else { |
| | | data.palletCount = values.palletCount; |
| | | } |
| | | const result = await generateBagCodes(data); |
| | | message.success( |
| | | `已成功生成 ${result.totalCount} 条袋码` + |
| | | (result.palletIds?.length |
| | | ? `,并自动生成 ${result.palletIds.length} 个托盘` |
| | | : ""), |
| | | ); |
| | | emit("success"); |
| | | await modalApi.close(); |
| | | } finally { |
| | |
| | | if (!isOpen) return; |
| | | modalApi.lock(); |
| | | try { |
| | | unitType.value = ""; |
| | | kgPerPallet.value = null; |
| | | isTon.value = false; |
| | | unitTypeError.value = false; |
| | | palletCountVal.value = null; |
| | | bagCountVal.value = null; |
| | | await formApi.setValues({ |
| | | itemId: undefined, |
| | | palletCount: undefined, |
| | | bagCount: undefined, |
| | | remark: undefined, |
| | | }); |
| | | await formApi.setState({ schema: buildSchema() }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | |
| | | <template> |
| | | <Modal title="生成袋码数据包" class="w-2/5"> |
| | | <Form class="mx-4" /> |
| | | <div |
| | | v-if="tipText" |
| | | class="mx-4 mb-2 rounded bg-gray-50 px-3 py-2 text-sm" |
| | | :class="unitTypeError ? 'text-red-500' : 'text-gray-500'" |
| | | > |
| | | {{ tipText }} |
| | | </div> |
| | | </Modal> |
| | | </template> |