<template>
|
<view class="list">
|
<CardTitle title="自检管理" :hideAction="false" :full="false">
|
<template #action>
|
<wd-button
|
icon="file-add"
|
:round="false"
|
size="small"
|
custom-class="add_btn"
|
@click="handleOpenAddDialog"
|
>
|
新增自检
|
</wd-button>
|
</template>
|
</CardTitle>
|
|
<!-- 自检列表(卡片样式) -->
|
<view class="inspection-list">
|
<wd-card
|
v-for="(item, index) in dataList"
|
:key="item.id || index"
|
class="card_bg"
|
style="margin-bottom: 12px"
|
>
|
<template #title>
|
<view class="flex justify-between w-full">
|
<view class="flex items-center">
|
<wd-icon name="file" color="#0D867F" size="20px"></wd-icon>
|
<text class="font-medium text-[#252525] ml-2">自检记录 #{{ index + 1 }}</text>
|
</view>
|
<view class="flex gap-2">
|
<wd-button
|
plain
|
type="primary"
|
size="small"
|
@click="handleEdit(item)"
|
style="margin-right: 10px"
|
>
|
编辑
|
</wd-button>
|
<wd-button plain type="error" size="small" @click="handleDelete(item)">
|
删除
|
</wd-button>
|
</view>
|
</view>
|
</template>
|
|
<view class="card-content">
|
<!-- 基本信息 -->
|
<view class="info-section">
|
<view class="section-header">
|
<wd-icon name="info" color="#0D867F" size="16px"></wd-icon>
|
<text class="section-title">基本信息</text>
|
</view>
|
<view class="info-grid">
|
<view class="info-item">
|
<text class="info-label">自检时间:</text>
|
<text class="info-value">{{ item.fixedInfo?.recordDate || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">机台:</text>
|
<text class="info-value">{{ item.fixedInfo?.deviceModel || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">班组:</text>
|
<text class="info-value">{{ item.fixedInfo?.teamName || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">首检单号:</text>
|
<text class="info-value">{{ item.fixedInfo?.firstNo || "-" }}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 原材料信息 -->
|
<view class="info-section">
|
<view class="section-header">
|
<wd-icon name="folder" color="#0D867F" size="16px"></wd-icon>
|
<text class="section-title">原材料信息</text>
|
</view>
|
<view class="info-grid">
|
<view class="info-item">
|
<text class="info-label">型号:</text>
|
<text class="info-value">{{ item.fixedInfo?.poleModel || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">批次:</text>
|
<text class="info-value">{{ item.fixedInfo?.poleNumber || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">生产轴数:</text>
|
<text class="info-value">{{ item.fixedInfo?.outputNumber || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">定径模具:</text>
|
<text class="info-value">{{ item.fixedInfo?.lastSlot || "-" }}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 单丝直径 -->
|
<view class="info-section">
|
<view class="section-header">
|
<wd-icon name="setting" color="#0D867F" size="16px"></wd-icon>
|
<text class="section-title">单丝直径(mm)</text>
|
</view>
|
<view class="info-grid">
|
<view class="info-item">
|
<text class="info-label">规格型号:</text>
|
<text class="info-value">{{ item.fixedInfo?.model || "-" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">最大值:</text>
|
<text class="info-value">
|
{{
|
item.inspectionResult?.maxDia !== null &&
|
item.inspectionResult?.maxDia !== undefined
|
? item.inspectionResult.maxDia
|
: "-"
|
}}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">最小值:</text>
|
<text class="info-value">
|
{{
|
item.inspectionResult?.minDia !== null &&
|
item.inspectionResult?.minDia !== undefined
|
? item.inspectionResult.minDia
|
: "-"
|
}}
|
</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 成盘质量 -->
|
<view class="info-section">
|
<view class="section-header">
|
<wd-icon name="check" color="#0D867F" size="16px"></wd-icon>
|
<text class="section-title">成盘质量</text>
|
</view>
|
<view class="info-grid">
|
<view class="info-item">
|
<text class="info-label">卷绕紧密:</text>
|
<text class="info-value">
|
{{ item.inspectionResult?.windingTightness || "是" }}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">排列整齐:</text>
|
<text class="info-value">
|
{{ item.inspectionResult?.arrangementNeatness || "是" }}
|
</text>
|
</view>
|
<view class="info-item-full">
|
<text class="info-label">外层铝线离侧板边缘距离(mm):</text>
|
<text
|
class="info-value"
|
:style="{
|
color: item.inspectionResult?.aluminumWireDistance < 25 ? '#f56c6c' : '',
|
}"
|
>
|
{{ item.inspectionResult?.aluminumWireDistance || "-" }}
|
</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 其他信息 -->
|
<view class="info-section">
|
<view class="section-header">
|
<wd-icon name="more" color="#0D867F" size="16px"></wd-icon>
|
<text class="section-title">其他信息</text>
|
</view>
|
<view class="info-grid">
|
<view class="info-item-full">
|
<text class="info-label">外观质量:</text>
|
<text class="info-value">
|
{{ getAppearanceLabel(item.inspectionResult?.appearance) }}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">成品模后接头情况:</text>
|
<text class="info-value">{{ item.inspectionResult?.jointCondition || "无" }}</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">结论:</text>
|
<text
|
class="info-value"
|
:style="{
|
color: item.inspectionResult?.conclusion === '合格' ? '#67c23a' : '#f56c6c',
|
fontWeight: '500',
|
}"
|
>
|
{{ item.inspectionResult?.conclusion || "合格" }}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">记录人:</text>
|
<text class="info-value">{{ item.fixedInfo?.createUserName || "-" }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</wd-card>
|
</view>
|
|
<!-- 新增/编辑弹框 -->
|
<wd-popup v-model="dialogVisible" position="bottom" custom-class="yl-popup">
|
<SelfInspectForm
|
:visible="dialogVisible"
|
:form-data="currentFormData"
|
:appearance-options="appearanceOptions"
|
:previous-appearance-value="previousAppearanceValueMap.get(currentFormData?.id || '')"
|
@update:visible="dialogVisible = $event"
|
@submit="handleFormSubmit"
|
@close="handleCloseDialog"
|
/>
|
</wd-popup>
|
|
<wd-toast />
|
</view>
|
</template>
|
|
<script setup lang="ts">
|
import CardTitle from "@/components/card-title/index.vue";
|
import { useToast, dayjs } from "wot-design-uni";
|
import { onLoad } from "@dcloudio/uni-app";
|
import { ref } from "vue";
|
import ManageApi from "@/api/product/manage";
|
import SelfInspectForm from "./form.vue";
|
|
const toast = useToast();
|
const wireId = ref<string>("");
|
const poleModel = ref<string>("");
|
const poleNumber = ref<string>("");
|
|
// 数据列表
|
const dataList = ref<any[]>([]);
|
const loading = ref(false);
|
|
// 外观选项
|
const appearanceOptions = ref<Array<{ label: string; value: string | number }>>([]);
|
|
// 存储每行外观质量的之前的值
|
const previousAppearanceValueMap = ref<Map<string, string[]>>(new Map());
|
|
// 弹框相关
|
const dialogVisible = ref(false);
|
const currentFormData = ref<any>(null);
|
|
// 加载外观字典数据
|
const loadAppearanceDict = async () => {
|
try {
|
const qualityRes = await ManageApi.dictAPI("draw_appearance_quality");
|
if (qualityRes.data && Array.isArray(qualityRes.data)) {
|
appearanceOptions.value = qualityRes.data.map((item: any) => ({
|
label: item.dictLabel || "",
|
value: item.dictValue || "",
|
}));
|
}
|
} catch (error) {
|
console.error("加载外观字典失败:", error);
|
}
|
};
|
|
// 获取外观标签
|
const getAppearanceLabel = (value: string | string[]) => {
|
if (Array.isArray(value) && value.length > 0) {
|
const labels = value.map((v) => {
|
const option = appearanceOptions.value.find((item) => item.value === v);
|
return option ? option.label : v;
|
});
|
return labels.join(", ");
|
}
|
if (typeof value === "string" && value) {
|
const option = appearanceOptions.value.find((item) => item.value === value);
|
return option ? option.label : value;
|
}
|
return "无";
|
};
|
|
// 获取数据
|
const getData = async () => {
|
if (!wireId.value) return;
|
|
loading.value = true;
|
try {
|
const { code, data } = await ManageApi.getSelfInspection({
|
wireId: wireId.value,
|
poleModel: poleModel.value,
|
poleNumber: poleNumber.value,
|
});
|
|
if (code === 200) {
|
dataList.value = data || [];
|
// 初始化每行的 previousAppearanceValue
|
dataList.value.forEach((item) => {
|
if (item.id) {
|
previousAppearanceValueMap.value.set(
|
item.id,
|
JSON.parse(JSON.stringify(item.inspectionResult?.appearance || []))
|
);
|
}
|
});
|
}
|
} catch (error) {
|
console.error("获取自检数据失败:", error);
|
toast.error("获取自检数据失败");
|
} finally {
|
loading.value = false;
|
}
|
};
|
|
// 存储从接口获取的原始数据(用于保存时补充缺失字段)
|
const originalApiData = ref<any>(null);
|
|
// 打开新增弹框
|
const handleOpenAddDialog = async () => {
|
const newItem = {
|
id: `temp_${Date.now()}`,
|
fixedInfo: {
|
firstNo: "",
|
recordDate: dayjs().format("YYYY-MM-DD"),
|
deviceModel: "",
|
teamName: "",
|
workShift: "",
|
poleModel: poleModel.value || "",
|
poleNumber: poleNumber.value || "",
|
outputNumber: "",
|
lastSlot: "",
|
model: "",
|
createUserName: "",
|
id: null,
|
teamId: null,
|
wireId: wireId.value ? Number(wireId.value) : null,
|
},
|
inspectionResult: {
|
maxDia: null,
|
minDia: null,
|
appearance: ["无外观问题"],
|
windingTightness: "是",
|
arrangementNeatness: "是",
|
aluminumWireDistance: 25,
|
jointCondition: "无",
|
conclusion: "合格",
|
dia: null,
|
twistedLayer: null,
|
wireId: wireId.value ? String(wireId.value) : null,
|
},
|
isEditing: true,
|
isNew: true,
|
};
|
|
// 调用API获取默认数据
|
try {
|
const { code, data } = await ManageApi.getDrawInspectStyleByGetDrawInspect({
|
wireId: wireId.value,
|
poleModel: poleModel.value,
|
poleNumber: poleNumber.value,
|
});
|
|
if (code === 200 && data) {
|
// 保存原始接口数据,用于提交时补充缺失字段
|
originalApiData.value = JSON.parse(JSON.stringify(data));
|
|
if (data.fixedInfo) {
|
const clonedFixedInfo = JSON.parse(JSON.stringify(data.fixedInfo));
|
// 合并数据,保留表单中已有的值,补充接口返回的值
|
Object.assign(newItem.fixedInfo, clonedFixedInfo, {
|
// 确保这些字段从接口数据中获取
|
id: clonedFixedInfo.id || null,
|
teamId: clonedFixedInfo.teamId || null,
|
wireId: clonedFixedInfo.wireId || (wireId.value ? Number(wireId.value) : null),
|
});
|
}
|
if (data.drawWireInfo) {
|
const clonedDrawWireInfo = JSON.parse(JSON.stringify(data.drawWireInfo));
|
// 合并数据,保留表单中已有的值,补充接口返回的值
|
Object.assign(newItem.inspectionResult, clonedDrawWireInfo, {
|
// 确保这些字段从接口数据中获取
|
dia: clonedDrawWireInfo.dia || null,
|
twistedLayer: clonedDrawWireInfo.twistedLayer || null,
|
wireId: clonedDrawWireInfo.wireId || (wireId.value ? String(wireId.value) : null),
|
});
|
}
|
}
|
} catch (error) {
|
console.error("获取默认数据失败:", error);
|
}
|
|
currentFormData.value = JSON.parse(JSON.stringify(newItem));
|
previousAppearanceValueMap.value.set(
|
currentFormData.value.id,
|
JSON.parse(JSON.stringify(currentFormData.value.inspectionResult.appearance || []))
|
);
|
dialogVisible.value = true;
|
};
|
|
// 编辑自检
|
const handleEdit = async (row: any) => {
|
// 编辑时也需要获取接口数据,确保有所有必要字段
|
try {
|
const { code, data } = await ManageApi.getDrawInspectStyleByGetDrawInspect({
|
wireId: wireId.value,
|
poleModel: poleModel.value,
|
poleNumber: poleNumber.value,
|
});
|
|
if (code === 200 && data) {
|
originalApiData.value = JSON.parse(JSON.stringify(data));
|
}
|
} catch (error) {
|
console.error("获取默认数据失败:", error);
|
}
|
|
currentFormData.value = JSON.parse(JSON.stringify(row));
|
previousAppearanceValueMap.value.set(
|
row.id,
|
JSON.parse(JSON.stringify(row.inspectionResult.appearance || []))
|
);
|
dialogVisible.value = true;
|
};
|
|
// 表单提交
|
const handleFormSubmit = async (formData: any) => {
|
const aluminumWireDistance = formData.inspectionResult.aluminumWireDistance;
|
if (aluminumWireDistance < 25) {
|
toast.error("外层铝线离侧板边缘距离不能低于25mm");
|
return;
|
}
|
|
// 构建提交数据,确保包含所有必要字段
|
const saveData: any = {
|
fixedInfo: JSON.parse(JSON.stringify(formData.fixedInfo)),
|
inspectionResult: JSON.parse(JSON.stringify(formData.inspectionResult)),
|
wireId: wireId.value,
|
};
|
|
// 编辑时,确保 fixedInfo.id 被正确传递
|
// 优先使用 formData 中的 id(编辑时应该存在)
|
if (formData.fixedInfo?.id !== null && formData.fixedInfo?.id !== undefined) {
|
saveData.fixedInfo.id = formData.fixedInfo.id;
|
} else if (!formData.isNew) {
|
// 如果不是新增,尝试从数据列表中查找 id
|
const existingItem = dataList.value.find((item) => item.id === formData.id);
|
if (existingItem?.fixedInfo?.id) {
|
saveData.fixedInfo.id = existingItem.fixedInfo.id;
|
}
|
}
|
|
// 如果是从接口获取的数据,补充表单中没有的字段
|
if (originalApiData.value) {
|
// 补充 fixedInfo 中缺失的字段
|
if (originalApiData.value.fixedInfo) {
|
const apiFixedInfo = originalApiData.value.fixedInfo;
|
// 确保这些字段存在(如果表单中没有,使用接口返回的值)
|
// 只有在 saveData.fixedInfo.id 不存在时才使用接口返回的 id
|
if (apiFixedInfo.id !== undefined && !saveData.fixedInfo.id) {
|
saveData.fixedInfo.id = apiFixedInfo.id;
|
}
|
if (apiFixedInfo.teamId !== undefined) {
|
saveData.fixedInfo.teamId = apiFixedInfo.teamId;
|
}
|
if (apiFixedInfo.wireId !== undefined) {
|
saveData.fixedInfo.wireId = apiFixedInfo.wireId;
|
}
|
// 补充其他可能缺失的字段
|
if (apiFixedInfo.recordDate && !saveData.fixedInfo.recordDate) {
|
saveData.fixedInfo.recordDate = apiFixedInfo.recordDate;
|
}
|
}
|
|
// 补充 inspectionResult 中缺失的字段
|
if (originalApiData.value.drawWireInfo) {
|
const apiInspectionResult = originalApiData.value.drawWireInfo;
|
// 确保这些字段存在(如果表单中没有,使用接口返回的值)
|
if (apiInspectionResult.dia !== undefined) {
|
saveData.inspectionResult.dia = apiInspectionResult.dia;
|
}
|
if (apiInspectionResult.twistedLayer !== undefined) {
|
saveData.inspectionResult.twistedLayer = apiInspectionResult.twistedLayer;
|
}
|
if (apiInspectionResult.wireId !== undefined) {
|
saveData.inspectionResult.wireId = apiInspectionResult.wireId;
|
}
|
}
|
}
|
|
// 确保 wireId 字段存在
|
if (!saveData.fixedInfo.wireId && wireId.value) {
|
saveData.fixedInfo.wireId = Number(wireId.value);
|
}
|
if (!saveData.inspectionResult.wireId && wireId.value) {
|
saveData.inspectionResult.wireId = String(wireId.value);
|
}
|
|
try {
|
const { code, data } = await ManageApi.addSelfInspection(saveData);
|
|
if (code === 200) {
|
toast.success("保存成功");
|
dialogVisible.value = false;
|
originalApiData.value = null; // 清空原始数据
|
previousAppearanceValueMap.value.delete(formData.id);
|
await getData();
|
} else {
|
toast.error(data || "保存失败");
|
}
|
} catch (error) {
|
console.error("保存失败:", error);
|
toast.error("保存失败");
|
}
|
};
|
|
// 关闭弹框
|
const handleCloseDialog = () => {
|
dialogVisible.value = false;
|
currentFormData.value = null;
|
originalApiData.value = null; // 清空原始数据
|
};
|
|
// 删除自检
|
const handleDelete = async (row: any) => {
|
try {
|
const res = await uni.showModal({
|
title: "提示",
|
content: "确定删除该自检记录吗?",
|
});
|
|
if (res.confirm) {
|
if (row.fixedInfo?.id && !row.isNew) {
|
const { code } = await ManageApi.deleteSelfInspection(row.fixedInfo.id);
|
|
if (code === 200) {
|
toast.success("删除成功");
|
await getData();
|
} else {
|
toast.error("删除失败");
|
}
|
} else {
|
const index = dataList.value.findIndex((item) => item.id === row.id);
|
if (index !== -1) {
|
dataList.value.splice(index, 1);
|
toast.success("删除成功");
|
}
|
}
|
}
|
} catch (error) {
|
console.error("删除自检失败:", error);
|
toast.error("删除失败");
|
}
|
};
|
|
onLoad(async (options: any) => {
|
wireId.value = options.wireId || "";
|
poleModel.value = options.poleModel || "";
|
poleNumber.value = options.poleNumber || "";
|
await loadAppearanceDict();
|
await getData();
|
});
|
</script>
|
|
<style lang="scss" scoped>
|
.list {
|
min-height: calc(100vh - 30px);
|
padding: 12px 4px;
|
background: #f3f9f8;
|
|
:deep() {
|
.round {
|
border-radius: 4px;
|
}
|
}
|
}
|
|
.inspection-list {
|
margin-top: 12px;
|
}
|
|
.card_bg {
|
box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
|
padding-bottom: 10px;
|
border-radius: 8px;
|
overflow: hidden;
|
}
|
|
.card-content {
|
padding: 0 4px;
|
}
|
|
.info-section {
|
margin-bottom: 16px;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
.section-header {
|
display: flex;
|
align-items: center;
|
margin-bottom: 12px;
|
padding-bottom: 8px;
|
border-bottom: 1px solid #e6e6e6;
|
}
|
|
.section-title {
|
font-size: 14px;
|
font-weight: 600;
|
color: #252525;
|
margin-left: 6px;
|
}
|
|
.info-grid {
|
display: grid;
|
grid-template-columns: repeat(2, 1fr);
|
gap: 12px 16px;
|
}
|
|
.info-item {
|
display: flex;
|
align-items: flex-start;
|
min-height: 24px;
|
}
|
|
.info-item-full {
|
display: flex;
|
align-items: flex-start;
|
min-height: 24px;
|
grid-column: 1 / -1;
|
}
|
|
.info-label {
|
font-size: 13px;
|
color: #646874;
|
margin-right: 8px;
|
white-space: nowrap;
|
flex-shrink: 0;
|
}
|
|
.info-value {
|
font-size: 13px;
|
color: #252525;
|
flex: 1;
|
word-break: break-all;
|
}
|
</style>
|