<script setup lang="ts">
|
import {computed, reactive, ref, watch, withDefaults} from "vue";
|
|
defineOptions({
|
name: "ProductionRecordForm"
|
});
|
|
type DeviceOption = {
|
id: string | number;
|
deviceName: string;
|
deviceCode?: string | number | null;
|
rpm?: string | number | null;
|
};
|
|
const props = withDefaults(
|
defineProps<{
|
list: any[];
|
labelWidth: number;
|
deviceOptions: DeviceOption[];
|
selectedDeviceId: string | number | null;
|
}>(),
|
{
|
list: () => [],
|
labelWidth: 120,
|
deviceOptions: () => [],
|
selectedDeviceId: null,
|
}
|
);
|
|
const formRef = ref();
|
const formData = reactive({
|
list: [] as any[],
|
});
|
|
const fieldLabel = (item: any) => {
|
if (!item.unit || item.unit === "/") {
|
return item.parameterItem;
|
}
|
return `${item.parameterItem}(${item.unit})`;
|
};
|
|
const getType = (item: any) => item.type || "文本格式";
|
|
const machineSelectItem = computed(() => {
|
return formData.list.find(item => getType(item) === '机台选择') || null;
|
});
|
|
const selectedDevice = computed(() => {
|
const machineValue = machineSelectItem.value?.value;
|
if (machineValue === null || machineValue === undefined || machineValue === '') return null;
|
return props.deviceOptions.find(device => String(device.id) === String(machineValue)) || null;
|
});
|
|
const AUTO_DEVICE_CODE_ID = "__auto_deviceCode__";
|
const AUTO_RPM_ID = "__auto_rpm__";
|
|
let isSyncingAutoFields = false;
|
|
const syncAutoDeviceFields = () => {
|
if (isSyncingAutoFields) return;
|
isSyncingAutoFields = true;
|
|
try {
|
const machineIndex = formData.list.findIndex(item => getType(item) === "机台选择");
|
if (machineIndex === -1) return;
|
|
const removeById = (id: string) => {
|
const idx = formData.list.findIndex(x => x?.id === id);
|
if (idx !== -1) formData.list.splice(idx, 1);
|
};
|
|
removeById(AUTO_DEVICE_CODE_ID);
|
removeById(AUTO_RPM_ID);
|
|
const dev = selectedDevice.value as any;
|
let insertPos = machineIndex + 1;
|
|
const hasCode =
|
dev &&
|
dev.deviceCode !== null &&
|
dev.deviceCode !== undefined &&
|
String(dev.deviceCode) !== "";
|
|
const hasRpm = dev && dev.rpm !== null && dev.rpm !== undefined;
|
|
if (hasCode) {
|
formData.list.splice(insertPos, 0, {
|
id: AUTO_DEVICE_CODE_ID,
|
parameterItem: "设备编号",
|
value: dev.deviceCode,
|
// 只读展示:避免影响后端参数结构(submitData 会过滤)
|
readonly: true,
|
isRequired: "0",
|
__autoExtra: true,
|
});
|
insertPos++;
|
}
|
|
if (hasRpm) {
|
formData.list.splice(insertPos, 0, {
|
id: AUTO_RPM_ID,
|
parameterItem: "转数",
|
value: dev.rpm,
|
readonly: true,
|
isRequired: "0",
|
__autoExtra: true,
|
});
|
}
|
} finally {
|
isSyncingAutoFields = false;
|
}
|
};
|
|
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: `请输入${item.parameterItem}`, trigger: "blur"}];
|
}
|
});
|
return result;
|
});
|
|
const initData = () => {
|
// 重要:不要直接复用 props.list 的引用,否则后续 splice formData.list 会触发 props watch,导致递归更新
|
formData.list = (props.list || []).map(item => ({ ...item }));
|
formData.list.forEach(item => {
|
if (item.value === undefined) {
|
item.value = null;
|
}
|
// 如果参数中存在“机台选择”,则使用父组件传入的默认机台回填
|
if (getType(item) === '机台选择' && (item.value === null || item.value === undefined || item.value === '')) {
|
item.value = props.selectedDeviceId ?? item.value;
|
}
|
});
|
};
|
|
const submitData = async () => {
|
const valid = await formRef.value.validate().catch(() => false)
|
|
if (valid) {
|
// 自动插入的只读字段不参与提交,避免后端参数结构变化
|
return formData.list.filter(item => !item.__autoExtra)
|
} else {
|
return null
|
}
|
}
|
|
watch(
|
() => props.list,
|
() => {
|
initData();
|
// 初始化后再同步自动插入字段
|
syncAutoDeviceFields();
|
},
|
{immediate: true, deep: true}
|
);
|
|
watch(
|
() => selectedDevice.value,
|
() => {
|
syncAutoDeviceFields();
|
},
|
{ immediate: true }
|
);
|
|
defineExpose({
|
submitData
|
})
|
</script>
|
|
<template>
|
<el-form ref="formRef" :model="formData" :rules="rules" :label-width="`${labelWidth}px`">
|
<el-row :gutter="30">
|
<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 in props.deviceOptions"
|
:key="device.id"
|
:label="device.deviceName"
|
:value="device.id"
|
/>
|
</el-select>
|
<el-input
|
v-else
|
v-model="item.value"
|
placeholder="请输入"
|
:disabled="item.readonly"
|
:clearable="!item.readonly"
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
</template>
|