<script setup lang="ts">
|
import {computed, reactive, ref, watch} from "vue";
|
import {getDeviceLedger} from "@/api/equipmentManagement/ledger";
|
|
defineOptions({
|
name: "ProductionRecordForm"
|
});
|
|
const props = defineProps({
|
list: {
|
type: Array,
|
default() {
|
return [];
|
}
|
},
|
labelWidth: {
|
type: Number,
|
default: 120
|
},
|
/** 本次生产数量(成型工序用于计算投入重量/数量) */
|
quantity: {
|
type: Number,
|
default: null
|
},
|
/** 当前工序是否为「成型」 */
|
isFormingProcess: {
|
type: Boolean,
|
default: false
|
},
|
/** 工单 BOM 投入重量,非成型工序回显到「投入重量/数量」 */
|
bomInputQty: {
|
type: Number,
|
default: null
|
}
|
});
|
|
const formRef = ref();
|
const formData = reactive({
|
list: [] as any[],
|
});
|
|
const INPUT_WEIGHT_PARAM_ITEM = "投入重量/数量";
|
|
/** 参数项展示名 */
|
const displayParameterItem = (name) => {
|
const trimmed = String(name ?? "").trim();
|
if (trimmed === "投入重量/数量") return INPUT_WEIGHT_PARAM_ITEM;
|
return trimmed;
|
};
|
|
const fieldLabel = (item: any) => {
|
const parameterItem = displayParameterItem(item.parameterItem);
|
if (!item.unit || item.unit === "/") {
|
return parameterItem;
|
}
|
return `${parameterItem}(${item.unit})`;
|
};
|
|
const getType = (item: any) => item.type || "文本格式";
|
|
const rules = computed(() => {
|
const result: Record<string, any[]> = {};
|
formData.list.forEach((item, index) => {
|
if (String(item.isRequired) === "1") {
|
result[`list.${index}.value`] = [{
|
required: true,
|
message: `请输入${displayParameterItem(item.parameterItem)}`,
|
trigger: "blur"
|
}];
|
}
|
});
|
return result;
|
});
|
|
const deviceOptions = ref([]);
|
const loadDeviceName = async () => {
|
const {data} = await getDeviceLedger();
|
deviceOptions.value = data;
|
};
|
|
const normalizeUnit = (unit) => String(unit ?? "").trim().toLowerCase();
|
|
const isInputWeightItem = (item) => {
|
const name = String(item?.parameterItem ?? "").trim();
|
const unit = normalizeUnit(item?.unit);
|
return name.includes(INPUT_WEIGHT_PARAM_ITEM) &&
|
(unit === "kg" || unit.startsWith("kg/"));
|
};
|
|
const isBlankCoeffItem = (item) => {
|
const unit = normalizeUnit(item?.unit);
|
return String(item?.parameterItem ?? "").includes("生坯系数") &&
|
(unit === "g" || unit.startsWith("g/"));
|
};
|
|
/** 投入重量/数量(KG) = 本次生产数量 × 生坯系数(g) / 1000 */
|
const syncFormingInputWeight = () => {
|
if (!props.isFormingProcess) return;
|
const weightItem = formData.list.find(isInputWeightItem);
|
if (!weightItem) return;
|
|
const qty = Number(props.quantity);
|
const coeffItem = formData.list.find(isBlankCoeffItem);
|
const coeff = coeffItem?.value === null || coeffItem?.value === undefined || coeffItem?.value === ""
|
? NaN
|
: Number(coeffItem.value);
|
|
if (!Number.isFinite(qty) || qty < 1 || !Number.isFinite(coeff)) {
|
return;
|
}
|
|
weightItem.value = Number(((qty * coeff) / 1000).toFixed(4));
|
};
|
|
/** 非成型:投入重量/数量取工单 bomInputQty(仅回显,不覆盖用户已编辑的值) */
|
const syncBomInputWeight = (force = false) => {
|
if (props.isFormingProcess) return;
|
const weightItem = formData.list.find(isInputWeightItem);
|
if (!weightItem) return;
|
const bom = props.bomInputQty;
|
if (bom === null || bom === undefined || Number.isNaN(Number(bom))) {
|
return;
|
}
|
const current = weightItem.value;
|
const isEmpty =
|
current === null || current === undefined || current === "";
|
if (!force && !isEmpty) {
|
return;
|
}
|
weightItem.value = Number(bom);
|
};
|
|
const syncInputWeight = () => {
|
if (props.isFormingProcess) {
|
syncFormingInputWeight();
|
} else {
|
syncBomInputWeight();
|
}
|
};
|
|
const cloneParamList = (list) =>
|
JSON.parse(JSON.stringify(list || []));
|
|
const initData = () => {
|
formData.list = cloneParamList(props.list);
|
formData.list.forEach(item => {
|
if (item.value === undefined) {
|
item.value = null;
|
}
|
});
|
loadDeviceName();
|
if (props.isFormingProcess) {
|
syncFormingInputWeight();
|
} else {
|
syncBomInputWeight(true);
|
}
|
};
|
|
const submitData = async () => {
|
const valid = await formRef.value.validate().catch(() => false)
|
|
if (valid) {
|
return formData.list
|
} else {
|
return null
|
}
|
}
|
|
watch(
|
() => props.list,
|
() => {
|
initData();
|
},
|
{immediate: true}
|
);
|
|
watch(
|
() => [props.quantity, props.isFormingProcess],
|
() => {
|
if (props.isFormingProcess) {
|
syncFormingInputWeight();
|
}
|
}
|
);
|
|
watch(
|
() => {
|
const coeffItem = formData.list.find(isBlankCoeffItem);
|
return coeffItem?.value;
|
},
|
() => {
|
if (props.isFormingProcess) {
|
syncFormingInputWeight();
|
}
|
}
|
);
|
|
watch(
|
() => [props.bomInputQty, props.isFormingProcess],
|
() => {
|
if (!props.isFormingProcess) {
|
syncBomInputWeight();
|
}
|
}
|
);
|
|
defineExpose({
|
submitData,
|
syncFormingInputWeight,
|
syncBomInputWeight,
|
syncInputWeight
|
})
|
</script>
|
|
<template>
|
<el-form ref="formRef" :model="formData" :rules="rules" :label-width="`${labelWidth}px`">
|
<el-row :gutter="20">
|
<el-col :span="12" v-for="(item, index) in formData.list" :key="item.id">
|
<el-form-item
|
:label="fieldLabel(item)"
|
:prop="`list.${index}.value`"
|
>
|
<el-input-number
|
v-if="getType(item) === '数值格式'"
|
v-model="item.value"
|
:controls="false"
|
style="width: 100%"
|
placeholder="请输入"
|
/>
|
<el-date-picker
|
v-else-if="getType(item) === '时间格式'"
|
v-model="item.value"
|
type="datetime"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
placeholder="请选择"
|
style="width: 100%"
|
/>
|
<el-date-picker
|
v-else-if="getType(item) === '日期格式'"
|
v-model="item.value"
|
type="date"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
placeholder="请选择"
|
style="width: 100%"
|
/>
|
<el-select
|
v-else-if="getType(item) === '是/否选框'"
|
v-model="item.value"
|
placeholder="请选择"
|
clearable
|
style="width: 100%"
|
>
|
<el-option label="是" value="是"/>
|
<el-option label="否" value="否"/>
|
</el-select>
|
<el-select
|
v-else-if="getType(item) === '机台选择'"
|
v-model="item.value"
|
placeholder="请选择"
|
clearable
|
style="width: 100%"
|
>
|
<el-option
|
v-for="(device, deviceIndex) in deviceOptions"
|
:key="deviceIndex"
|
:label="device.deviceName"
|
:value="device.deviceName"
|
></el-option>
|
</el-select>
|
<el-input
|
v-else
|
v-model="item.value"
|
placeholder="请输入"
|
clearable
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
</template>
|