宁夏万通需求:出库单行支持主/辅单位录入;物料型号维护;考勤节假日配置时间段;设备批量删除;质检导出按筛选条件
1. WLS 仓储:6 张出入库单行录入弹窗(采购入库、杂项出库、外协发料、生产领料、销售出库、采购退货)支持「主单位 + 辅单位(结合型号换算)」录入,新增 wls 单位换算工具与型号选择,行列表与接口适配新增字段。
2. 基础数据:物料新增「型号」子表维护(item-model 接口 + 型号配置组件),物料表单适配主辅单位与型号。
3. HRM 考勤:节假日配置由「单日」改为「时间段」(RangePicker 录入日期区间),列表按区间展示,筛选改为按日期区间交集查询。
4. MES 设备:设备台账支持批量删除。
5. MES 质检:IQC/IPQC/OQC/RQC 四个页面导出改为按当前筛选条件直接导出,删除原「导出区间」弹窗组件。
6. ERP 采购订单/采购申请表单编号占位提示调整。
| | |
| | | export interface Holiday { |
| | | id?: number; |
| | | name?: string; |
| | | date?: string; |
| | | /** å¼å§æ¥æ */ |
| | | startDate?: string; |
| | | /** ç»ææ¥æ */ |
| | | endDate?: string; |
| | | type?: number; |
| | | typeName?: string; |
| | | isLegal?: number; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | export namespace MdmItemModelApi { |
| | | /** ç©æåå·ï¼åå·åç§° + åå·è®¡éåä½ + æ¢ç®æ¯çï¼ */ |
| | | export interface ItemModel { |
| | | id?: number; // åå·ç¼å· |
| | | itemId?: number; // ç©æç¼å· |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | model?: string; // åå·åç§° |
| | | unitMeasureId?: number; // åå·è®¡éåä½ç¼å·ï¼è¾
åä½ï¼ |
| | | unitMeasureName?: string; // åå·è®¡éåä½åç§° |
| | | unitMeasureRate?: number; // æ¢ç®æ¯çï¼1 åå·è®¡éåä½ = N ç©æä¸»è®¡éåä½ |
| | | status?: number; // ç¶æï¼0æ£å¸¸ 1åç¨ï¼ |
| | | remark?: string; // 夿³¨ |
| | | createTime?: string; // å建æ¶é´ |
| | | } |
| | | } |
| | | |
| | | /** æ¥è¯¢æç©æçåå·å表 */ |
| | | export function getItemModelListByItem(itemId: number) { |
| | | return requestClient.get<MdmItemModelApi.ItemModel[]>( |
| | | '/mdm/item-model/list-by-item', |
| | | { params: { itemId } }, |
| | | ); |
| | | } |
| | | |
| | | /** æ¹éæ¥è¯¢å¤ä¸ªç©æçåå·å表 */ |
| | | export function getItemModelListByItems(itemIds: number[]) { |
| | | return requestClient.get<MdmItemModelApi.ItemModel[]>( |
| | | '/mdm/item-model/list-by-items', |
| | | { params: { itemIds: itemIds.join(',') } }, |
| | | ); |
| | | } |
| | | |
| | | /** å
¨éè¦çä¿åæç©æçåå·å表ï¼å
å åæï¼ */ |
| | | export function saveItemModelList( |
| | | itemId: number, |
| | | list: MdmItemModelApi.ItemModel[], |
| | | ) { |
| | | return requestClient.post<boolean>( |
| | | '/mdm/item-model/save-list', |
| | | list, |
| | | { params: { itemId } }, |
| | | ); |
| | | } |
| | |
| | | return requestClient.delete(`/mes/dv/machinery/delete?id=${id}`); |
| | | } |
| | | |
| | | /** æ¹éå é¤è®¾å¤ */ |
| | | export function deleteMachineryList(ids: number[]) { |
| | | return requestClient.delete(`/mes/dv/machinery/delete-list?ids=${ids.join(',')}`); |
| | | } |
| | | |
| | | /** 导åºè®¾å¤ */ |
| | | export function exportMachinery(params: any) { |
| | | return requestClient.download('/mes/dv/machinery/export-excel', { params }); |
| | |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureName?: string; // åä½ |
| | | receivedQuantity?: number; // å
¥åºæ°é |
| | | unitMeasureId?: number; // 主计éåä½ç¼å·ï¼ç©æä¸»åä½ï¼ |
| | | unitMeasureName?: string; // 主计éåä½åç§°ï¼ç©æä¸»åä½ï¼ |
| | | itemModelId?: number; // ç©æåå·ç¼å· |
| | | itemModel?: string; // ç©æåå·åç§° |
| | | enterUnitMeasureId?: number; // å½å
¥åä½ç¼å· |
| | | enterUnitMeasureName?: string; // å½å
¥åä½åç§° |
| | | enterQuantity?: number; // å½å
¥æ°éï¼æå½å
¥åä½è®¡ï¼ |
| | | receivedQuantity?: number; // å
¥åºæ°éï¼ç©æä¸»åä½å£å¾ï¼éè¾
åä½å½å
¥æ¶ç±å端æ¢ç®ï¼ |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡å· |
| | | productionDate?: number; // çäº§æ¥æ |
| | |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureId?: number; // 主计éåä½ç¼å·ï¼ç©æä¸»åä½ï¼ |
| | | unitMeasure?: string; // 计éåä½ |
| | | unitMeasureName?: string; // 计éåä½åç§° |
| | | quantity?: number; // åºåºæ°é |
| | | unitMeasureName?: string; // 主计éåä½åç§°ï¼ç©æä¸»åä½ï¼ |
| | | itemModelId?: number; // ç©æåå·ç¼å· |
| | | itemModel?: string; // ç©æåå·åç§° |
| | | enterUnitMeasureId?: number; // å½å
¥åä½ç¼å· |
| | | enterUnitMeasureName?: string; // å½å
¥åä½åç§° |
| | | enterQuantity?: number; // å½å
¥æ°éï¼æå½å
¥åä½è®¡ï¼ |
| | | quantity?: number; // åºåºæ°éï¼ç©æä¸»åä½å£å¾ï¼éè¾
åä½å½å
¥æ¶ç±å端æ¢ç®ï¼ |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡å· |
| | | warehouseId?: number; // ä»åºç¼å· |
| | |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureName?: string; // 计éåä½åç§° |
| | | quantity?: number; // åææ°é |
| | | unitMeasureId?: number; // 主计éåä½ç¼å·ï¼ç©æä¸»åä½ï¼ |
| | | unitMeasureName?: string; // 主计éåä½åç§° |
| | | itemModelId?: number; // ç©æåå·ç¼å· |
| | | itemModel?: string; // ç©æåå·åç§° |
| | | enterUnitMeasureId?: number; // å½å
¥åä½ç¼å· |
| | | enterUnitMeasureName?: string; // å½å
¥åä½åç§° |
| | | enterQuantity?: number; // å½å
¥æ°éï¼æå½å
¥åä½è®¡ï¼ |
| | | quantity?: number; // åææ°éï¼ç©æä¸»åä½å£å¾ï¼æå½å
¥åä½å½å
¥æ¶ç±å端æ¢ç®ï¼ |
| | | materialStockId?: number; // åºåç¼å· |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡ç¼ç |
| | |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureName?: string; // åä½ |
| | | quantity?: number; // 颿æ°é |
| | | unitMeasureId?: number; // 主计éåä½ç¼å·ï¼ç©æä¸»åä½ï¼ |
| | | unitMeasureName?: string; // 主计éåä½åç§° |
| | | itemModelId?: number; // ç©æåå·ç¼å· |
| | | itemModel?: string; // ç©æåå·åç§° |
| | | enterUnitMeasureId?: number; // å½å
¥åä½ç¼å· |
| | | enterUnitMeasureName?: string; // å½å
¥åä½åç§° |
| | | enterQuantity?: number; // å½å
¥æ°éï¼æå½å
¥åä½è®¡ï¼ |
| | | quantity?: number; // 颿æ°éï¼ç©æä¸»åä½å£å¾ï¼æå½å
¥åä½å½å
¥æ¶ç±å端æ¢ç®ï¼ |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | remark?: string; // 夿³¨ |
| | | } |
| | |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureName?: string; // åä½ |
| | | quantity?: number; // åºåºæ°é |
| | | unitMeasureId?: number; // 主计éåä½ç¼å·ï¼ç©æä¸»åä½ï¼ |
| | | unitMeasureName?: string; // 主计éåä½åç§° |
| | | itemModelId?: number; // ç©æåå·ç¼å· |
| | | itemModel?: string; // ç©æåå·åç§° |
| | | enterUnitMeasureId?: number; // å½å
¥åä½ç¼å· |
| | | enterUnitMeasureName?: string; // å½å
¥åä½åç§° |
| | | enterQuantity?: number; // å½å
¥æ°éï¼æå½å
¥åä½è®¡ï¼ |
| | | quantity?: number; // åºåºæ°éï¼ç©æä¸»åä½å£å¾ï¼æå½å
¥åä½å½å
¥æ¶ç±å端æ¢ç®ï¼ |
| | | pickedQuantity?: number; // å·²æ£è´§æ°é |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡å· |
| | |
| | | itemCode?: string; // ç©æç¼ç |
| | | itemName?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | | unitMeasureName?: string; // åä½ |
| | | quantity?: number; // éè´§æ°é |
| | | unitMeasureId?: number; // 主计éåä½ç¼å·ï¼ç©æä¸»åä½ï¼ |
| | | unitMeasureName?: string; // 主计éåä½åç§° |
| | | itemModelId?: number; // ç©æåå·ç¼å· |
| | | itemModel?: string; // ç©æåå·åç§° |
| | | enterUnitMeasureId?: number; // å½å
¥åä½ç¼å· |
| | | enterUnitMeasureName?: string; // å½å
¥åä½åç§° |
| | | enterQuantity?: number; // å½å
¥æ°éï¼æå½å
¥åä½è®¡ï¼ |
| | | quantity?: number; // éè´§æ°éï¼ç©æä¸»åä½å£å¾ï¼æå½å
¥åä½å½å
¥æ¶ç±å端æ¢ç®ï¼ |
| | | batchId?: number; // æ¹æ¬¡ç¼å· |
| | | batchCode?: string; // æ¹æ¬¡å· |
| | | remark?: string; // 夿³¨ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { MdmItemModelApi } from '#/api/mdm/item-model'; |
| | | |
| | | import { ref } from 'vue'; |
| | | |
| | | import { |
| | | Button, |
| | | Divider, |
| | | Empty, |
| | | Input, |
| | | InputNumber, |
| | | Popconfirm, |
| | | Select, |
| | | Spin, |
| | | Table, |
| | | } from 'ant-design-vue'; |
| | | |
| | | import { |
| | | getItemModelListByItem, |
| | | saveItemModelList, |
| | | } from '#/api/mdm/item-model'; |
| | | import { getUnitPage } from '#/api/mdm/unit'; |
| | | |
| | | /** è¡å
ç¼è¾éè¦ç¨³å®çè¡æ è¯ï¼æ
卿¥å£æ°æ®ä¸è¡¥ä¸ä¸ªæ¬å° _key */ |
| | | type ModelRow = MdmItemModelApi.ItemModel & { _key: number }; |
| | | |
| | | const rows = ref<ModelRow[]>([]); |
| | | const units = ref<{ label: string; value: number }[]>([]); |
| | | const loading = ref(false); |
| | | let rowKey = 0; |
| | | |
| | | const columns = [ |
| | | { title: 'åå·åç§°', dataIndex: 'model', width: 200 }, |
| | | { title: 'åå·è®¡éåä½', dataIndex: 'unitMeasureId', width: 170 }, |
| | | { title: 'æ¢ç®æ¯ç', dataIndex: 'unitMeasureRate', width: 200 }, |
| | | { title: '夿³¨', dataIndex: 'remark' }, |
| | | { title: 'æä½', dataIndex: 'action', width: 70, align: 'center' as const }, |
| | | ]; |
| | | |
| | | /** å 载计éåä½ä¸æé项 */ |
| | | async function loadUnits() { |
| | | if (units.value.length > 0) { |
| | | return; |
| | | } |
| | | const res = await getUnitPage({ pageNo: 1, pageSize: 100, status: 0 }); |
| | | units.value = (res.list || []).map((unit) => ({ |
| | | label: unit.name, |
| | | value: unit.id!, |
| | | })); |
| | | } |
| | | |
| | | /** å è½½æå®ç©æå·²é
ç½®çåå· */ |
| | | async function load(itemId?: number) { |
| | | if (!itemId) { |
| | | reset(); |
| | | return; |
| | | } |
| | | loading.value = true; |
| | | try { |
| | | await loadUnits(); |
| | | const list = await getItemModelListByItem(itemId); |
| | | rows.value = (list || []).map((model) => ({ |
| | | ...model, |
| | | _key: ++rowKey, |
| | | })); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | /** æ°å¢ä¸è¡åå· */ |
| | | async function handleAdd() { |
| | | await loadUnits(); |
| | | rows.value.push({ |
| | | _key: ++rowKey, |
| | | model: '', |
| | | unitMeasureId: undefined, |
| | | unitMeasureRate: undefined, |
| | | status: 0, |
| | | remark: '', |
| | | }); |
| | | } |
| | | |
| | | /** å 餿è¡åå· */ |
| | | function handleRemove(key: number) { |
| | | rows.value = rows.value.filter((row) => row._key !== key); |
| | | } |
| | | |
| | | /** æ¸
空 */ |
| | | function reset() { |
| | | rows.value = []; |
| | | } |
| | | |
| | | /** åå·è®¡éåä½ååæ¶ï¼åæ¥åä½åç§° */ |
| | | function handleUnitChange(row: ModelRow, value: unknown) { |
| | | row.unitMeasureName = units.value.find((u) => u.value === value)?.label; |
| | | } |
| | | |
| | | /** åä½ä¸ææ¯ææåç§°æç´¢ */ |
| | | function filterUnitOption(input: string, option: { label?: string }) { |
| | | return String(option?.label ?? '') |
| | | .toLowerCase() |
| | | .includes(input.toLowerCase()); |
| | | } |
| | | |
| | | /** æ ¡éªåå·å表ï¼è¿å第ä¸å¤é®é¢ï¼æ é®é¢è¿å undefined */ |
| | | function validate(): string | undefined { |
| | | const names = new Set<string>(); |
| | | for (const [index, row] of rows.value.entries()) { |
| | | const label = `第 ${index + 1} è¡`; |
| | | const name = row.model?.trim(); |
| | | if (!name) { |
| | | return `${label}çåå·åç§°ä¸è½ä¸ºç©ºï¼è¯·å¡«ååå·åç§°`; |
| | | } |
| | | if (names.has(name)) { |
| | | return `${label}çåå·åç§°ã${name}ãä¸åé¢å¡«åéå¤ï¼åä¸ç©æä¸åå·åç§°ä¸è½éåï¼è¯·ä¿®æ¹`; |
| | | } |
| | | names.add(name); |
| | | if (row.unitMeasureId == null) { |
| | | return `${label}åå·ã${name}ãè¿æªéæ©åå·è®¡éåä½ï¼è¯·éæ©è¯¥åå·å®é
æ¶å货使ç¨çåä½`; |
| | | } |
| | | if (row.unitMeasureRate == null || row.unitMeasureRate <= 0) { |
| | | return `${label}åå·ã${name}ãçæ¢ç®æ¯çæªå¡«åæä¸å¤§äº 0ï¼è¯·å¡«å 1 个åå·è®¡éåä½å¯¹åºå¤å°ä¸ªç©æä¸»åä½`; |
| | | } |
| | | } |
| | | return undefined; |
| | | } |
| | | |
| | | /** å
¨éè¦çä¿ååå·å表 */ |
| | | async function save(itemId: number) { |
| | | const payload = rows.value.map((row) => ({ |
| | | id: row.id, |
| | | itemId, |
| | | model: row.model!.trim(), |
| | | unitMeasureId: row.unitMeasureId, |
| | | unitMeasureRate: row.unitMeasureRate, |
| | | status: row.status ?? 0, |
| | | remark: row.remark, |
| | | })); |
| | | await saveItemModelList(itemId, payload); |
| | | } |
| | | |
| | | defineExpose({ load, reset, validate, save }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="mx-4 mt-2"> |
| | | <Divider orientation="left">åå·é
ç½®ï¼ä¸»è¾
å使¢ç®ï¼</Divider> |
| | | <p class="mb-3 text-xs text-gray-400"> |
| | | åä¸ç©æä¸ååå·å¯ä½¿ç¨ä¸åç计éåä½ä¸æ¢ç®æ¯çãæ¢ç®æ¯çå«ä¹ï¼1 个åå·è®¡éåä½ = N ä¸ªç©æä¸»åä½ï¼ä¾ï¼åå· |
| | | ã4ç±³/æ ¹ãç计éåä½å¡«ãæ ¹ããæ¢ç®æ¯çå¡« 4ï¼è¡¨ç¤º 1 æ ¹ = 4 ç±³ï¼ãåºå
¥åºæ¶å¯æåå·éæ©è¿äºåä½å½å
¥ï¼ç³»ç»èªå¨æ¢ç®ä¸ºç©æä¸»å使°éè®°è´¦ã |
| | | </p> |
| | | <Button class="mb-3" type="primary" @click="handleAdd">æ·»å åå·</Button> |
| | | <Spin :spinning="loading"> |
| | | <div> |
| | | <Table |
| | | v-if="rows.length > 0" |
| | | :columns="columns" |
| | | :data-source="rows" |
| | | :pagination="false" |
| | | row-key="_key" |
| | | size="small" |
| | | bordered |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.dataIndex === 'model'"> |
| | | <Input |
| | | v-model:value="record.model" |
| | | :maxlength="128" |
| | | placeholder="å¦ï¼4ç±³/æ ¹" |
| | | /> |
| | | </template> |
| | | <template v-else-if="column.dataIndex === 'unitMeasureId'"> |
| | | <Select |
| | | v-model:value="record.unitMeasureId" |
| | | :filter-option="filterUnitOption" |
| | | :options="units" |
| | | allow-clear |
| | | class="w-full" |
| | | placeholder="å¦ï¼æ ¹" |
| | | show-search |
| | | @change="(value) => handleUnitChange(record, value)" |
| | | /> |
| | | </template> |
| | | <template v-else-if="column.dataIndex === 'unitMeasureRate'"> |
| | | <InputNumber |
| | | v-model:value="record.unitMeasureRate" |
| | | :min="0" |
| | | :precision="6" |
| | | class="!w-full" |
| | | placeholder="1 åå·åä½ = N 主åä½" |
| | | /> |
| | | </template> |
| | | <template v-else-if="column.dataIndex === 'remark'"> |
| | | <Input v-model:value="record.remark" :maxlength="500" /> |
| | | </template> |
| | | <template v-else-if="column.dataIndex === 'action'"> |
| | | <Popconfirm |
| | | title="确认å é¤è¯¥åå·åï¼" |
| | | @confirm="handleRemove(record._key)" |
| | | > |
| | | <Button danger size="small" type="link">å é¤</Button> |
| | | </Popconfirm> |
| | | </template> |
| | | </template> |
| | | </Table> |
| | | <Empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" description="ææ åå·ï¼å¦éæè¾
åä½ï¼å¦æ ¹ãè¢ãç®±ï¼æ¶åè´§ï¼è¯·æ·»å åå·" /> |
| | | </div> |
| | | </Spin> |
| | | </div> |
| | | </template> |
| | |
| | | |
| | | import { useFormSchema, clearUnitListCache, buildCategoryTree } from '../data'; |
| | | import { getItemTypeSimpleList } from '#/api/mes/md/item/type'; |
| | | import ItemModelConfig from '../components/item-model-config.vue'; |
| | | |
| | | defineOptions({ name: "ItemForm" }); |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref<MdmItemApi.Item>(); |
| | | const itemModelRef = ref<InstanceType<typeof ItemModelConfig>>(); |
| | | |
| | | const [Form, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | // åå·å
æ ¡éªï¼é¿å
ç©æå·²ä¿åèåå·æªä¿å |
| | | const modelError = itemModelRef.value?.validate(); |
| | | if (modelError) { |
| | | message.error(modelError); |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | const data = (await formApi.getValues()) as MdmItemApi.Item; |
| | | try { |
| | | await (formData.value?.id ? updateItem(data) : createItem(data)); |
| | | const itemId = formData.value?.id ?? (await createItem(data)); |
| | | if (formData.value?.id) { |
| | | await updateItem(data); |
| | | } |
| | | await itemModelRef.value?.save(itemId); |
| | | await modalApi.close(); |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = undefined; |
| | | itemModelRef.value?.reset(); |
| | | return; |
| | | } |
| | | const data = modalApi.getData<MdmItemApi.Item>(); |
| | |
| | | // åæ¥ç¶ææ å°ï¼è¯¦æ
æ¥å£è¿å syncedMesï¼è¡¨ååæ®µä¸º syncMes |
| | | formData.value.syncMes = formData.value.syncedMes ?? true; |
| | | await formApi.setValues(formData.value); |
| | | await itemModelRef.value?.load(data.id); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | // æ°å¢æ¨¡å¼ |
| | | formData.value = undefined; |
| | | await formApi.resetForm(); |
| | | itemModelRef.value?.reset(); |
| | | } |
| | | }, |
| | | }); |
| | |
| | | <template> |
| | | <Modal class="w-[1000px]" :title="formData?.id ? $t('ui.actionTitle.edit', ['ç©æ']) : $t('ui.actionTitle.create', ['ç©æ'])"> |
| | | <Form class="mx-4" /> |
| | | <ItemModelConfig ref="itemModelRef" /> |
| | | </Modal> |
| | | </template> |
| | |
| | | label: '订ååå·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: 'ç³»ç»èªå¨çæ', |
| | | placeholder: '订åå·èªå®ä¹', |
| | | disabled: true, |
| | | }, |
| | | }, |
| | |
| | | label: 'ç³è¯·ç¼å·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: 'ç³»ç»èªå¨çæ', |
| | | placeholder: 'ç³»ç»èªå®ä¹ç¼å·', |
| | | disabled: true, |
| | | }, |
| | | }, |
| | |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'date', |
| | | label: 'æ¥æ', |
| | | component: 'DatePicker', |
| | | fieldName: 'dateRange', |
| | | label: 'æ¥æåºé´', |
| | | component: 'RangePicker', |
| | | componentProps: { |
| | | placeholder: 'éæ©æ¥æ', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | style: { width: '100%' }, |
| | | }, |
| | |
| | | export function useGridColumns(): VxeTableGridOptions<HrmAttendanceHolidayApi.Holiday>['columns'] { |
| | | return [ |
| | | { field: 'name', title: 'è忥åç§°', minWidth: 150 }, |
| | | { field: 'date', title: 'æ¥æ', width: 120 }, |
| | | { |
| | | field: 'startDate', |
| | | title: 'æ¥æåºé´', |
| | | minWidth: 200, |
| | | slots: { |
| | | default: 'dateRange', |
| | | }, |
| | | }, |
| | | { |
| | | field: 'type', |
| | | title: 'ç±»å', |
| | |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #dateRange="{ row }"> |
| | | <span v-if="!row.startDate && !row.endDate">-</span> |
| | | <span v-else-if="row.startDate === row.endDate">{{ row.startDate }}</span> |
| | | <span v-else>{{ row.startDate }} ~ {{ row.endDate }}</span> |
| | | </template> |
| | | <template #isLegal="{ row }"> |
| | | <Tag v-if="row.isLegal === 1" color="red">æ³å®</Tag> |
| | | <span v-else>-</span> |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | const data = (await formApi.getValues()) as HrmAttendanceHolidayApi.Holiday; |
| | | const values = (await formApi.getValues()) as HrmAttendanceHolidayApi.Holiday & { |
| | | dateRange?: string[]; |
| | | }; |
| | | const { dateRange, ...rest } = values; |
| | | const data: HrmAttendanceHolidayApi.Holiday = { |
| | | ...rest, |
| | | startDate: dateRange?.[0], |
| | | endDate: dateRange?.[1], |
| | | }; |
| | | try { |
| | | if (formType.value === 'update') { |
| | | await updateAttendanceHoliday(data); |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | await formApi.setValues(await getAttendanceHoliday(data.id)); |
| | | const detail = await getAttendanceHoliday(data.id); |
| | | await formApi.setValues({ |
| | | ...detail, |
| | | dateRange: |
| | | detail.startDate && detail.endDate |
| | | ? [detail.startDate, detail.endDate] |
| | | : undefined, |
| | | }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | deleteMachinery, |
| | | deleteMachineryList, |
| | | exportMachinery, |
| | | getMachineryPage, |
| | | } from '#/api/mes/dv/machinery'; |
| | |
| | | records: MesDvMachineryApi.Machinery[]; |
| | | }) { |
| | | checkedIds.value = records.map((item) => item.id!); |
| | | } |
| | | |
| | | /** |
| | | * è¡¨æ ¼æ°æ®éè½½åï¼æ¥è¯¢/翻页/å·æ°/åæ¢è®¾å¤ç±»åï¼æ¸
空å¾éï¼ |
| | | * é¿å
å¾éäºä¸ä¸é¡µç设å¤åï¼é¡µé¢å·²å·æ°ä½ä»ææ§å¾éå é¤ |
| | | */ |
| | | function handleDataChange() { |
| | | checkedIds.value = []; |
| | | gridApi.grid.clearCheckboxRow(); |
| | | } |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | |
| | | |
| | | /** æ¹éå é¤è®¾å¤ */ |
| | | async function handleDeleteBatch() { |
| | | if (checkedIds.value.length === 0) { |
| | | return; |
| | | } |
| | | const count = checkedIds.value.length; |
| | | const hideLoading = message.loading({ |
| | | content: $t('ui.actionMessage.deleting', [`${checkedIds.value.length} å°`]), |
| | | content: $t('ui.actionMessage.deleting', [`${count} å°`]), |
| | | duration: 0, |
| | | }); |
| | | try { |
| | | await Promise.all(checkedIds.value.map((id) => deleteMachinery(id))); |
| | | message.success($t('ui.actionMessage.deleteSuccess', [''])); |
| | | checkedIds.value = []; |
| | | handleRefresh(); |
| | | await deleteMachineryList(checkedIds.value); |
| | | message.success($t('ui.actionMessage.deleteSuccess', [`${count} å°`])); |
| | | } finally { |
| | | hideLoading(); |
| | | handleDataChange(); |
| | | handleRefresh(); |
| | | } |
| | | } |
| | | |
| | |
| | | gridEvents: { |
| | | checkboxAll: handleRowCheckboxChange, |
| | | checkboxChange: handleRowCheckboxChange, |
| | | dataChange: handleDataChange, |
| | | }, |
| | | }); |
| | | </script> |
| | |
| | | auth: ['mes:dv-machinery:delete'], |
| | | disabled: checkedIds.length === 0, |
| | | popConfirm: { |
| | | disabled: checkedIds.length === 0, |
| | | title: $t('ui.actionMessage.deleteConfirm', [ |
| | | `${checkedIds.length} å°`, |
| | | ]), |
| | |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { MesQcStatusEnum } from '@vben/constants'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message } from 'ant-design-vue'; |
| | | |
| | |
| | | importIpqcTemplate, |
| | | } from '#/api/mes/qc/ipqc'; |
| | | import { $t } from '#/locales'; |
| | | import QcExportRangeModal from '#/views/mes/qc/components/export-range-modal.vue'; |
| | | import QcImportFormModal from '#/views/mes/qc/components/import-form-modal.vue'; |
| | | import QcReportGenerateModal from '#/views/mes/qc/components/report-generate-modal.vue'; |
| | | |
| | |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const [ExportRangeModal, exportRangeModalApi] = useVbenModal({ |
| | | connectedComponent: QcExportRangeModal, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** 导åºè¡¨æ ¼ï¼å¼¹çªéæ£éªæ¶é´èå´ï¼ */ |
| | | function handleExport() { |
| | | exportRangeModalApi |
| | | .setData({ |
| | | title: 'ææ£éªæ¶é´å¯¼åºè¿ç¨æ£éªå', |
| | | exportApi: exportIpqc, |
| | | fileName: 'è¿ç¨æ£éªå.xls', |
| | | }) |
| | | .open(); |
| | | /** 导åºè¡¨æ ¼ï¼æå表ç鿡件坼åºï¼ */ |
| | | async function handleExport() { |
| | | const data = await exportIpqc(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: 'è¿ç¨æ£éªå.xls', source: data }); |
| | | } |
| | | |
| | | /** åºæ¥åï¼æ°æ®ç±å端ä»è¯¥è´¨æ£ååï¼å端åªéæ¨¡æ¿ */ |
| | |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <ExportRangeModal /> |
| | | <ReportModal /> |
| | | <ImportModal @success="handleRefresh" /> |
| | | <Grid table-title="è¿ç¨æ£éªåå表"> |
| | |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { MesQcStatusEnum } from '@vben/constants'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message } from 'ant-design-vue'; |
| | | |
| | |
| | | importIqcTemplate, |
| | | } from '#/api/mes/qc/iqc'; |
| | | import { $t } from '#/locales'; |
| | | import QcExportRangeModal from '#/views/mes/qc/components/export-range-modal.vue'; |
| | | import QcImportFormModal from '#/views/mes/qc/components/import-form-modal.vue'; |
| | | import QcReportGenerateModal from '#/views/mes/qc/components/report-generate-modal.vue'; |
| | | |
| | |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const [ExportRangeModal, exportRangeModalApi] = useVbenModal({ |
| | | connectedComponent: QcExportRangeModal, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** 导åºè¡¨æ ¼ï¼å¼¹çªéæ£éªæ¶é´èå´ï¼ */ |
| | | function handleExport() { |
| | | exportRangeModalApi |
| | | .setData({ |
| | | title: 'ææ£éªæ¶é´å¯¼åºæ¥ææ£éªå', |
| | | exportApi: exportIqc, |
| | | fileName: 'æ¥ææ£éªå.xls', |
| | | }) |
| | | .open(); |
| | | /** 导åºè¡¨æ ¼ï¼æå表ç鿡件坼åºï¼ */ |
| | | async function handleExport() { |
| | | const data = await exportIqc(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: 'æ¥ææ£éªå.xls', source: data }); |
| | | } |
| | | |
| | | /** åºæ¥åï¼æ°æ®ç±å端ä»è¯¥è´¨æ£ååï¼å端åªéæ¨¡æ¿ */ |
| | |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <ExportRangeModal /> |
| | | <ReportModal /> |
| | | <ImportModal @success="handleRefresh" /> |
| | | <Grid table-title="æ¥ææ£éªåå表"> |
| | |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { MesQcStatusEnum } from '@vben/constants'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message } from 'ant-design-vue'; |
| | | |
| | |
| | | importOqcTemplate, |
| | | } from '#/api/mes/qc/oqc'; |
| | | import { $t } from '#/locales'; |
| | | import QcExportRangeModal from '#/views/mes/qc/components/export-range-modal.vue'; |
| | | import QcImportFormModal from '#/views/mes/qc/components/import-form-modal.vue'; |
| | | import QcReportGenerateModal from '#/views/mes/qc/components/report-generate-modal.vue'; |
| | | |
| | |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const [ExportRangeModal, exportRangeModalApi] = useVbenModal({ |
| | | connectedComponent: QcExportRangeModal, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** 导åºè¡¨æ ¼ï¼å¼¹çªéæ£éªæ¶é´èå´ï¼ */ |
| | | function handleExport() { |
| | | exportRangeModalApi |
| | | .setData({ |
| | | title: 'ææ£éªæ¶é´å¯¼åºè´§æ£éªå', |
| | | exportApi: exportOqc, |
| | | fileName: 'åºè´§æ£éªå.xls', |
| | | }) |
| | | .open(); |
| | | /** 导åºè¡¨æ ¼ï¼æå表ç鿡件坼åºï¼ */ |
| | | async function handleExport() { |
| | | const data = await exportOqc(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: 'åºè´§æ£éªå.xls', source: data }); |
| | | } |
| | | |
| | | /** åºæ¥åï¼æ°æ®ç±å端ä»è¯¥è´¨æ£ååï¼å端åªéæ¨¡æ¿ */ |
| | |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <ExportRangeModal /> |
| | | <ReportModal /> |
| | | <ImportModal @success="handleRefresh" /> |
| | | <Grid table-title="åºè´§æ£éªåå表"> |
| | |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { MesQcStatusEnum } from '@vben/constants'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { deleteRqc, exportRqc, getRqcPage } from '#/api/mes/qc/rqc'; |
| | | import { $t } from '#/locales'; |
| | | import QcExportRangeModal from '#/views/mes/qc/components/export-range-modal.vue'; |
| | | import QcReportGenerateModal from '#/views/mes/qc/components/report-generate-modal.vue'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const [ExportRangeModal, exportRangeModalApi] = useVbenModal({ |
| | | connectedComponent: QcExportRangeModal, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** 导åºè¡¨æ ¼ï¼å¼¹çªéæ£éªæ¶é´èå´ï¼ */ |
| | | function handleExport() { |
| | | exportRangeModalApi |
| | | .setData({ |
| | | title: 'ææ£éªæ¶é´å¯¼éè´§æ£éªå', |
| | | exportApi: exportRqc, |
| | | fileName: 'éè´§æ£éªå.xls', |
| | | }) |
| | | .open(); |
| | | /** 导åºè¡¨æ ¼ï¼æå表ç鿡件坼åºï¼ */ |
| | | async function handleExport() { |
| | | const data = await exportRqc(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: 'éè´§æ£éªå.xls', source: data }); |
| | | } |
| | | |
| | | /** åºæ¥åï¼æ°æ®ç±å端ä»è¯¥è´¨æ£ååï¼å端åªéæ¨¡æ¿ */ |
| | |
| | | <template> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <ExportRangeModal /> |
| | | <ReportModal /> |
| | | <Grid table-title="éè´§æ£éªåå表"> |
| | | <template #toolbar-tools> |
| | |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MdmItemModelApi } from '#/api/mdm/item-model'; |
| | | import type { MesMdItemApi } from '#/api/mes/md/item'; |
| | | import type { MesWmArrivalNoticeApi } from '#/api/mes/wm/arrivalnotice'; |
| | | import type { MesWmArrivalNoticeLineApi } from '#/api/mes/wm/arrivalnotice/line'; |
| | | import type { MesWmItemReceiptApi } from '#/api/mes/wm/itemreceipt'; |
| | | import type { MesWmItemReceiptDetailApi } from '#/api/mes/wm/itemreceipt/detail'; |
| | | import type { MesWmItemReceiptLineApi } from '#/api/mes/wm/itemreceipt/line'; |
| | | import type { SrmSupplierApi } from '#/api/srm/supplier'; |
| | | |
| | | import { h, markRaw } from 'vue'; |
| | | |
| | |
| | | |
| | | import { Button } from 'ant-design-vue'; |
| | | |
| | | import { getItem as getMdmItem } from '#/api/mdm/item'; |
| | | import { getItemModelListByItem } from '#/api/mdm/item-model'; |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { ErpSupplierSelect } from '#/views/erp/purchase/supplier/components'; |
| | | import { SrmSupplierSelect } from '#/views/srm/supplier/components'; |
| | | import { |
| | | WmArrivalNoticeLineSelect, |
| | | WmArrivalNoticeSelect, |
| | |
| | | { |
| | | fieldName: 'vendorId', |
| | | label: 'ä¾åºå', |
| | | component: markRaw(ErpSupplierSelect), |
| | | component: markRaw(SrmSupplierSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ä¾åºå', |
| | | onChange: async (supplier?: any) => { |
| | | onChange: async (supplier?: SrmSupplierApi.SupplierVO) => { |
| | | await formApi?.setFieldValue('vendorName', supplier?.name); |
| | | }, |
| | | }, |
| | |
| | | { |
| | | fieldName: 'vendorId', |
| | | label: 'ä¾åºå', |
| | | component: markRaw(ErpSupplierSelect), |
| | | component: markRaw(SrmSupplierSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ä¾åºå', |
| | | }, |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemModel', |
| | | title: 'ç©æåå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | title: 'åä½', |
| | | width: 80, |
| | | title: '主计éåä½', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'enterUnitMeasureName', |
| | | title: 'å½å
¥åä½', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'enterQuantity', |
| | | title: 'å½å
¥æ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'receivedQuantity', |
| | |
| | | ]; |
| | | } |
| | | |
| | | /** å½å
¥åä½é项ï¼å«å°ç©æä¸»åä½çæ¢ç®æ¯çï¼ */ |
| | | export interface ItemEnterUnitOption { |
| | | id: number; |
| | | name: string; |
| | | rate: number; |
| | | } |
| | | |
| | | /** åå·ä¸æé项ï¼ApiSelect 伿 id/model æ å°æ value/labelï¼å
¶ä½åæ®µåæ ·ä¿ç */ |
| | | type ItemModelSelectOption = Pick< |
| | | MdmItemModelApi.ItemModel, |
| | | 'unitMeasureId' | 'unitMeasureName' | 'unitMeasureRate' |
| | | >; |
| | | |
| | | /** å
¥åºåè¡è¡¨åä¸ä¸åå使¢ç®ç¸å
³çåæ®µ */ |
| | | interface LineUnitFormValues { |
| | | enterQuantity?: number; |
| | | enterUnitMeasureId?: number; |
| | | enterUnitMeasureName?: string; |
| | | enterUnitRate?: number; |
| | | itemId?: number; |
| | | itemModelId?: number; |
| | | itemPrimaryUnitId?: number; |
| | | itemPrimaryUnitName?: string; |
| | | } |
| | | |
| | | /** åå使¢ç®ç¨ç临æ¶è¡¨ååæ®µï¼åªä¾å端æ¢ç®ä¸å±ç¤ºï¼æäº¤åå¿
é¡»åé¤ï¼ */ |
| | | const LINE_TEMP_FIELDS = [ |
| | | 'itemPrimaryUnitId', |
| | | 'itemPrimaryUnitName', |
| | | 'enterUnitMeasureName', |
| | | 'enterUnitRate', |
| | | ] as const; |
| | | |
| | | /** åé¤åå使¢ç®ç¨ç临æ¶å段ï¼å¾å°å¯ç´æ¥æäº¤çè¡æ°æ® */ |
| | | export function omitLineTempFields( |
| | | values: Record<string, unknown>, |
| | | ): MesWmItemReceiptLineApi.ItemReceiptLine { |
| | | const data = { ...values }; |
| | | for (const field of LINE_TEMP_FIELDS) { |
| | | delete data[field]; |
| | | } |
| | | return data as MesWmItemReceiptLineApi.ItemReceiptLine; |
| | | } |
| | | |
| | | /** æ¢ç®æ¯çæ¯å¦ææï¼å¿
é¡»å¤§äº 0ï¼ */ |
| | | function isValidRate(rate?: number): rate is number { |
| | | return typeof rate === 'number' && rate > 0; |
| | | } |
| | | |
| | | /** æ¢ç®ç»ææ 6 ä½å°æ°å±ç¤ºï¼æç»ä»¥å端æ¢ç®ç»æä¸ºåï¼ */ |
| | | function roundQuantity(quantity: number): number { |
| | | return Math.round(quantity * 1e6) / 1e6; |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢ç©æå¯éçå½å
¥åä½ï¼ä¸»åä½ + è¾
åä½ |
| | | * |
| | | * éå®åå·æ¶åªä¿çãç©æä¸»åä½ãä¸ãåå·è®¡éåä½ã两ç§å£å¾ï¼ä¸å端æ¢ç®è§åä¿æä¸è´ |
| | | */ |
| | | export async function getItemEnterUnits(params: { |
| | | itemId?: number; |
| | | itemModelId?: number; |
| | | }): Promise<ItemEnterUnitOption[]> { |
| | | const itemId = params.itemId; |
| | | if (!itemId) { |
| | | return []; |
| | | } |
| | | const item = await getMdmItem(itemId); |
| | | if (!item?.unitMeasureId) { |
| | | return []; |
| | | } |
| | | // 主åä½å§ç»å¯éï¼æä¸»åä½å½å
¥æ¶ä¸åæ¢ç® |
| | | const primaryUnit: ItemEnterUnitOption = { |
| | | id: item.unitMeasureId, |
| | | name: item.unitMeasureName || 'ç©æä¸»åä½', |
| | | rate: 1, |
| | | }; |
| | | const unitOptions: ItemEnterUnitOption[] = [primaryUnit]; |
| | | const pushUnit = (id?: number, name?: string, rate?: number) => { |
| | | if ( |
| | | !id || |
| | | id === primaryUnit.id || |
| | | !isValidRate(rate) || |
| | | unitOptions.some((unit) => unit.id === id) |
| | | ) { |
| | | return; |
| | | } |
| | | unitOptions.push({ id, name: name || 'è¾
åä½', rate }); |
| | | }; |
| | | if (params.itemModelId) { |
| | | const models = await getItemModelListByItem(itemId); |
| | | const modelOption = models?.find((option) => option.id === params.itemModelId); |
| | | pushUnit( |
| | | modelOption?.unitMeasureId, |
| | | modelOption?.unitMeasureName, |
| | | modelOption?.unitMeasureRate, |
| | | ); |
| | | return unitOptions; |
| | | } |
| | | // æªéåå·æ¶ï¼ç©æä¸»æ°æ®ä¸é
ç½®äºæ¢ç®æ¯ççè¾
åä½å¯é |
| | | pushUnit(item.unitMeasureId2, item.unitMeasureName2, item.unitMeasureRate1); |
| | | pushUnit(item.unitMeasureId3, item.unitMeasureName3, item.unitMeasureRate2); |
| | | return unitOptions; |
| | | } |
| | | |
| | | /** æ¥è¯¢æä¸ªå½å
¥åä½å°ç©æä¸»åä½çæ¢ç®æ¯çï¼ç¼è¾åæ¾æ¶è¡¥é½å端æ¢ç®ä¸ä¸æï¼ */ |
| | | export async function getEnterUnitRate( |
| | | itemId?: number, |
| | | itemModelId?: number, |
| | | enterUnitMeasureId?: number, |
| | | ): Promise<number | undefined> { |
| | | if (!itemId || !enterUnitMeasureId) { |
| | | return undefined; |
| | | } |
| | | const unitOptions = await getItemEnterUnits({ itemId, itemModelId }); |
| | | return unitOptions.find((unit) => unit.id === enterUnitMeasureId)?.rate; |
| | | } |
| | | |
| | | /** å
¥åºåè¡æ°å¢/ä¿®æ¹ç表å */ |
| | | export function useLineFormSchema( |
| | | hasNotice: boolean, |
| | | formApi?: VbenFormApi, |
| | | ): VbenFormSchema[] { |
| | | /** æ¯å¦æç©æä¸»åä½å½å
¥ï¼æªéå½å
¥åä½ãæå½å
¥åä½å°±æ¯ç©æä¸»åä½ï¼ */ |
| | | function isPrimaryUnitEnter(values: LineUnitFormValues) { |
| | | return ( |
| | | !values.enterUnitMeasureId || |
| | | values.enterUnitMeasureId === values.itemPrimaryUnitId |
| | | ); |
| | | } |
| | | |
| | | /** åæ¢ç©æï¼éæ°è®°å½ç©æä¸»åä½ï¼å¹¶æ¸
空åå·ãå½å
¥åä½ä¸æ°éï¼å£å¾é½éç©æååï¼ */ |
| | | async function handleItemChange(itemId?: number) { |
| | | // å
æ¸
空ï¼é¿å
ä¸ä¸ä¸ªç©æçåå·ä¸åä½å£å¾æ®ç |
| | | await formApi?.setValues({ |
| | | itemId, |
| | | itemModelId: undefined, |
| | | itemPrimaryUnitId: undefined, |
| | | itemPrimaryUnitName: undefined, |
| | | enterUnitMeasureId: undefined, |
| | | enterUnitMeasureName: undefined, |
| | | enterUnitRate: undefined, |
| | | enterQuantity: undefined, |
| | | receivedQuantity: undefined, |
| | | }); |
| | | if (!itemId) { |
| | | return; |
| | | } |
| | | const item = await getMdmItem(itemId); |
| | | await formApi?.setValues({ |
| | | itemPrimaryUnitId: item?.unitMeasureId, |
| | | itemPrimaryUnitName: item?.unitMeasureName, |
| | | }); |
| | | } |
| | | |
| | | /** éæ©åå·ï¼é»è®¤æåå·è®¡éåä½å½å
¥ï¼å¹¶è®°å½æ¢ç®æ¯ç */ |
| | | async function handleModelChange( |
| | | option: ItemModelSelectOption | undefined, |
| | | values: LineUnitFormValues, |
| | | ) { |
| | | const enterUnitMeasureId = |
| | | option?.unitMeasureId && option.unitMeasureId !== values.itemPrimaryUnitId |
| | | ? option.unitMeasureId |
| | | : undefined; |
| | | await formApi?.setValues({ |
| | | enterUnitMeasureId, |
| | | enterUnitMeasureName: enterUnitMeasureId |
| | | ? option?.unitMeasureName |
| | | : undefined, |
| | | enterUnitRate: enterUnitMeasureId ? option?.unitMeasureRate : undefined, |
| | | enterQuantity: undefined, |
| | | // åå°åå·åä½å½å
¥åå
¥åºæ°éç±ç³»ç»æ¢ç®ï¼å
æ¸
æä¸ä¸æ¬¡å£å¾çæ°å¼ |
| | | ...(enterUnitMeasureId ? { receivedQuantity: undefined } : {}), |
| | | }); |
| | | } |
| | | |
| | | /** 忢å½å
¥åä½ï¼è®°å½æ¢ç®æ¯çå¹¶ç«å³éç®å
¥åºæ°éï¼æ¹å主å使¶æ¸
æå½å
¥æ°é */ |
| | | async function handleEnterUnitChange( |
| | | value: number | undefined, |
| | | option: { label?: string; rate?: number } | undefined, |
| | | values: LineUnitFormValues, |
| | | ) { |
| | | if (!value || value === values.itemPrimaryUnitId) { |
| | | await formApi?.setValues({ |
| | | enterUnitMeasureName: undefined, |
| | | enterUnitRate: undefined, |
| | | enterQuantity: undefined, |
| | | }); |
| | | return; |
| | | } |
| | | await formApi?.setValues({ |
| | | enterUnitMeasureName: option?.label, |
| | | enterUnitRate: option?.rate, |
| | | ...(values.enterQuantity == null || !isValidRate(option?.rate) |
| | | ? { receivedQuantity: undefined } |
| | | : { |
| | | receivedQuantity: roundQuantity(values.enterQuantity * option.rate), |
| | | }), |
| | | }); |
| | | } |
| | | |
| | | /** å½å
¥æ°éååï¼æå½å
¥åä½ä¸æ¢ç®æ¯çè¯ç®å
¥åºæ°éï¼ä¾ç¨æ·æ ¸å¯¹æ¢ç®ç»æ */ |
| | | async function handleEnterQuantityChange( |
| | | value: number | undefined, |
| | | values: LineUnitFormValues, |
| | | ) { |
| | | if (isPrimaryUnitEnter(values) || !isValidRate(values.enterUnitRate)) { |
| | | return; |
| | | } |
| | | await formApi?.setFieldValue( |
| | | 'receivedQuantity', |
| | | value == null ? undefined : roundQuantity(value * values.enterUnitRate), |
| | | ); |
| | | } |
| | | |
| | | return [ |
| | | { |
| | | fieldName: 'noticeId', |
| | |
| | | label: 'å°è´§éç¥åè¡', |
| | | component: markRaw(WmArrivalNoticeLineSelect), |
| | | componentProps: { |
| | | // éæ©å°è´§éç¥åè¡åï¼èªå¨åå¡«ç©æåå
¥åºæ°é |
| | | // éæ©å°è´§éç¥åè¡åï¼èªå¨åå¡«ç©æä¸å
¥åºæ°é |
| | | onChange: async ( |
| | | line?: MesWmArrivalNoticeLineApi.ArrivalNoticeLine, |
| | | ) => { |
| | | await formApi?.setValues({ |
| | | itemId: line?.itemId, |
| | | receivedQuantity: line?.arrivalQuantity, |
| | | }); |
| | | await handleItemChange(line?.itemId); |
| | | if (line?.arrivalQuantity != null) { |
| | | await formApi?.setFieldValue( |
| | | 'receivedQuantity', |
| | | line.arrivalQuantity, |
| | | ); |
| | | } |
| | | }, |
| | | }, |
| | | dependencies: { |
| | |
| | | component: markRaw(MdItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ç©æ', |
| | | // åæ¢ç©æåï¼åå·ãå½å
¥åä½ä¸æ°éé½è¦éæ°é |
| | | onChange: (item?: MesMdItemApi.Item) => handleItemChange(item?.id), |
| | | }, |
| | | rules: 'selectRequired', |
| | | dependencies: { |
| | |
| | | }), |
| | | }, |
| | | }, |
| | | // ç©æä¸»åä½éæéç©æååï¼ä½è¡¨å props åªè½éæå£°æï¼æ
ç¨éèåæ®µæ¿è½½ |
| | | { |
| | | fieldName: 'itemPrimaryUnitId', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'itemPrimaryUnitName', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'itemModelId', |
| | | label: 'ç©æåå·', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | labelField: 'model', |
| | | valueField: 'id', |
| | | allowClear: true, |
| | | api: (params: { itemId?: number }) => |
| | | getItemModelListByItem(params.itemId!), |
| | | shouldFetch: (params: { itemId?: number }) => !!params?.itemId, |
| | | placeholder: '请å
éæ©ç©æ', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['itemId'], |
| | | componentProps: (values) => ({ |
| | | disabled: !values.itemId, |
| | | params: { itemId: values.itemId }, |
| | | placeholder: values.itemId ? 'è¯·éæ©ç©æåå·' : '请å
éæ©ç©æ', |
| | | // éå®åå·åé»è®¤æå
¶è®¡éåä½å½å
¥ |
| | | onChange: (option?: ItemModelSelectOption) => |
| | | handleModelChange(option, values), |
| | | }), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'enterUnitMeasureId', |
| | | label: 'å½å
¥åä½', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | allowClear: true, |
| | | labelField: 'name', |
| | | valueField: 'id', |
| | | api: (params: { itemId?: number; itemModelId?: number }) => |
| | | getItemEnterUnits(params), |
| | | shouldFetch: (params: { itemId?: number }) => !!params?.itemId, |
| | | placeholder: 'é»è®¤ä¸ºç©æä¸»è®¡éåä½', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['itemId', 'itemModelId', 'itemPrimaryUnitName'], |
| | | componentProps: (values) => ({ |
| | | disabled: !values.itemId, |
| | | params: { itemId: values.itemId, itemModelId: values.itemModelId }, |
| | | placeholder: values.itemId |
| | | ? `é»è®¤æç©æä¸»åä½${values.itemPrimaryUnitName ? `ã${values.itemPrimaryUnitName}ã` : ''}å½å
¥` |
| | | : '请å
éæ©ç©æ', |
| | | onChange: ( |
| | | value: number | undefined, |
| | | option?: { label?: string; rate?: number }, |
| | | ) => handleEnterUnitChange(value, option, values), |
| | | }), |
| | | }, |
| | | }, |
| | | // å½å
¥åä½åç§°ä¸æ¢ç®æ¯çéæéåä½ååï¼åæ ·ç¨éèåæ®µæ¿è½½ |
| | | { |
| | | fieldName: 'enterUnitMeasureName', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'enterUnitRate', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'enterQuantity', |
| | | label: 'å½å
¥æ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | precision: 6, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: [ |
| | | 'enterUnitMeasureId', |
| | | 'enterUnitMeasureName', |
| | | 'itemPrimaryUnitId', |
| | | ], |
| | | show: (values) => !isPrimaryUnitEnter(values), |
| | | // è¿å null 表示ä¸è¿½å è§åï¼åéåºç¡ rulesï¼ |
| | | rules: (values) => (isPrimaryUnitEnter(values) ? null : 'required'), |
| | | componentProps: (values) => ({ |
| | | placeholder: values.enterUnitMeasureName |
| | | ? `请填åæã${values.enterUnitMeasureName}ãè®¡çæ°é` |
| | | : '请æå½å
¥åä½å¡«åæ°é', |
| | | // å½å
¥æ°éååæ¶ç«å³è¯ç®å
¥åºæ°é |
| | | onChange: (value: number | undefined) => |
| | | handleEnterQuantityChange(value, values), |
| | | }), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'receivedQuantity', |
| | | label: 'å
¥åºæ°é', |
| | |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥å
¥åºæ°é', |
| | | precision: 2, |
| | | precision: 6, |
| | | }, |
| | | rules: 'required', |
| | | dependencies: { |
| | | triggerFields: [ |
| | | 'enterUnitMeasureId', |
| | | 'itemPrimaryUnitId', |
| | | 'itemPrimaryUnitName', |
| | | ], |
| | | // æä¸»åä½å½å
¥æ¶æå·¥å¡«åãå¿
å¡«ï¼æè¾
åä½å½å
¥æ¶ä¸ºç³»ç»æ¢ç®ç»æï¼æ éæ ¡éª |
| | | rules: (values) => (isPrimaryUnitEnter(values) ? 'required' : null), |
| | | componentProps: (values) => { |
| | | const primary = isPrimaryUnitEnter(values); |
| | | return { |
| | | disabled: !primary, |
| | | placeholder: primary |
| | | ? `请æç©æä¸»åä½${values.itemPrimaryUnitName ? `ã${values.itemPrimaryUnitName}ã` : ''}å¡«åæ°é` |
| | | : 'æå½å
¥åä½ä¸æ¢ç®æ¯çèªå¨æ¢ç®', |
| | | }; |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'productionDate', |
| | |
| | | } from '#/api/mes/wm/itemreceipt/line'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useLineFormSchema } from '../data'; |
| | | import { |
| | | getEnterUnitRate, |
| | | omitLineTempFields, |
| | | useLineFormSchema, |
| | | } from '../data'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref<MesWmItemReceiptLineApi.ItemReceiptLine>(); |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = |
| | | (await formApi.getValues()) as MesWmItemReceiptLineApi.ItemReceiptLine; |
| | | // æäº¤è¡¨åï¼åé¤ä»
ç¨äºå端æ¢ç®/å±ç¤ºç临æ¶åæ®µï¼ |
| | | const data = omitLineTempFields(await formApi.getValues()); |
| | | data.receiptId = receiptId.value; |
| | | try { |
| | | await (formData.value?.id |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getItemReceiptLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues({ ...formData.value, noticeId: noticeId.value }); |
| | | const line = await getItemReceiptLine(data.id); |
| | | formData.value = line; |
| | | // è®¾ç½®å° valuesï¼è¯¦æ
éç unitMeasureId/unitMeasureName å³ç©æä¸»åä½ï¼è¡¥å°å端æ¢ç®ç¨çéèåæ®µä¸ |
| | | await formApi.setValues({ |
| | | ...line, |
| | | noticeId: noticeId.value, |
| | | itemPrimaryUnitId: line.unitMeasureId, |
| | | itemPrimaryUnitName: line.unitMeasureName, |
| | | }); |
| | | // åæ¾å½å
¥å使¶è¡¥é½æ¢ç®æ¯çï¼å端é¢è§æ¢ç®éè¦ï¼ |
| | | if (line.enterUnitMeasureId) { |
| | | await formApi.setFieldValue( |
| | | 'enterUnitRate', |
| | | await getEnterUnitRate( |
| | | line.itemId, |
| | | line.itemModelId, |
| | | line.enterUnitMeasureId, |
| | | ), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | |
| | | import { generateAutoCode } from '#/api/mes/md/autocode/record'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | | import { |
| | | useLineUnitHandlers, |
| | | buildItemUnitSchema, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | import { WmMaterialStockSelect } from '#/views/wls/materialstock/components'; |
| | | import { |
| | | WmWarehouseAreaSelect, |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemModel', |
| | | title: 'ç©æåå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | title: 'åä½', |
| | | width: 80, |
| | | title: '主计éåä½', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'enterUnitMeasureName', |
| | | title: 'å½å
¥åä½', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'enterQuantity', |
| | | title: 'å½å
¥æ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'quantity', |
| | |
| | | |
| | | /** åºåºåè¡æ°å¢/ä¿®æ¹ç表å */ |
| | | export function useLineFormSchema(formApi?: VbenFormApi): VbenFormSchema[] { |
| | | const unitHandlers = useLineUnitHandlers(formApi); |
| | | return [ |
| | | { |
| | | fieldName: 'itemId', |
| | |
| | | componentProps: { |
| | | // éæ©åºåç©èµåï¼èªå¨åå¡«ç©æãæ¹æ¬¡å·ãä»åºä½ç½®åæå¤§å¯åºåºæ°é |
| | | onChange: async (stock?: MesWmMaterialStockApi.MaterialStock) => { |
| | | // 忢åºåç©èµçäºåæ¢ç©æï¼å
æ¸
æä¸ä¸ä»½åå·ä¸å½å
¥åä½å£å¾ |
| | | await unitHandlers.handleItemChange(stock?.itemId); |
| | | await formApi?.setValues({ |
| | | areaId: stock?.areaId, |
| | | batchCode: stock?.batchCode, |
| | | itemId: stock?.itemId, |
| | | locationId: stock?.locationId, |
| | | quantityMax: stock?.quantity, |
| | | warehouseId: stock?.warehouseId, |
| | |
| | | }), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: 'åºåºæ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0.01, |
| | | placeholder: '请è¾å
¥åºåºæ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | dependencies: { |
| | | triggerFields: ['quantityMax'], |
| | | componentProps: (values) => ({ |
| | | class: '!w-full', |
| | | max: values.quantityMax, |
| | | min: 0.01, |
| | | placeholder: '请è¾å
¥åºåºæ°é', |
| | | precision: 2, |
| | | }), |
| | | }, |
| | | }, |
| | | // ç©æåå· / å½å
¥åä½ / å½å
¥æ°é / åºåºæ°éï¼ä¸»åä½å£å¾ï¼ |
| | | ...buildItemUnitSchema(formApi), |
| | | { |
| | | fieldName: 'batchCode', |
| | | label: 'æ¹æ¬¡å·', |
| | |
| | | updateMiscIssueLine, |
| | | } from '#/api/mes/wm/miscissue/line'; |
| | | import { $t } from '#/locales'; |
| | | import { |
| | | getEnterUnitRate, |
| | | omitLineTempFields, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | |
| | | import { useLineFormSchema } from '../data'; |
| | | |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = |
| | | (await formApi.getValues()) as MesWmMiscIssueLineApi.MiscIssueLine; |
| | | // æäº¤è¡¨åï¼åé¤ä»
ç¨äºå端æ¢ç®/å±ç¤ºç临æ¶åæ®µï¼ |
| | | const data = omitLineTempFields( |
| | | (await formApi.getValues()) as MesWmMiscIssueLineApi.MiscIssueLine, |
| | | ); |
| | | data.issueId = issueId.value; |
| | | try { |
| | | await (formData.value?.id |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getMiscIssueLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues(formData.value); |
| | | const line = await getMiscIssueLine(data.id); |
| | | formData.value = line; |
| | | // è®¾ç½®å° valuesï¼è¯¦æ
éç unitMeasureId/unitMeasureName å³ç©æä¸»åä½ï¼è¡¥å°å端æ¢ç®ç¨çéèåæ®µä¸ |
| | | await formApi.setValues({ |
| | | ...line, |
| | | itemPrimaryUnitId: line.unitMeasureId, |
| | | itemPrimaryUnitName: line.unitMeasureName, |
| | | }); |
| | | // åæ¾å½å
¥å使¶è¡¥é½æ¢ç®æ¯çï¼å端é¢è§æ¢ç®éè¦ï¼ |
| | | if (line.enterUnitMeasureId) { |
| | | await formApi.setFieldValue( |
| | | 'enterUnitRate', |
| | | await getEnterUnitRate( |
| | | line.itemId, |
| | | line.itemModelId, |
| | | line.enterUnitMeasureId, |
| | | ), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesMdItemApi } from '#/api/mes/md/item'; |
| | | import type { MesProWorkOrderApi } from '#/api/mes/pro/workorder'; |
| | | import type { MesWmMaterialStockApi } from '#/api/mes/wm/materialstock'; |
| | | import type { MesWmOutsourceIssueApi } from '#/api/mes/wm/outsourceissue'; |
| | |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { MdVendorSelect } from '#/views/mes/md/vendor/components'; |
| | | import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components'; |
| | | import { |
| | | buildItemUnitSchema, |
| | | useLineUnitHandlers, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | import { WmMaterialStockSelect } from '#/views/wls/materialstock/components'; |
| | | import { |
| | | WmWarehouseAreaSelect, |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemModel', |
| | | title: 'ç©æåå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | title: 'åä½', |
| | | width: 80, |
| | | title: '主计éåä½', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'enterUnitMeasureName', |
| | | title: 'å½å
¥åä½', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'enterQuantity', |
| | | title: 'å½å
¥æ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'quantity', |
| | | title: '颿æ°é', |
| | | title: 'åææ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | |
| | | } |
| | | |
| | | /** åæåè¡æ°å¢/ä¿®æ¹ç表å */ |
| | | export function useLineFormSchema(): VbenFormSchema[] { |
| | | export function useLineFormSchema(formApi?: VbenFormApi): VbenFormSchema[] { |
| | | const unitHandlers = useLineUnitHandlers(formApi); |
| | | return [ |
| | | { |
| | | fieldName: 'itemId', |
| | |
| | | component: markRaw(MdItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ç©æ', |
| | | // åæ¢ç©æåï¼éæ°è®°å½ç©æä¸»åä½å¹¶æ¸
空åå·ãå½å
¥åä½å£å¾ |
| | | onChange: async (item?: MesMdItemApi.Item) => { |
| | | await unitHandlers.handleItemChange(item?.id); |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: 'åææ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥åææ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | // ç©æåå· / å½å
¥åä½ / å½å
¥æ°é / åææ°éï¼ç©æä¸»åä½å£å¾ï¼ |
| | | ...buildItemUnitSchema(formApi, { quantityLabel: 'åææ°é' }), |
| | | { |
| | | fieldName: 'batchCode', |
| | | label: 'æ¹æ¬¡å·', |
| | |
| | | updateOutsourceIssueLine, |
| | | } from '#/api/mes/wm/outsourceissue/line'; |
| | | import { $t } from '#/locales'; |
| | | import { |
| | | getEnterUnitRate, |
| | | omitLineTempFields, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | |
| | | import { useLineFormSchema } from '../data'; |
| | | |
| | |
| | | labelWidth: 90, |
| | | }, |
| | | layout: 'horizontal', |
| | | schema: useLineFormSchema(), |
| | | schema: [], |
| | | showDefaultActions: false, |
| | | wrapperClass: 'grid-cols-3', |
| | | }); |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = |
| | | (await formApi.getValues()) as MesWmOutsourceIssueLineApi.OutsourceIssueLine; |
| | | // æäº¤è¡¨åï¼åé¤ä»
ç¨äºå端æ¢ç®/å±ç¤ºç临æ¶åæ®µï¼ |
| | | const data = omitLineTempFields( |
| | | (await formApi.getValues()) as MesWmOutsourceIssueLineApi.OutsourceIssueLine, |
| | | ); |
| | | data.issueId = issueId.value; |
| | | try { |
| | | await (formData.value?.id |
| | |
| | | formData.value = undefined; |
| | | return; |
| | | } |
| | | formApi.setState({ schema: useLineFormSchema(formApi) }); |
| | | // å è½½æ°æ® |
| | | const data = modalApi.getData<{ |
| | | id?: number; |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getOutsourceIssueLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues(formData.value); |
| | | const line = await getOutsourceIssueLine(data.id); |
| | | formData.value = line; |
| | | // è®¾ç½®å° valuesï¼è¯¦æ
éç unitMeasureId/unitMeasureName å³ç©æä¸»åä½ï¼è¡¥å°å端æ¢ç®ç¨çéèåæ®µä¸ |
| | | await formApi.setValues({ |
| | | ...line, |
| | | itemPrimaryUnitId: line.unitMeasureId, |
| | | itemPrimaryUnitName: line.unitMeasureName, |
| | | }); |
| | | // åæ¾å½å
¥å使¶è¡¥é½æ¢ç®æ¯çï¼å端é¢è§æ¢ç®éè¦ï¼ |
| | | if (line.enterUnitMeasureId) { |
| | | await formApi.setFieldValue( |
| | | 'enterUnitRate', |
| | | await getEnterUnitRate( |
| | | line.itemId, |
| | | line.itemModelId, |
| | | line.enterUnitMeasureId, |
| | | ), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesMdItemApi } from '#/api/mes/md/item'; |
| | | import type { MesProTaskApi } from '#/api/mes/pro/task'; |
| | | import type { MesWmMaterialStockApi } from '#/api/mes/wm/materialstock'; |
| | | import type { MesWmProductIssueApi } from '#/api/mes/wm/productissue'; |
| | |
| | | import { ProTaskSelect } from '#/views/mes/pro/task/components'; |
| | | import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components'; |
| | | import { WmMaterialStockSelect } from '#/views/wls/materialstock/components'; |
| | | import { |
| | | buildItemUnitSchema, |
| | | useLineUnitHandlers, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | import { |
| | | WmWarehouseAreaSelect, |
| | | WmWarehouseLocationSelect, |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemModel', |
| | | title: 'ç©æåå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | title: 'åä½', |
| | | width: 80, |
| | | title: '主计éåä½', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'enterUnitMeasureName', |
| | | title: 'å½å
¥åä½', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'enterQuantity', |
| | | title: 'å½å
¥æ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'quantity', |
| | |
| | | } |
| | | |
| | | /** 颿åè¡æ°å¢/ä¿®æ¹ç表å */ |
| | | export function useLineFormSchema(): VbenFormSchema[] { |
| | | export function useLineFormSchema(formApi?: VbenFormApi): VbenFormSchema[] { |
| | | const unitHandlers = useLineUnitHandlers(formApi); |
| | | return [ |
| | | { |
| | | fieldName: 'itemId', |
| | |
| | | component: markRaw(MdItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | // åæ¢ç©æåï¼éæ°è®°å½ç©æä¸»åä½å¹¶æ¸
空åå·ãå½å
¥åä½å£å¾ |
| | | onChange: async (item?: MesMdItemApi.Item) => { |
| | | await unitHandlers.handleItemChange(item?.id); |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: '颿æ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥é¢ææ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | // ç©æåå· / å½å
¥åä½ / å½å
¥æ°é / 颿æ°éï¼ç©æä¸»åä½å£å¾ï¼ |
| | | ...buildItemUnitSchema(formApi, { quantityLabel: '颿æ°é' }), |
| | | { |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | |
| | | updateProductIssueLine, |
| | | } from '#/api/mes/wm/productissue/line'; |
| | | import { $t } from '#/locales'; |
| | | import { |
| | | getEnterUnitRate, |
| | | omitLineTempFields, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | |
| | | import { useLineFormSchema } from '../data'; |
| | | |
| | |
| | | labelWidth: 90, |
| | | }, |
| | | layout: 'horizontal', |
| | | schema: useLineFormSchema(), |
| | | schema: [], |
| | | showDefaultActions: false, |
| | | wrapperClass: 'grid-cols-3', |
| | | }); |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = |
| | | (await formApi.getValues()) as MesWmProductIssueLineApi.ProductIssueLine; |
| | | // æäº¤è¡¨åï¼åé¤ä»
ç¨äºå端æ¢ç®/å±ç¤ºç临æ¶åæ®µï¼ |
| | | const data = omitLineTempFields( |
| | | (await formApi.getValues()) as MesWmProductIssueLineApi.ProductIssueLine, |
| | | ); |
| | | data.issueId = issueId.value; |
| | | try { |
| | | await (formData.value?.id |
| | |
| | | formData.value = undefined; |
| | | return; |
| | | } |
| | | formApi.setState({ schema: useLineFormSchema(formApi) }); |
| | | // å è½½æ°æ® |
| | | const data = modalApi.getData<{ id?: number; issueId: number }>(); |
| | | issueId.value = data.issueId; |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getProductIssueLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues(formData.value); |
| | | const line = await getProductIssueLine(data.id); |
| | | formData.value = line; |
| | | // è®¾ç½®å° valuesï¼è¯¦æ
éç unitMeasureId/unitMeasureName å³ç©æä¸»åä½ï¼è¡¥å°å端æ¢ç®ç¨çéèåæ®µä¸ |
| | | await formApi.setValues({ |
| | | ...line, |
| | | itemPrimaryUnitId: line.unitMeasureId, |
| | | itemPrimaryUnitName: line.unitMeasureName, |
| | | }); |
| | | // åæ¾å½å
¥å使¶è¡¥é½æ¢ç®æ¯çï¼å端é¢è§æ¢ç®éè¦ï¼ |
| | | if (line.enterUnitMeasureId) { |
| | | await formApi.setFieldValue( |
| | | 'enterUnitRate', |
| | | await getEnterUnitRate( |
| | | line.itemId, |
| | | line.itemModelId, |
| | | line.enterUnitMeasureId, |
| | | ), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesMdItemApi } from '#/api/mes/md/item'; |
| | | import type { MesWmMaterialStockApi } from '#/api/mes/wm/materialstock'; |
| | | import type { MesWmProductSalesApi } from '#/api/mes/wm/productsales'; |
| | | import type { MesWmProductSalesDetailApi } from '#/api/mes/wm/productsales/detail'; |
| | |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | | import { MdItemSelect } from '#/views/mes/md/item/components'; |
| | | import { WmMaterialStockSelect } from '#/views/wls/materialstock/components'; |
| | | import { |
| | | buildItemUnitSchema, |
| | | useLineUnitHandlers, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | import { |
| | | WmSalesNoticeLineSelect, |
| | | WmSalesNoticeSelect, |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemModel', |
| | | title: 'ç©æåå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | title: 'åä½', |
| | | width: 80, |
| | | title: '主计éåä½', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'enterUnitMeasureName', |
| | | title: 'å½å
¥åä½', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'enterQuantity', |
| | | title: 'å½å
¥æ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'quantity', |
| | |
| | | hasNotice: boolean, |
| | | formApi?: VbenFormApi, |
| | | ): VbenFormSchema[] { |
| | | const unitHandlers = useLineUnitHandlers(formApi); |
| | | return [ |
| | | { |
| | | fieldName: 'noticeId', |
| | |
| | | componentProps: { |
| | | // éæ©åè´§éç¥åè¡åï¼èªå¨åå¡«ç©æãæ°éãæ¹æ¬¡ãæ¯å¦æ£éª |
| | | onChange: async (line?: MesWmSalesNoticeLineApi.SalesNoticeLine) => { |
| | | // 忢éç¥è¡çäºåæ¢äº§åï¼å
éç½®åå·ä¸åä½å£å¾ï¼ä¼æ¸
空æ°éï¼ï¼åæéç¥è¡åå¡« |
| | | await unitHandlers.handleItemChange(line?.itemId); |
| | | await formApi?.setValues({ |
| | | batchCode: line?.batchCode, |
| | | itemId: line?.itemId, |
| | |
| | | component: markRaw(MdItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§å', |
| | | // åæ¢äº§ååï¼éæ°è®°å½ç©æä¸»åä½å¹¶æ¸
空åå·ãå½å
¥åä½å£å¾ |
| | | onChange: async (item?: MesMdItemApi.Item) => { |
| | | await unitHandlers.handleItemChange(item?.id); |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | | dependencies: { |
| | |
| | | }), |
| | | }, |
| | | }, |
| | | // ç©æåå· / å½å
¥åä½ / å½å
¥æ°é / åºåºæ°éï¼ç©æä¸»åä½å£å¾ï¼ |
| | | ...buildItemUnitSchema(formApi), |
| | | { |
| | | fieldName: 'batchCode', |
| | | label: 'æ¹æ¬¡å·', |
| | |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥æ¹æ¬¡å·', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: 'åºåºæ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥åºåºæ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'oqcCheckFlag', |
| | |
| | | updateProductSalesLine, |
| | | } from '#/api/mes/wm/productsales/line'; |
| | | import { $t } from '#/locales'; |
| | | import { |
| | | getEnterUnitRate, |
| | | omitLineTempFields, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | |
| | | import { useLineFormSchema } from '../data'; |
| | | |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = |
| | | (await formApi.getValues()) as MesWmProductSalesLineApi.ProductSalesLine; |
| | | // æäº¤è¡¨åï¼åé¤ä»
ç¨äºå端æ¢ç®/å±ç¤ºç临æ¶åæ®µï¼ |
| | | const data = omitLineTempFields( |
| | | (await formApi.getValues()) as MesWmProductSalesLineApi.ProductSalesLine, |
| | | ); |
| | | data.salesId = salesId.value; |
| | | try { |
| | | await (formData.value?.id |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getProductSalesLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues({ ...formData.value, noticeId: noticeId.value }); |
| | | const line = await getProductSalesLine(data.id); |
| | | formData.value = line; |
| | | // è®¾ç½®å° valuesï¼è¯¦æ
éç unitMeasureId/unitMeasureName å³ç©æä¸»åä½ï¼è¡¥å°å端æ¢ç®ç¨çéèåæ®µä¸ |
| | | await formApi.setValues({ |
| | | ...line, |
| | | noticeId: noticeId.value, |
| | | itemPrimaryUnitId: line.unitMeasureId, |
| | | itemPrimaryUnitName: line.unitMeasureName, |
| | | }); |
| | | // åæ¾å½å
¥å使¶è¡¥é½æ¢ç®æ¯çï¼å端é¢è§æ¢ç®éè¦ï¼ |
| | | if (line.enterUnitMeasureId) { |
| | | await formApi.setFieldValue( |
| | | 'enterUnitRate', |
| | | await getEnterUnitRate( |
| | | line.itemId, |
| | | line.itemModelId, |
| | | line.enterUnitMeasureId, |
| | | ), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { MesMdItemApi } from '#/api/mes/md/item'; |
| | | import type { MesWmMaterialStockApi } from '#/api/mes/wm/materialstock'; |
| | | import type { MesWmReturnVendorApi } from '#/api/mes/wm/returnvendor'; |
| | | import type { MesWmReturnVendorDetailApi } from '#/api/mes/wm/returnvendor/detail'; |
| | |
| | | import { ErpPurchaseOrderSelect } from '#/views/erp/purchase/order/components'; |
| | | import { WmBatchSelect } from '#/views/wls/batch/components'; |
| | | import { WmMaterialStockSelect } from '#/views/wls/materialstock/components'; |
| | | import { |
| | | buildItemUnitSchema, |
| | | useLineUnitHandlers, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | import { |
| | | WmWarehouseAreaSelect, |
| | | WmWarehouseLocationSelect, |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'itemModel', |
| | | title: 'ç©æåå·', |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'unitMeasureName', |
| | | title: 'åä½', |
| | | width: 80, |
| | | title: '主计éåä½', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'enterUnitMeasureName', |
| | | title: 'å½å
¥åä½', |
| | | width: 90, |
| | | }, |
| | | { |
| | | field: 'enterQuantity', |
| | | title: 'å½å
¥æ°é', |
| | | width: 100, |
| | | }, |
| | | { |
| | | field: 'quantity', |
| | |
| | | vendorId?: number, |
| | | formApi?: VbenFormApi, |
| | | ): VbenFormSchema[] { |
| | | const unitHandlers = useLineUnitHandlers(formApi); |
| | | return [ |
| | | { |
| | | fieldName: 'itemId', |
| | |
| | | component: markRaw(MdItemSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©äº§åç©æ', |
| | | // åæ¢äº§ååï¼éæ°è®°å½ç©æä¸»åä½å¹¶æ¸
空åå·ãå½å
¥åä½å£å¾ |
| | | onChange: async (item?: MesMdItemApi.Item) => { |
| | | await unitHandlers.handleItemChange(item?.id); |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | fieldName: 'quantity', |
| | | label: 'éè´§æ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | placeholder: '请è¾å
¥éè´§æ°é', |
| | | precision: 2, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | // ç©æåå· / å½å
¥åä½ / å½å
¥æ°é / éè´§æ°éï¼ç©æä¸»åä½å£å¾ï¼ |
| | | ...buildItemUnitSchema(formApi, { quantityLabel: 'éè´§æ°é' }), |
| | | { |
| | | fieldName: 'batchId', |
| | | label: 'æ¹æ¬¡å·', |
| | |
| | | updateReturnVendorLine, |
| | | } from '#/api/mes/wm/returnvendor/line'; |
| | | import { $t } from '#/locales'; |
| | | import { |
| | | getEnterUnitRate, |
| | | omitLineTempFields, |
| | | } from '#/views/wls/utils/item-unit-convert'; |
| | | |
| | | import { useLineFormSchema } from '../data'; |
| | | |
| | |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | // æäº¤è¡¨å |
| | | const data = |
| | | (await formApi.getValues()) as MesWmReturnVendorLineApi.ReturnVendorLine; |
| | | // æäº¤è¡¨åï¼åé¤ä»
ç¨äºå端æ¢ç®/å±ç¤ºç临æ¶åæ®µï¼ |
| | | const data = omitLineTempFields( |
| | | (await formApi.getValues()) as MesWmReturnVendorLineApi.ReturnVendorLine, |
| | | ); |
| | | data.returnId = returnId.value; |
| | | try { |
| | | await (formData.value?.id |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getReturnVendorLine(data.id); |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues(formData.value); |
| | | const line = await getReturnVendorLine(data.id); |
| | | formData.value = line; |
| | | // è®¾ç½®å° valuesï¼è¯¦æ
éç unitMeasureId/unitMeasureName å³ç©æä¸»åä½ï¼è¡¥å°å端æ¢ç®ç¨çéèåæ®µä¸ |
| | | await formApi.setValues({ |
| | | ...line, |
| | | itemPrimaryUnitId: line.unitMeasureId, |
| | | itemPrimaryUnitName: line.unitMeasureName, |
| | | }); |
| | | // åæ¾å½å
¥å使¶è¡¥é½æ¢ç®æ¯çï¼å端é¢è§æ¢ç®éè¦ï¼ |
| | | if (line.enterUnitMeasureId) { |
| | | await formApi.setFieldValue( |
| | | 'enterUnitRate', |
| | | await getEnterUnitRate( |
| | | line.itemId, |
| | | line.itemModelId, |
| | | line.enterUnitMeasureId, |
| | | ), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; |
| | | import type { MdmItemModelApi } from '#/api/mdm/item-model'; |
| | | |
| | | import { getItem as getMdmItem } from '#/api/mdm/item'; |
| | | import { getItemModelListByItem } from '#/api/mdm/item-model'; |
| | | |
| | | /** å½å
¥åä½é项ï¼å«å°ç©æä¸»åä½çæ¢ç®æ¯çï¼ */ |
| | | export interface ItemEnterUnitOption { |
| | | id: number; |
| | | name: string; |
| | | rate: number; |
| | | } |
| | | |
| | | /** åå·ä¸æé项ï¼ApiSelect 伿 id/model æ å°æ value/labelï¼å
¶ä½åæ®µåæ ·ä¿ç */ |
| | | export type ItemModelSelectOption = Pick< |
| | | MdmItemModelApi.ItemModel, |
| | | 'unitMeasureId' | 'unitMeasureName' | 'unitMeasureRate' |
| | | >; |
| | | |
| | | /** åºåº/å
¥åºåè¡è¡¨åä¸ä¸åå使¢ç®ç¸å
³çåæ®µ */ |
| | | export interface LineUnitFormValues { |
| | | enterQuantity?: number; |
| | | enterUnitMeasureId?: number; |
| | | enterUnitMeasureName?: string; |
| | | enterUnitRate?: number; |
| | | itemId?: number; |
| | | itemModelId?: number; |
| | | itemPrimaryUnitId?: number; |
| | | itemPrimaryUnitName?: string; |
| | | quantityMax?: number; |
| | | } |
| | | |
| | | /** åå使¢ç®ç¨ç临æ¶è¡¨ååæ®µï¼åªä¾å端æ¢ç®ä¸å±ç¤ºï¼æäº¤åå¿
é¡»åé¤ï¼ */ |
| | | const LINE_TEMP_FIELDS = [ |
| | | 'itemPrimaryUnitId', |
| | | 'itemPrimaryUnitName', |
| | | 'enterUnitMeasureName', |
| | | 'enterUnitRate', |
| | | ] as const; |
| | | |
| | | /** åé¤åå使¢ç®ç¨ç临æ¶å段ï¼å¾å°å¯ç´æ¥æäº¤çè¡æ°æ® */ |
| | | export function omitLineTempFields<T extends object>(values: T): T { |
| | | const data = { ...values } as Record<string, unknown>; |
| | | for (const field of LINE_TEMP_FIELDS) { |
| | | delete data[field]; |
| | | } |
| | | return data as T; |
| | | } |
| | | |
| | | /** æ¢ç®æ¯çæ¯å¦ææï¼å¿
é¡»å¤§äº 0ï¼ */ |
| | | function isValidRate(rate?: number): rate is number { |
| | | return typeof rate === 'number' && rate > 0; |
| | | } |
| | | |
| | | /** æ¢ç®ç»ææ 6 ä½å°æ°å±ç¤ºï¼æç»ä»¥å端æ¢ç®ç»æä¸ºåï¼ */ |
| | | function roundQuantity(quantity: number): number { |
| | | return Math.round(quantity * 1e6) / 1e6; |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢ç©æå¯éçå½å
¥åä½ï¼ä¸»åä½ + è¾
åä½ |
| | | * |
| | | * éå®åå·æ¶åªä¿çãç©æä¸»åä½ãä¸ãåå·è®¡éåä½ã两ç§å£å¾ï¼ä¸å端æ¢ç®è§åä¿æä¸è´ |
| | | */ |
| | | export async function getItemEnterUnits(params: { |
| | | itemId?: number; |
| | | itemModelId?: number; |
| | | }): Promise<ItemEnterUnitOption[]> { |
| | | const itemId = params.itemId; |
| | | if (!itemId) { |
| | | return []; |
| | | } |
| | | const item = await getMdmItem(itemId); |
| | | if (!item?.unitMeasureId) { |
| | | return []; |
| | | } |
| | | // 主åä½å§ç»å¯éï¼æä¸»åä½å½å
¥æ¶ä¸åæ¢ç® |
| | | const primaryUnit: ItemEnterUnitOption = { |
| | | id: item.unitMeasureId, |
| | | name: item.unitMeasureName || 'ç©æä¸»åä½', |
| | | rate: 1, |
| | | }; |
| | | const unitOptions: ItemEnterUnitOption[] = [primaryUnit]; |
| | | const pushUnit = (id?: number, name?: string, rate?: number) => { |
| | | if ( |
| | | !id || |
| | | id === primaryUnit.id || |
| | | !isValidRate(rate) || |
| | | unitOptions.some((unit) => unit.id === id) |
| | | ) { |
| | | return; |
| | | } |
| | | unitOptions.push({ id, name: name || 'è¾
åä½', rate }); |
| | | }; |
| | | if (params.itemModelId) { |
| | | const models = await getItemModelListByItem(itemId); |
| | | const modelOption = models?.find( |
| | | (option) => option.id === params.itemModelId, |
| | | ); |
| | | pushUnit( |
| | | modelOption?.unitMeasureId, |
| | | modelOption?.unitMeasureName, |
| | | modelOption?.unitMeasureRate, |
| | | ); |
| | | return unitOptions; |
| | | } |
| | | // æªéåå·æ¶ï¼ç©æä¸»æ°æ®ä¸é
ç½®äºæ¢ç®æ¯ççè¾
åä½å¯é |
| | | pushUnit(item.unitMeasureId2, item.unitMeasureName2, item.unitMeasureRate1); |
| | | pushUnit(item.unitMeasureId3, item.unitMeasureName3, item.unitMeasureRate2); |
| | | return unitOptions; |
| | | } |
| | | |
| | | /** æ¥è¯¢æä¸ªå½å
¥åä½å°ç©æä¸»åä½çæ¢ç®æ¯çï¼ç¼è¾åæ¾æ¶è¡¥é½å端æ¢ç®ä¸ä¸æï¼ */ |
| | | export async function getEnterUnitRate( |
| | | itemId?: number, |
| | | itemModelId?: number, |
| | | enterUnitMeasureId?: number, |
| | | ): Promise<number | undefined> { |
| | | if (!itemId || !enterUnitMeasureId) { |
| | | return undefined; |
| | | } |
| | | const unitOptions = await getItemEnterUnits({ itemId, itemModelId }); |
| | | return unitOptions.find((unit) => unit.id === enterUnitMeasureId)?.rate; |
| | | } |
| | | |
| | | /** è¡è¡¨åååä½å½å
¥çè卿¹æ³ */ |
| | | export interface LineUnitHandlers { |
| | | /** æ¯å¦æç©æä¸»åä½å½å
¥ï¼æªéå½å
¥åä½ãæå½å
¥åä½å°±æ¯ç©æä¸»åä½ï¼ */ |
| | | isPrimaryUnitEnter: (values: LineUnitFormValues) => boolean; |
| | | /** åæ¢ç©æï¼éæ°è®°å½ç©æä¸»åä½ï¼å¹¶æ¸
空åå·ãå½å
¥åä½ä¸æ°éï¼å£å¾é½éç©æååï¼ */ |
| | | handleItemChange: (itemId?: number) => Promise<void>; |
| | | /** éæ©åå·ï¼é»è®¤æåå·è®¡éåä½å½å
¥ï¼å¹¶è®°å½æ¢ç®æ¯ç */ |
| | | handleModelChange: ( |
| | | option: ItemModelSelectOption | undefined, |
| | | values: LineUnitFormValues, |
| | | ) => Promise<void>; |
| | | /** 忢å½å
¥åä½ï¼è®°å½æ¢ç®æ¯çå¹¶ç«å³éç®ä¸»å使°éï¼æ¹å主å使¶æ¸
æå½å
¥æ°é */ |
| | | handleEnterUnitChange: ( |
| | | value: number | undefined, |
| | | option: { label?: string; rate?: number } | undefined, |
| | | values: LineUnitFormValues, |
| | | ) => Promise<void>; |
| | | /** å½å
¥æ°éååï¼æå½å
¥åä½ä¸æ¢ç®æ¯çè¯ç®ä¸»å使°éï¼ä¾ç¨æ·æ ¸å¯¹æ¢ç®ç»æ */ |
| | | handleEnterQuantityChange: ( |
| | | value: number | undefined, |
| | | values: LineUnitFormValues, |
| | | ) => Promise<void>; |
| | | } |
| | | |
| | | /** |
| | | * çæè¡è¡¨åçååä½å½å
¥è卿¹æ³ |
| | | * |
| | | * @param quantityField ç©æä¸»åä½å£å¾çæ°éåæ®µåï¼åºåºä¸º quantityï¼å
¥åºä¸º receivedQuantityï¼ |
| | | */ |
| | | export function useLineUnitHandlers( |
| | | formApi?: VbenFormApi, |
| | | quantityField = 'quantity', |
| | | ): LineUnitHandlers { |
| | | function isPrimaryUnitEnter(values: LineUnitFormValues) { |
| | | return ( |
| | | !values.enterUnitMeasureId || |
| | | values.enterUnitMeasureId === values.itemPrimaryUnitId |
| | | ); |
| | | } |
| | | |
| | | async function handleItemChange(itemId?: number) { |
| | | // å
æ¸
空ï¼é¿å
ä¸ä¸ä¸ªç©æçåå·ä¸åä½å£å¾æ®ç |
| | | await formApi?.setValues({ |
| | | itemId, |
| | | itemModelId: undefined, |
| | | itemPrimaryUnitId: undefined, |
| | | itemPrimaryUnitName: undefined, |
| | | enterUnitMeasureId: undefined, |
| | | enterUnitMeasureName: undefined, |
| | | enterUnitRate: undefined, |
| | | enterQuantity: undefined, |
| | | [quantityField]: undefined, |
| | | }); |
| | | if (!itemId) { |
| | | return; |
| | | } |
| | | const item = await getMdmItem(itemId); |
| | | await formApi?.setValues({ |
| | | itemPrimaryUnitId: item?.unitMeasureId, |
| | | itemPrimaryUnitName: item?.unitMeasureName, |
| | | }); |
| | | } |
| | | |
| | | async function handleModelChange( |
| | | option: ItemModelSelectOption | undefined, |
| | | values: LineUnitFormValues, |
| | | ) { |
| | | const enterUnitMeasureId = |
| | | option?.unitMeasureId && option.unitMeasureId !== values.itemPrimaryUnitId |
| | | ? option.unitMeasureId |
| | | : undefined; |
| | | await formApi?.setValues({ |
| | | enterUnitMeasureId, |
| | | enterUnitMeasureName: enterUnitMeasureId |
| | | ? option?.unitMeasureName |
| | | : undefined, |
| | | enterUnitRate: enterUnitMeasureId ? option?.unitMeasureRate : undefined, |
| | | enterQuantity: undefined, |
| | | // åå°åå·åä½å½å
¥å主å使°éç±ç³»ç»æ¢ç®ï¼å
æ¸
æä¸ä¸æ¬¡å£å¾çæ°å¼ |
| | | ...(enterUnitMeasureId ? { [quantityField]: undefined } : {}), |
| | | }); |
| | | } |
| | | |
| | | async function handleEnterUnitChange( |
| | | value: number | undefined, |
| | | option: { label?: string; rate?: number } | undefined, |
| | | values: LineUnitFormValues, |
| | | ) { |
| | | if (!value || value === values.itemPrimaryUnitId) { |
| | | await formApi?.setValues({ |
| | | enterUnitMeasureName: undefined, |
| | | enterUnitRate: undefined, |
| | | enterQuantity: undefined, |
| | | }); |
| | | return; |
| | | } |
| | | await formApi?.setValues({ |
| | | enterUnitMeasureName: option?.label, |
| | | enterUnitRate: option?.rate, |
| | | ...(values.enterQuantity == null || !isValidRate(option?.rate) |
| | | ? { [quantityField]: undefined } |
| | | : { |
| | | [quantityField]: roundQuantity( |
| | | values.enterQuantity * option.rate, |
| | | ), |
| | | }), |
| | | }); |
| | | } |
| | | |
| | | async function handleEnterQuantityChange( |
| | | value: number | undefined, |
| | | values: LineUnitFormValues, |
| | | ) { |
| | | if (isPrimaryUnitEnter(values) || !isValidRate(values.enterUnitRate)) { |
| | | return; |
| | | } |
| | | await formApi?.setFieldValue( |
| | | quantityField, |
| | | value == null ? undefined : roundQuantity(value * values.enterUnitRate), |
| | | ); |
| | | } |
| | | |
| | | return { |
| | | handleEnterQuantityChange, |
| | | handleEnterUnitChange, |
| | | handleItemChange, |
| | | handleModelChange, |
| | | isPrimaryUnitEnter, |
| | | }; |
| | | } |
| | | |
| | | /** è¡è¡¨åãç©æåå· / å½å
¥åä½ / å½å
¥æ°é / 主å使°éãç¸å
³å段çéç¨é
ç½® */ |
| | | export interface ItemUnitSchemaOptions { |
| | | /** ç©æä¸»åä½å£å¾çæ°éåæ®µåï¼é»è®¤ quantityï¼ */ |
| | | quantityField?: string; |
| | | /** ç©æä¸»åä½å£å¾çæ°éåæ®µæ ç¾ï¼é»è®¤ãåºåºæ°éãï¼ */ |
| | | quantityLabel?: string; |
| | | } |
| | | |
| | | /** |
| | | * çæè¡è¡¨åçååä½å段ç»ï¼åå·ãå½å
¥åä½ãå½å
¥æ°éã主å使°é忢ç®ç¨éèåæ®µï¼ |
| | | * |
| | | * 主å使°éåæ®µå¨æè¾
åä½å½å
¥æ¶ç±ç³»ç»æ¢ç®ãä¸å¯æå·¥ä¿®æ¹ï¼æä¸»åä½å½å
¥æ¶æå·¥å¡«åå¹¶ååºåä¸é约æ |
| | | */ |
| | | export function buildItemUnitSchema( |
| | | formApi?: VbenFormApi, |
| | | options: ItemUnitSchemaOptions = {}, |
| | | ): VbenFormSchema[] { |
| | | const quantityField = options.quantityField ?? 'quantity'; |
| | | const quantityLabel = options.quantityLabel ?? 'åºåºæ°é'; |
| | | const handlers = useLineUnitHandlers(formApi, quantityField); |
| | | |
| | | return [ |
| | | // ç©æä¸»åä½éæéç©æååï¼ä½è¡¨å props åªè½éæå£°æï¼æ
ç¨éèåæ®µæ¿è½½ |
| | | { |
| | | fieldName: 'itemPrimaryUnitId', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'itemPrimaryUnitName', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'itemModelId', |
| | | label: 'ç©æåå·', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | labelField: 'model', |
| | | valueField: 'id', |
| | | allowClear: true, |
| | | api: (params: { itemId?: number }) => |
| | | getItemModelListByItem(params.itemId!), |
| | | shouldFetch: (params: { itemId?: number }) => !!params?.itemId, |
| | | placeholder: '请å
éæ©ç©æ', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['itemId'], |
| | | componentProps: (values) => ({ |
| | | disabled: !values.itemId, |
| | | params: { itemId: values.itemId }, |
| | | placeholder: values.itemId ? 'è¯·éæ©ç©æåå·' : '请å
éæ©ç©æ', |
| | | // éå®åå·åé»è®¤æå
¶è®¡éåä½å½å
¥ |
| | | onChange: (option?: ItemModelSelectOption) => |
| | | handlers.handleModelChange(option, values), |
| | | }), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'enterUnitMeasureId', |
| | | label: 'å½å
¥åä½', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | allowClear: true, |
| | | labelField: 'name', |
| | | valueField: 'id', |
| | | api: (params: { itemId?: number; itemModelId?: number }) => |
| | | getItemEnterUnits(params), |
| | | shouldFetch: (params: { itemId?: number }) => !!params?.itemId, |
| | | placeholder: 'é»è®¤ä¸ºç©æä¸»è®¡éåä½', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['itemId', 'itemModelId', 'itemPrimaryUnitName'], |
| | | componentProps: (values) => ({ |
| | | disabled: !values.itemId, |
| | | params: { itemId: values.itemId, itemModelId: values.itemModelId }, |
| | | placeholder: values.itemId |
| | | ? `é»è®¤æç©æä¸»åä½${values.itemPrimaryUnitName ? `ã${values.itemPrimaryUnitName}ã` : ''}å½å
¥` |
| | | : '请å
éæ©ç©æ', |
| | | onChange: ( |
| | | value: number | undefined, |
| | | option?: { label?: string; rate?: number }, |
| | | ) => handlers.handleEnterUnitChange(value, option, values), |
| | | }), |
| | | }, |
| | | }, |
| | | // å½å
¥åä½åç§°ä¸æ¢ç®æ¯çéæéåä½ååï¼åæ ·ç¨éèåæ®µæ¿è½½ |
| | | { |
| | | fieldName: 'enterUnitMeasureName', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'enterUnitRate', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'enterQuantity', |
| | | label: 'å½å
¥æ°é', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0, |
| | | precision: 6, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: [ |
| | | 'enterUnitMeasureId', |
| | | 'enterUnitMeasureName', |
| | | 'itemPrimaryUnitId', |
| | | 'quantityMax', |
| | | 'enterUnitRate', |
| | | ], |
| | | show: (values) => !handlers.isPrimaryUnitEnter(values), |
| | | // è¿å null 表示ä¸è¿½å è§åï¼åéåºç¡ rulesï¼ |
| | | rules: (values) => |
| | | handlers.isPrimaryUnitEnter(values) ? null : 'required', |
| | | componentProps: (values) => ({ |
| | | placeholder: values.enterUnitMeasureName |
| | | ? `请填åæã${values.enterUnitMeasureName}ãè®¡çæ°é` |
| | | : '请æå½å
¥åä½å¡«åæ°é', |
| | | // æè¾
åä½å½å
¥æ¶ï¼å¯å½å
¥ä¸é为ãåºåä¸é ÷ æ¢ç®æ¯çã |
| | | max: |
| | | values.quantityMax != null && isValidRate(values.enterUnitRate) |
| | | ? Math.floor((values.quantityMax / values.enterUnitRate) * 1e6) / |
| | | 1e6 |
| | | : undefined, |
| | | // å½å
¥æ°éååæ¶ç«å³è¯ç®ä¸»å使°é |
| | | onChange: (value: number | undefined) => |
| | | handlers.handleEnterQuantityChange(value, values), |
| | | }), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: quantityField, |
| | | label: quantityLabel, |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | min: 0.01, |
| | | precision: 6, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: [ |
| | | 'enterUnitMeasureId', |
| | | 'itemPrimaryUnitId', |
| | | 'itemPrimaryUnitName', |
| | | 'quantityMax', |
| | | ], |
| | | // æä¸»åä½å½å
¥æ¶æå·¥å¡«åãå¿
å¡«ï¼æè¾
åä½å½å
¥æ¶ä¸ºç³»ç»æ¢ç®ç»æï¼æ éæ ¡éª |
| | | rules: (values) => |
| | | handlers.isPrimaryUnitEnter(values) ? 'required' : null, |
| | | componentProps: (values) => { |
| | | const primary = handlers.isPrimaryUnitEnter(values); |
| | | return { |
| | | disabled: !primary, |
| | | max: values.quantityMax, |
| | | placeholder: primary |
| | | ? `请æç©æä¸»åä½${values.itemPrimaryUnitName ? `ã${values.itemPrimaryUnitName}ã` : ''}å¡«åæ°é` |
| | | : 'æå½å
¥åä½ä¸æ¢ç®æ¯çèªå¨æ¢ç®', |
| | | }; |
| | | }, |
| | | }, |
| | | }, |
| | | ]; |
| | | } |