| | |
| | | 保存 |
| | | </wd-button> |
| | | <view class="placeholder"></view> |
| | | <view class="scan-info"> |
| | | <text class="scan-device-text">当前扫码机台: {{ scannedDeviceModel || "未扫码" }}</text> |
| | | </view> |
| | | <view class="scan-wrapper" @click="openScan"> |
| | | <wd-icon name="scan" size="24px" color="#0D867F"></wd-icon> |
| | | </view> |
| | |
| | | <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 label="张力设置" prop="tensionSetting"> |
| | | {{ formatValue(recordData.fixedInfo?.tensionSetting, "N/m") }} |
| | | </wd-form-item> |
| | | <!-- 绞制外径(可编辑) --> |
| | | <wd-form-item label="绞制外径" prop="twistDiameter" required> |
| | | <wd-form-item label="绞合外径" prop="twistedOuterDiameter" required> |
| | | <template v-if="isEdit"> |
| | | <wd-input |
| | | v-model="formData.twistDiameter" |
| | | placeholder="请输入绞制外径(mm)" |
| | | v-model="formData.twistedOuterDiameter" |
| | | placeholder="请输入绞合外径(mm)" |
| | | type="number" |
| | | /> |
| | | </template> |
| | | <template v-else> |
| | | {{ formatValue(formData.twistDiameter, "mm") }} |
| | | {{ formatValue(formData.twistedOuterDiameter, "mm") }} |
| | | </template> |
| | | </wd-form-item> |
| | | </wd-col> |
| | |
| | | </wd-form-item> |
| | | <wd-form-item label="节距" prop="pitch" required> |
| | | <template v-if="isEdit"> |
| | | <wd-input v-model="item.pitch" placeholder="请输入节距(mm)" type="number" /> |
| | | <wd-input |
| | | v-model="item.pitch" |
| | | placeholder="请输入节距(mm)" |
| | | type="number" |
| | | @input="updatePitchRatio(item)" |
| | | /> |
| | | </template> |
| | | <template v-else> |
| | | {{ formatValue(item.pitch, "mm") }} |
| | |
| | | <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"> |
| | | <view 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> |
| | | </wd-checkbox-group> |
| | | </view> |
| | | </template> |
| | | <template v-else> |
| | | {{ formatProductAppearance(formData.productAppearance) }} |
| | |
| | | <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 { ref, reactive, computed, onUnmounted } from "vue"; |
| | | import { onLoad, onShow, onHide } 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"; |
| | | import { useUserStore } from "@/store/modules/user"; |
| | | import { useScanCode } from "@/composables/useScanCode"; |
| | | |
| | | const paramsType = ref(""); |
| | | const paramsId = ref(""); |
| | |
| | | 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 userStore = useUserStore(); |
| | | const userInfo: any = computed(() => userStore.userInfo); |
| | | |
| | | // 使用扫码管理 composable(全局监听器,不随页面切换关闭) |
| | | const { |
| | | deviceUid, |
| | | deviceModel: scannedDeviceModel, |
| | | loadFromCache, |
| | | enableListener, |
| | | } = useScanCode("scanJX"); |
| | | |
| | | const formData = reactive({ |
| | | twistDiameter: "", // 绞制外径 |
| | | twistedOuterDiameter: "", // 绞制外径 |
| | | structureFormula: "", // 成品结构 |
| | | structureItems: [], // 结构标准值和实测 |
| | | inspectTwist: [], // 绞线工艺质量控制 |
| | |
| | | const structureResult = recordData.value.structureInfo?.structureRecordResult || {}; |
| | | const inspectionResult = recordData.value.inspectionResult || {}; |
| | | |
| | | formData.twistDiameter = inspectionResult.twistDiameter || ""; |
| | | formData.twistedOuterDiameter = |
| | | recordData.value.structureInfo.structureRecordResult.twistedOuterDiameter || ""; |
| | | formData.structureFormula = structureResult.inspectStructure?.structureFormula || ""; |
| | | formData.sampleComplete = inspectionResult.sampleComplete || ""; |
| | | formData.conclusion = structureResult.conclusion || ""; |
| | | formData.productAppearance = Array.isArray(structureResult.productAppearance) |
| | | |
| | | // 初始化产品外观 |
| | | const appearance = Array.isArray(structureResult.productAppearance) |
| | | ? structureResult.productAppearance |
| | | : structureResult.productAppearance |
| | | ? [structureResult.productAppearance] |
| | | : []; |
| | | ? [structureResult.productAppearance] |
| | | : []; |
| | | formData.productAppearance = appearance; |
| | | |
| | | formData.structureItems = JSON.parse( |
| | | JSON.stringify(structureResult.inspectStructure?.structureItems || []) |
| | |
| | | const response = await RoutingInspectionApi.getStrandedInspectionStructureInfoById({ id }); |
| | | recordData.value = response.data; |
| | | detailData.value = response.data.structureInfo; |
| | | |
| | | // 如果记录人为空,默认设置为当前登录用户 |
| | | if (recordData.value.structureInfo && !recordData.value.structureInfo.createUserName) { |
| | | recordData.value.structureInfo.createUserName = |
| | | userInfo.value?.nickName || userInfo.value?.userName || ""; |
| | | } |
| | | |
| | | console.log("detailData.value", detailData.value); |
| | | 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.twistedOuterDiameter) |
| | | 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 (!item.pitchRatio) |
| | | return uni.showToast({ title: `${item.twistName}节径比为必填项`, icon: "none" }); |
| | | } |
| | | console.log("1111", deviceUid.value); |
| | | if (!deviceUid.value) return uni.showToast({ title: "请扫描二维码", icon: "none" }); |
| | | // 验证扫码数据(从缓存或新扫码获取) |
| | | console.log("保存前检查 deviceUid:", deviceUid.value); |
| | | if (!deviceUid.value) { |
| | | return uni.showToast({ |
| | | title: "请先扫描设备二维码", |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | } |
| | | const { newFiles } = attachmentRef.value.getSubmitFiles(); |
| | | console.log("newFiles", newFiles); |
| | | const allFileIds = [...newFiles]; |
| | |
| | | deviceUid: deviceUid.value, |
| | | id: paramsId.value, |
| | | result: { |
| | | twistDiameter: formData.twistDiameter, |
| | | twistedOuterDiameter: formData.twistedOuterDiameter, |
| | | structureFormula: formData.structureFormula, |
| | | structureItems: formData.structureItems, |
| | | inspectTwist: formData.inspectTwist, |
| | |
| | | }); |
| | | |
| | | if (res.code === 200) { |
| | | uni.showToast({ title: "保存成功", icon: "success" }); |
| | | isEdit.value = false; |
| | | getDetailData(paramsId.value, paramsType.value); |
| | | // 设置刷新标记,告诉列表页需要刷新 |
| | | uni.setStorageSync("needRefreshInspectionList", true); |
| | | |
| | | uni.showToast({ |
| | | title: "保存成功", |
| | | icon: "success", |
| | | duration: 1500, |
| | | }); |
| | | // 延迟返回列表页,让用户看到成功提示 |
| | | setTimeout(() => { |
| | | uni.navigateBack({ |
| | | delta: 1, |
| | | }); |
| | | }, 1500); |
| | | } else { |
| | | uni.showModal({ title: res.msg || "保存失败", icon: "error" }); |
| | | } |
| | |
| | | case 1: |
| | | return "danger"; // 已驳回 |
| | | case 2: |
| | | return "info"; // 待审核 |
| | | return "primary"; // 待审核 |
| | | case 3: |
| | | return "success"; // 通过 |
| | | default: |
| | | return "info"; |
| | | return "default"; |
| | | } |
| | | }; |
| | | |
| | |
| | | }); |
| | | }; |
| | | |
| | | const openScan = () => { |
| | | scanRef.value.triggerScan(); |
| | | // 计算节径比 |
| | | const calculatePitchRatio = (pitch: string, dia: string) => { |
| | | // 如果pitch或dia为空,则返回"-" |
| | | if (!pitch || !dia) return "-"; |
| | | |
| | | // 将pitch和dia转换为浮点数 |
| | | const pitchNum = parseFloat(pitch); |
| | | const diaNum = parseFloat(dia); |
| | | |
| | | // 如果pitchNum或diaNum是NaN,或者diaNum为0,则返回"-" |
| | | if (isNaN(pitchNum) || isNaN(diaNum) || diaNum === 0) return "-"; |
| | | |
| | | // 计算pitchNum和diaNum的比值,并保留两位小数 |
| | | return (pitchNum / diaNum).toFixed(2); |
| | | }; |
| | | const getScanCode = (params: any) => { |
| | | console.log("完整参数:", params); |
| | | let codeObj = {}; |
| | | try { |
| | | codeObj = JSON.parse(params.code); |
| | | } catch (err) { |
| | | console.error("JSON解析失败:", err); |
| | | toast.error("扫码数据异常"); |
| | | return; |
| | | |
| | | // 更新节径比(当节距变化时自动计算) |
| | | const updatePitchRatio = (item: any) => { |
| | | // 使用绞合外径作为直径来计算节径比 |
| | | const dia = item.dia; |
| | | item.pitchRatio = calculatePitchRatio(item.pitch, dia); |
| | | }; |
| | | |
| | | // 处理产品外观选择的互斥逻辑 |
| | | const handleAppearanceClick = (value: string) => { |
| | | const currentValues = [...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]; |
| | | } |
| | | } |
| | | deviceUid.value = codeObj?.uid; |
| | | toast.success("扫码成功"); |
| | | |
| | | formData.productAppearance = newSelection; |
| | | }; |
| | | // 确保先移除再添加监听 |
| | | const setupScanListener = () => { |
| | | uni.$off("scan", getScanCode); // 先移除旧的 |
| | | uni.$on("scan", getScanCode); // 再添加新的 |
| | | |
| | | const openScan = () => { |
| | | console.log("indexJX - 点击扫码按钮(全局扫码模式,无需手动触发)"); |
| | | // 全局扫码模式下,硬件扫码会自动触发,无需手动调用 |
| | | uni.showToast({ |
| | | title: "请使用扫码枪扫描", |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | onUnmounted(() => { |
| | | // 开启广播监听事件 |
| | | uni.$off("scan", getScanCode); |
| | | console.log("离开1"); |
| | | }); |
| | | onMounted(() => { |
| | | // 开启广播监听事件 |
| | | setupScanListener(); |
| | | console.log("显示1"); |
| | | |
| | | // 页面显示时的处理 |
| | | onShow(() => { |
| | | console.log("========== indexJX - onShow 触发 =========="); |
| | | // 重新启用监听器(确保监听器有效) |
| | | enableListener(); |
| | | // 加载缓存(更新UI显示) |
| | | const cachedData = loadFromCache(); |
| | | |
| | | // 如果没有缓存数据,提示用户需要扫码 |
| | | if (!cachedData || !cachedData.uid) { |
| | | console.log("⚠️ 未检测到扫码缓存,用户需要扫描设备二维码"); |
| | | // 在编辑模式下才提示 |
| | | if (isEdit.value) { |
| | | setTimeout(() => { |
| | | uni.showToast({ |
| | | title: "请扫描设备二维码后再保存", |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | }, 500); |
| | | } |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | |
| | | flex: 1; |
| | | } |
| | | |
| | | .scan-info { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-right: 10px; |
| | | |
| | | .scan-device-text { |
| | | font-size: 14px; |
| | | color: #0d867f; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .scan-wrapper { |
| | | width: 38px; |
| | | height: 38px; |