| src/api/routingInspection/routingInspection.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/routingInspection/detail/indexJX.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/routingInspection/detail/indexLS.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/routingInspection/product_card/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | 
src/api/routingInspection/routingInspection.ts
@@ -34,6 +34,22 @@ // data: params, }); }, // 拉丝巡检保存 drawPatrolCheckInspection(data: any) { return request<BaseResult<any>>({ url: "/wireInspection/drawPatrolCheckInspection?deviceUid=" + data.deviceUid, method: "POST", data: data, }); }, // 绞线巡检保存 strandedPatrolCheckInspection(data: any) { return request<BaseResult<any>>({ url: "/wireInspection/strandedPatrolCheckInspection?deviceUid=" + data.deviceUid, method: "POST", data: data, }); }, }; export default RoutingInspectionApi; src/pages/routingInspection/detail/indexJX.vue
@@ -73,11 +73,22 @@ <wd-form-item label="张力设置" prop="twistTension"> {{ formatValue(recordData.fixedInfo?.twistTension, "N/m") }} </wd-form-item> <wd-form-item label="绞制外径" prop="twistDiameter"> {{ formatValue(recordData.inspectionResult?.twistDiameter, "mm") }} <!-- 绞制外径(可编辑) --> <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"> @@ -97,27 +108,32 @@ </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="inspectStructure"> {{ recordData.structureInfo.structureRecordResult.inspectStructure.structureFormula || "-" }} <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="recordData.structureInfo.structureRecordResult.inspectStructure.structureItems"> <!-- 结构标准值和实测(可编辑) --> <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 recordData.structureInfo.structureRecordResult.inspectStructure .structureItems" v-for="(item, index) in formData.structureItems" :key="index" style="padding-bottom: 10px" > @@ -125,26 +141,42 @@ :label="formatValue(item.structureName)" label-width="400rpx" style="color: red" required ></wd-form-item> <wd-form-item label="标准值" prop="structureValue"> <wd-form-item label="标准值" prop="structureValue" required> {{ formatValue(item.structureValue) }} </wd-form-item> <wd-form-item label="实测根数" prop="actualValue1"> <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"> <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="recordData.structureInfo?.structureRecordResult?.inspectTwist"> <!-- 绞线工艺质量控制(可编辑) --> <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 recordData.structureInfo.structureRecordResult.inspectTwist" v-for="(item, index) in formData.inspectTwist" :key="index" style="padding-bottom: 10px" > @@ -152,57 +184,115 @@ :label="formatValue(item.twistName)" label-width="400rpx" style="color: red" required ></wd-form-item> <wd-form-item label="绞向" prop="direction"> <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">{{ formatValue(item.pitch, "mm") }}</wd-form-item> <wd-form-item label="节径比" prop="pitchRatio"> <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="conclusion"> {{ formatValue(recordData.structureInfo.structureRecordResult.conclusion) }} <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="productAppearance"> {{ formatProductAppearance( recordData.structureInfo.structureRecordResult.productAppearance ) }} <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"> {{ formatValue(recordData.inspectionResult?.sampleComplete) }} <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> <!-- 用 flex 容器包裹图片列,实现自动换行 --> <view class="attachment-grid"> <wd-col v-for="(file, index) in recordData.structureInfo.files" :key="index" class="attachment-item" > <!-- 已上传附件(包含新上传的) --> <wd-col v-for="(file, index) in allFiles" :key="file.id || index" class="attachment-item"> <wd-img :width="80" :height="80" :src="file.url" @click="previewImage(file.url)"> <template #error> <view class="error-wrap">加载失败</view> @@ -213,26 +303,276 @@ </view> </template> </wd-img> <!-- 编辑模式下显示删除按钮 --> <!-- <wd-icon v-if="isEdit" name="close-circle" class="delete-icon" @click.stop="deleteFile(file.id || index)" ></wd-icon> --> </wd-col> <!-- 上传按钮(仅编辑模式显示) --> <wd-col v-if="isEdit" class="attachment-item upload-btn"> <wd-upload :multiple="true" :max-count="5" :before-upload="beforeUpload" @success="handleUploadSuccess" @fail="handleUploadFail" > <view class="upload-icon">+</view> </wd-upload> </wd-col> </view> </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"; // 核心状态 const paramsId = ref(""); const recordData = ref<any>({}); 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 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 allFiles = computed(() => { return [...(recordData.value.structureInfo?.files || []), ...tempFiles.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; tempFiles.value = []; // 清空临时文件 initFormData(); // 数据返回后初始化表单 } catch (error) { console.error("获取详情失败:", error); uni.showToast({ title: "加载失败", icon: "error" }); } }; // 页面加载 onLoad((options: any) => { paramsId.value = options.id; getDetailData(options.id, options.deviceType); }); // 编辑模式切换 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" }); // 4. 提交数据到接口 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: tempFiles.value.map((f) => f.url), // 新上传的附件 }); if (res.code === 200) { uni.showToast({ title: "保存成功", icon: "success" }); isEdit.value = false; getDetailData(paramsId.value, recordData.value.deviceType); // 刷新数据 } else { uni.showModal({ title: res.msg || "保存失败", icon: "error" }); } } catch (e) { console.error("保存失败:", e); uni.showModal({ title: e.message || "保存失败", icon: "error" }); } }; // 附件上传前置校验 const beforeUpload = (file: any) => { // 限制图片大小不超过2M const maxSize = 2 * 1024 * 1024; if (file.size > maxSize) { uni.showToast({ title: "图片大小不能超过2M", icon: "none" }); return false; } return true; }; // 附件上传成功回调 const handleUploadSuccess = (res: any) => { // 假设接口返回格式: { url: 'xxx', id: 'xxx' } if (Array.isArray(res)) { tempFiles.value = [ ...tempFiles.value, ...res.map((file) => ({ ...file, id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, // 生成临时ID })), ]; } else { tempFiles.value.push({ ...res, id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, }); } }; // 附件上传失败回调 const handleUploadFail = (err: any) => { uni.showToast({ title: "附件上传失败", icon: "error" }); }; // 删除附件 const deleteFile = (id: string | number) => { // 删除临时文件 tempFiles.value = tempFiles.value.filter((file) => file.id !== id); // 如果是原有文件,需要标记删除(实际项目中可能需要接口交互) if (typeof id !== "string" || !id.startsWith("temp-")) { // 这里可以实现删除原有文件的逻辑 recordData.value.structureInfo.files = recordData.value.structureInfo.files.filter( (file: any, index: number) => index !== id ); } }; // 图片预览 const previewImage = (url: string) => { previewImageUrl.value = url; show.value = true; }; const handleClose = () => { show.value = false; }; // 状态类型映射 const getStatusType = (status: number) => { @@ -266,12 +606,6 @@ } }; // 获取外观文本 const getAppearanceText = (appearance: string[]) => { if (!appearance || appearance.length === 0) return "-"; return appearance.join("、"); }; // 格式化产品外观显示 const formatProductAppearance = (productAppearance: string[]) => { if (!productAppearance || productAppearance.length === 0) return "-"; @@ -294,82 +628,40 @@ }); }; // 格式化结构值显示 const formatStructureValue = (value1: any, value2: any) => { const val1 = value1 || "-"; const val2 = value2 ? `${value2}mm` : "-"; return { count: val1, diameter: val2 }; const openScan = () => { scanRef.value.triggerScan(); }; const getDetailData = async (id: string, deviceType: string) => { const getScanCode = (params: any) => { console.log("完整参数:", params); let codeObj = {}; try { let response; // 获取绞线单个结构 response = await RoutingInspectionApi.getStrandedInspectionStructureInfoById({ id: id, }); recordData.value = response.data; console.log(recordData.value); } catch (error) { console.error("获取详情失败:", error); codeObj = JSON.parse(params.code); } catch (err) { console.error("JSON解析失败:", err); toast.error("扫码数据异常"); return; // 解析失败直接返回,避免后续错误 } deviceUid.value = codeObj?.uid; toast.success("扫码成功"); }; onLoad((options: any) => { paramsId.value = options.id; getDetailData(options.id, options.deviceType); // 确保先移除再添加监听 const setupScanListener = () => { uni.$off("scan", getScanCode); // 先移除旧的 uni.$on("scan", getScanCode); // 再添加新的 }; onUnmounted(() => { // 开启广播监听事件 uni.$off("scan", getScanCode); console.log("离开1"); }); const previewImage = (url: string) => { previewImageUrl.value = url; show.value = true; }; const handleClose = () => { show.value = false; }; // 编辑列表 const editList = () => {}; // 关闭 const close = () => {}; // 保存列表 const saveList = async () => { // try { // let response; // // 保存列表 // response = await RoutingInspectionApi.saveStrandedInspectionStructureInfo({ // id: paramsId.value, // structureInfo: recordData.value.structureInfo, // }); // if (response.code === 200) { // uni.showToast({ // title: "保存成功", // icon: "success", // }); // // 刷新详情数据 // getDetailData(paramsId.value, recordData.value.deviceType); // } else { // uni.showToast({ // title: response.msg || "保存失败", // icon: "error", // }); // } // } catch (error) { // console.error("保存列表失败:", error); // uni.showToast({ // title: "保存失败", // icon: "error", // }); // } }; onMounted(() => { // 开启广播监听事件 setupScanListener(); console.log("显示1"); }); </script> <style lang="scss" scoped> .placeholder { flex: 1; } .fixed-header { position: fixed; top: 44; @@ -391,14 +683,8 @@ gap: 10px; } .search-wrapper { .placeholder { flex: 1; min-width: 0; } :deep(.search-wrapper .wd-search) { width: 100% !important; min-width: 0 !important; } .scan-wrapper { @@ -413,11 +699,11 @@ .list { padding: 12px; padding-top: 84px; background: #f3f9f8; min-height: 100vh; box-sizing: border-box; overflow-y: auto; } .title { @@ -439,6 +725,20 @@ 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%; } @@ -453,6 +753,39 @@ .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) { @@ -460,4 +793,36 @@ 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> src/pages/routingInspection/detail/indexLS.vue
@@ -68,7 +68,6 @@ <wd-form-item label="型号" prop="poleModel"> {{ formatValue(detailData.fixedInfo?.poleModel) }} </wd-form-item> <wd-form-item label="批次" prop="poleNumber"> {{ formatValue(detailData.fixedInfo?.poleNumber) }} </wd-form-item> @@ -80,6 +79,7 @@ </wd-form-item> </wd-col> </wd-row> <!-- 自检记录详情模块 --> <wd-row> <view style="margin: 10rpx"> @@ -96,6 +96,7 @@ </wd-form-item> </wd-col> </wd-row> <!-- 检验结果 --> <wd-row> <view style="margin: 10rpx"> @@ -105,52 +106,186 @@ <wd-form-item label="单丝直径" prop="dia"> {{ formatValue(detailData.inspectionResult?.dia, "mm") || "-" }} </wd-form-item> <wd-form-item label="最大直径" prop="maxDia"> <wd-form-item label="最大直径" prop="maxDia" required> <template v-if="isEdit"> <wd-input v-model="formData.maxDia" placeholder="请输入最大直径(mm)" type="number" /> </template> <template v-else> {{ formatValue(detailData.inspectionResult?.maxDia, "mm") || "-" }} </template> </wd-form-item> <wd-form-item label="最小直径" prop="minDia"> <wd-form-item label="最小直径" prop="minDia" required> <template v-if="isEdit"> <wd-input v-model="formData.minDia" placeholder="请输入最小直径(mm)" type="number" /> </template> <template v-else> {{ formatValue(detailData.inspectionResult?.minDia, "mm") || "-" }} </template> </wd-form-item> <wd-form-item label="外观" prop="appearance"> {{ formatProductAppearance(detailData.inspectionResult?.appearance) || "-" }} <wd-form-item label="外观" prop="appearance" required> <template v-if="isEdit"> <wd-checkbox-group v-model="formData.appearance" 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(detailData.inspectionResult?.appearance).join("、") || "-" }} </template> </wd-form-item> <wd-form-item label="卷绕紧密" prop="windingTightness"> <wd-form-item label="卷绕紧密" prop="windingTightness" required> <template v-if="isEdit"> <wd-radio-group v-model="formData.windingTightness" 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(detailData.inspectionResult?.windingTightness) }} </template> </wd-form-item> <wd-form-item label="排列整齐" prop="arrangementNeatness"> <wd-form-item label="排列整齐" prop="arrangementNeatness" required> <template v-if="isEdit"> <wd-radio-group v-model="formData.arrangementNeatness" 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(detailData.inspectionResult?.arrangementNeatness) }} </template> </wd-form-item> <wd-form-item label="外层铝线离侧板边缘距离" prop="aluminumWireDistance" label-width="500rpx" label-width="360rpx" required > <template v-if="isEdit"> <wd-input v-model="formData.aluminumWireDistance" placeholder="请输入距离(mm)" type="number" /> </template> <template v-else> {{ formatValue(detailData.inspectionResult?.aluminumWireDistance, "mm") || "-" }} </template> </wd-form-item> <wd-form-item label="成品模后接头情况" prop="jointCondition" label-width="250rpx"> <wd-form-item label="成品模后接头情况" prop="jointCondition" label-width="280rpx" required > <template v-if="isEdit"> <wd-radio-group v-model="formData.jointCondition" inline class="conclusion-radio-group" > <wd-radio v-for="(opt, idx) in jointConditionOptions" :key="idx" :value="opt.value" shape="dot" > {{ opt.label }} </wd-radio> </wd-radio-group> </template> <template v-else> {{ formatValue(detailData.inspectionResult?.jointCondition) || "-" }} </template> </wd-form-item> <wd-form-item label="结论" prop="conclusion"> <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(detailData.inspectionResult?.conclusion) || "-" }} </template> </wd-form-item> </wd-col> </wd-row> <!-- 巡检结果 --> <wd-row v-if="detailData.processInspectionResult?.isFully"> <view style="margin: 10rpx"> <text class="title">{{ "巡检结果" }}</text> </view> <wd-col :span="24"> <wd-form-item label="铝杆前、中、尾样品是否齐全" prop="processInspectionUserName"> <wd-form-item label="铝杆前、中、尾样品是否齐全" prop="isFully" required> <template v-if="isEdit"> <wd-radio-group v-model="formData.isFully" 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> <wd-tag custom-class="space" :type="detailData.processInspectionResult?.isFully ? 'success' : 'danger'" > {{ detailData.processInspectionResult?.isFully ? "是" : "否" }} </wd-tag> </template> </wd-form-item> </wd-col> </wd-row> <!-- 附件模块 --> <wd-row class="attachment-section" v-if="detailData.files && detailData.files.length > 0"> <view style="margin: 10rpx"> @@ -159,15 +294,29 @@ <view class="attachment-grid"> <wd-col v-for="(file, index) in detailData.files" :key="index" class="attachment-item"> <wd-img :width="80" :height="80" :src="file.url" @click="previewImage(file.url)"> <template #error> <view class="error-wrap">加载失败</view> </template> <template #error><view class="error-wrap">加载失败</view></template> <template #loading> <view class="loading-wrap"> <wd-loading /> </view> <view class="loading-wrap"><wd-loading /></view> </template> </wd-img> <!-- <wd-icon v-if="isEdit" name="close-circle" class="delete-icon" @click.stop="deleteFile(index)" ></wd-icon> --> </wd-col> <wd-col v-if="isEdit" class="attachment-item upload-btn"> <wd-upload :multiple="true" :max-count="5" :before-upload="beforeUpload" @success="handleUploadSuccess" @fail="handleUploadFail" accept="all" > <view class="upload-icon">+</view> </wd-upload> </wd-col> </view> </wd-row> @@ -177,36 +326,77 @@ <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 } 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"; // 核心状态 const paramsId = ref(""); const detailData = ref<any>({}); 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 formData = reactive({ dia: "", maxDia: "", minDia: "", appearance: "", windingTightness: "", arrangementNeatness: "", aluminumWireDistance: "", jointCondition: "", conclusion: "", isFully: "", }); // 外观选项 const appearanceOptions = [ { label: "无外观问题", value: "无外观问题" }, { label: "表面划伤", value: "表面划伤" }, { label: "直径不均", value: "直径不均" }, { label: "其他缺陷", value: "其他缺陷" }, ]; const sampleCompleteOptions = [ { label: "是", value: "是" }, { label: "否", value: "否" }, ]; const jointConditionOptions = [ { label: "有", value: "有" }, { label: "无", value: "无" }, ]; const conclusionOptions = [ { label: "合格", value: "合格" }, { label: "不合格", value: "不合格" }, ]; // 状态映射 const getStatusType = (status: number) => { switch (status) { case 0: return "warning"; // 待巡检 return "warning"; case 1: return "danger"; // 已驳回 return "danger"; case 2: return "info"; // 待审核 return "info"; case 3: return "success"; // 通过 return "success"; default: return "info"; } }; // 状态文本映射 const getStatusText = (status: number) => { switch (status) { case 0: @@ -222,25 +412,16 @@ } }; // 获取外观文本 const getAppearanceText = (appearance: string[]) => { if (!appearance || appearance.length === 0) return "-"; return appearance.join("、"); // 格式化工具 const formatProductAppearance = (productAppearance: string) => { return !productAppearance ? "-" : productAppearance; }; // 格式化产品外观显示 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", { @@ -250,32 +431,145 @@ }); }; // 格式化结构值显示 const formatStructureValue = (value1: any, value2: any) => { const val1 = value1 || "-"; const val2 = value2 ? `${value2}mm` : "-"; return { count: val1, diameter: val2 }; // 初始化表单 const initFormData = () => { const inspectionResult = detailData.value.inspectionResult || {}; const processInspectionResult = detailData.value.processInspectionResult || {}; formData.dia = inspectionResult.dia || ""; formData.maxDia = inspectionResult.maxDia || ""; formData.minDia = inspectionResult.minDia || ""; formData.appearance = inspectionResult.appearance || ""; formData.windingTightness = inspectionResult.windingTightness || ""; formData.arrangementNeatness = inspectionResult.arrangementNeatness || ""; formData.aluminumWireDistance = inspectionResult.aluminumWireDistance || ""; formData.jointCondition = inspectionResult.jointCondition || ""; formData.conclusion = inspectionResult.conclusion || ""; formData.isFully = processInspectionResult.isFully ? "是" : "否"; }; // 获取详情 const getDetailData = async (id: string, deviceType: string) => { try { let response; // 获取拉丝单个结构 response = await RoutingInspectionApi.getDrawInspectInfoById({ id: id, }); const response = await RoutingInspectionApi.getDrawInspectInfoById({ id }); detailData.value = response.data; console.log(detailData.value); tempFiles.value = []; initFormData(); } catch (error) { console.error("获取详情失败:", error); } }; // 页面加载 onLoad((options: any) => { paramsId.value = options.id; getDetailData(options.id, options.deviceType); }); // 编辑切换 const editList = () => { isEdit.value = true; }; // 取消编辑 const close = () => { isEdit.value = false; tempFiles.value = []; initFormData(); }; // 保存编辑 const saveList = async () => { // 校验 if (!formData.maxDia) return uni.showToast({ title: "最大直径为必填项", icon: "none" }); if (!formData.minDia) return uni.showToast({ title: "最小直径为必填项", icon: "none" }); if (!formData.appearance) return uni.showToast({ title: "外观为必填项", icon: "none" }); if (!formData.windingTightness) return uni.showToast({ title: "卷绕紧密为必填项", icon: "none" }); if (!formData.arrangementNeatness) return uni.showToast({ title: "排列整齐为必填项", icon: "none" }); if (!formData.aluminumWireDistance) return uni.showToast({ title: "外层铝线离侧板边缘距离为必填项", icon: "none" }); if (!formData.jointCondition) return uni.showToast({ title: "成品模后接头情况为必填项", icon: "none" }); if (!formData.conclusion) return uni.showToast({ title: "结论为必填项", icon: "none" }); if (!formData.isFully) return uni.showToast({ title: "铝杆样品是否齐全为必填项", icon: "none" }); if (!deviceUid.value) return uni.showToast({ title: "请扫描二维码", icon: "none" }); // 提交 try { const res = await RoutingInspectionApi.drawPatrolCheckInspection({ deviceUid: deviceUid.value, id: paramsId.value, result: { dia: formData.dia, maxDia: formData.maxDia, minDia: formData.minDia, appearance: formData.appearance, windingTightness: formData.windingTightness, arrangementNeatness: formData.arrangementNeatness, aluminumWireDistance: formData.aluminumWireDistance, jointCondition: formData.jointCondition, conclusion: formData.conclusion, }, inspectionResult: { isFully: formData.isFully }, processInspectionAttachmentList: tempFiles.value.map((f) => f.url), }); if (res.code === 200) { uni.showToast({ title: "保存成功", icon: "success" }); isEdit.value = false; getDetailData(paramsId.value, detailData.value.deviceType); } else { uni.showModal({ title: res.msg || "保存失败", icon: "error" }); } } catch (e) { console.error("保存失败:", e); uni.showModal({ title: e.message || "保存失败", icon: "error" }); } }; // 附件上传校验 const beforeUpload = (file: any) => { const maxSize = 2 * 1024 * 1024; if (file.size > maxSize) { uni.showToast({ title: "图片大小不能超过2M", icon: "none" }); return false; } return true; }; // 附件上传成功 const handleUploadSuccess = (res: any) => { if (Array.isArray(res)) { tempFiles.value = [ ...tempFiles.value, ...res.map((file) => ({ ...file, id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, })), ]; } else { tempFiles.value.push({ ...res, id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, }); } }; // 附件上传失败 const handleUploadFail = (err: any) => { uni.showToast({ title: "附件上传失败", icon: "error" }); }; // 删除附件 const deleteFile = (index: number) => { if (index >= detailData.value.files.length) { tempFiles.value = tempFiles.value.filter( (_, idx) => idx !== index - detailData.value.files.length ); } else { detailData.value.files = detailData.value.files.filter((_, idx) => idx !== index); } }; // 图片预览 const previewImage = (url: string) => { previewImageUrl.value = url; show.value = true; @@ -285,54 +579,82 @@ show.value = false; }; // 编辑列表 const editList = () => {}; // 关闭 const close = () => {}; // 保存列表 const saveList = async () => { // try { // let response; // // 保存列表 // response = await RoutingInspectionApi.saveStrandedInspectionStructureInfo({ // id: paramsId.value, // structureInfo: recordData.value.structureInfo, // }); // if (response.code === 200) { // uni.showToast({ // title: "保存成功", // icon: "success", // }); // // 刷新详情数据 // getDetailData(paramsId.value, recordData.value.deviceType); // } else { // uni.showToast({ // title: response.msg || "保存失败", // icon: "error", // }); // } // } catch (error) { // console.error("保存列表失败:", error); // uni.showToast({ // title: "保存失败", // icon: "error", // }); // } 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> .list { height: calc(100vh - 80px); padding: 12px; background: #f3f9f8; :deep() { .round { border-radius: 4px; <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 { @@ -361,22 +683,79 @@ .attachment-grid { display: flex; flex-wrap: wrap; /* 超出自动换行 */ gap: 10px; /* 图片之间的间距 */ padding: 10px 0; } .attachment-item { width: calc(25% - 10px); /* 每行4张,间距由gap控制,需计算宽度 */ 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; } /* 适配小屏幕,可调整每行数量(如每行2张) */ .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); margin: 10; } } :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> src/pages/routingInspection/product_card/index.vue
@@ -121,12 +121,12 @@ </view> </wd-col> <wd-col :span="8"> <view class="flex"> <view class="flex" @click.stop> <wd-button v-if="data[map.status] == 1" size="small" type="primary" @click.stop="showRejectPopup = true" @click="showRejectPopup = true" style="margin-left: auto" > 查看驳回信息