From 944be786cefe66d7db1bb84904822ac559713841 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 15 五月 2026 13:24:45 +0800
Subject: [PATCH] 进销存app 1.设备保养、巡检、报修添加字段
---
src/pages/equipmentManagement/upkeep/index.vue | 8
src/pages/inspectionUpload/attachment.vue | 460 ++++++++
src/pages/inspectionUpload/components/formDia.vue | 228 +++
src/pages.json | 14
src/pages/inspectionUpload/upload.vue | 885 ++++++++++++++++
src/pages/equipmentManagement/upkeep/add.vue | 34
src/pages/equipmentManagement/repair/index.vue | 12
src/pages/equipmentManagement/repair/add.vue | 18
src/pages/inspectionUpload/index.vue | 1474 ---------------------------
9 files changed, 1,623 insertions(+), 1,510 deletions(-)
diff --git a/src/pages.json b/src/pages.json
index f2353d0..b3d204b 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -761,6 +761,20 @@
}
},
{
+ "path": "pages/inspectionUpload/upload",
+ "style": {
+ "navigationBarTitleText": "涓婁紶宸℃璁板綍",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/inspectionUpload/attachment",
+ "style": {
+ "navigationBarTitleText": "鏌ョ湅闄勪欢",
+ "navigationStyle": "custom"
+ }
+ },
+ {
"path": "pages/equipmentManagement/faultAnalysis/index",
"style": {
"navigationBarTitleText": "鏁呴殰鍒嗘瀽杩芥函",
diff --git a/src/pages/equipmentManagement/repair/add.vue b/src/pages/equipmentManagement/repair/add.vue
index 71de940..e931494 100644
--- a/src/pages/equipmentManagement/repair/add.vue
+++ b/src/pages/equipmentManagement/repair/add.vue
@@ -69,6 +69,20 @@
placeholder="璇疯緭鍏ユ姤淇汉"
clearable />
</u-form-item>
+ <u-form-item label="缁翠慨浜�"
+ prop="maintenanceName"
+ border-bottom>
+ <u-input v-model="form.maintenanceName"
+ placeholder="璇疯緭鍏ョ淮淇汉"
+ clearable />
+ </u-form-item>
+ <u-form-item label="缁翠慨椤圭洰"
+ prop="maintenanceProject"
+ border-bottom>
+ <u-input v-model="form.maintenanceProject"
+ placeholder="璇疯緭鍏ョ淮淇」鐩�"
+ clearable />
+ </u-form-item>
<u-form-item label="鏁呴殰鐜拌薄"
prop="remark"
required
@@ -169,6 +183,8 @@
deviceModel: undefined, // 瑙勬牸鍨嬪彿
repairTime: dayjs().format("YYYY-MM-DD"), // 鎶ヤ慨鏃ユ湡
repairName: undefined, // 鎶ヤ慨浜�
+ maintenanceName: undefined, // 缁翠慨浜�
+ maintenanceProject: undefined, // 缁翠慨椤圭洰
remark: undefined, // 鏁呴殰鐜拌薄
});
@@ -221,6 +237,8 @@
form.value.deviceModel = data.deviceModel;
form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD");
form.value.repairName = data.repairName;
+ form.value.maintenanceName = data.maintenanceName;
+ form.value.maintenanceProject = data.maintenanceProject;
form.value.remark = data.remark;
repairStatusText.value =
repairStatusOptions.value.find(item => item.value == data.status)
diff --git a/src/pages/equipmentManagement/repair/index.vue b/src/pages/equipmentManagement/repair/index.vue
index e280595..5543e43 100644
--- a/src/pages/equipmentManagement/repair/index.vue
+++ b/src/pages/equipmentManagement/repair/index.vue
@@ -58,14 +58,18 @@
<text class="detail-value">{{ item.repairName || '-' }}</text>
</view>
<view class="detail-row">
- <text class="detail-label">鏁呴殰鐜拌薄</text>
- <text class="detail-value">{{ item.remark || '-' }}</text>
- </view>
- <view class="detail-row">
<text class="detail-label">缁翠慨浜�</text>
<text class="detail-value">{{ item.maintenanceName || '-' }}</text>
</view>
<view class="detail-row">
+ <text class="detail-label">缁翠慨椤圭洰</text>
+ <text class="detail-value">{{ item.maintenanceProject || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">鏁呴殰鐜拌薄</text>
+ <text class="detail-value">{{ item.remark || '-' }}</text>
+ </view>
+ <view class="detail-row">
<text class="detail-label">缁翠慨缁撴灉</text>
<text class="detail-value">{{ item.maintenanceResult || '-' }}</text>
</view>
diff --git a/src/pages/equipmentManagement/upkeep/add.vue b/src/pages/equipmentManagement/upkeep/add.vue
index 8dedb1b..2b5d3da 100644
--- a/src/pages/equipmentManagement/upkeep/add.vue
+++ b/src/pages/equipmentManagement/upkeep/add.vue
@@ -41,6 +41,22 @@
</template>
</u-form-item>
+ <u-form-item label="淇濆吇浜�" prop="maintenancePerson" border-bottom>
+ <u-input
+ v-model="form.maintenancePerson"
+ placeholder="璇疯緭鍏ヤ繚鍏讳汉"
+ clearable
+ />
+ </u-form-item>
+
+ <u-form-item label="淇濆吇椤圭洰" prop="maintenanceProject" border-bottom>
+ <u-input
+ v-model="form.maintenanceProject"
+ placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
+ clearable
+ />
+ </u-form-item>
+
<!-- 鎻愪氦鎸夐挳 -->
<view class="footer-btns">
<u-button class="cancel-btn" @click="goBack">鍙栨秷</u-button>
@@ -122,6 +138,8 @@
deviceLedgerId: undefined, // 璁惧ID
deviceModel: undefined, // 瑙勬牸鍨嬪彿
maintenancePlanTime: dayjs().format("YYYY-MM-DD"), // 璁″垝淇濆吇鏃ユ湡
+ maintenancePerson: undefined, // 淇濆吇浜�
+ maintenanceProject: undefined, // 淇濆吇椤圭洰
});
// 鍔犺浇璁惧鍒楄〃
@@ -142,13 +160,15 @@
const { code, data } = await getUpkeepById(id);
if (code == 200) {
form.value.deviceLedgerId = data.deviceLedgerId;
- form.value.deviceModel = data.deviceModel;
- form.value.maintenancePlanTime = dayjs(data.maintenancePlanTime).format("YYYY-MM-DD");
- // 璁剧疆璁惧鍚嶇О鏄剧ず
- const device = deviceOptions.value.find(item => item.id === data.deviceLedgerId);
- if (device) {
- form.value.deviceNameText = device.deviceName;
- }
+ form.value.deviceModel = data.deviceModel;
+ form.value.maintenancePlanTime = dayjs(data.maintenancePlanTime).format("YYYY-MM-DD");
+ form.value.maintenancePerson = data.maintenancePerson;
+ form.value.maintenanceProject = data.maintenanceProject;
+ // 璁剧疆璁惧鍚嶇О鏄剧ず
+ const device = deviceOptions.value.find(item => item.id === data.deviceLedgerId);
+ if (device) {
+ form.value.deviceNameText = device.deviceName;
+ }
}
} catch (e) {
showToast('鑾峰彇璇︽儏澶辫触');
diff --git a/src/pages/equipmentManagement/upkeep/index.vue b/src/pages/equipmentManagement/upkeep/index.vue
index cca1b04..8646554 100644
--- a/src/pages/equipmentManagement/upkeep/index.vue
+++ b/src/pages/equipmentManagement/upkeep/index.vue
@@ -63,6 +63,14 @@
<text class="detail-value">{{ formatDateTime(item.createTime) || '-' }}</text>
</view>
<view class="detail-row">
+ <text class="detail-label">淇濆吇浜�</text>
+ <text class="detail-value">{{ item.maintenancePerson || '-' }}</text>
+ </view>
+ <view class="detail-row">
+ <text class="detail-label">淇濆吇椤圭洰</text>
+ <text class="detail-value">{{ item.maintenanceProject || '-' }}</text>
+ </view>
+ <view class="detail-row">
<text class="detail-label">瀹為檯淇濆吇浜�</text>
<text class="detail-value">{{ item.maintenanceActuallyName || '-' }}</text>
</view>
diff --git a/src/pages/inspectionUpload/attachment.vue b/src/pages/inspectionUpload/attachment.vue
new file mode 100644
index 0000000..c94efa5
--- /dev/null
+++ b/src/pages/inspectionUpload/attachment.vue
@@ -0,0 +1,460 @@
+<template>
+ <view class="attachment-page">
+ <!-- 椤甸潰澶撮儴 -->
+ <PageHeader :title="`鏌ョ湅闄勪欢 - ${taskInfo?.taskName || ''}`" @back="goBack" />
+
+ <!-- 椤甸潰鍐呭 -->
+ <view class="attachment-content">
+ <!-- 鍒嗙被鏍囩椤� -->
+ <view class="attachment-tabs">
+ <view
+ class="tab-item"
+ :class="{ active: currentViewType === 'before' }"
+ @click="switchViewType('before')"
+ >
+ 鐢熶骇鍓� ({{ getAttachmentsByType(0).length }})
+ </view>
+ <view
+ class="tab-item"
+ :class="{ active: currentViewType === 'after' }"
+ @click="switchViewType('after')"
+ >
+ 鐢熶骇涓� ({{ getAttachmentsByType(1).length }})
+ </view>
+ <view
+ class="tab-item"
+ :class="{ active: currentViewType === 'issue' }"
+ @click="switchViewType('issue')"
+ >
+ 鐢熶骇鍚� ({{ getAttachmentsByType(2).length }})
+ </view>
+ </view>
+
+ <!-- 褰撳墠鍒嗙被鐨勯檮浠跺垪琛� -->
+ <view class="attachment-list-container">
+ <view v-if="getCurrentViewAttachments().length > 0" class="attachment-list">
+ <view
+ v-for="(file, index) in getCurrentViewAttachments()"
+ :key="index"
+ class="attachment-item"
+ @click="previewAttachment(file)"
+ >
+ <view class="attachment-preview-container">
+ <image
+ v-if="isImageFile(file)"
+ :src="file.url || file.downloadUrl"
+ class="attachment-preview"
+ mode="aspectFill"
+ />
+ <view v-else class="attachment-video-preview">
+ <u-icon name="video" size="40" color="#409eff"></u-icon>
+ <text class="video-text">瑙嗛</text>
+ </view>
+ </view>
+ <view class="attachment-info">
+ <text class="attachment-name">{{ file.originalFilename || file.bucketFilename || file.name || '闄勪欢' }}</text>
+ <text class="attachment-size">{{ formatFileSize(file.byteSize || file.size) }}</text>
+ </view>
+ </view>
+ </view>
+ <view v-else class="attachment-empty">
+ <u-icon name="folder-open" size="60" color="#ccc"></u-icon>
+ <text class="empty-text">璇ュ垎绫绘殏鏃犻檮浠�</text>
+ </view>
+ </view>
+ </view>
+
+ <!-- 瑙嗛棰勮寮圭獥 -->
+ <view v-if="showVideoDialog" class="video-modal-overlay" @click="closeVideoPreview">
+ <view class="video-modal-container" @click.stop>
+ <view class="video-modal-header">
+ <text class="video-modal-title">{{ currentVideoFile?.originalFilename || '瑙嗛棰勮' }}</text>
+ <view class="close-btn-video" @click="closeVideoPreview">
+ <u-icon name="close" size="20" color="#fff"></u-icon>
+ </view>
+ </view>
+ <view class="video-modal-body">
+ <video
+ v-if="currentVideoFile"
+ :src="currentVideoFile.url || currentVideoFile.downloadUrl"
+ class="video-player"
+ controls
+ autoplay
+ @error="handleVideoError"
+ ></video>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import PageHeader from '@/components/PageHeader.vue';
+import config from '@/config';
+
+// 浠诲姟淇℃伅
+const taskInfo = ref(null);
+
+// 闄勪欢鍒楄〃
+const attachmentList = ref([]);
+
+// 褰撳墠鏌ョ湅绫诲瀷
+const currentViewType = ref('before'); // 'before', 'after', 'issue'
+
+// 瑙嗛棰勮鐩稿叧鐘舵��
+const showVideoDialog = ref(false);
+const currentVideoFile = ref(null);
+
+// 鏂囦欢璁块棶鍩虹鍩�
+const filePreviewBase = config.fileUrl;
+
+// 椤甸潰鍔犺浇
+onLoad((options) => {
+ if (options.taskInfo) {
+ try {
+ taskInfo.value = JSON.parse(decodeURIComponent(options.taskInfo));
+ loadAttachments();
+ } catch (e) {
+ console.error('瑙f瀽浠诲姟淇℃伅澶辫触:', e);
+ uni.showToast({
+ title: '鍔犺浇澶辫触',
+ icon: 'error'
+ });
+ }
+ }
+});
+
+// 鍔犺浇闄勪欢鏁版嵁
+const loadAttachments = () => {
+ const task = taskInfo.value;
+ if (!task) return;
+
+ attachmentList.value = [];
+
+ // 鍚庣鍙嶆樉瀛楁
+ const allList = Array.isArray(task?.commonFileList) ? task.commonFileList : [];
+ const beforeList = Array.isArray(task?.commonFileListBefore)
+ ? task.commonFileListBefore
+ : allList.filter((f) => f?.type === 10);
+ const afterList = Array.isArray(task?.commonFileListAfter)
+ ? task.commonFileListAfter
+ : allList.filter((f) => f?.type === 11);
+ const issueList = Array.isArray(task?.commonFileListIssue)
+ ? task.commonFileListIssue
+ : allList.filter((f) => f?.type === 12);
+
+ const mapToViewFile = (file, viewType) => {
+ const u = normalizeFileUrl(file?.url || file?.downloadUrl || '');
+ return {
+ ...file,
+ type: viewType,
+ name: file?.name || file?.originalFilename || file?.bucketFilename,
+ bucketFilename: file?.bucketFilename || file?.name,
+ originalFilename: file?.originalFilename || file?.name,
+ url: u,
+ downloadUrl: u,
+ size: file?.size || file?.byteSize,
+ };
+ };
+
+ attachmentList.value.push(...beforeList.map((f) => mapToViewFile(f, 0)));
+ attachmentList.value.push(...afterList.map((f) => mapToViewFile(f, 1)));
+ attachmentList.value.push(...issueList.map((f) => mapToViewFile(f, 2)));
+};
+
+// 灏嗗悗绔繑鍥炵殑鏂囦欢鍦板潃瑙勮寖鎴愬彲璁块棶URL
+const normalizeFileUrl = (rawUrl) => {
+ try {
+ if (!rawUrl || typeof rawUrl !== 'string') return '';
+ const url = rawUrl.trim();
+ if (!url) return '';
+ if (/^https?:\/\//i.test(url)) return url;
+ if (url.startsWith('/')) return `${filePreviewBase}${url}`;
+
+ // Windows path -> web path
+ if (/^[a-zA-Z]:\\/.test(url)) {
+ const normalized = url.replace(/\\/g, '/');
+ const idx = normalized.indexOf('/prod/');
+ if (idx >= 0) {
+ const relative = normalized.slice(idx + '/prod/'.length);
+ return `${filePreviewBase}/${relative}`;
+ }
+ return normalized;
+ }
+
+ return `${filePreviewBase}/${url.replace(/^\//, '')}`;
+ } catch (e) {
+ return rawUrl || '';
+ }
+};
+
+// 杩斿洖涓婁竴椤�
+const goBack = () => {
+ uni.navigateBack();
+};
+
+// 鍒囨崲鏌ョ湅绫诲瀷
+const switchViewType = (type) => {
+ currentViewType.value = type;
+};
+
+// 鏍规嵁type鑾峰彇瀵瑰簲鍒嗙被鐨勯檮浠�
+const getAttachmentsByType = (typeValue) => {
+ return attachmentList.value.filter((file) => file.type === typeValue) || [];
+};
+
+// 鑾峰彇褰撳墠鏌ョ湅绫诲瀷鐨勯檮浠�
+const getCurrentViewAttachments = () => {
+ switch (currentViewType.value) {
+ case 'before':
+ return getAttachmentsByType(0);
+ case 'after':
+ return getAttachmentsByType(1);
+ case 'issue':
+ return getAttachmentsByType(2);
+ default:
+ return [];
+ }
+};
+
+// 鍒ゆ柇鏄惁涓哄浘鐗囨枃浠�
+const isImageFile = (file) => {
+ if (file.contentType && file.contentType.startsWith('image/')) {
+ return true;
+ }
+ if (file.type === 'image') return true;
+
+ const name = file.bucketFilename || file.originalFilename || file.name || '';
+ const ext = name.split('.').pop()?.toLowerCase();
+ return ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext);
+};
+
+// 棰勮闄勪欢
+const previewAttachment = (file) => {
+ if (isImageFile(file)) {
+ const imageUrls = getCurrentViewAttachments()
+ .filter((f) => isImageFile(f))
+ .map((f) => f.url || f.downloadUrl);
+
+ uni.previewImage({
+ urls: imageUrls,
+ current: file.url || file.downloadUrl,
+ });
+ } else {
+ showVideoPreview(file);
+ }
+};
+
+// 鏄剧ず瑙嗛棰勮
+const showVideoPreview = (file) => {
+ currentVideoFile.value = file;
+ showVideoDialog.value = true;
+};
+
+// 鍏抽棴瑙嗛棰勮
+const closeVideoPreview = () => {
+ showVideoDialog.value = false;
+ currentVideoFile.value = null;
+};
+
+// 瑙嗛鎾斁閿欒澶勭悊
+const handleVideoError = () => {
+ uni.showToast({
+ title: '瑙嗛鎾斁澶辫触',
+ icon: 'error',
+ });
+};
+
+// 鏍煎紡鍖栨枃浠跺ぇ灏�
+const formatFileSize = (size) => {
+ if (!size) return '';
+ if (size < 1024) return size + 'B';
+ if (size < 1024 * 1024) return (size / 1024).toFixed(1) + 'KB';
+ return (size / (1024 * 1024)).toFixed(1) + 'MB';
+};
+</script>
+
+<style scoped>
+.attachment-page {
+ min-height: 100vh;
+ background-color: #f5f5f5;
+}
+
+.attachment-content {
+ padding: 15px;
+}
+
+/* 鏍囩椤垫牱寮� */
+.attachment-tabs {
+ display: flex;
+ background: #fff;
+ border-radius: 12px;
+ margin-bottom: 15px;
+ padding: 4px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+}
+
+.tab-item {
+ flex: 1;
+ text-align: center;
+ padding: 12px 8px;
+ font-size: 14px;
+ color: #666;
+ border-radius: 8px;
+ transition: all 0.3s ease;
+}
+
+.tab-item.active {
+ background: #409eff;
+ color: #fff;
+ font-weight: 500;
+}
+
+/* 闄勪欢鍒楄〃鏍峰紡 */
+.attachment-list-container {
+ background: #fff;
+ border-radius: 12px;
+ padding: 15px;
+ min-height: 400px;
+}
+
+.attachment-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 15px;
+}
+
+.attachment-item {
+ width: calc(33.33% - 10px);
+ background: #f8f9fa;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ transition: all 0.3s ease;
+}
+
+.attachment-item:active {
+ transform: scale(0.98);
+}
+
+.attachment-preview-container {
+ width: 100%;
+ height: 120px;
+ background: #e9ecef;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.attachment-preview {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.attachment-video-preview {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+.video-text {
+ font-size: 12px;
+ color: #666;
+}
+
+.attachment-info {
+ padding: 10px;
+}
+
+.attachment-name {
+ font-size: 12px;
+ color: #333;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-bottom: 4px;
+}
+
+.attachment-size {
+ font-size: 10px;
+ color: #999;
+}
+
+/* 绌虹姸鎬佹牱寮� */
+.attachment-empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 80px 20px;
+ color: #999;
+}
+
+.empty-text {
+ margin-top: 15px;
+ font-size: 14px;
+}
+
+/* 瑙嗛寮圭獥鏍峰紡 */
+.video-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.9);
+ z-index: 10000;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20px;
+}
+
+.video-modal-container {
+ width: 100%;
+ max-width: 800px;
+ background: #000;
+ border-radius: 12px;
+ overflow: hidden;
+}
+
+.video-modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ background: #1a1a1a;
+}
+
+.video-modal-title {
+ font-size: 16px;
+ color: #fff;
+ font-weight: 500;
+}
+
+.close-btn-video {
+ width: 32px;
+ height: 32px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: rgba(255, 255, 255, 0.1);
+ border-radius: 50%;
+}
+
+.video-modal-body {
+ padding: 20px;
+}
+
+.video-player {
+ width: 100%;
+ height: 400px;
+ border-radius: 8px;
+}
+</style>
diff --git a/src/pages/inspectionUpload/components/formDia.vue b/src/pages/inspectionUpload/components/formDia.vue
index 6b900cd..62bf40f 100644
--- a/src/pages/inspectionUpload/components/formDia.vue
+++ b/src/pages/inspectionUpload/components/formDia.vue
@@ -8,53 +8,99 @@
>
<view class="popup-content">
<view class="popup-header">
- <text class="popup-title">涓婁紶</text>
+ <text class="popup-title">宸℃璁板綍涓婁紶</text>
</view>
<view class="upload-container">
+ <!-- 寮傚父鐘舵�侀�夋嫨 -->
<view class="form-container">
- <view class="title">鐢熶骇鍓�</view>
- <u-upload
- :fileList="beforeModelValue"
- @afterRead="afterRead"
- @delete="deleteFile"
- name="before"
- multiple
- :maxCount="10"
- :maxSize="5 * 1024 * 1024"
- accept="image/*"
- :previewFullImage="true"
- ></u-upload>
+ <view class="title">宸℃鐘舵��</view>
+ <view class="exception-section">
+ <view class="exception-options">
+ <view
+ class="exception-option"
+ :class="{ active: hasException === false }"
+ @click="setExceptionStatus(false)"
+ >
+ <u-icon name="checkmark-circle" size="20" color="#52c41a"></u-icon>
+ <text class="option-text">姝e父</text>
+ </view>
+ <view
+ class="exception-option"
+ :class="{ active: hasException === true }"
+ @click="setExceptionStatus(true)"
+ >
+ <u-icon name="close-circle" size="20" color="#ff4d4f"></u-icon>
+ <text class="option-text">瀛樺湪寮傚父</text>
+ </view>
+ </view>
+ </view>
+ </view>
+
+ <!-- 寮傚父鎻忚堪锛堜粎鍦ㄥ紓甯告椂鏄剧ず锛� -->
+ <view class="form-container" v-if="hasException === true">
+ <view class="title">寮傚父鎻忚堪</view>
+ <u-input
+ v-model="exceptionDescription"
+ type="textarea"
+ :maxlength="500"
+ placeholder="璇锋弿杩板紓甯告儏鍐�..."
+ :customStyle="{ padding: '10px', backgroundColor: '#f5f5f5' }"
+ />
</view>
- <view class="form-container">
- <view class="title">鐢熶骇鍚�</view>
- <u-upload
- :fileList="afterModelValue"
- @afterRead="afterRead"
- @delete="deleteFile"
- name="after"
- multiple
- :maxCount="10"
- :maxSize="5 * 1024 * 1024"
- accept="image/*"
- :previewFullImage="true"
- ></u-upload>
- </view>
-
- <view class="form-container">
- <view class="title">鐢熶骇闂</view>
- <u-upload
- :fileList="issueModelValue"
- @afterRead="afterRead"
- @delete="deleteFile"
- name="issue"
- multiple
- :maxCount="10"
- :maxSize="5 * 1024 * 1024"
- accept="image/*"
- :previewFullImage="true"
- ></u-upload>
+ <!-- 涓婁紶鍖哄煙锛堜粎鍦ㄥ紓甯告椂鏄剧ず锛� -->
+ <template v-if="hasException === true">
+ <view class="form-container">
+ <view class="title">鐢熶骇鍓�</view>
+ <u-upload
+ :fileList="beforeModelValue"
+ @afterRead="afterRead"
+ @delete="deleteFile"
+ name="before"
+ multiple
+ :maxCount="10"
+ :maxSize="5 * 1024 * 1024"
+ accept="image/*"
+ :previewFullImage="true"
+ ></u-upload>
+ </view>
+
+ <view class="form-container">
+ <view class="title">鐢熶骇鍚�</view>
+ <u-upload
+ :fileList="afterModelValue"
+ @afterRead="afterRead"
+ @delete="deleteFile"
+ name="after"
+ multiple
+ :maxCount="10"
+ :maxSize="5 * 1024 * 1024"
+ accept="image/*"
+ :previewFullImage="true"
+ ></u-upload>
+ </view>
+
+ <view class="form-container">
+ <view class="title">鐢熶骇闂</view>
+ <u-upload
+ :fileList="issueModelValue"
+ @afterRead="afterRead"
+ @delete="deleteFile"
+ name="issue"
+ multiple
+ :maxCount="10"
+ :maxSize="5 * 1024 * 1024"
+ accept="image/*"
+ :previewFullImage="true"
+ ></u-upload>
+ </view>
+ </template>
+
+ <!-- 姝e父鐘舵�佹彁绀� -->
+ <view class="form-container normal-tip" v-if="hasException === false">
+ <u-icon name="info-circle" size="40" color="#52c41a"></u-icon>
+ <text class="tip-text">璁惧杩愯姝e父锛屾棤闇�涓婁紶鐓х墖</text>
</view>
</view>
@@ -79,6 +125,11 @@
const afterModelValue = ref([])
const issueModelValue = ref([])
const infoData = ref(null)
+
+// 寮傚父鐘舵�侊細null=鏈�夋嫨, false=姝e父, true=寮傚父
+const hasException = ref(null)
+// 寮傚父鎻忚堪
+const exceptionDescription = ref('')
// 璁$畻涓婁紶URL
const uploadFileUrl = computed(() => {
@@ -196,9 +247,43 @@
}
}
+// 璁剧疆寮傚父鐘舵��
+const setExceptionStatus = (status) => {
+ hasException.value = status
+}
+
// 鎻愪氦琛ㄥ崟
const submitForm = async () => {
try {
+ // 妫�鏌ユ槸鍚﹂�夋嫨浜嗗贰妫�鐘舵��
+ if (hasException.value === null) {
+ uni.showToast({
+ title: '璇烽�夋嫨宸℃鐘舵��',
+ icon: 'none'
+ })
+ return
+ }
+
+ // 濡傛灉鏄紓甯哥姸鎬侊紝妫�鏌ユ槸鍚︽湁涓婁紶鏂囦欢
+ if (hasException.value === true) {
+ const totalFiles = beforeModelValue.value.length + afterModelValue.value.length + issueModelValue.value.length
+ if (totalFiles === 0) {
+ uni.showToast({
+ title: '璇蜂笂浼犲紓甯哥収鐗�',
+ icon: 'none'
+ })
+ return
+ }
+ // 妫�鏌ユ槸鍚﹀~鍐欎簡寮傚父鎻忚堪
+ if (!exceptionDescription.value.trim()) {
+ uni.showToast({
+ title: '璇峰~鍐欏紓甯告弿杩�',
+ icon: 'none'
+ })
+ return
+ }
+ }
+
let arr = []
if (beforeModelValue.value.length > 0) {
arr.push(...beforeModelValue.value.map(item => ({ ...item, statusType: 0 })))
@@ -212,6 +297,8 @@
// 鎻愪氦鏁版嵁
infoData.value.storageBlobDTO = arr
+ infoData.value.hasException = hasException.value
+ infoData.value.exceptionDescription = exceptionDescription.value
await submitInspectionRecord({ ...infoData.value })
uni.showToast({
@@ -238,6 +325,8 @@
beforeModelValue.value = []
afterModelValue.value = []
issueModelValue.value = []
+ hasException.value = null
+ exceptionDescription.value = ''
}
// 鍏抽棴寮规
@@ -311,4 +400,61 @@
border-top: 1px solid #f0f0f0;
background-color: #fafafa;
}
+
+// 寮傚父鐘舵�侀�夋嫨鏍峰紡
+.exception-section {
+ padding: 10px 0;
+}
+
+.exception-options {
+ display: flex;
+ gap: 15px;
+}
+
+.exception-option {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ padding: 15px 20px;
+ border: 2px solid #e0e0e0;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.3s;
+ background-color: #fff;
+
+ &.active {
+ border-color: #1890ff;
+ background-color: #e6f7ff;
+ }
+
+ &:active {
+ opacity: 0.8;
+ }
+}
+
+.option-text {
+ font-size: 14px;
+ color: #333;
+ font-weight: 500;
+}
+
+// 姝e父鐘舵�佹彁绀烘牱寮�
+.normal-tip {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 40px 20px;
+ background-color: #f6ffed;
+ border: 1px dashed #b7eb8f;
+ border-radius: 8px;
+
+ .tip-text {
+ margin-top: 15px;
+ font-size: 14px;
+ color: #52c41a;
+ }
+}
</style>
diff --git a/src/pages/inspectionUpload/index.vue b/src/pages/inspectionUpload/index.vue
index 135244b..3c6547b 100644
--- a/src/pages/inspectionUpload/index.vue
+++ b/src/pages/inspectionUpload/index.vue
@@ -56,6 +56,10 @@
<text class="detail-value">{{ item.taskId || item.id }}</text>
</view>
<view class="detail-item">
+ <text class="detail-label">宸℃椤圭洰</text>
+ <text class="detail-value">{{ item.inspectionProject || '鏃�' }}</text>
+ </view>
+ <view class="detail-item">
<text class="detail-label">澶囨敞</text>
<text class="detail-value">{{ item.remarks || '鏃�' }}</text>
</view>
@@ -95,227 +99,6 @@
<view v-if="taskTableData?.length === 0"
class="no-data">
<text>鏆傛棤鏁版嵁</text>
- </view>
- </view>
- <!-- 鍥剧墖涓婁紶寮圭獥 - 鍘熺敓瀹炵幇 -->
- <view v-if="showUploadDialog"
- class="custom-modal-overlay"
- @click="closeUploadDialog">
- <view class="custom-modal-container"
- @click.stop>
- <view class="upload-popup-content">
- <view class="upload-popup-header">
- <text class="upload-popup-title">涓婁紶宸℃璁板綍</text>
- </view>
- <view class="upload-popup-body">
- <!-- 鍒嗙被鏍囩椤� -->
- <view class="upload-tabs">
- <view class="tab-item"
- :class="{ active: currentUploadType === 'before' }"
- @click="switchUploadType('before')">
- 鐢熶骇鍓�
- </view>
- <view class="tab-item"
- :class="{ active: currentUploadType === 'after' }"
- @click="switchUploadType('after')">
- 鐢熶骇涓�
- </view>
- <view class="tab-item"
- :class="{ active: currentUploadType === 'issue' }"
- @click="switchUploadType('issue')">
- 鐢熶骇鍚�
- </view>
- </view>
- <!-- 寮傚父鐘舵�侀�夋嫨 -->
- <view class="exception-section">
- <text class="section-title">鏄惁瀛樺湪寮傚父锛�</text>
- <view class="exception-options">
- <view class="exception-option"
- :class="{ active: hasException === false }"
- @click="setExceptionStatus(false)">
- <u-icon name="checkmark-circle"
- size="20"
- color="#52c41a"></u-icon>
- <text>姝e父</text>
- </view>
- <view class="exception-option"
- :class="{ active: hasException === true }"
- @click="setExceptionStatus(true)">
- <u-icon name="close-circle"
- size="20"
- color="#ff4d4f"></u-icon>
- <text>瀛樺湪寮傚父</text>
- </view>
- </view>
- </view>
- <!-- 褰撳墠鍒嗙被鐨勪笂浼犲尯鍩� -->
- <view class="simple-upload-area">
- <view class="upload-buttons">
- <u-button type="primary"
- @click="chooseMedia('image')"
- :loading="uploading"
- :disabled="getCurrentFiles().length >= uploadConfig.limit"
- :customStyle="{ marginRight: '10px', flex: 1 }">
- <u-icon name="camera"
- size="18"
- color="#fff"
- style="margin-right: 5px;"></u-icon>
- {{ uploading ? '涓婁紶涓�...' : '鎷嶇収' }}
- </u-button>
- <u-button type="success"
- @click="chooseMedia('video')"
- :loading="uploading"
- :disabled="getCurrentFiles().length >= uploadConfig.limit"
- :customStyle="{ flex: 1 }">
- <uni-icons type="videocam"
- name="videocam"
- size="18"
- color="#fff"
- style="margin-right: 5px;"></uni-icons>
- {{ uploading ? '涓婁紶涓�...' : '鎷嶈棰�' }}
- </u-button>
- </view>
- <!-- 涓婁紶杩涘害 -->
- <view v-if="uploading"
- class="upload-progress">
- <u-line-progress :percentage="uploadProgress"
- :showText="true"
- activeColor="#409eff"></u-line-progress>
- </view>
- <!-- 褰撳墠鍒嗙被鐨勬枃浠跺垪琛� -->
- <view v-if="getCurrentFiles().length > 0"
- class="file-list">
- <view v-for="(file, index) in getCurrentFiles()"
- :key="index"
- class="file-item">
- <view class="file-preview-container">
- <image v-if="file.type === 'image' || (file.type !== 'video' && !file.type)"
- :src="file.url || file.tempFilePath || file.path || file.downloadUrl"
- class="file-preview"
- mode="aspectFill" />
- <view v-else-if="file.type === 'video'"
- class="video-preview">
- <uni-icons type="videocam"
- name="videocam"
- size="18"
- color="#fff"
- style="margin-right: 5px;"></uni-icons>
- <text class="video-text">瑙嗛</text>
- </view>
- <!-- 鍒犻櫎鎸夐挳 -->
- <view class="delete-btn"
- @click="removeFile(index)">
- <u-icon name="close"
- size="12"
- color="#fff"></u-icon>
- </view>
- </view>
- <view class="file-info">
- <text class="file-name">{{ file.bucketFilename || file.name || (file.type === 'image' ? '鍥剧墖' : '瑙嗛')
- }}</text>
- <text class="file-size">{{ formatFileSize(file.size) }}</text>
- </view>
- </view>
- </view>
- <view v-if="getCurrentFiles().length === 0"
- class="empty-state">
- <text>璇烽�夋嫨瑕佷笂浼犵殑{{ getUploadTypeText() }}鍥剧墖鎴栬棰�</text>
- </view>
- <!-- 缁熻淇℃伅 -->
- <view class="upload-summary">
- <text class="summary-text">
- 鐢熶骇鍓�: {{ beforeModelValue.length }}涓枃浠� |
- 鐢熶骇涓�: {{ afterModelValue.length }}涓枃浠� |
- 鐢熶骇鍚�: {{ issueModelValue.length }}涓枃浠�
- </text>
- </view>
- </view>
- </view>
- <view class="upload-popup-footer">
- <u-button @click="closeUploadDialog"
- :customStyle="{ marginRight: '10px' }">鍙栨秷</u-button>
- <u-button v-if="hasException === true"
- type="warning"
- @click="goToRepair"
- :customStyle="{ marginRight: '10px' }">
- 鏂板鎶ヤ慨
- </u-button>
- <u-button type="primary"
- @click="submitUpload">鎻愪氦</u-button>
- </view>
- </view>
- </view>
- </view>
- <!-- 鏌ョ湅闄勪欢寮圭獥 -->
- <view v-if="showAttachmentDialog"
- class="custom-modal-overlay"
- @click="closeAttachmentDialog">
- <view class="custom-modal-container"
- @click.stop>
- <view class="attachment-popup-content">
- <view class="attachment-popup-header">
- <text class="attachment-popup-title">鏌ョ湅闄勪欢 - {{ currentViewTask?.taskName }}</text>
- <view class="close-btn-attachment"
- @click="closeAttachmentDialog">
- <u-icon name="close"
- size="16"
- color="#666"></u-icon>
- </view>
- </view>
- <view class="attachment-popup-body">
- <!-- 鍒嗙被鏍囩椤� -->
- <view class="attachment-tabs">
- <view class="tab-item"
- :class="{ active: currentViewType === 'before' }"
- @click="switchViewType('before')">
- 鐢熶骇鍓� ({{ getAttachmentsByType(0).length }})
- </view>
- <view class="tab-item"
- :class="{ active: currentViewType === 'after' }"
- @click="switchViewType('after')">
- 鐢熶骇涓� ({{ getAttachmentsByType(1).length }})
- </view>
- <view class="tab-item"
- :class="{ active: currentViewType === 'issue' }"
- @click="switchViewType('issue')">
- 鐢熶骇鍚� ({{ getAttachmentsByType(2).length }})
- </view>
- </view>
- <!-- 褰撳墠鍒嗙被鐨勯檮浠跺垪琛� -->
- <view class="attachment-content">
- <view v-if="getCurrentViewAttachments().length > 0"
- class="attachment-list">
- <view v-for="(file, index) in getCurrentViewAttachments()"
- :key="index"
- class="attachment-item"
- @click="previewAttachment(file)">
- <view class="attachment-preview-container">
- <image v-if="file.type === 'image' || isImageFile(file)"
- :src="file.url || file.downloadUrl"
- class="attachment-preview"
- mode="aspectFill" />
- <view v-else
- class="attachment-video-preview">
- <u-icon name="video"
- size="24"
- color="#409eff"></u-icon>
- <text class="video-text">瑙嗛</text>
- </view>
- </view>
- <view class="attachment-info">
- <text class="attachment-name">{{ file.originalFilename || file.bucketFilename || file.name || '闄勪欢'
- }}</text>
- <text class="attachment-size">{{ formatFileSize(file.byteSize || file.size) }}</text>
- </view>
- </view>
- </view>
- <view v-else
- class="attachment-empty">
- <text>璇ュ垎绫绘殏鏃犻檮浠�</text>
- </view>
- </view>
- </view>
- </view>
</view>
</view>
<!-- 瑙嗛棰勮寮圭獥 -->
@@ -378,57 +161,9 @@
const currentScanningTask = ref(null);
const infoData = ref(null);
- // 涓婁紶鐩稿叧鐘舵��
- const showUploadDialog = ref(false);
- const uploadFiles = ref([]); // 淇濈暀鐢ㄤ簬鍏煎鎬�
- const uploadStatusType = ref(0);
- const uploading = ref(false);
- const uploadProgress = ref(0);
- const number = ref(0);
- const uploadList = ref([]);
-
- // 涓変釜鍒嗙被鐨勪笂浼犵姸鎬�
- const beforeModelValue = ref([]); // 鐢熶骇鍓�
- const afterModelValue = ref([]); // 鐢熶骇涓�
- const issueModelValue = ref([]); // 鐢熶骇鍚�
-
- // 褰撳墠婵�娲荤殑涓婁紶绫诲瀷
- const currentUploadType = ref("before"); // 'before', 'after', 'issue'
-
- // 鏌ョ湅闄勪欢鐩稿叧鐘舵��
- const showAttachmentDialog = ref(false);
- const currentViewTask = ref(null);
- const currentViewType = ref("before"); // 'before', 'after', 'issue'
- const attachmentList = ref([]); // 褰撳墠鏌ョ湅浠诲姟鐨勯檮浠跺垪琛�
-
// 瑙嗛棰勮鐩稿叧鐘舵��
const showVideoDialog = ref(false);
const currentVideoFile = ref(null);
-
- // 寮傚父鐘舵��
- const hasException = ref(null); // null: 鏈�夋嫨, true: 瀛樺湪寮傚父, false: 姝e父
-
- // 涓婁紶閰嶇疆
- const uploadConfig = {
- action: "/file/upload",
- limit: 10,
- fileSize: 50, // MB
- fileType: ["jpg", "jpeg", "png", "mp4", "mov"],
- maxVideoDuration: 60, // 绉�
- };
-
- // 璁$畻涓婁紶URL
- const uploadFileUrl = computed(() => {
- const baseUrl = config.baseUrl;
-
- return baseUrl + uploadConfig.action;
- });
-
- // 璁$畻璇锋眰澶�
- const headers = computed(() => {
- const token = getToken();
- return token ? { Authorization: "Bearer " + token } : {};
- });
// 璇锋眰鍙栨秷鏍囧織锛岀敤浜庡彇娑堟鍦ㄨ繘琛岀殑璇锋眰
let isRequestCancelled = false;
@@ -489,11 +224,6 @@
onUnmounted(() => {
// 璁剧疆鍙栨秷鏍囧織锛岄樆姝㈠悗缁殑寮傛鎿嶄綔
isRequestCancelled = true;
-
- // 鍏抽棴涓婁紶寮圭獥
- if (showUploadDialog.value) {
- showUploadDialog.value = false;
- }
});
// 杩斿洖涓婁竴椤�
@@ -653,322 +383,27 @@
}
};
- // 鎵撳紑涓婁紶寮圭獥
+ // 鎵撳紑涓婁紶椤甸潰
const openUploadDialog = task => {
- // 璁剧疆浠诲姟淇℃伅鍒癷nfoData
- if (task) {
- infoData.value = {
- ...task,
- taskId: task.taskId || task.id,
- storageBlobDTO: [], // 鍒濆鍖栨枃浠跺垪琛�
- };
- }
-
- // 璁剧疆涓婁紶鐘舵�佺被鍨嬶紙鍙互鏍规嵁浠诲姟绫诲瀷璁剧疆涓嶅悓鐨勭姸鎬侊級
- uploadStatusType.value = 0; // 榛樿鐘舵��
-
- // 娓呯┖涔嬪墠鐨勬枃浠�
- uploadFiles.value = [];
-
- // 鏄剧ず涓婁紶寮圭獥
- showUploadDialog.value = true;
- };
-
- // 鍏抽棴涓婁紶寮圭獥
- const closeUploadDialog = () => {
- showUploadDialog.value = false;
- uploadFiles.value = [];
- // 娓呯悊涓変釜鍒嗙被鐨勬暟鎹�
- beforeModelValue.value = [];
- afterModelValue.value = [];
- issueModelValue.value = [];
- currentUploadType.value = "before";
- hasException.value = null; // 閲嶇疆寮傚父鐘舵��
- infoData.value = null; // 娓呯悊浠诲姟鏁版嵁
- };
-
- // 鍒囨崲涓婁紶绫诲瀷
- const switchUploadType = type => {
- currentUploadType.value = type;
- };
-
- // 鑾峰彇褰撳墠鍒嗙被鐨勬枃浠跺垪琛�
- const getCurrentFiles = () => {
- switch (currentUploadType.value) {
- case "before":
- return beforeModelValue.value || [];
- case "after":
- return afterModelValue.value || [];
- case "issue":
- return issueModelValue.value || [];
- default:
- return [];
- }
- };
-
- // 鑾峰彇涓婁紶绫诲瀷鏂囨湰
- const getUploadTypeText = () => {
- switch (currentUploadType.value) {
- case "before":
- return "鐢熶骇鍓�";
- case "after":
- return "鐢熶骇涓�";
- case "issue":
- return "鐢熶骇鍚�";
- default:
- return "";
- }
- };
-
- // 澶勭悊涓婁紶鏂囦欢鏇存柊
- const handleUploadUpdate = files => {
- uploadFiles.value = files;
- };
-
- // 璁剧疆寮傚父鐘舵��
- const setExceptionStatus = status => {
- hasException.value = status;
- };
-
- // 璺宠浆鍒版柊澧炴姤淇〉闈�
- const goToRepair = () => {
- try {
- // 瀛樺偍褰撳墠浠诲姟淇℃伅鍒版湰鍦板瓨鍌紝渚涙姤淇〉闈娇鐢�
- const taskInfo = {
- taskId: infoData.value?.taskId || infoData.value?.id,
- taskName: infoData.value?.taskName,
- inspectionLocation: infoData.value?.inspectionLocation,
- inspector: infoData.value?.inspector,
- // 浼犻�掑綋鍓嶄笂浼犵殑鏂囦欢淇℃伅
- uploadedFiles: {
- before: beforeModelValue.value,
- after: afterModelValue.value,
- issue: issueModelValue.value,
- },
- };
-
- uni.setStorageSync("repairTaskInfo", JSON.stringify(taskInfo));
-
- // 璺宠浆鍒版柊澧炴姤淇〉闈�
- uni.navigateTo({
- url: "/pages/equipmentManagement/repair/add",
- });
-
- // 鍏抽棴涓婁紶寮圭獥
- closeUploadDialog();
- } catch (error) {
- console.error("璺宠浆鎶ヤ慨椤甸潰澶辫触:", error);
- uni.showToast({
- title: "璺宠浆澶辫触锛岃閲嶈瘯",
- icon: "error",
- });
- }
- };
-
- // 鎻愪氦涓婁紶
- const submitUpload = async () => {
- try {
- // 妫�鏌ユ槸鍚﹂�夋嫨浜嗗紓甯哥姸鎬�
- if (hasException.value === null) {
- uni.showToast({
- title: "璇烽�夋嫨鏄惁瀛樺湪寮傚父",
- icon: "none",
- });
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁浠讳綍鏂囦欢涓婁紶
- const totalFiles =
- beforeModelValue.value.length +
- afterModelValue.value.length +
- issueModelValue.value.length;
- if (totalFiles === 0) {
- uni.showToast({
- title: "璇峰厛涓婁紶鏂囦欢",
- icon: "none",
- });
- return;
- }
-
- // 鏄剧ず鎻愪氦涓殑鍔犺浇鎻愮ず
- showLoadingToast("鎻愪氦涓�...");
-
- // 鎸夌収鎮ㄧ殑閫昏緫鍚堝苟鎵�鏈夊垎绫荤殑鏂囦欢
- let arr = [];
- if (beforeModelValue.value.length > 0) {
- arr.push(...beforeModelValue.value);
- }
- if (afterModelValue.value.length > 0) {
- arr.push(...afterModelValue.value);
- }
- if (issueModelValue.value.length > 0) {
- arr.push(...issueModelValue.value);
- }
-
- // 浼犵粰鍚庣鐨勪复鏃舵枃浠禝D鍒楄〃锛坱empFileIds锛�
- // 鍏煎锛氭湁浜涙帴鍙e彲鑳借繑鍥� tempId / tempFileId / id
- let tempFileIds = [];
- if (arr !== null && arr.length > 0) {
- tempFileIds = arr
- .map(item => item?.tempId ?? item?.tempFileId ?? item?.id)
- .filter(v => v !== undefined && v !== null && v !== "");
- }
-
- // 鎻愪氦鏁版嵁
- infoData.value.storageBlobDTO = arr;
- // 娣诲姞寮傚父鐘舵�佷俊鎭�
- infoData.value.hasException = hasException.value;
- infoData.value.tempFileIds = tempFileIds;
- const result = await uploadInspectionTask({ ...infoData.value });
-
- // 妫�鏌ユ彁浜ょ粨鏋�
- if (result && (result.code === 200 || result.success)) {
- // 鎻愪氦鎴愬姛
- closeToast(); // 鍏抽棴鍔犺浇鎻愮ず
-
- uni.showToast({
- title: "鎻愪氦鎴愬姛",
- icon: "success",
- });
-
- // 鍏抽棴寮圭獥
- closeUploadDialog();
-
- // 鍒锋柊鍒楄〃
- setTimeout(() => {
- reloadPage();
- }, 500);
- } else {
- // 鎻愪氦澶辫触
- closeToast();
- uni.showToast({
- title: result?.msg || result?.message || "鎻愪氦澶辫触",
- icon: "error",
- });
- }
- } catch (error) {
- console.error("鎻愪氦涓婁紶澶辫触:", error);
- closeToast(); // 鍏抽棴鍔犺浇鎻愮ず
-
- let errorMessage = "鎻愪氦澶辫触";
- if (error.message) {
- errorMessage = error.message;
- } else if (error.msg) {
- errorMessage = error.msg;
- } else if (typeof error === "string") {
- errorMessage = error;
- }
-
- uni.showToast({
- title: errorMessage,
- icon: "error",
- });
- }
+ // 灏嗕换鍔′俊鎭紶閫掑埌涓婁紶椤甸潰
+ const taskData = encodeURIComponent(JSON.stringify(task));
+ uni.navigateTo({
+ url: `/pages/inspectionUpload/upload?taskInfo=${taskData}`,
+ });
};
// 鍥剧墖涓婁紶(鍙�夋嫨鍥剧墖涓婁紶鎴栬�呮槸鐩告満鎷嶇収)
const startUploadForTask = async (task, type) => {
- // 鐩存帴鎵撳紑涓婁紶寮圭獥
+ // 鎵撳紑涓婁紶椤甸潰
openUploadDialog(task);
};
- // 鏌ョ湅闄勪欢
+ // 鏌ョ湅闄勪欢 - 璺宠浆鍒伴檮浠堕〉闈�
const viewAttachments = async task => {
- try {
- currentViewTask.value = task;
- currentViewType.value = "before";
-
- // 瑙f瀽鏂扮殑鏁版嵁缁撴瀯
- attachmentList.value = [];
-
- // 鍚庣鍙嶆樉瀛楁锛堜綘鎻愪緵鐨勬暟鎹粨鏋勶級锛�
- // - commonFileListBefore锛氱敓浜у墠锛堥�氬父 type=10锛�
- // - commonFileListAfter锛氱敓浜т腑锛堥�氬父 type=11锛�
- // - commonFileList锛氬彲鑳芥槸鍏ㄩ儴/鍏滃簳锛堣嫢鍖呭惈鐢熶骇鍚庯紝涓�鑸� type=12锛�
- const allList = Array.isArray(task?.commonFileList)
- ? task.commonFileList
- : [];
- const beforeList = Array.isArray(task?.commonFileListBefore)
- ? task.commonFileListBefore
- : allList.filter(f => f?.type === 10);
- const afterList = Array.isArray(task?.commonFileListAfter)
- ? task.commonFileListAfter
- : allList.filter(f => f?.type === 11);
- // 濡傛灉鍚庣鍚庣画琛ヤ簡 commonFileListIssue锛屽垯浼樺厛鐢紱鍚﹀垯浠� commonFileList 閲屾寜 type=12 鍏滃簳
- const issueList = Array.isArray(task?.commonFileListIssue)
- ? task.commonFileListIssue
- : allList.filter(f => f?.type === 12);
-
- const mapToViewFile = (file, viewType) => {
- const u = normalizeFileUrl(file?.url || file?.downloadUrl || "");
- return {
- ...file,
- // 鐢ㄤ簬涓夋爣绛鹃〉鍒嗙粍锛�0=鐢熶骇鍓� 1=鐢熶骇涓� 2=鐢熶骇鍚�
- type: viewType,
- name: file?.name || file?.originalFilename || file?.bucketFilename,
- bucketFilename: file?.bucketFilename || file?.name,
- originalFilename: file?.originalFilename || file?.name,
- url: u,
- downloadUrl: u,
- size: file?.size || file?.byteSize,
- };
- };
-
- attachmentList.value.push(...beforeList.map(f => mapToViewFile(f, 0)));
- attachmentList.value.push(...afterList.map(f => mapToViewFile(f, 1)));
- attachmentList.value.push(...issueList.map(f => mapToViewFile(f, 2)));
-
- showAttachmentDialog.value = true;
- } catch (error) {
- uni.showToast({
- title: "鑾峰彇闄勪欢澶辫触",
- icon: "error",
- });
- }
- };
-
- // 鍏抽棴闄勪欢鏌ョ湅寮圭獥
- const closeAttachmentDialog = () => {
- showAttachmentDialog.value = false;
- currentViewTask.value = null;
- attachmentList.value = [];
- currentViewType.value = "before";
- };
-
- // 鍒囨崲鏌ョ湅绫诲瀷
- const switchViewType = type => {
- currentViewType.value = type;
- };
-
- // 鏍规嵁type鑾峰彇瀵瑰簲鍒嗙被鐨勯檮浠�
- const getAttachmentsByType = typeValue => {
- return attachmentList.value.filter(file => file.type === typeValue) || [];
- };
- // 鑾峰彇type鍊�
- const getTabType = () => {
- switch (currentUploadType.value) {
- case "before":
- return 10;
- case "after":
- return 11;
- case "issue":
- return 12;
- default:
- return 10;
- }
- };
- // 鑾峰彇褰撳墠鏌ョ湅绫诲瀷鐨勯檮浠�
- const getCurrentViewAttachments = () => {
- switch (currentViewType.value) {
- case "before":
- return getAttachmentsByType(0);
- case "after":
- return getAttachmentsByType(1);
- case "issue":
- return getAttachmentsByType(2);
- default:
- return [];
- }
+ const taskData = encodeURIComponent(JSON.stringify(task));
+ uni.navigateTo({
+ url: `/pages/inspectionUpload/attachment?taskInfo=${taskData}`,
+ });
};
// 鍒ゆ柇鏄惁涓哄浘鐗囨枃浠�
@@ -1060,474 +495,7 @@
});
};
- // 鎷嶇収/鎷嶈棰戯紙鐪熸満浼樺厛鐢� chooseMedia锛涗笉鏀寔鍒欓檷绾э級
- const chooseMedia = type => {
- if (getCurrentFiles().length >= uploadConfig.limit) {
- uni.showToast({
- title: `鏈�澶氬彧鑳介�夋嫨${uploadConfig.limit}涓枃浠禶,
- icon: "none",
- });
- return;
- }
- const remaining = uploadConfig.limit - getCurrentFiles().length;
-
- // 浼樺厛锛歝hooseMedia锛堟敮鎸� image/video锛�
- if (typeof uni.chooseMedia === "function") {
- uni.chooseMedia({
- count: Math.min(remaining, 1),
- mediaType: [type || "image"],
- sizeType: ["compressed", "original"],
- sourceType: ["camera"],
- success: res => {
- try {
- const files = res?.tempFiles || [];
- if (!files.length) throw new Error("鏈幏鍙栧埌鏂囦欢");
-
- files.forEach((tf, idx) => {
- const filePath = tf.tempFilePath || tf.path || "";
- const fileType = tf.fileType || type || "image";
- const ext = fileType === "video" ? "mp4" : "jpg";
- const file = {
- tempFilePath: filePath,
- path: filePath,
- type: fileType,
- name: `${fileType}_${Date.now()}_${idx}.${ext}`,
- size: tf.size || 0,
- duration: tf.duration || 0,
- createTime: Date.now(),
- uid: Date.now() + Math.random() + idx,
- };
- handleBeforeUpload(file);
- });
- } catch (e) {
- console.error("澶勭悊鎷嶆憚缁撴灉澶辫触:", e);
- uni.showToast({ title: "澶勭悊鏂囦欢澶辫触", icon: "error" });
- }
- },
- fail: err => {
- console.error("鎷嶆憚澶辫触:", err);
- uni.showToast({ title: "鎷嶆憚澶辫触", icon: "error" });
- },
- });
- return;
- }
-
- // 闄嶇骇锛歝hooseImage / chooseVideo
- if (type === "video") {
- chooseVideo();
- } else {
- uni.chooseImage({
- count: 1,
- sizeType: ["compressed", "original"],
- sourceType: ["camera"],
- success: res => {
- const tempFilePath = res?.tempFilePaths?.[0];
- const tempFile = res?.tempFiles?.[0] || {};
- if (!tempFilePath) return;
- handleBeforeUpload({
- tempFilePath,
- path: tempFilePath,
- type: "image",
- name: `photo_${Date.now()}.jpg`,
- size: tempFile.size || 0,
- createTime: Date.now(),
- uid: Date.now() + Math.random(),
- });
- },
- });
- }
- };
-
- // 鎷嶇収
- const chooseImage = () => {
- if (uploadFiles.value.length >= uploadConfig.limit) {
- uni.showToast({
- title: `鏈�澶氬彧鑳芥媿鎽�${uploadConfig.limit}涓枃浠禶,
- icon: "none",
- });
- return;
- }
-
- uni.chooseMedia({
- count: 1,
- mediaType: ["image", "video"],
- sizeType: ["compressed", "original"],
- sourceType: ["camera"],
- success: res => {
- try {
- if (!res.tempFiles || res.tempFiles.length === 0) {
- throw new Error("鏈幏鍙栧埌鍥剧墖鏂囦欢");
- }
-
- const tempFilePath = res.tempFiles[0];
- const tempFile =
- res.tempFiles && res.tempFiles[0] ? res.tempFiles[0] : {};
-
- const file = {
- tempFilePath: tempFilePath,
- path: tempFilePath, // 淇濇寔鍏煎鎬�
- type: "image",
- name: `photo_${Date.now()}.jpg`,
- size: tempFile.size || 0,
- createTime: new Date().getTime(),
- uid: Date.now() + Math.random(),
- };
-
- handleBeforeUpload(file);
- } catch (error) {
- console.error("澶勭悊鎷嶇収缁撴灉澶辫触:", error);
- uni.showToast({
- title: "澶勭悊鍥剧墖澶辫触",
- icon: "error",
- });
- }
- },
- fail: err => {
- console.error("鎷嶇収澶辫触:", err);
- uni.showToast({
- title: "鎷嶇収澶辫触: " + (err.errMsg || "鏈煡閿欒"),
- icon: "error",
- });
- },
- });
- };
-
- // 鎷嶈棰�
- const chooseVideo = () => {
- if (uploadFiles.value.length >= uploadConfig.limit) {
- uni.showToast({
- title: `鏈�澶氬彧鑳芥媿鎽�${uploadConfig.limit}涓枃浠禶,
- icon: "none",
- });
- return;
- }
-
- uni.chooseVideo({
- sourceType: ["camera"],
- maxDuration: uploadConfig.maxVideoDuration,
- camera: "back",
- success: res => {
- try {
- if (!res.tempFilePath) {
- throw new Error("鏈幏鍙栧埌瑙嗛鏂囦欢");
- }
-
- const file = {
- tempFilePath: res.tempFilePath,
- path: res.tempFilePath, // 淇濇寔鍏煎鎬�
- type: "video",
- name: `video_${Date.now()}.mp4`,
- size: res.size || 0,
- duration: res.duration || 0,
- createTime: new Date().getTime(),
- uid: Date.now() + Math.random(),
- };
-
- handleBeforeUpload(file);
- } catch (error) {
- console.error("澶勭悊鎷嶈棰戠粨鏋滃け璐�:", error);
- uni.showToast({
- title: "澶勭悊瑙嗛澶辫触",
- icon: "error",
- });
- }
- },
- fail: err => {
- console.error("鎷嶈棰戝け璐�:", err);
- uni.showToast({
- title: "鎷嶈棰戝け璐�: " + (err.errMsg || "鏈煡閿欒"),
- icon: "error",
- });
- },
- });
- };
-
- // 鍒犻櫎鏂囦欢
- const removeFile = index => {
- uni.showModal({
- title: "纭鍒犻櫎",
- content: "纭畾瑕佸垹闄よ繖涓枃浠跺悧锛�",
- success: res => {
- if (res.confirm) {
- // 鏍规嵁褰撳墠涓婁紶绫诲瀷鍒犻櫎瀵瑰簲鍒嗙被鐨勬枃浠�
- switch (currentUploadType.value) {
- case "before":
- beforeModelValue.value.splice(index, 1);
- break;
- case "after":
- afterModelValue.value.splice(index, 1);
- break;
- case "issue":
- issueModelValue.value.splice(index, 1);
- break;
- }
- uni.showToast({
- title: "鍒犻櫎鎴愬姛",
- icon: "success",
- });
- }
- },
- });
- };
-
- // 妫�鏌ョ綉缁滆繛鎺�
- const checkNetworkConnection = () => {
- return new Promise(resolve => {
- uni.getNetworkType({
- success: res => {
- if (res.networkType === "none") {
- resolve(false);
- } else {
- resolve(true);
- }
- },
- fail: () => {
- resolve(false);
- },
- });
- });
- };
-
- // 涓婁紶鍓嶆牎楠�
- const handleBeforeUpload = async file => {
- // 鏍¢獙鏂囦欢绫诲瀷
- if (
- uploadConfig.fileType &&
- Array.isArray(uploadConfig.fileType) &&
- uploadConfig.fileType.length > 0
- ) {
- const fileName = file.name || "";
- const fileExtension = fileName
- ? fileName.split(".").pop().toLowerCase()
- : "";
-
- // 鏍规嵁鏂囦欢绫诲瀷纭畾鏈熸湜鐨勬墿灞曞悕
- let expectedTypes = [];
- if (file.type === "image") {
- expectedTypes = ["jpg", "jpeg", "png", "gif", "webp"];
- } else if (file.type === "video") {
- expectedTypes = ["mp4", "mov", "avi", "wmv"];
- }
-
- // 妫�鏌ユ枃浠舵墿灞曞悕鏄惁鍦ㄥ厑璁哥殑绫诲瀷涓�
- if (fileExtension && expectedTypes.length > 0) {
- const isAllowed = expectedTypes.some(
- type => uploadConfig.fileType.includes(type) && type === fileExtension
- );
-
- if (!isAllowed) {
- uni.showToast({
- title: `鏂囦欢鏍煎紡涓嶆敮鎸侊紝璇锋媿鎽� ${expectedTypes.join("/")} 鏍煎紡鐨勬枃浠禶,
- icon: "none",
- });
- return false;
- }
- }
- }
-
- // 鏍¢獙閫氳繃锛屽紑濮嬩笂浼�
- uploadFile(file);
- return true;
- };
-
- // 鏂囦欢涓婁紶澶勭悊锛堢湡鏈鸿蛋 uni.uploadFile锛�
- const uploadFile = async file => {
- uploading.value = true;
- uploadProgress.value = 0;
- number.value++; // 澧炲姞涓婁紶璁℃暟
-
- // 纭繚token瀛樺湪
- const token = getToken();
- if (!token) {
- handleUploadError("鐢ㄦ埛鏈櫥褰�");
- return;
- }
-
- const typeValue = getTabType(); // 鐢熶骇鍓�:10, 鐢熶骇涓�:11, 鐢熶骇鍚�:12
-
- uploadWithUniUploadFile(
- file,
- file.tempFilePath || file.path || "",
- typeValue,
- token
- );
- };
-
- // 浣跨敤uni.uploadFile涓婁紶锛堥潪H5鐜鎴朒5鍥為��鏂规锛�
- const uploadWithUniUploadFile = (file, filePath, typeValue, token) => {
- if (!filePath) {
- handleUploadError("鏂囦欢璺緞涓嶅瓨鍦�");
- return;
- }
-
- const uploadTask = uni.uploadFile({
- url: uploadFileUrl.value,
- filePath: filePath,
- name: "file",
- formData: {
- type: typeValue,
- },
- header: {
- Authorization: `Bearer ${token}`,
- },
- success: res => {
- try {
- if (res.statusCode === 200) {
- const response = JSON.parse(res.data);
- if (response.code === 200) {
- handleUploadSuccess(response, file);
- uni.showToast({
- title: "涓婁紶鎴愬姛",
- icon: "success",
- });
- } else {
- handleUploadError(response.msg || "鏈嶅姟鍣ㄨ繑鍥為敊璇�");
- }
- } else {
- handleUploadError(`鏈嶅姟鍣ㄩ敊璇紝鐘舵�佺爜: ${res.statusCode}`);
- }
- } catch (e) {
- console.error("瑙f瀽鍝嶅簲澶辫触:", e);
- console.error("鍘熷鍝嶅簲鏁版嵁:", res.data);
- handleUploadError("鍝嶅簲鏁版嵁瑙f瀽澶辫触: " + e.message);
- }
- },
- fail: err => {
- console.error("涓婁紶澶辫触:", err.errMsg || err);
- number.value--; // 涓婁紶澶辫触鏃跺噺灏戣鏁�
-
- let errorMessage = "涓婁紶澶辫触";
- if (err.errMsg) {
- if (err.errMsg.includes("statusCode: null")) {
- errorMessage = "缃戠粶杩炴帴澶辫触锛岃妫�鏌ョ綉缁滆缃�";
- } else if (err.errMsg.includes("timeout")) {
- errorMessage = "涓婁紶瓒呮椂锛岃閲嶈瘯";
- } else if (err.errMsg.includes("fail")) {
- errorMessage = "涓婁紶澶辫触锛岃妫�鏌ョ綉缁滆繛鎺�";
- } else {
- errorMessage = err.errMsg;
- }
- }
-
- handleUploadError(errorMessage);
- },
- complete: () => {
- uploading.value = false;
- uploadProgress.value = 0;
- },
- });
-
- // 鐩戝惉涓婁紶杩涘害
- if (uploadTask && uploadTask.onProgressUpdate) {
- uploadTask.onProgressUpdate(res => {
- uploadProgress.value = res.progress;
- });
- }
- };
-
- // 涓婁紶澶辫触澶勭悊
- const handleUploadError = (message = "涓婁紶鏂囦欢澶辫触", showRetry = false) => {
- uploading.value = false;
- uploadProgress.value = 0;
-
- if (showRetry) {
- uni.showModal({
- title: "涓婁紶澶辫触",
- content: message + "锛屾槸鍚﹂噸璇曪紵",
- success: res => {
- if (res.confirm) {
- // 鐢ㄦ埛閫夋嫨閲嶈瘯锛岃繖閲屽彲浠ラ噸鏂拌Е鍙戜笂浼�
- }
- },
- });
- } else {
- uni.showToast({
- title: message,
- icon: "error",
- });
- }
- };
-
- // 涓婁紶鎴愬姛鍥炶皟
- const handleUploadSuccess = (res, file) => {
- console.log("涓婁紶鎴愬姛鍝嶅簲:", res);
-
- // 澶勭悊涓嶅悓鐨勬暟鎹粨鏋勶細鍙兘鏄暟缁勶紝涔熷彲鑳芥槸鍗曚釜瀵硅薄
- let uploadedFile = null;
- uploadedFile = res.data;
-
- if (!uploadedFile) {
- console.error("鏃犳硶瑙f瀽涓婁紶鍝嶅簲鏁版嵁:", res);
- number.value--; // 涓婁紶澶辫触鏃跺噺灏戣鏁�
- handleUploadError("涓婁紶鍝嶅簲鏁版嵁鏍煎紡閿欒", false);
- return;
- }
-
- // 鏍规嵁褰撳墠涓婁紶绫诲瀷璁剧疆type瀛楁
- let typeValue = 0; // 榛樿涓虹敓浜у墠
- switch (currentUploadType.value) {
- case "before":
- typeValue = 0;
- break;
- case "after":
- typeValue = 1;
- break;
- case "issue":
- typeValue = 2;
- break;
- }
-
- // 纭繚涓婁紶鐨勬枃浠舵暟鎹畬鏁达紝鍖呭惈id鍜宼ype
- const fileData = {
- ...file,
- id: uploadedFile.id, // 娣诲姞鏈嶅姟鍣ㄨ繑鍥炵殑id
- tempId: uploadedFile.tempId ?? uploadedFile.tempFileId ?? uploadedFile.id,
- url:
- uploadedFile.url ||
- uploadedFile.downloadUrl ||
- file.tempFilePath ||
- file.path,
- bucketFilename:
- uploadedFile.bucketFilename || uploadedFile.originalFilename || file.name,
- downloadUrl: uploadedFile.downloadUrl || uploadedFile.url,
- size: uploadedFile.size || uploadedFile.byteSize || file.size,
- createTime: uploadedFile.createTime || new Date().getTime(),
- type: typeValue, // 娣诲姞绫诲瀷瀛楁锛�0=鐢熶骇鍓�, 1=鐢熶骇涓�, 2=鐢熶骇鍚�
- };
-
- uploadList.value.push(fileData);
-
- // 绔嬪嵆娣诲姞鍒板搴旂殑鍒嗙被锛屼笉绛夊緟鎵�鏈夋枃浠朵笂浼犲畬鎴�
- switch (currentUploadType.value) {
- case "before":
- beforeModelValue.value.push(fileData);
- break;
- case "after":
- afterModelValue.value.push(fileData);
- break;
- case "issue":
- issueModelValue.value.push(fileData);
- break;
- }
-
- // 閲嶇疆涓婁紶鍒楄〃锛堝洜涓哄凡缁忔坊鍔犲埌瀵瑰簲鍒嗙被浜嗭級
- uploadList.value = [];
- number.value = 0;
- };
-
- // 涓婁紶缁撴潫澶勭悊锛堝凡搴熷純锛岀幇鍦ㄥ湪handleUploadSuccess涓洿鎺ュ鐞嗭級
- const uploadedSuccessfully = () => {
- // 姝ゅ嚱鏁板凡涓嶅啀浣跨敤锛屾枃浠朵笂浼犳垚鍔熷悗绔嬪嵆娣诲姞鍒板搴斿垎绫�
- };
-
- // 鏍煎紡鍖栨枃浠跺ぇ灏�
- const formatFileSize = size => {
- if (!size) return "";
- if (size < 1024) return size + "B";
- if (size < 1024 * 1024) return (size / 1024).toFixed(1) + "KB";
- return (size / (1024 * 1024)).toFixed(1) + "MB";
- };
</script>
<style scoped>
@@ -1725,416 +693,6 @@
display: flex;
align-items: center;
justify-content: center;
- }
-
- /* 涓婁紶寮圭獥鏍峰紡 */
- .upload-popup-content {
- background: #fff;
- border-radius: 12px;
- width: 100%;
- min-height: 300px;
- max-height: 70vh;
- overflow: hidden;
- display: flex;
- flex-direction: column;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
- }
-
- .upload-popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px 20px;
- border-bottom: 1px solid #eee;
- }
-
- .upload-popup-title {
- font-size: 16px;
- font-weight: 600;
- color: #333;
- }
-
- .upload-popup-body {
- flex: 1;
- padding: 20px;
- overflow-y: auto;
- }
-
- .upload-popup-footer {
- display: flex;
- justify-content: flex-end;
- padding: 15px 20px;
- border-top: 1px solid #eee;
- gap: 10px;
- }
-
- /* 绠�鍖栦笂浼犵粍浠舵牱寮� */
- .simple-upload-area {
- padding: 15px;
- }
-
- .upload-buttons {
- display: flex;
- gap: 10px;
- margin-bottom: 15px;
- }
-
- .file-list {
- margin-top: 15px;
- display: flex;
- flex-wrap: wrap;
- gap: 12px;
- }
-
- .file-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- background: #fff;
- border-radius: 12px;
- padding: 8px;
- border: 1px solid #e9ecef;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- transition: all 0.3s ease;
- width: calc(50% - 6px);
- min-width: 120px;
- }
-
- .file-item:hover {
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
- transform: translateY(-2px);
- }
-
- .file-preview-container {
- position: relative;
- margin-bottom: 8px;
- }
-
- .file-preview {
- width: 80px;
- height: 80px;
- border-radius: 8px;
- object-fit: cover;
- border: 2px solid #f0f0f0;
- }
-
- .video-preview {
- width: 80px;
- height: 80px;
- background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
- border-radius: 8px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- border: 2px solid #f0f0f0;
- }
-
- .video-text {
- font-size: 12px;
- color: #666;
- margin-top: 4px;
- }
-
- .delete-btn {
- position: absolute;
- top: -6px;
- right: -6px;
- width: 20px;
- height: 20px;
- background: #ff4757;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- box-shadow: 0 2px 4px rgba(255, 71, 87, 0.3);
- transition: all 0.3s ease;
- }
-
- .delete-btn:hover {
- background: #ff3742;
- transform: scale(1.1);
- }
-
- .file-info {
- text-align: center;
- width: 100%;
- }
-
- .file-name {
- font-size: 12px;
- color: #333;
- font-weight: 500;
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 100px;
- }
-
- .file-size {
- font-size: 10px;
- color: #999;
- margin-top: 2px;
- display: block;
- }
-
- .empty-state {
- text-align: center;
- padding: 40px 20px;
- color: #999;
- font-size: 14px;
- background: #f8f9fa;
- border-radius: 8px;
- border: 2px dashed #ddd;
- }
-
- .upload-progress {
- margin: 15px 0;
- padding: 0 10px;
- }
-
- /* 涓婁紶鏍囩椤垫牱寮� */
- .upload-tabs {
- display: flex;
- background: #f8f9fa;
- border-radius: 8px;
- margin-bottom: 15px;
- padding: 4px;
- }
-
- .tab-item {
- flex: 1;
- text-align: center;
- padding: 8px 12px;
- font-size: 14px;
- color: #666;
- border-radius: 6px;
- transition: all 0.3s ease;
- cursor: pointer;
- }
-
- .tab-item.active {
- background: #409eff;
- color: #fff;
- font-weight: 500;
- }
-
- .tab-item:hover:not(.active) {
- background: #e9ecef;
- color: #333;
- }
-
- /* 寮傚父鐘舵�侀�夋嫨鏍峰紡 */
- .exception-section {
- margin-bottom: 20px;
- padding: 15px;
- background: #f8f9fa;
- border-radius: 8px;
- border: 1px solid #e9ecef;
- }
-
- .section-title {
- display: block;
- font-size: 14px;
- font-weight: 600;
- color: #333;
- margin-bottom: 12px;
- }
-
- .exception-options {
- display: flex;
- gap: 12px;
- }
-
- .exception-option {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 8px;
- padding: 12px 16px;
- background: #fff;
- border: 2px solid #e9ecef;
- border-radius: 8px;
- cursor: pointer;
- transition: all 0.3s ease;
- font-size: 14px;
- color: #666;
- }
-
- .exception-option.active {
- border-color: #409eff;
- background: #f0f8ff;
- color: #409eff;
- font-weight: 500;
- }
-
- .exception-option:hover:not(.active) {
- border-color: #d9d9d9;
- background: #fafafa;
- }
-
- /* 缁熻淇℃伅鏍峰紡 */
- .upload-summary {
- margin-top: 15px;
- padding: 10px;
- background: #f8f9fa;
- border-radius: 6px;
- border-left: 3px solid #409eff;
- }
-
- .summary-text {
- font-size: 12px;
- color: #666;
- line-height: 1.4;
- }
-
- /* 鏌ョ湅闄勪欢寮圭獥鏍峰紡 */
- .attachment-popup-content {
- background: #fff;
- border-radius: 12px;
- width: 100%;
- min-height: 400px;
- max-height: 70vh;
- overflow: hidden;
- display: flex;
- flex-direction: column;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
- }
-
- .attachment-popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px 20px;
- border-bottom: 1px solid #eee;
- background: #f8f9fa;
- }
-
- .attachment-popup-title {
- font-size: 16px;
- font-weight: 600;
- color: #333;
- }
-
- .close-btn-attachment {
- width: 28px;
- height: 28px;
- border-radius: 50%;
- background: #f5f5f5;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: all 0.3s ease;
- }
-
- .close-btn-attachment:hover {
- background: #e9ecef;
- transform: scale(1.1);
- }
-
- .attachment-popup-body {
- flex: 1;
- padding: 15px 20px;
- overflow-y: auto;
- }
-
- .attachment-tabs {
- display: flex;
- background: #f8f9fa;
- border-radius: 8px;
- margin-bottom: 15px;
- padding: 4px;
- }
-
- .attachment-content {
- min-height: 200px;
- }
-
- .attachment-list {
- display: flex;
- flex-wrap: wrap;
- gap: 12px;
- }
-
- .attachment-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- background: #fff;
- border-radius: 12px;
- padding: 8px;
- border: 1px solid #e9ecef;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
- transition: all 0.3s ease;
- width: calc(33.33% - 8px);
- min-width: 100px;
- cursor: pointer;
- }
-
- .attachment-item:hover {
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
- transform: translateY(-2px);
- }
-
- .attachment-preview-container {
- margin-bottom: 8px;
- }
-
- .attachment-preview {
- width: 80px;
- height: 80px;
- border-radius: 8px;
- object-fit: cover;
- border: 2px solid #f0f0f0;
- }
-
- .attachment-video-preview {
- width: 80px;
- height: 80px;
- background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
- border-radius: 8px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- border: 2px solid #f0f0f0;
- }
-
- .attachment-info {
- text-align: center;
- width: 100%;
- }
-
- .attachment-name {
- font-size: 12px;
- color: #333;
- font-weight: 500;
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 80px;
- }
-
- .attachment-size {
- font-size: 10px;
- color: #999;
- margin-top: 2px;
- display: block;
- }
-
- .attachment-empty {
- text-align: center;
- padding: 60px 20px;
- color: #999;
- font-size: 14px;
- background: #f8f9fa;
- border-radius: 8px;
- border: 2px dashed #ddd;
}
/* 瑙嗛棰勮寮圭獥鏍峰紡 */
diff --git a/src/pages/inspectionUpload/upload.vue b/src/pages/inspectionUpload/upload.vue
new file mode 100644
index 0000000..746e995
--- /dev/null
+++ b/src/pages/inspectionUpload/upload.vue
@@ -0,0 +1,885 @@
+<template>
+ <view class="inspection-upload-page">
+ <!-- 椤甸潰澶撮儴 -->
+ <PageHeader title="涓婁紶宸℃璁板綍" @back="goBack" />
+
+ <!-- 椤甸潰鍐呭 -->
+ <view class="upload-content">
+ <!-- 浠诲姟淇℃伅鍗$墖 -->
+ <view class="task-info-card" v-if="taskInfo">
+ <view class="task-info-header">
+ <text class="task-name">{{ taskInfo.taskName }}</text>
+ </view>
+ <view class="task-info-body">
+ <view class="info-item">
+ <text class="info-label">浠诲姟ID</text>
+ <text class="info-value">{{ taskInfo.taskId || taskInfo.id }}</text>
+ </view>
+ <view class="info-item">
+ <text class="info-label">宸℃浣嶇疆</text>
+ <text class="info-value">{{ taskInfo.inspectionLocation || '-' }}</text>
+ </view>
+ <view class="info-item">
+ <text class="info-label">鎵ц浜�</text>
+ <text class="info-value">{{ taskInfo.inspector || '-' }}</text>
+ </view>
+ </view>
+ </view>
+
+ <!-- 寮傚父鐘舵�侀�夋嫨 -->
+ <view class="section-card">
+ <view class="section-title">宸℃鐘舵��</view>
+ <view class="exception-options">
+ <view
+ class="exception-option"
+ :class="{ active: hasException === false }"
+ @click="setExceptionStatus(false)"
+ >
+ <u-icon name="checkmark-circle" size="20" color="#52c41a"></u-icon>
+ <text class="option-text">姝e父</text>
+ </view>
+ <view
+ class="exception-option"
+ :class="{ active: hasException === true }"
+ @click="setExceptionStatus(true)"
+ >
+ <u-icon name="close-circle" size="20" color="#ff4d4f"></u-icon>
+ <text class="option-text">瀛樺湪寮傚父</text>
+ </view>
+ </view>
+ </view>
+
+ <!-- 寮傚父鎻忚堪锛堜粎鍦ㄥ紓甯告椂鏄剧ず锛� -->
+ <view class="section-card" v-if="hasException === true">
+ <view class="section-title">寮傚父鎻忚堪</view>
+ <textarea
+ v-model="abnormalDescription"
+ class="exception-textarea"
+ maxlength="500"
+ placeholder="璇锋弿杩板紓甯告儏鍐�..."
+ />
+ </view>
+
+ <!-- 鍒嗙被鏍囩椤碉紙浠呭湪寮傚父鏃舵樉绀猴級 -->
+ <view class="section-card" v-if="hasException === true">
+ <view class="upload-tabs">
+ <view
+ class="tab-item"
+ :class="{ active: currentUploadType === 'before' }"
+ @click="switchUploadType('before')"
+ >
+ 鐢熶骇鍓�
+ </view>
+ <view
+ class="tab-item"
+ :class="{ active: currentUploadType === 'after' }"
+ @click="switchUploadType('after')"
+ >
+ 鐢熶骇涓�
+ </view>
+ <view
+ class="tab-item"
+ :class="{ active: currentUploadType === 'issue' }"
+ @click="switchUploadType('issue')"
+ >
+ 鐢熶骇鍚�
+ </view>
+ </view>
+
+ <!-- 褰撳墠鍒嗙被鐨勪笂浼犲尯鍩� -->
+ <view class="upload-area">
+ <view class="upload-buttons">
+ <u-button
+ type="primary"
+ @click="chooseMedia('image')"
+ :loading="uploading"
+ :disabled="getCurrentFiles().length >= uploadConfig.limit"
+ :customStyle="{ marginRight: '10px', flex: 1 }"
+ >
+ <u-icon name="camera" size="18" color="#fff" style="margin-right: 5px"></u-icon>
+ {{ uploading ? '涓婁紶涓�...' : '鎷嶇収' }}
+ </u-button>
+ <u-button
+ type="success"
+ @click="chooseMedia('video')"
+ :loading="uploading"
+ :disabled="getCurrentFiles().length >= uploadConfig.limit"
+ :customStyle="{ flex: 1 }"
+ >
+ <uni-icons type="videocam" size="18" color="#fff" style="margin-right: 5px"></uni-icons>
+ {{ uploading ? '涓婁紶涓�...' : '鎷嶈棰�' }}
+ </u-button>
+ </view>
+
+ <!-- 涓婁紶杩涘害 -->
+ <view v-if="uploading" class="upload-progress">
+ <u-line-progress :percentage="uploadProgress" :showText="true" activeColor="#409eff"></u-line-progress>
+ </view>
+
+ <!-- 褰撳墠鍒嗙被鐨勬枃浠跺垪琛� -->
+ <view v-if="getCurrentFiles().length > 0" class="file-list">
+ <view v-for="(file, index) in getCurrentFiles()" :key="index" class="file-item">
+ <view class="file-preview-container">
+ <image
+ v-if="file.type === 'image' || (file.type !== 'video' && !file.type)"
+ :src="file.url || file.tempFilePath || file.path || file.downloadUrl"
+ class="file-preview"
+ mode="aspectFill"
+ />
+ <view v-else-if="file.type === 'video'" class="video-preview">
+ <uni-icons type="videocam" size="18" color="#fff" style="margin-right: 5px"></uni-icons>
+ <text class="video-text">瑙嗛</text>
+ </view>
+ <!-- 鍒犻櫎鎸夐挳 -->
+ <view class="delete-btn" @click="removeFile(index)">
+ <u-icon name="close" size="12" color="#fff"></u-icon>
+ </view>
+ </view>
+ <view class="file-info">
+ <text class="file-name">{{ file.bucketFilename || file.name || (file.type === 'image' ? '鍥剧墖' : '瑙嗛') }}</text>
+ <text class="file-size">{{ formatFileSize(file.size) }}</text>
+ </view>
+ </view>
+ </view>
+
+ <view v-if="getCurrentFiles().length === 0" class="empty-state">
+ <text>璇烽�夋嫨瑕佷笂浼犵殑{{ getUploadTypeText() }}鍥剧墖鎴栬棰�</text>
+ </view>
+ </view>
+
+ <!-- 缁熻淇℃伅 -->
+ <view class="upload-summary">
+ <text class="summary-text">
+ 鐢熶骇鍓�: {{ beforeModelValue.length }}涓枃浠� |
+ 鐢熶骇涓�: {{ afterModelValue.length }}涓枃浠� |
+ 鐢熶骇鍚�: {{ issueModelValue.length }}涓枃浠�
+ </text>
+ </view>
+ </view>
+
+ <!-- 姝e父鐘舵�佹彁绀� -->
+ <view class="normal-tip-card" v-if="hasException === false">
+ <u-icon name="info-circle" size="60" color="#52c41a"></u-icon>
+ <text class="tip-text">璁惧杩愯姝e父锛屾棤闇�涓婁紶鐓х墖</text>
+ </view>
+ </view>
+
+ <!-- 搴曢儴鎸夐挳 -->
+ <view class="footer-buttons">
+ <u-button @click="goBack" :customStyle="{ marginRight: '10px' }">鍙栨秷</u-button>
+ <u-button v-if="hasException === true" type="warning" @click="goToRepair" :customStyle="{ marginRight: '10px' }">
+ 鏂板鎶ヤ慨
+ </u-button>
+ <u-button type="primary" @click="submitUpload">鎻愪氦</u-button>
+ </view>
+ </view>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import PageHeader from '@/components/PageHeader.vue';
+import { uploadInspectionTask } from '@/api/inspectionManagement';
+import { getToken } from '@/utils/auth';
+import config from '@/config';
+
+// 浠诲姟淇℃伅
+const taskInfo = ref(null);
+
+// 涓婁紶鐩稿叧鐘舵��
+const uploading = ref(false);
+const uploadProgress = ref(0);
+
+// 涓変釜鍒嗙被鐨勪笂浼犵姸鎬�
+const beforeModelValue = ref([]); // 鐢熶骇鍓�
+const afterModelValue = ref([]); // 鐢熶骇涓�
+const issueModelValue = ref([]); // 鐢熶骇鍚�
+
+// 褰撳墠婵�娲荤殑涓婁紶绫诲瀷
+const currentUploadType = ref('before'); // 'before', 'after', 'issue'
+
+// 寮傚父鐘舵��
+const hasException = ref(null); // null: 鏈�夋嫨, true: 瀛樺湪寮傚父, false: 姝e父
+// 寮傚父鎻忚堪
+const abnormalDescription = ref('');
+
+// 涓婁紶閰嶇疆
+const uploadConfig = {
+ action: '/file/upload',
+ limit: 10,
+ fileSize: 50, // MB
+ fileType: ['jpg', 'jpeg', 'png', 'mp4', 'mov'],
+ maxVideoDuration: 60, // 绉�
+};
+
+// 璁$畻涓婁紶URL
+const uploadFileUrl = computed(() => {
+ const baseUrl = config.baseUrl;
+ return baseUrl + uploadConfig.action;
+});
+
+// 椤甸潰鍔犺浇
+onLoad((options) => {
+ if (options.taskInfo) {
+ try {
+ taskInfo.value = JSON.parse(decodeURIComponent(options.taskInfo));
+ } catch (e) {
+ console.error('瑙f瀽浠诲姟淇℃伅澶辫触:', e);
+ }
+ }
+});
+
+// 杩斿洖涓婁竴椤�
+const goBack = () => {
+ uni.navigateBack();
+};
+
+// 鍒囨崲涓婁紶绫诲瀷
+const switchUploadType = (type) => {
+ currentUploadType.value = type;
+};
+
+// 鑾峰彇褰撳墠鍒嗙被鐨勬枃浠跺垪琛�
+const getCurrentFiles = () => {
+ switch (currentUploadType.value) {
+ case 'before':
+ return beforeModelValue.value || [];
+ case 'after':
+ return afterModelValue.value || [];
+ case 'issue':
+ return issueModelValue.value || [];
+ default:
+ return [];
+ }
+};
+
+// 鑾峰彇涓婁紶绫诲瀷鏂囨湰
+const getUploadTypeText = () => {
+ switch (currentUploadType.value) {
+ case 'before':
+ return '鐢熶骇鍓�';
+ case 'after':
+ return '鐢熶骇涓�';
+ case 'issue':
+ return '鐢熶骇鍚�';
+ default:
+ return '';
+ }
+};
+
+// 璁剧疆寮傚父鐘舵��
+const setExceptionStatus = (status) => {
+ hasException.value = status;
+};
+
+// 璺宠浆鍒版柊澧炴姤淇〉闈�
+const goToRepair = () => {
+ try {
+ const taskData = {
+ taskId: taskInfo.value?.taskId || taskInfo.value?.id,
+ taskName: taskInfo.value?.taskName,
+ inspectionLocation: taskInfo.value?.inspectionLocation,
+ inspector: taskInfo.value?.inspector,
+ uploadedFiles: {
+ before: beforeModelValue.value,
+ after: afterModelValue.value,
+ issue: issueModelValue.value,
+ },
+ };
+
+ uni.setStorageSync('repairTaskInfo', JSON.stringify(taskData));
+
+ uni.navigateTo({
+ url: '/pages/equipmentManagement/repair/add',
+ });
+ } catch (error) {
+ console.error('璺宠浆鎶ヤ慨椤甸潰澶辫触:', error);
+ uni.showToast({
+ title: '璺宠浆澶辫触锛岃閲嶈瘯',
+ icon: 'error',
+ });
+ }
+};
+
+// 鎻愪氦涓婁紶
+const submitUpload = async () => {
+ try {
+ // 妫�鏌ユ槸鍚﹂�夋嫨浜嗗紓甯哥姸鎬�
+ if (hasException.value === null) {
+ uni.showToast({
+ title: '璇烽�夋嫨宸℃鐘舵��',
+ icon: 'none',
+ });
+ return;
+ }
+
+ // 濡傛灉鏄紓甯哥姸鎬侊紝妫�鏌ユ槸鍚︽湁涓婁紶鏂囦欢鍜屾弿杩�
+ if (hasException.value === true) {
+ const totalFiles = beforeModelValue.value.length + afterModelValue.value.length + issueModelValue.value.length;
+ if (totalFiles === 0) {
+ uni.showToast({
+ title: '璇蜂笂浼犲紓甯哥収鐗�',
+ icon: 'none',
+ });
+ return;
+ }
+ // 妫�鏌ユ槸鍚﹀~鍐欎簡寮傚父鎻忚堪
+ if (!abnormalDescription.value.trim()) {
+ uni.showToast({
+ title: '璇峰~鍐欏紓甯告弿杩�',
+ icon: 'none',
+ });
+ return;
+ }
+ }
+
+ // 鏄剧ず鎻愪氦涓殑鍔犺浇鎻愮ず
+ uni.showLoading({
+ title: '鎻愪氦涓�...',
+ mask: true,
+ });
+
+ // 鎸夌収閫昏緫鍚堝苟鎵�鏈夊垎绫荤殑鏂囦欢
+ let arr = [];
+ if (beforeModelValue.value.length > 0) {
+ arr.push(...beforeModelValue.value);
+ }
+ if (afterModelValue.value.length > 0) {
+ arr.push(...afterModelValue.value);
+ }
+ if (issueModelValue.value.length > 0) {
+ arr.push(...issueModelValue.value);
+ }
+
+ // 浼犵粰鍚庣鐨勪复鏃舵枃浠禝D鍒楄〃
+ let tempFileIds = [];
+ if (arr !== null && arr.length > 0) {
+ tempFileIds = arr
+ .map((item) => item?.tempId ?? item?.tempFileId ?? item?.id)
+ .filter((v) => v !== undefined && v !== null && v !== '');
+ }
+
+ // 鎻愪氦鏁版嵁
+ const submitData = {
+ ...taskInfo.value,
+ storageBlobDTO: arr,
+ hasException: hasException.value,
+ abnormalDescription: abnormalDescription.value,
+ tempFileIds: tempFileIds,
+ };
+
+ const result = await uploadInspectionTask(submitData);
+
+ // 妫�鏌ユ彁浜ょ粨鏋�
+ if (result && (result.code === 200 || result.success)) {
+ uni.hideLoading();
+ uni.showToast({
+ title: '鎻愪氦鎴愬姛',
+ icon: 'success',
+ });
+
+ // 杩斿洖鍒楄〃椤靛苟鍒锋柊
+ setTimeout(() => {
+ uni.navigateBack();
+ }, 500);
+ } else {
+ uni.hideLoading();
+ uni.showToast({
+ title: result?.msg || result?.message || '鎻愪氦澶辫触',
+ icon: 'error',
+ });
+ }
+ } catch (error) {
+ console.error('鎻愪氦涓婁紶澶辫触:', error);
+ uni.hideLoading();
+ uni.showToast({
+ title: error?.message || '鎻愪氦澶辫触',
+ icon: 'error',
+ });
+ }
+};
+
+// 鏍煎紡鍖栨枃浠跺ぇ灏�
+const formatFileSize = (size) => {
+ if (!size) return '0 B';
+ const units = ['B', 'KB', 'MB', 'GB'];
+ let index = 0;
+ let fileSize = size;
+ while (fileSize >= 1024 && index < units.length - 1) {
+ fileSize /= 1024;
+ index++;
+ }
+ return `${fileSize.toFixed(2)} ${units[index]}`;
+};
+
+// 鎷嶇収/鎷嶈棰�
+const chooseMedia = (type) => {
+ if (getCurrentFiles().length >= uploadConfig.limit) {
+ uni.showToast({
+ title: `鏈�澶氬彧鑳介�夋嫨${uploadConfig.limit}涓枃浠禶,
+ icon: 'none',
+ });
+ return;
+ }
+
+ const remaining = uploadConfig.limit - getCurrentFiles().length;
+
+ // 浼樺厛浣跨敤 chooseMedia
+ if (typeof uni.chooseMedia === 'function') {
+ uni.chooseMedia({
+ count: Math.min(remaining, 1),
+ mediaType: [type || 'image'],
+ sizeType: ['compressed', 'original'],
+ sourceType: ['camera'],
+ success: (res) => {
+ try {
+ const files = res?.tempFiles || [];
+ if (!files.length) throw new Error('鏈幏鍙栧埌鏂囦欢');
+
+ files.forEach((tf, idx) => {
+ const filePath = tf.tempFilePath || tf.path || '';
+ const fileType = tf.fileType || type || 'image';
+ const ext = fileType === 'video' ? 'mp4' : 'jpg';
+ const file = {
+ tempFilePath: filePath,
+ path: filePath,
+ type: fileType,
+ name: `${fileType}_${Date.now()}_${idx}.${ext}`,
+ size: tf.size || 0,
+ duration: tf.duration || 0,
+ createTime: Date.now(),
+ };
+ uploadFile(file);
+ });
+ } catch (err) {
+ uni.showToast({ title: err.message || '澶勭悊鏂囦欢澶辫触', icon: 'none' });
+ }
+ },
+ fail: (err) => {
+ console.error('閫夋嫨濯掍綋澶辫触:', err);
+ uni.showToast({ title: '閫夋嫨澶辫触', icon: 'none' });
+ },
+ });
+ } else {
+ // 闄嶇骇鏂规
+ if (type === 'video') {
+ uni.chooseVideo({
+ sourceType: ['camera'],
+ success: (res) => {
+ const file = {
+ tempFilePath: res.tempFilePath,
+ path: res.tempFilePath,
+ type: 'video',
+ name: `video_${Date.now()}.mp4`,
+ size: res.size || 0,
+ duration: res.duration || 0,
+ createTime: Date.now(),
+ };
+ uploadFile(file);
+ },
+ fail: () => {
+ uni.showToast({ title: '閫夋嫨瑙嗛澶辫触', icon: 'none' });
+ },
+ });
+ } else {
+ uni.chooseImage({
+ count: Math.min(remaining, 9),
+ sizeType: ['compressed'],
+ sourceType: ['camera'],
+ success: (res) => {
+ const list = res.tempFilePaths || res.tempFiles || [];
+ list.forEach((src, idx) => {
+ const path = typeof src === 'string' ? src : src.path;
+ const file = {
+ tempFilePath: path,
+ path: path,
+ type: 'image',
+ name: `image_${Date.now()}_${idx}.jpg`,
+ size: 0,
+ createTime: Date.now(),
+ };
+ uploadFile(file);
+ });
+ },
+ fail: () => {
+ uni.showToast({ title: '閫夋嫨鍥剧墖澶辫触', icon: 'none' });
+ },
+ });
+ }
+ }
+};
+
+// 涓婁紶鍗曚釜鏂囦欢
+const uploadFile = (file) => {
+ const token = getToken();
+ if (!token) {
+ uni.showToast({ title: '鐢ㄦ埛鏈櫥褰�', icon: 'none' });
+ return;
+ }
+
+ uploading.value = true;
+ uploadProgress.value = 0;
+
+ const uploadTask = uni.uploadFile({
+ url: uploadFileUrl.value,
+ filePath: file.tempFilePath,
+ name: 'file',
+ header: {
+ Authorization: `Bearer ${token}`,
+ },
+ formData: {
+ type: getTabType(),
+ },
+ success: (res) => {
+ try {
+ const data = JSON.parse(res.data);
+ if (data.code === 200) {
+ const uploadedFile = {
+ ...file,
+ url: data.data.url,
+ tempId: data.data.tempId || data.data.id,
+ status: 'success',
+ };
+
+ // 鏍规嵁褰撳墠绫诲瀷娣诲姞鍒板搴旀暟缁�
+ if (currentUploadType.value === 'before') {
+ beforeModelValue.value.push(uploadedFile);
+ } else if (currentUploadType.value === 'after') {
+ afterModelValue.value.push(uploadedFile);
+ } else if (currentUploadType.value === 'issue') {
+ issueModelValue.value.push(uploadedFile);
+ }
+
+ uni.showToast({ title: '涓婁紶鎴愬姛', icon: 'success' });
+ } else {
+ uni.showToast({ title: data.msg || '涓婁紶澶辫触', icon: 'none' });
+ }
+ } catch (e) {
+ uni.showToast({ title: '瑙f瀽鍝嶅簲澶辫触', icon: 'none' });
+ }
+ },
+ fail: (err) => {
+ console.error('涓婁紶澶辫触:', err);
+ uni.showToast({ title: '涓婁紶澶辫触', icon: 'none' });
+ },
+ complete: () => {
+ uploading.value = false;
+ },
+ });
+
+ // 鐩戝惉涓婁紶杩涘害
+ uploadTask.onProgressUpdate((res) => {
+ uploadProgress.value = res.progress;
+ });
+};
+
+// 鑾峰彇type鍊�
+const getTabType = () => {
+ switch (currentUploadType.value) {
+ case 'before':
+ return 10;
+ case 'after':
+ return 11;
+ case 'issue':
+ return 12;
+ default:
+ return 10;
+ }
+};
+
+// 鍒犻櫎鏂囦欢
+const removeFile = (index) => {
+ const files = getCurrentFiles();
+ files.splice(index, 1);
+};
+</script>
+
+<style scoped>
+.inspection-upload-page {
+ min-height: 100vh;
+ background-color: #f5f5f5;
+ padding-bottom: 80px;
+}
+
+.upload-content {
+ padding: 15px;
+}
+
+/* 浠诲姟淇℃伅鍗$墖 */
+.task-info-card {
+ background: #fff;
+ border-radius: 12px;
+ padding: 15px;
+ margin-bottom: 15px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+}
+
+.task-info-header {
+ margin-bottom: 12px;
+ padding-bottom: 12px;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.task-name {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
+
+.task-info-body {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.info-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.info-label {
+ font-size: 13px;
+ color: #999;
+}
+
+.info-value {
+ font-size: 13px;
+ color: #666;
+}
+
+/* 閫氱敤鍗$墖鏍峰紡 */
+.section-card {
+ background: #fff;
+ border-radius: 12px;
+ padding: 15px;
+ margin-bottom: 15px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+}
+
+.section-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #333;
+ margin-bottom: 12px;
+}
+
+/* 寮傚父鐘舵�侀�夋嫨 */
+.exception-options {
+ display: flex;
+ gap: 12px;
+}
+
+.exception-option {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ padding: 14px 16px;
+ background: #f8f9fa;
+ border: 2px solid #e9ecef;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.exception-option.active {
+ border-color: #409eff;
+ background: #f0f8ff;
+}
+
+.option-text {
+ font-size: 14px;
+ color: #333;
+ font-weight: 500;
+}
+
+/* 寮傚父鎻忚堪 */
+.exception-textarea {
+ width: 100%;
+ min-height: 100px;
+ padding: 12px;
+ background: #f8f9fa;
+ border: 1px solid #e9ecef;
+ border-radius: 8px;
+ font-size: 14px;
+ color: #333;
+ resize: none;
+ box-sizing: border-box;
+}
+
+.exception-textarea:focus {
+ outline: none;
+ border-color: #409eff;
+ background: #fff;
+}
+
+/* 鍒嗙被鏍囩椤� */
+.upload-tabs {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 15px;
+}
+
+.tab-item {
+ flex: 1;
+ padding: 10px;
+ text-align: center;
+ background: #f5f5f5;
+ border-radius: 6px;
+ font-size: 13px;
+ color: #666;
+ cursor: pointer;
+ transition: all 0.3s;
+}
+
+.tab-item.active {
+ background: #409eff;
+ color: #fff;
+}
+
+/* 涓婁紶鍖哄煙 */
+.upload-area {
+ padding: 10px 0;
+}
+
+.upload-buttons {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 15px;
+}
+
+.upload-progress {
+ margin-bottom: 15px;
+}
+
+/* 鏂囦欢鍒楄〃 */
+.file-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+.file-item {
+ width: calc(33.33% - 7px);
+}
+
+.file-preview-container {
+ position: relative;
+ width: 100%;
+ aspect-ratio: 1;
+ border-radius: 8px;
+ overflow: hidden;
+ background: #f5f5f5;
+}
+
+.file-preview {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.video-preview {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: #333;
+}
+
+.video-text {
+ font-size: 12px;
+ color: #fff;
+ margin-top: 5px;
+}
+
+.delete-btn {
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ width: 22px;
+ height: 22px;
+ background: rgba(0, 0, 0, 0.5);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.file-info {
+ margin-top: 5px;
+}
+
+.file-name {
+ display: block;
+ font-size: 11px;
+ color: #666;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.file-size {
+ display: block;
+ font-size: 10px;
+ color: #999;
+ margin-top: 2px;
+}
+
+.empty-state {
+ text-align: center;
+ padding: 30px;
+ color: #999;
+ font-size: 13px;
+}
+
+/* 缁熻淇℃伅 */
+.upload-summary {
+ margin-top: 15px;
+ padding: 10px;
+ background: #f8f9fa;
+ border-radius: 6px;
+ border-left: 3px solid #409eff;
+}
+
+.summary-text {
+ font-size: 12px;
+ color: #666;
+}
+
+/* 姝e父鐘舵�佹彁绀� */
+.normal-tip-card {
+ background: #f6ffed;
+ border: 2px dashed #b7eb8f;
+ border-radius: 12px;
+ padding: 50px 20px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 15px;
+}
+
+.normal-tip-card .tip-text {
+ margin-top: 15px;
+ font-size: 16px;
+ color: #52c41a;
+ font-weight: 500;
+}
+
+/* 搴曢儴鎸夐挳 */
+.footer-buttons {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ padding: 15px;
+ background: #fff;
+ border-top: 1px solid #f0f0f0;
+ box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
+}
+</style>
--
Gitblit v1.9.3