<template>
|
<view class="fixed-header">
|
<view class="header-container">
|
<wd-button
|
icon="file-add"
|
:round="false"
|
size="small"
|
custom-class="add_btn"
|
@click="editList"
|
v-if="!isEdit"
|
>
|
编辑
|
</wd-button>
|
<wd-button
|
icon="close"
|
type="info"
|
:round="false"
|
size="small"
|
custom-class="add_btn"
|
@click="close"
|
v-if="isEdit"
|
>
|
取消
|
</wd-button>
|
<wd-button
|
icon="check"
|
type="success"
|
:round="false"
|
size="small"
|
custom-class="add_btn"
|
@click="saveList"
|
v-if="isEdit"
|
>
|
保存
|
</wd-button>
|
<view class="placeholder"></view>
|
<view class="scan-wrapper" @click="openScan">
|
<wd-icon name="scan" size="24px" color="#0D867F"></wd-icon>
|
</view>
|
</view>
|
</view>
|
<view class="list">
|
<!-- 基本信息模块 -->
|
<wd-row>
|
<view style="margin: 10rpx">
|
<text class="title">{{ "基本信息" }}</text>
|
</view>
|
<wd-col :span="24">
|
<wd-form-item label="日期" prop="recordDate">
|
{{ formatDate(recordData.fixedInfo?.recordDate) }}
|
</wd-form-item>
|
<wd-form-item label="班次" prop="workShift">
|
{{ formatValue(recordData.fixedInfo?.workShift) }}
|
</wd-form-item>
|
<wd-form-item label="型号规格" prop="model">
|
{{ formatValue(recordData.fixedInfo?.model) }}
|
</wd-form-item>
|
<wd-form-item label="成品线盘号" prop="systemNo">
|
{{ formatValue(recordData.fixedInfo?.systemNo) }}
|
</wd-form-item>
|
<wd-form-item label="记录人" prop="createUserName">
|
{{ formatValue(recordData.fixedInfo?.createUserName) }}
|
</wd-form-item>
|
<wd-form-item label="机台" prop="deviceModel">
|
{{ formatValue(recordData.fixedInfo?.deviceModel) }}
|
</wd-form-item>
|
<wd-form-item label="产品类别" prop="productType">
|
{{ formatValue(recordData.fixedInfo?.productType) }}
|
</wd-form-item>
|
<wd-form-item label="生产长度" prop="actuallyLength">
|
{{ formatValue(recordData.fixedInfo?.actuallyLength, "m") }}
|
</wd-form-item>
|
<wd-form-item label="张力设置" prop="twistTension">
|
{{ formatValue(recordData.fixedInfo?.twistTension, "N/m") }}
|
</wd-form-item>
|
<!-- 绞制外径(可编辑) -->
|
<wd-form-item label="绞制外径" prop="twistDiameter" required>
|
<template v-if="isEdit">
|
<wd-input
|
v-model="formData.twistDiameter"
|
placeholder="请输入绞制外径(mm)"
|
type="number"
|
/>
|
</template>
|
<template v-else>
|
{{ formatValue(formData.twistDiameter, "mm") }}
|
</template>
|
</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="recordPosition">
|
{{ recordData.structureInfo?.recordPosition || "-" }}
|
</wd-form-item>
|
<wd-form-item label="记录人" prop="createUserName">
|
{{ recordData.structureInfo?.createUserName || "-" }}
|
</wd-form-item>
|
<wd-form-item label="状态" prop="status">
|
<wd-tag custom-class="space" :type="getStatusType(recordData.structureInfo?.status)">
|
{{ getStatusText(recordData.structureInfo?.status) }}
|
</wd-tag>
|
</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="structureFormula" required>
|
<template v-if="isEdit">
|
<wd-input v-model="formData.structureFormula" placeholder="请输入成品结构" />
|
</template>
|
<template v-else>
|
{{ formData.structureFormula || "-" }}
|
</template>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
|
<!-- 结构标准值和实测(可编辑) -->
|
<wd-row v-if="formData.structureItems.length">
|
<view style="margin: 10rpx">
|
<text class="title">{{ "结构标准值和实测" }}</text>
|
</view>
|
<wd-col
|
:span="24"
|
v-for="(item, index) in formData.structureItems"
|
:key="index"
|
style="padding-bottom: 10px"
|
>
|
<wd-form-item
|
prop="structureItemsGroup"
|
:label="formatValue(item.structureName)"
|
label-width="400rpx"
|
style="color: red"
|
required
|
></wd-form-item>
|
<wd-form-item label="标准值" prop="structureValue" required>
|
{{ formatValue(item.structureValue) }}
|
</wd-form-item>
|
<wd-form-item label="实测根数" prop="actualValue1" required>
|
<template v-if="isEdit">
|
<wd-input v-model="item.actualValue1" placeholder="请输入实测根数" type="number" />
|
</template>
|
<template v-else>
|
{{ formatValue(item.actualValue1, "根") }}
|
</template>
|
</wd-form-item>
|
<wd-form-item label="实测直径" prop="actualValue2" required>
|
<template v-if="isEdit">
|
<wd-input
|
v-model="item.actualValue2"
|
placeholder="请输入实测直径(mm)"
|
type="number"
|
/>
|
</template>
|
<template v-else>
|
{{ formatValue(item.actualValue2, "mm") }}
|
</template>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
|
<!-- 绞线工艺质量控制(可编辑) -->
|
<wd-row v-if="formData.inspectTwist.length">
|
<view style="margin: 10rpx">
|
<text class="title">{{ "绞线工艺质量控制" }}</text>
|
</view>
|
<wd-col
|
:span="24"
|
v-for="(item, index) in formData.inspectTwist"
|
:key="index"
|
style="padding-bottom: 10px"
|
>
|
<wd-form-item
|
:label="formatValue(item.twistName)"
|
label-width="400rpx"
|
style="color: red"
|
prop="inspectTwistGroup"
|
required
|
></wd-form-item>
|
<wd-form-item label="绞向" prop="direction" required>
|
<template v-if="isEdit">
|
<wd-select-picker
|
label=""
|
v-model="item.direction"
|
:columns="twistDirectionOptions"
|
type="radio"
|
placeholder="请选择绞向"
|
:clearable="false"
|
></wd-select-picker>
|
</template>
|
<template v-else>
|
{{ formatValue(item.direction) }}
|
</template>
|
</wd-form-item>
|
<wd-form-item label="节距" prop="pitch" required>
|
<template v-if="isEdit">
|
<wd-input v-model="item.pitch" placeholder="请输入节距(mm)" type="number" />
|
</template>
|
<template v-else>
|
{{ formatValue(item.pitch, "mm") }}
|
</template>
|
</wd-form-item>
|
<wd-form-item label="节径比" prop="pitchRatio" required>
|
{{ formatValue(item.pitchRatio) }}
|
</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>
|
<template v-if="isEdit">
|
<wd-checkbox-group
|
v-model="formData.productAppearance"
|
inline
|
v-for="(opt, idx) in appearanceOptions"
|
:key="idx"
|
style="text-align: justify"
|
>
|
<wd-checkbox :modelValue="opt.value" style="width: 100px">
|
{{ opt.label }}
|
</wd-checkbox>
|
</wd-checkbox-group>
|
</template>
|
<template v-else>
|
{{ formatProductAppearance(formData.productAppearance) }}
|
</template>
|
</wd-form-item>
|
<wd-form-item label="结论" prop="conclusion" required>
|
<template v-if="isEdit">
|
<wd-radio-group v-model="formData.conclusion" inline class="conclusion-radio-group">
|
<wd-radio
|
v-for="(opt, idx) in conclusionOptions"
|
:key="idx"
|
:value="opt.value"
|
shape="dot"
|
>
|
{{ opt.label }}
|
</wd-radio>
|
</wd-radio-group>
|
</template>
|
<template v-else>
|
{{ formatValue(formData.conclusion) }}
|
</template>
|
</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="sampleComplete" required>
|
<template v-if="isEdit">
|
<wd-radio-group v-model="formData.sampleComplete" inline class="conclusion-radio-group">
|
<wd-radio
|
v-for="(opt, idx) in sampleCompleteOptions"
|
:key="idx"
|
:value="opt.value"
|
shape="dot"
|
>
|
{{ opt.label }}
|
</wd-radio>
|
</wd-radio-group>
|
</template>
|
<template v-else>
|
{{ formatValue(formData.sampleComplete) }}
|
</template>
|
</wd-form-item>
|
</wd-col>
|
</wd-row>
|
|
<!-- 附件模块(含上传功能) -->
|
<wd-row class="attachment-section">
|
<view style="margin: 10rpx">
|
<text class="title">{{ "附件" }}</text>
|
</view>
|
<wd-col :span="24">
|
<AttachmentUpload
|
:detailData="detailData"
|
:isEdit="isEdit"
|
:deviceType="paramsType"
|
ref="attachmentRef"
|
v-if="detailDataLoaded"
|
/>
|
</wd-col>
|
</wd-row>
|
|
<wd-popup v-model="show" custom-style="border-radius:32rpx;" @close="handleClose">
|
<div class="image-preview">
|
<img :src="previewImageUrl" alt="预览图片" style="width: 100%; height: auto" />
|
</div>
|
</wd-popup>
|
<Scan ref="scanRef" emitName="scan" />
|
<wd-toast />
|
</view>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, reactive, computed } from "vue";
|
import { onLoad } from "@dcloudio/uni-app";
|
import RoutingInspectionApi from "@/api/routingInspection/routingInspection";
|
import Scan from "@/components/scan/index.vue";
|
import { useToast } from "wot-design-uni";
|
import AttachmentUpload from "../upload.vue";
|
|
const paramsType = ref("");
|
const paramsId = ref("");
|
const recordData = ref<any>({ structureInfo: { files: [], structureRecordResult: {} } });
|
const show = ref(false);
|
const previewImageUrl = ref("");
|
const isEdit = ref(false);
|
const tempFiles = ref<any[]>([]); // 临时存储新上传的附件
|
const deviceUid = ref("");
|
const scanRef = ref();
|
const toast = useToast();
|
const attachmentRef = ref<any>(null);
|
const detailData = reactive<any>({});
|
const detailDataLoaded = ref(false);
|
|
const formData = reactive({
|
twistDiameter: "", // 绞制外径
|
structureFormula: "", // 成品结构
|
structureItems: [], // 结构标准值和实测
|
inspectTwist: [], // 绞线工艺质量控制
|
productAppearance: [] as string[], // 产品外观(改为数组存储选中值)
|
conclusion: "", // 结论(改为数组存储选中值)
|
sampleComplete: "", // 样品是否齐全
|
});
|
|
const twistDirectionOptions = [
|
{ label: "左向", value: "左向" },
|
{ label: "右向", value: "右向" },
|
];
|
|
const appearanceOptions = [
|
{ label: "无外观问题", value: "无外观问题" },
|
{ label: "表面划伤", value: "表面划伤" },
|
{ label: "直径不均", value: "直径不均" },
|
{ label: "其他缺陷", value: "其他缺陷" },
|
];
|
|
const conclusionOptions = [
|
{ label: "合格", value: "合格" },
|
{ label: "不合格", value: "不合格" },
|
];
|
const sampleCompleteOptions = [
|
{ label: "是", value: "是" },
|
{ label: "否", value: "否" },
|
];
|
|
const initFormData = () => {
|
const structureResult = recordData.value.structureInfo?.structureRecordResult || {};
|
const inspectionResult = recordData.value.inspectionResult || {};
|
|
formData.twistDiameter = inspectionResult.twistDiameter || "";
|
formData.structureFormula = structureResult.inspectStructure?.structureFormula || "";
|
formData.sampleComplete = inspectionResult.sampleComplete || "";
|
formData.conclusion = structureResult.conclusion || "";
|
formData.productAppearance = Array.isArray(structureResult.productAppearance)
|
? structureResult.productAppearance
|
: structureResult.productAppearance
|
? [structureResult.productAppearance]
|
: [];
|
|
formData.structureItems = JSON.parse(
|
JSON.stringify(structureResult.inspectStructure?.structureItems || [])
|
);
|
formData.inspectTwist = JSON.parse(JSON.stringify(structureResult.inspectTwist || []));
|
|
formData.inspectTwist.forEach((item: any) => {
|
if (!item.direction) item.direction = "";
|
});
|
};
|
|
const getDetailData = async (id: string, deviceType: string) => {
|
try {
|
const response = await RoutingInspectionApi.getStrandedInspectionStructureInfoById({ id });
|
recordData.value = response.data;
|
detailData.value = response.data.structureInfo;
|
console.log("detailData.value", detailData.value);
|
tempFiles.value = []; // 清空临时文件
|
initFormData(); // 数据返回后初始化表单
|
detailDataLoaded.value = true; // 数据加载完成后,渲染子组件
|
console.log("父组件-数据就绪后打印");
|
} catch (error) {
|
console.error("获取详情失败:", error);
|
uni.showToast({ title: "加载失败", icon: "error" });
|
}
|
};
|
|
// 页面加载
|
onLoad((options: any) => {
|
try {
|
paramsId.value = options.id;
|
paramsType.value = options.deviceType;
|
getDetailData(options.id, options.deviceType);
|
} catch (error) {
|
console.error("获取详情失败:", error);
|
uni.showToast({ title: "加载失败", icon: "error" });
|
}
|
});
|
|
// 编辑模式切换
|
const editList = () => {
|
isEdit.value = true;
|
};
|
|
// 取消编辑(重置表单)
|
const close = () => {
|
isEdit.value = false;
|
tempFiles.value = [];
|
initFormData();
|
};
|
|
// 保存编辑(含必填项校验)
|
const saveList = async () => {
|
// 1. 基础字段校验
|
if (!formData.structureFormula) return uni.showToast({ title: "成品结构为必填项", icon: "none" });
|
if (!formData.twistDiameter) return uni.showToast({ title: "绞制外径为必填项", icon: "none" });
|
if (!formData.productAppearance.length)
|
return uni.showToast({ title: "产品外观为必填项", icon: "none" });
|
if (!formData.conclusion) return uni.showToast({ title: "结论为必填项", icon: "none" });
|
if (!formData.sampleComplete)
|
return uni.showToast({ title: "样品是否齐全为必填项", icon: "none" });
|
// 2. 结构项循环校验
|
for (const item of formData.structureItems) {
|
if (!item.structureValue)
|
return uni.showToast({ title: `${item.structureName}标准值为必填项`, icon: "none" });
|
if (!item.actualValue1)
|
return uni.showToast({ title: `${item.structureName}实测根数为必填项`, icon: "none" });
|
if (!item.actualValue2)
|
return uni.showToast({ title: `${item.structureName}实测直径为必填项`, icon: "none" });
|
}
|
|
// 3. 绞线工艺项循环校验
|
for (const item of formData.inspectTwist) {
|
if (!item.direction)
|
return uni.showToast({ title: `${item.twistName}绞向为必填项`, icon: "none" });
|
if (!item.pitch) return uni.showToast({ title: `${item.twistName}节距为必填项`, icon: "none" });
|
if (!item.pitchRatio)
|
return uni.showToast({ title: `${item.twistName}节径比为必填项`, icon: "none" });
|
}
|
console.log("1111", deviceUid.value);
|
if (!deviceUid.value) return uni.showToast({ title: "请扫描二维码", icon: "none" });
|
const { newFiles } = attachmentRef.value.getSubmitFiles();
|
console.log("newFiles", newFiles);
|
const allFileIds = [...newFiles];
|
try {
|
const res = await RoutingInspectionApi.strandedPatrolCheckInspection({
|
deviceUid: deviceUid.value,
|
id: paramsId.value,
|
result: {
|
twistDiameter: formData.twistDiameter,
|
structureFormula: formData.structureFormula,
|
structureItems: formData.structureItems,
|
inspectTwist: formData.inspectTwist,
|
productAppearance: formData.productAppearance,
|
conclusion: formData.conclusion,
|
sampleComplete: formData.sampleComplete,
|
},
|
inspectionResult: {
|
sampleComplete: formData.sampleComplete,
|
},
|
processInspectionAttachmentList: allFileIds,
|
});
|
|
if (res.code === 200) {
|
uni.showToast({ title: "保存成功", icon: "success" });
|
isEdit.value = false;
|
getDetailData(paramsId.value, paramsType.value);
|
} else {
|
uni.showModal({ title: res.msg || "保存失败", icon: "error" });
|
}
|
} catch (e) {
|
console.error("保存失败:", e);
|
uni.showModal({ title: e.message || "保存失败", icon: "error" });
|
}
|
};
|
|
const handleClose = () => {
|
show.value = false;
|
};
|
|
// 状态类型映射
|
const getStatusType = (status: number) => {
|
switch (status) {
|
case 0:
|
return "warning"; // 待巡检
|
case 1:
|
return "danger"; // 已驳回
|
case 2:
|
return "info"; // 待审核
|
case 3:
|
return "success"; // 通过
|
default:
|
return "info";
|
}
|
};
|
|
// 状态文本映射
|
const getStatusText = (status: number) => {
|
switch (status) {
|
case 0:
|
return "待巡检";
|
case 1:
|
return "已驳回";
|
case 2:
|
return "待审核";
|
case 3:
|
return "通过";
|
default:
|
return "未知";
|
}
|
};
|
|
// 格式化产品外观显示
|
const formatProductAppearance = (productAppearance: string[]) => {
|
if (!productAppearance || productAppearance.length === 0) return "-";
|
return productAppearance.join("、");
|
};
|
|
// 格式化数值显示
|
const formatValue = (value: any, unit?: string) => {
|
if (value === null || value === undefined || value === "") return "-";
|
return unit ? `${value}${unit}` : value;
|
};
|
|
// 格式化日期显示
|
const formatDate = (date: string) => {
|
if (!date) return "-";
|
return new Date(date).toLocaleDateString("zh-CN", {
|
year: "numeric",
|
month: "2-digit",
|
day: "2-digit",
|
});
|
};
|
|
const openScan = () => {
|
scanRef.value.triggerScan();
|
};
|
const getScanCode = (params: any) => {
|
console.log("完整参数:", params);
|
let codeObj = {};
|
try {
|
codeObj = JSON.parse(params.code);
|
} catch (err) {
|
console.error("JSON解析失败:", err);
|
toast.error("扫码数据异常");
|
return;
|
}
|
deviceUid.value = codeObj?.uid;
|
toast.success("扫码成功");
|
};
|
// 确保先移除再添加监听
|
const setupScanListener = () => {
|
uni.$off("scan", getScanCode); // 先移除旧的
|
uni.$on("scan", getScanCode); // 再添加新的
|
};
|
onUnmounted(() => {
|
// 开启广播监听事件
|
uni.$off("scan", getScanCode);
|
console.log("离开1");
|
});
|
onMounted(() => {
|
// 开启广播监听事件
|
setupScanListener();
|
console.log("显示1");
|
});
|
</script>
|
|
<style lang="scss" scoped>
|
.fixed-header {
|
position: fixed;
|
top: 44;
|
left: 0;
|
right: 0;
|
background: #f3f9f8;
|
z-index: 999;
|
padding: 12px;
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
min-height: 60px;
|
box-sizing: border-box;
|
overflow: visible;
|
}
|
|
.header-container {
|
display: flex;
|
align-items: center;
|
width: 100%;
|
gap: 10px;
|
}
|
|
.placeholder {
|
flex: 1;
|
}
|
|
.scan-wrapper {
|
width: 38px;
|
height: 38px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
padding: 6px;
|
flex-shrink: 0;
|
}
|
|
.list {
|
padding: 12px;
|
padding-top: 84px;
|
background: #f3f9f8;
|
min-height: 100vh;
|
box-sizing: border-box;
|
overflow-y: auto;
|
}
|
|
.title {
|
position: relative;
|
margin-left: 10px;
|
font-size: 16px;
|
font-weight: 500;
|
color: #0d867f;
|
}
|
|
.title::after {
|
position: absolute;
|
content: "";
|
top: 4px;
|
left: -10px;
|
width: 4px;
|
height: 16px;
|
background: #0d867f;
|
border-radius: 2px;
|
}
|
|
// 产品外观和结论选择器样式(一行两个)
|
.checkbox-group {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 16rpx;
|
padding: 8rpx 0;
|
}
|
|
.checkbox-item {
|
width: calc(50% - 8rpx);
|
margin-bottom: 8rpx;
|
}
|
|
// 附件相关样式
|
.attachment-section {
|
width: 100%;
|
}
|
|
.attachment-grid {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 10px;
|
padding: 10px 0;
|
}
|
|
.attachment-item {
|
width: calc(25% - 10px);
|
box-sizing: border-box;
|
position: relative;
|
}
|
|
.upload-btn {
|
width: 80px;
|
height: 80px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
border: 1px dashed #ccc;
|
border-radius: 4px;
|
box-sizing: border-box;
|
}
|
|
.upload-icon {
|
font-size: 32px;
|
color: #0d867f;
|
}
|
|
// 附件删除图标
|
.delete-icon {
|
position: absolute;
|
top: -8px;
|
right: -8px;
|
width: 24px;
|
height: 24px;
|
background-color: rgba(255, 0, 0, 0.8);
|
color: white;
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
z-index: 10;
|
}
|
|
@media (max-width: 768px) {
|
.attachment-item {
|
width: calc(25% - 10px);
|
}
|
}
|
|
// 编辑模式下表单组件样式优化
|
:deep(.wd-form-item) {
|
margin-bottom: 8rpx;
|
}
|
|
:deep(.wd-input, .wd-select, .wd-radio-group, .wd-checkbox-group) {
|
width: 100%;
|
box-sizing: border-box;
|
}
|
|
:deep(.wd-form-item__label) {
|
&::after {
|
content: "*";
|
color: red;
|
margin-left: 4rpx;
|
}
|
}
|
|
// 修复选择器样式
|
:deep(.wd-select) {
|
width: 100%;
|
}
|
|
:deep(.wd-checkbox) {
|
margin-right: 0;
|
}
|
.conclusion-radio-group {
|
display: flex;
|
align-items: flex-start; // 垂直方向顶部对齐(上移关键)
|
gap: 20rpx; // 选项之间的间距
|
}
|
</style>
|