liu
2 天以前 18340ebdeb405be3ba01eb4d1600d9b26cee7ccd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<script lang="ts" setup>
import type { VbenFormSchema } from '#/adapter/form';
import type { MesWmProductIssueLineApi } from '#/api/mes/wm/productissue/line';
 
import { computed, markRaw, ref } from 'vue';
 
import { useVbenModal } from '@vben/common-ui';
 
import { message } from 'ant-design-vue';
 
import { useVbenForm } from '#/adapter/form';
import {
  createProductIssueLine,
  getBomItemList,
  getProductIssueLine,
  updateProductIssueLine,
} from '#/api/mes/wm/productissue/line';
import { MdItemSelect } from '#/views/mes/md/item/components';
 
const emit = defineEmits(['success']);
const formData = ref<MesWmProductIssueLineApi.ProductIssueLine>();
const issueId = ref<number>();
/** 当前工单 BOM 可领物料 ID 白名单(为空时选择器展示全量物料) */
const bomItemIds = ref<number[]>([]);
 
/**
 * 获取当前领料单对应工单 BOM 的可领物料 ID 列表
 * 仅新增/编辑物料时查询当前订单所需物料,其他物料不展示
 */
async function loadBomItemIds() {
  if (!issueId.value) {
    bomItemIds.value = [];
    return;
  }
  try {
    const bomItems = await getBomItemList(issueId.value);
    bomItemIds.value = (bomItems ?? [])
      .map((item) => item.itemId)
      .filter((id): id is number => id != null);
  } catch {
    bomItemIds.value = [];
  }
}
 
/** 更新物料选择器的可选范围,仅展示当前工单 BOM 物料 */
async function applyBomItemScope() {
  await formApi.updateSchema([
    {
      fieldName: 'itemId',
      componentProps: { productIds: bomItemIds.value },
    },
  ]);
}
 
const getTitle = computed(() => {
  return formData.value?.id ? '编辑物料' : '添加物料';
});
 
/** 物料行表单 schema */
function buildLineFormSchema(): VbenFormSchema[] {
  return [
    {
      fieldName: 'itemId',
      label: '产品物料',
      component: markRaw(MdItemSelect),
      componentProps: { placeholder: '请选择产品物料' },
      rules: 'selectRequired',
    },
    {
      fieldName: 'quantity',
      label: '领料数量',
      component: 'InputNumber',
      componentProps: {
        class: '!w-full',
        min: 0,
        placeholder: '请输入领料数量',
        precision: 2,
      },
      rules: 'required',
    },
    {
      fieldName: 'remark',
      label: '备注',
      component: 'Textarea',
      formItemClass: 'col-span-3',
      componentProps: { placeholder: '请输入备注', rows: 2 },
    },
  ];
}
 
const [Form, formApi] = useVbenForm({
  commonConfig: { componentProps: { class: 'w-full' }, formItemClass: 'col-span-1', labelWidth: 90 },
  layout: 'horizontal',
  schema: buildLineFormSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-3',
});
 
const [Modal, modalApi] = useVbenModal({
  async onConfirm() {
    const { valid } = await formApi.validate();
    if (!valid) return;
    modalApi.lock();
    const data = (await formApi.getValues()) as MesWmProductIssueLineApi.ProductIssueLine;
    data.issueId = issueId.value;
    try {
      if (formData.value?.id) {
        await updateProductIssueLine({ ...data, id: formData.value.id });
      } else {
        await createProductIssueLine(data);
      }
      await modalApi.close();
      emit('success');
      message.success('操作成功');
    } finally {
      modalApi.unlock();
    }
  },
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      formData.value = undefined;
      bomItemIds.value = [];
      // 关闭时恢复选择器为不限定范围
      await applyBomItemScope();
      return;
    }
    const data = modalApi.getData<{ id?: number; issueId: number }>();
    issueId.value = data.issueId;
    // 加载当前工单 BOM 可领物料范围
    await loadBomItemIds();
    if (!data.id) {
      await formApi.resetForm();
      await applyBomItemScope();
      return;
    }
    modalApi.lock();
    try {
      formData.value = await getProductIssueLine(data.id);
      // 编辑场景:若当前物料不在 BOM 范围内(历史数据),并入白名单保证可回显可选
      if (
        formData.value?.itemId != null &&
        !bomItemIds.value.includes(formData.value.itemId)
      ) {
        bomItemIds.value = [...bomItemIds.value, formData.value.itemId];
      }
      await applyBomItemScope();
      await formApi.setValues(formData.value);
    } finally {
      modalApi.unlock();
    }
  },
});
</script>
 
<template>
  <Modal :title="getTitle" class="w-3/5">
    <Form class="mx-4" />
  </Modal>
</template>