<template>
|
<view class="form-container">
|
<wd-form ref="formRef" :model="formData">
|
<!-- 结构检查 -->
|
<wd-row>
|
<view style="margin: 10rpx">
|
<text class="title">结构检查</text>
|
</view>
|
<wd-col :span="24">
|
<wd-form-item label="成品结构" prop="structureFormula" required>
|
<wd-input
|
v-model="formData.structureFormula"
|
placeholder="请输入成品结构"
|
clearable
|
:disabled="isViewMode"
|
/>
|
</wd-form-item>
|
<wd-form-item label="记录位置" prop="recordPosition" required>
|
<wd-select-picker
|
v-model="formData.recordPosition"
|
:columns="recordLocationColumns"
|
type="radio"
|
placeholder="请选择记录位置"
|
:clearable="false"
|
:disabled="isViewMode"
|
/>
|
</wd-form-item>
|
<wd-form-item label="绞合外径(mm)" prop="twistedOuterDiameter" required>
|
<wd-input
|
v-model="formData.twistedOuterDiameter"
|
placeholder="请输入绞合外径"
|
clearable
|
type="number"
|
:disabled="isViewMode"
|
/>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
|
<!-- 结构标准值和实测 -->
|
<wd-row v-if="structureItems.length > 0">
|
<view style="margin: 10rpx">
|
<text class="title">结构标准值和实测</text>
|
</view>
|
<wd-col
|
:span="24"
|
v-for="(item, index) in structureItems"
|
:key="index"
|
style="padding-bottom: 10px"
|
>
|
<wd-form-item
|
:label="item.structureName"
|
label-width="180px"
|
style="color: red"
|
required
|
/>
|
<wd-form-item label="标准值" prop="structureValue">
|
<text>{{ item.structureValue || "-" }}</text>
|
</wd-form-item>
|
<wd-form-item label="实测根数" prop="actualValue1" required>
|
<wd-input
|
v-model="item.actualValue1"
|
placeholder="请输入根数"
|
clearable
|
type="number"
|
:disabled="isViewMode"
|
/>
|
</wd-form-item>
|
<wd-form-item label="实测直径" prop="actualValue2" required>
|
<wd-input
|
v-model="item.actualValue2"
|
placeholder="请输入直径"
|
clearable
|
type="number"
|
:disabled="isViewMode"
|
>
|
<template #append>mm</template>
|
</wd-input>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
|
<!-- 绞线工艺质量控制 -->
|
<wd-row v-if="twistItems.length > 0">
|
<view style="margin: 10rpx">
|
<text class="title">绞线工艺质量控制</text>
|
</view>
|
<wd-col
|
:span="24"
|
v-for="(item, index) in twistItems"
|
:key="index"
|
style="padding-bottom: 10px"
|
>
|
<wd-form-item :label="item.twistName" label-width="180px" style="color: red" required />
|
<wd-form-item label="绞向" prop="direction" required>
|
<wd-select-picker
|
v-model="item.direction"
|
:columns="twistDirectionColumns"
|
type="radio"
|
placeholder="请选择绞向"
|
:clearable="false"
|
:disabled="isViewMode"
|
/>
|
</wd-form-item>
|
<wd-form-item label="节距" prop="pitch" required>
|
<wd-input
|
v-model="item.pitch"
|
placeholder="请输入节距"
|
clearable
|
type="number"
|
:disabled="isViewMode"
|
@input="updatePitchRatio(item)"
|
>
|
<template #append>mm</template>
|
</wd-input>
|
</wd-form-item>
|
<wd-form-item label="节径比" prop="pitchRatio">
|
<text>{{ calculatePitchRatio(item.pitch, item.dia) }}</text>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
|
<!-- 外观和结论 -->
|
<wd-row>
|
<view style="margin: 10rpx">
|
<text class="title">外观和结论</text>
|
</view>
|
<wd-col :span="24">
|
<wd-form-item label="成品外观" prop="productAppearance" required>
|
<view v-if="!isViewMode" style="display: flex; flex-wrap: wrap; gap: 10px">
|
<wd-checkbox
|
v-for="(opt, idx) in appearanceOptions"
|
:key="idx"
|
:value="opt.value"
|
:modelValue="formData.productAppearance.includes(opt.value)"
|
@click="handleAppearanceClick(opt.value)"
|
style="width: 100px"
|
>
|
{{ opt.label }}
|
</wd-checkbox>
|
</view>
|
<text v-else>{{ formatProductAppearance(formData.productAppearance) }}</text>
|
</wd-form-item>
|
<wd-form-item label="结论" prop="conclusion" required>
|
<wd-radio-group
|
v-model="formData.conclusion"
|
inline
|
class="conclusion-radio-group"
|
:disabled="isViewMode"
|
>
|
<wd-radio value="合格" shape="dot">合格</wd-radio>
|
<wd-radio value="不合格" shape="dot">不合格</wd-radio>
|
</wd-radio-group>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
</wd-form>
|
</view>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, reactive, watch, computed } from "vue";
|
|
const props = defineProps({
|
formData: {
|
type: Object,
|
default: () => ({}),
|
},
|
structureItems: {
|
type: Array,
|
default: () => [],
|
},
|
twistItems: {
|
type: Array,
|
default: () => [],
|
},
|
isViewMode: {
|
type: Boolean,
|
default: false,
|
},
|
recordLocation: {
|
type: Array,
|
default: () => [],
|
},
|
appearanceOptions: {
|
type: Array,
|
default: () => [],
|
},
|
});
|
|
const emit = defineEmits(["update:formData", "update:structureItems", "update:twistItems"]);
|
|
const formRef = ref();
|
|
// 绞向选项
|
const twistDirectionColumns = [
|
{ label: "左向", value: "左向" },
|
{ label: "右向", value: "右向" },
|
];
|
|
// 记录位置选项
|
const recordLocationColumns = computed(() => {
|
return props.recordLocation.map((item: any) => ({
|
label: item.label,
|
value: item.value,
|
}));
|
});
|
|
// 计算节径比
|
const calculatePitchRatio = (pitch: string, dia: string) => {
|
if (!pitch || !dia) return "-";
|
const pitchNum = parseFloat(pitch);
|
const diaNum = parseFloat(dia);
|
if (isNaN(pitchNum) || isNaN(diaNum) || diaNum === 0) return "-";
|
return (pitchNum / diaNum).toFixed(2);
|
};
|
|
// 更新节径比
|
const updatePitchRatio = (item: any) => {
|
item.pitchRatio = calculatePitchRatio(item.pitch, item.dia);
|
emit("update:twistItems", [...props.twistItems]);
|
};
|
|
// 格式化产品外观显示
|
const formatProductAppearance = (productAppearance: string[]) => {
|
if (!productAppearance || productAppearance.length === 0) return "-";
|
return productAppearance.join("、");
|
};
|
|
// 处理产品外观选择的互斥逻辑
|
const handleAppearanceClick = (value: string) => {
|
const currentValues = [...props.formData.productAppearance];
|
const isCurrentlyChecked = currentValues.includes(value);
|
|
let newSelection: string[] = [];
|
|
if (value === "无外观问题") {
|
if (isCurrentlyChecked) {
|
newSelection = [];
|
} else {
|
newSelection = ["无外观问题"];
|
}
|
} else {
|
if (isCurrentlyChecked) {
|
newSelection = currentValues.filter((v) => v !== value);
|
} else {
|
const filteredValues = currentValues.filter((v) => v !== "无外观问题");
|
newSelection = [...filteredValues, value];
|
}
|
}
|
|
emit("update:formData", {
|
...props.formData,
|
productAppearance: newSelection,
|
});
|
};
|
|
// 表单验证
|
const validate = async () => {
|
try {
|
await formRef.value?.validate();
|
return true;
|
} catch (error) {
|
return false;
|
}
|
};
|
|
// 验证结构项
|
const validateStructureItems = () => {
|
for (const item of props.structureItems) {
|
if (!item.actualValue1) {
|
return { valid: false, message: `${item.structureName}实测根数为必填项` };
|
}
|
if (!item.actualValue2) {
|
return { valid: false, message: `${item.structureName}实测直径为必填项` };
|
}
|
}
|
return { valid: true };
|
};
|
|
// 验证绞线工艺项
|
const validateTwistItems = () => {
|
for (const item of props.twistItems) {
|
if (!item.direction) {
|
return { valid: false, message: `${item.twistName}绞向为必填项` };
|
}
|
if (!item.pitch) {
|
return { valid: false, message: `${item.twistName}节距为必填项` };
|
}
|
}
|
return { valid: true };
|
};
|
|
// 完整验证
|
const validateAll = async () => {
|
// 基础字段验证
|
if (!props.formData.structureFormula) {
|
return { valid: false, message: "成品结构为必填项" };
|
}
|
if (!props.formData.recordPosition) {
|
return { valid: false, message: "记录位置为必填项" };
|
}
|
if (!props.formData.twistedOuterDiameter) {
|
return { valid: false, message: "绞合外径为必填项" };
|
}
|
if (!props.formData.productAppearance || props.formData.productAppearance.length === 0) {
|
return { valid: false, message: "成品外观为必填项" };
|
}
|
if (!props.formData.conclusion) {
|
return { valid: false, message: "结论为必填项" };
|
}
|
|
// 结构项验证
|
const structureResult = validateStructureItems();
|
if (!structureResult.valid) {
|
return structureResult;
|
}
|
|
// 绞线工艺项验证
|
const twistResult = validateTwistItems();
|
if (!twistResult.valid) {
|
return twistResult;
|
}
|
|
return { valid: true };
|
};
|
|
defineExpose({
|
validate,
|
validateAll,
|
});
|
</script>
|
|
<style lang="scss" scoped>
|
.form-container {
|
padding: 12px;
|
max-height: 70vh;
|
overflow-y: auto;
|
}
|
|
.title {
|
position: relative;
|
margin-left: 10px;
|
font-size: 14px;
|
font-weight: 600;
|
color: #0d867f;
|
}
|
|
.title::after {
|
position: absolute;
|
content: "";
|
top: 4px;
|
left: -10px;
|
width: 3px;
|
height: 14px;
|
background: #0d867f;
|
border-radius: 2px;
|
}
|
|
.conclusion-radio-group {
|
display: flex;
|
align-items: flex-start;
|
gap: 20rpx;
|
}
|
|
:deep(.wd-form-item) {
|
margin-bottom: 8rpx;
|
}
|
</style>
|