| 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/pages/routingInspection/upload.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,54 +108,76 @@ </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" > <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"> <wd-form-item label="æ åå¼" prop="structureValue" required> {{ formatValue(item.structureValue) }} </wd-form-item> <wd-form-item label="宿µæ ¹æ°" prop="actualValue1"> {{ formatValue(item.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"> {{ formatValue(item.actualValue2, "mm") }} <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,87 +185,319 @@ :label="formatValue(item.twistName)" label-width="400rpx" style="color: red" prop="inspectTwistGroup" required ></wd-form-item> <wd-form-item label="ç»å" prop="direction"> {{ formatValue(item.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-img :width="80" :height="80" :src="file.url" @click="previewImage(file.url)"> <template #error> <view class="error-wrap">å 载失败</view> </template> <template #loading> <view class="loading-wrap"> <wd-loading /> </view> </template> </wd-img> </wd-col> </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>({}); 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) => { @@ -266,12 +531,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 +553,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 +608,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 +624,11 @@ .list { padding: 12px; padding-top: 84px; background: #f3f9f8; min-height: 100vh; box-sizing: border-box; overflow-y: auto; } .title { @@ -439,6 +650,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 +678,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 +718,36 @@ width: calc(25% - 10px); } } </style> // ç¼è¾æ¨¡å¼ä¸è¡¨åç»ä»¶æ ·å¼ä¼å :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
@@ -40,173 +40,334 @@ </view> </view> <view class="list"> <div class="inspection-report"> <!-- åºæ¬ä¿¡æ¯æ¨¡å --> <wd-row> <view style="margin: 10rpx"> <text class="title">{{ "åºæ¬ä¿¡æ¯" }}</text> </view> <wd-col :span="24"> <wd-form-item label="æ¥æ" prop="recordDate"> {{ formatDate(detailData.fixedInfo?.recordDate) }} </wd-form-item> <wd-form-item label="æºå°" prop="deviceModel"> {{ formatValue(detailData.fixedInfo?.deviceModel) }} </wd-form-item> <wd-form-item label="çæ¬¡" prop="workShift"> {{ formatValue(detailData.fixedInfo?.workShift) }} </wd-form-item> <wd-form-item label="çç»" prop="teamName"> {{ formatValue(detailData.fixedInfo?.teamName) }} </wd-form-item> <wd-form-item label="åä¸è§æ ¼" prop="model"> {{ formatValue(detailData.fixedInfo?.model) }} </wd-form-item> <wd-form-item label="ç产轴æ°" prop="outputNumber"> {{ formatValue(detailData.fixedInfo?.outputNumber, "è½´") }} </wd-form-item> <wd-form-item label="åå·" prop="poleModel"> {{ formatValue(detailData.fixedInfo?.poleModel) }} </wd-form-item> <!-- åºæ¬ä¿¡æ¯æ¨¡å --> <wd-row> <view style="margin: 10rpx"> <text class="title">{{ "åºæ¬ä¿¡æ¯" }}</text> </view> <wd-col :span="24"> <wd-form-item label="æ¥æ" prop="recordDate"> {{ formatDate(detailData.fixedInfo?.recordDate) }} </wd-form-item> <wd-form-item label="æºå°" prop="deviceModel"> {{ formatValue(detailData.fixedInfo?.deviceModel) }} </wd-form-item> <wd-form-item label="çæ¬¡" prop="workShift"> {{ formatValue(detailData.fixedInfo?.workShift) }} </wd-form-item> <wd-form-item label="çç»" prop="teamName"> {{ formatValue(detailData.fixedInfo?.teamName) }} </wd-form-item> <wd-form-item label="åä¸è§æ ¼" prop="model"> {{ formatValue(detailData.fixedInfo?.model) }} </wd-form-item> <wd-form-item label="ç产轴æ°" prop="outputNumber"> {{ formatValue(detailData.fixedInfo?.outputNumber, "è½´") }} </wd-form-item> <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> <wd-form-item label="è®°å½äºº" prop="createUserName"> {{ formatValue(detailData.fixedInfo?.createUserName) }} </wd-form-item> <wd-form-item label="馿£çå·" prop="firstNo"> {{ formatValue(detailData.fixedInfo?.firstNo) }} </wd-form-item> </wd-col> </wd-row> <wd-form-item label="æ¹æ¬¡" prop="poleNumber"> {{ formatValue(detailData.fixedInfo?.poleNumber) }} </wd-form-item> <wd-form-item label="è®°å½äºº" prop="createUserName"> {{ formatValue(detailData.fixedInfo?.createUserName) }} </wd-form-item> <wd-form-item label="馿£çå·" prop="firstNo"> {{ formatValue(detailData.fixedInfo?.firstNo) }} </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="processInspectionUserName"> {{ detailData.processInspectionUserName || "-" }} </wd-form-item> <wd-form-item label="ç¶æ" prop="status"> <wd-tag custom-class="space" :type="getStatusType(detailData.status)"> {{ getStatusText(detailData.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="dia"> {{ formatValue(detailData.inspectionResult?.dia, "mm") || "-" }} </wd-form-item> <wd-form-item label="æå¤§ç´å¾" prop="maxDia"> <!-- èªæ£è®°å½è¯¦æ 模å --> <wd-row> <view style="margin: 10rpx"> <text class="title">{{ "èªæ£è®°å½è¯¦æ " }}</text> </view> <wd-col :span="24"> <wd-form-item label="å·¡æ£å" prop="processInspectionUserName"> {{ detailData.processInspectionUserName || "-" }} </wd-form-item> <wd-form-item label="ç¶æ" prop="status"> <wd-tag custom-class="space" :type="getStatusType(detailData.status)"> {{ getStatusText(detailData.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="dia"> {{ formatValue(detailData.inspectionResult?.dia, "mm") || "-" }} </wd-form-item> <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") || "-" }} </wd-form-item> <wd-form-item label="æå°ç´å¾" prop="minDia"> </template> </wd-form-item> <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") || "-" }} </wd-form-item> <wd-form-item label="å¤è§" prop="appearance"> {{ formatProductAppearance(detailData.inspectionResult?.appearance) || "-" }} </wd-form-item> <wd-form-item label="å·ç»ç´§å¯" prop="windingTightness"> </template> </wd-form-item> <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(formData.appearance) }} </template> </wd-form-item> <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) }} </wd-form-item> <wd-form-item label="æåæ´é½" prop="arrangementNeatness"> </template> </wd-form-item> <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) }} </wd-form-item> <wd-form-item label="å¤å±é线离侧æ¿è¾¹ç¼è·ç¦»" prop="aluminumWireDistance" label-width="500rpx" > </template> </wd-form-item> <wd-form-item label="å¤å±é线离侧æ¿è¾¹ç¼è·ç¦»" prop="aluminumWireDistance" 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") || "-" }} </wd-form-item> <wd-form-item label="æåæ¨¡åæ¥å¤´æ åµ" prop="jointCondition" label-width="250rpx"> </template> </wd-form-item> <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) || "-" }} </wd-form-item> <wd-form-item label="ç»è®º" prop="conclusion"> </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(detailData.inspectionResult?.conclusion) || "-" }} </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"> </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="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> </wd-form-item> </wd-col> </wd-row> <!-- é件模å --> <wd-row class="attachment-section" v-if="detailData.files && detailData.files.length > 0"> <view style="margin: 10rpx"> <text class="title">{{ "éä»¶" }}</text> </view> <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 #loading> <view class="loading-wrap"> <wd-loading /> </view> </template> </wd-img> </wd-col> </view> </wd-row> </div> </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"> <text class="title">{{ "éä»¶" }}</text> </view> <wd-col :span="24"> <AttachmentUpload :detailData="detailData" :isEdit="isEdit" :deviceType="paramsType" ref="attachmentRef" /> </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 } 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 paramsId = ref(""); const paramsType = 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 attachmentRef = ref<any>(null); // ç¶æç±»åæ å° // è¡¨åæ°æ® 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 +383,16 @@ } }; // è·åå¤è§ææ¬ const getAppearanceText = (appearance: string[]) => { if (!appearance || appearance.length === 0) return "-"; return appearance.join("ã"); }; // æ ¼å¼å产åå¤è§æ¾ç¤º // æ ¼å¼åå·¥å · const formatProductAppearance = (productAppearance: string[]) => { if (!productAppearance || productAppearance.length === 0) return "-"; return productAppearance.join("ã"); return !productAppearance.length ? "-" : 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,89 +402,182 @@ }); }; // æ ¼å¼åç»æå¼æ¾ç¤º 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; paramsType.value = options.deviceType; getDetailData(options.id, options.deviceType); }); const previewImage = (url: string) => { previewImageUrl.value = url; show.value = true; // ç¼è¾åæ¢ 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.length) 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" }); const { newFiles } = attachmentRef.value.getSubmitFiles(); console.log("newFiles", newFiles); const allFileIds = [...newFiles]; // æäº¤ 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: 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 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(); }; </script> <style lang="scss" scoped> .list { height: calc(100vh - 80px); padding: 12px; background: #f3f9f8; :deep() { .round { border-radius: 4px; } const getScanCode = (params: any) => { let codeObj = {}; try { codeObj = JSON.parse(params.code); } catch (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 { @@ -361,22 +606,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" > æ¥ç驳åä¿¡æ¯ src/pages/routingInspection/upload.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,359 @@ <template> <view class="attachment-container"> <!-- 头鍿ä½åº --> <view class="header-actions"> <wd-button icon="file-add" :round="false" size="small" custom-class="add_btn" @click="addAttachment" v-if="isEdit" > æ°å¢ </wd-button> </view> <!-- éä»¶å表 --> <view class="attachment-list"> <wd-status-tip v-if="attachmentList.length === 0" image="content" tip="ææ éä»¶" /> <wd-card v-for="item in attachmentList" :key="item.id" type="rectangle" custom-class="attachment-card" :border="false" > <view class="attachment-item" @click="previewAttachment(item)"> <view class="attachment-info"> <view class="attachment-name">{{ item.bucketFileName || item.name }}</view> <view class="attachment-meta"> <text class="file-type">{{ getFileType(item.bucketFileName) }}</text> <text class="upload-time">{{ formatTime(item.createTime) }}</text> </view> </view> <view class="attachment-actions" @click.stop v-if="isEdit"> <wd-icon name="delete" color="#ff4757" @click="deleteAttachment(item.id)" /> </view> </view> </wd-card> </view> <wd-toast /> </view> </template> <script setup lang="ts"> import { ref, onMounted } from "vue"; import { useToast } from "wot-design-uni"; import AttachmentAPI from "@/api/product/attachment"; // å¤é¨åæ° const props = defineProps({ detailData: { type: Object, default: () => ({}) }, isEdit: { type: Boolean, default: false }, deviceType: { type: String, default: "" }, }); const toast = useToast(); const attachmentList = props.deviceType == "1" ? ref<any[]>(props.detailData.value.files || []) : ref<any[]>(props.detailData.files || []); const attachmentIds = props.deviceType == "1" ? ref<string[]>(props.detailData.value.attachmentId || []) : ref<string[]>(props.detailData.attachmentId || []); // æ°å¢éä»¶ const addAttachment = () => { // æ¾ç¤ºéæ©æä»¶ç±»åçå¼¹çª uni.showActionSheet({ itemList: ["éæ©å¾ç", "éæ©è§é¢", "æç §", "å½å"], success: (res) => { switch (res.tapIndex) { case 0: // éæ©å¾ç chooseImages(); break; case 1: // éæ©è§é¢ chooseVideos(); break; case 2: // æç § takePhoto(); break; case 3: // å½å recordVideo(); break; } }, fail: (error) => { console.error("éæ©æä»¶ç±»å失败:", error); toast.show("éæ©æä»¶ç±»å失败"); }, }); }; // éæ©å¾ç const chooseImages = () => { uni.chooseImage({ count: 9, sizeType: ["original", "compressed"], sourceType: ["album"], success: async (res) => { const filePaths = Array.isArray(res.tempFilePaths) ? res.tempFilePaths : [res.tempFilePaths]; await handleFileUpload(filePaths); }, fail: (error) => { console.error("éæ©å¾ç失败:", error); toast.show("éæ©å¾ç失败"); }, }); }; // éæ©è§é¢ const chooseVideos = () => { uni.chooseVideo({ sourceType: ["album"], maxDuration: 60, camera: "back", success: async (res) => { await handleFileUpload([res.tempFilePath]); }, fail: (error) => { console.error("éæ©è§é¢å¤±è´¥:", error); toast.show("éæ©è§é¢å¤±è´¥"); }, }); }; // æç § const takePhoto = () => { uni.chooseImage({ count: 1, sizeType: ["original", "compressed"], sourceType: ["camera"], success: async (res) => { const filePaths = Array.isArray(res.tempFilePaths) ? res.tempFilePaths : [res.tempFilePaths]; await handleFileUpload(filePaths); }, fail: (error) => { console.error("æç §å¤±è´¥:", error); toast.show("æç §å¤±è´¥"); }, }); }; // å½å const recordVideo = () => { uni.chooseVideo({ sourceType: ["camera"], maxDuration: 60, camera: "back", success: async (res) => { await handleFileUpload([res.tempFilePath]); }, fail: (error) => { console.error("å½å失败:", error); toast.show("å½å失败"); }, }); }; // å¤çæä»¶ä¸ä¼ const handleFileUpload = async (filePaths: string[]) => { try { toast.show("æ£å¨ä¸ä¼ ..."); // ä¸ä¼ æä»¶ const uploadResults: any = await AttachmentAPI.uploadAttachmentFiles(filePaths); const result = uploadResults.map((it: any) => { return it.data; }); console.log("result", result); // æ´æ°éä»¶å表 const flattenedResult = result.flat(); attachmentList.value.push(...flattenedResult); console.log(attachmentList.value); // æåéä»¶ID attachmentIds.value = attachmentList.value.map((item: any) => item.id); toast.show("ä¸ä¼ æå"); console.log("111", attachmentIds.value.attachmentId); } catch (error) { console.error("ä¸ä¼ 失败:", error); toast.show("ä¸ä¼ 失败"); } }; // å é¤éä»¶ const deleteAttachment = async (aid: number) => { try { uni.showModal({ title: "确认å é¤", content: "ç¡®å®è¦å é¤è¿ä¸ªéä»¶åï¼", success: async (res) => { if (res.confirm) { // å端æå¨å é¤ï¼ç´æ¥ä»å表ä¸ç§»é¤è¿æ¡æ°æ® attachmentList.value = attachmentList.value.filter((item) => item.id !== aid); // è·åå©ä½çéä»¶IDç»å attachmentIds.value = attachmentList.value.map((item) => item.id).join(","); toast.show("å 餿å"); } }, }); console.log("111", attachmentIds.value.attachmentId); } catch (error) { console.error("å é¤å¤±è´¥:", error); toast.show("å é¤å¤±è´¥"); } }; // é¢è§éä»¶ const previewAttachment = (item: any) => { // æ ¹æ®æä»¶ç±»åè¿è¡é¢è§ const fileName = item.bucketFileName || item.name; const fileType = getFileType(fileName); if (fileType.startsWith("image")) { // å¾çé¢è§ uni.previewImage({ urls: [item.url], current: item.url, }); } else { // å ¶ä»æä»¶ç±»åï¼å¯ä»¥ä¸è½½ææå¼ uni.downloadFile({ url: item.url, success: (res) => { uni.openDocument({ filePath: res.tempFilePath, success: () => { console.log("æå¼ææ¡£æå"); }, fail: (error) => { console.error("æå¼ææ¡£å¤±è´¥:", error); toast.show("æ æ³é¢è§æ¤æä»¶ç±»å"); }, }); }, fail: (error) => { console.error("ä¸è½½æä»¶å¤±è´¥:", error); toast.show("ä¸è½½æä»¶å¤±è´¥"); }, }); } }; // è·åæä»¶ç±»å const getFileType = (fileName: string) => { if (!fileName) return "unknown"; const extension = fileName.split(".").pop()?.toLowerCase(); switch (extension) { case "jpg": case "jpeg": case "png": case "gif": case "bmp": case "webp": return "image"; case "pdf": return "pdf"; case "doc": case "docx": return "word"; case "xls": case "xlsx": return "excel"; case "ppt": case "pptx": return "powerpoint"; case "txt": return "text"; case "zip": case "rar": return "archive"; default: return "file"; } }; // æ ¼å¼åæä»¶å¤§å° const formatFileSize = (size: number) => { if (size < 1024) return size + " B"; if (size < 1024 * 1024) return (size / 1024).toFixed(1) + " KB"; return (size / (1024 * 1024)).toFixed(1) + " MB"; }; // æ ¼å¼åæ¶é´ const formatTime = (time: string) => { const date = new Date(time); return date.toLocaleString(); }; // 坹夿´é²æ¹æ³ï¼è·åææéæäº¤çæä»¶ const getSubmitFiles = () => ({ newFiles: attachmentIds.value || [], }); defineExpose({ getSubmitFiles }); </script> <style lang="scss" scoped> .attachment-container { padding: 12px; background: #f3f9f8; min-height: 100vh; } .header-actions { margin-bottom: 12px; :deep(.add_btn) { background: #0d867f; color: white; border: none; } } .attachment-list { .attachment-card { margin-bottom: 12px; border-radius: 4px; } } .attachment-item { display: flex; align-items: center; padding: 12px; .attachment-info { flex: 1; .attachment-name { font-size: 16px; font-weight: 500; color: #333; margin-bottom: 4px; word-break: break-all; } .attachment-meta { display: flex; gap: 12px; font-size: 12px; color: #999; } } .attachment-actions { margin-left: 12px; :deep(.wd-icon) { font-size: 20px; cursor: pointer; } } } </style>