From 944f8c5c49b1dad9bea2c82f422d9e90d150398c Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 20 五月 2026 15:39:38 +0800
Subject: [PATCH] 设备巡检
---
src/pages/inspectionUpload/index.vue | 3312 ++++++++++++++++++++++++----------------------------------
1 files changed, 1,375 insertions(+), 1,937 deletions(-)
diff --git a/src/pages/inspectionUpload/index.vue b/src/pages/inspectionUpload/index.vue
index badcebb..bb4ea87 100644
--- a/src/pages/inspectionUpload/index.vue
+++ b/src/pages/inspectionUpload/index.vue
@@ -1,52 +1,33 @@
<template>
<view class="inspection-upload-page">
<!-- 椤甸潰澶撮儴 -->
- <PageHeader title="璁惧宸℃"
- @back="goBack" />
+ <PageHeader title="璁惧宸℃" @back="goBack" />
<!-- 鏁版嵁鍒楄〃 -->
<view class="table-section">
<!-- 鐢熶骇宸℃鍒楄〃 -->
<view class="task-list">
- <view v-for="(item, index) in taskTableData"
- :key="index"
- class="task-item">
+ <view v-for="(item, index) in taskTableData" :key="index" class="task-item">
<view class="task-header">
<view class="task-info">
<text class="task-name">{{ item.taskName }}</text>
<text class="task-location">{{ item.inspectionLocation }}</text>
</view>
<view class="task-actions">
- <!-- <u-button type="primary"
- size="small"
- @click.stop="startScanForTask(item)"
- :customStyle="{
- borderRadius: '15px',
- height: '30px',
- fontSize: '12px',
- marginRight: '8px'
- }">
- 鎵爜涓婁紶
- </u-button> -->
- <u-button type="primary"
- size="small"
- @click.stop="startUploadForTask(item)"
- :customStyle="{
- borderRadius: '15px',
- height: '30px',
- fontSize: '12px',
- marginRight: '8px'
- }">
- 鍥剧墖涓婁紶
+ <u-button type="primary" size="small" :disabled="item.inspectionStatus > 0 && item.acceptStatus !== 2"
+ @click.stop="startUploadForTask(item)" :customStyle="{
+ borderRadius: '15px',
+ height: '30px',
+ fontSize: '12px',
+ marginRight: '8px'
+ }">
+ 宸℃
</u-button>
- <u-button type="success"
- size="small"
- @click.stop="viewAttachments(item)"
- :customStyle="{
+ <u-button type="success" size="small" @click.stop="viewAttachments(item)" :customStyle="{
borderRadius: '15px',
height: '30px',
fontSize: '12px'
}">
- 鏌ョ湅闄勪欢
+ 鏌ョ湅璇︽儏
</u-button>
</view>
</view>
@@ -70,21 +51,19 @@
<view class="detail-item">
<text class="detail-label">宸℃鐘舵��</text>
<view class="detail-value">
- <uni-tag v-if="item.fileStatus==2"
- text="宸插畬鎴�"
- size="small"
- type="success"
- inverted></uni-tag>
- <uni-tag v-else-if="item.fileStatus==1"
- text="宸℃涓�"
- size="small"
- type="primary"
- inverted></uni-tag>
- <uni-tag v-else=""
- text="鏈贰妫�"
- size="small"
- type="warning"
- inverted></uni-tag>
+ <uni-tag v-if="item.inspectionStatus === 1" text="姝e父" size="small" type="success" inverted></uni-tag>
+ <uni-tag v-else-if="item.inspectionStatus === 2" text="寮傚父" size="small" type="error" inverted></uni-tag>
+ <uni-tag v-else text="鏈贰妫�" size="small" type="warning" inverted></uni-tag>
+ </view>
+ </view>
+ <view class="detail-item">
+ <text class="detail-label">楠屾敹鐘舵��</text>
+ <view class="detail-value">
+ <uni-tag v-if="item.acceptStatus === 1" text="宸查�氳繃" size="small" type="success" inverted></uni-tag>
+ <uni-tag v-else-if="item.acceptStatus === 2" text="宸查��鍥�" size="small" type="error" inverted></uni-tag>
+ <uni-tag v-else-if="item.inspectionStatus > 0" text="寰呴獙鏀�" size="small" type="warning"
+ inverted></uni-tag>
+ <text v-else>--</text>
</view>
</view>
</view>
@@ -92,122 +71,72 @@
<uni-load-more :status="loadMoreStatus"></uni-load-more>
</view>
<!-- 绌虹姸鎬� -->
- <view v-if="taskTableData?.length === 0"
- class="no-data">
+ <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 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>
+ <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>
+ <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>
+ <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>
+ <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 v-if="hasException === true" class="media-upload-section">
+ <!-- 鎷嶇収鍜岃棰戜笂浼犳寜閽� -->
<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>
+ <u-button type="primary" @click="chooseMedia('image')" :loading="uploading"
+ :disabled="uploadFiles.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>
+ <u-button type="success" @click="chooseMedia('video')" :loading="uploading"
+ :disabled="uploadFiles.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 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="isImageFile(file)"
- :src="getFileAccessUrl(file)"
- class="file-preview"
- mode="aspectFill" />
- <view v-else-if="isVideoFile(file)"
- class="video-preview">
- <uni-icons type="videocam"
- name="videocam"
- size="18"
- color="#fff"
- style="margin-right: 5px;"></uni-icons>
+
+ <!-- 鏂囦欢鍒楄〃 -->
+ <view v-if="uploadFiles.length > 0" class="file-list">
+ <view v-for="(file, index) in uploadFiles" :key="index" class="file-item">
+ <view class="file-preview-container" @click="previewUploadedMedia(file)">
+ <image v-if="isImageFile(file)" :src="getFileAccessUrl(file)" class="file-preview"
+ mode="aspectFill" />
+ <view v-else-if="isVideoFile(file)" 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 class="delete-btn" @click.stop="removeFile(index)">
+ <u-icon name="close" size="12" color="#fff"></u-icon>
</view>
</view>
<view class="file-info">
@@ -217,88 +146,68 @@
</view>
</view>
</view>
- <view v-if="getCurrentFiles().length === 0"
- class="empty-state">
- <text>璇烽�夋嫨瑕佷笂浼犵殑{{ getUploadTypeText() }}鍥剧墖鎴栬棰�</text>
+
+ <!-- 绌虹姸鎬佹彁绀� -->
+ <view v-if="uploadFiles.length === 0" class="empty-state">
+ <text>璇锋媿鎽勫紓甯告儏鍐电殑鐓х墖鎴栬棰�</text>
</view>
+
<!-- 缁熻淇℃伅 -->
<view class="upload-summary">
<text class="summary-text">
- 鐢熶骇鍓�: {{ beforeModelValue.length }}涓枃浠� |
- 鐢熶骇涓�: {{ afterModelValue.length }}涓枃浠� |
- 鐢熶骇鍚�: {{ issueModelValue.length }}涓枃浠�
+ 宸蹭笂浼� {{ uploadFiles.length }} 涓枃浠讹紙鍥剧墖/瑙嗛锛�
</text>
</view>
</view>
+
+ <!-- 寮傚父鎻忚堪杈撳叆妗� -->
+ <view v-if="hasException === true" class="exception-desc-section">
+ <text class="section-title">寮傚父鎻忚堪</text>
+ <u-input v-model="exceptionDesc" type="textarea" :autoHeight="true" :minHeight="120"
+ placeholder="璇疯缁嗘弿杩板紓甯哥幇璞″強鎯呭喌" :maxlength="500" count />
+ </view>
+
+ <!-- 姝e父鐘舵�佺殑鎻愮ず -->
+ <view v-if="hasException === false" class="normal-tip">
+ <u-icon name="info-circle" size="20" color="#52c41a"></u-icon>
+ <text class="tip-text">璁惧妫�鏌ユ甯革紝鏃犻渶涓婁紶闄勪欢</text>
+ </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>
+ <u-button @click="closeUploadDialog" :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 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>
+ <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 class="detail-info-section" v-if="currentViewTask?.inspectionStatus === 2">
+ <text class="info-label">寮傚父鎻忚堪锛�</text>
+ <text class="info-value">{{ currentViewTask?.inspectionRemark || '鏃�' }}</text>
</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 v-if="attachmentList.length > 0" class="attachment-list">
+ <view v-for="(file, index) in attachmentList" :key="index" class="attachment-item"
+ @click="previewAttachment(file)">
<view class="attachment-preview-container">
- <image v-if="file.type === 'image' || isImageFile(file)"
- :src="getFileAccessUrl(file)"
- class="attachment-preview"
- mode="aspectFill" />
- <view v-else
- class="attachment-video-preview">
- <u-icon name="video"
- size="24"
- color="#409eff"></u-icon>
+ <image v-if="isImageFile(file)" :src="getFileAccessUrl(file)" 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>
@@ -309,37 +218,27 @@
</view>
</view>
</view>
- <view v-else
- class="attachment-empty">
- <text>璇ュ垎绫绘殏鏃犻檮浠�</text>
+ <view v-else class="attachment-empty">
+ <text>鏆傛棤闄勪欢</text>
</view>
</view>
</view>
</view>
</view>
</view>
+
<!-- 瑙嗛棰勮寮圭獥 -->
- <view v-if="showVideoDialog"
- class="video-modal-overlay"
- @click="closeVideoPreview">
- <view class="video-modal-container"
- @click.stop>
+ <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="16"
- color="#fff"></u-icon>
+ <view class="close-btn-video" @click="closeVideoPreview">
+ <u-icon name="close" size="16" color="#fff"></u-icon>
</view>
</view>
<view class="video-modal-body">
- <video v-if="currentVideoFile"
- :src="getFileAccessUrl(currentVideoFile)"
- class="video-player"
- controls
- autoplay
- @error="handleVideoError"></video>
+ <video v-if="currentVideoFile" :src="currentVideoFile._playUrl" class="video-player" controls autoplay
+ @error="handleVideoError"></video>
</view>
</view>
</view>
@@ -347,1877 +246,1416 @@
</template>
<script setup>
- import { onMounted, onUnmounted, ref, nextTick, computed, reactive } from "vue";
- import { onShow, onReachBottom, onPullDownRefresh } from "@dcloudio/uni-app";
- import PageHeader from "@/components/PageHeader.vue";
- import { getLedgerById } from "@/api/equipmentManagement/ledger.js";
- import {
- inspectionTaskList,
- uploadInspectionTask,
- } from "@/api/inspectionManagement";
- import { getToken } from "@/utils/auth";
- import config from "@/config";
+import { onMounted, onUnmounted, ref, nextTick, computed, reactive } from "vue";
+import { onShow, onReachBottom, onPullDownRefresh } from "@dcloudio/uni-app";
+import PageHeader from "@/components/PageHeader.vue";
+import {
+ inspectionTaskList,
+ uploadInspectionTask,
+} from "@/api/inspectionManagement";
+import { getToken } from "@/utils/auth";
+import config from "@/config";
- // 缁勪欢寮曠敤宸茬Щ闄�
-
- // 鍔犺浇鎻愮ず鏂规硶
- const showLoadingToast = message => {
- uni.showLoading({
- title: message,
- mask: true,
- });
- };
- const closeToast = () => {
- uni.hideLoading();
- };
-
- // 琛ㄦ牸鏁版嵁
- const taskTableData = ref([]); // 鐢熶骇宸℃鏁版嵁
-
- // 褰撳墠鎵弿鐨勪换鍔�
- 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 showLoadingToast = message => {
+ uni.showLoading({
+ title: message,
+ mask: true,
});
+};
+const closeToast = () => {
+ uni.hideLoading();
+};
- // 璁$畻璇锋眰澶�
- const headers = computed(() => {
- const token = getToken();
- return token ? { Authorization: "Bearer " + token } : {};
- });
+// 琛ㄦ牸鏁版嵁
+const taskTableData = ref([]);
- // 璇锋眰鍙栨秷鏍囧織锛岀敤浜庡彇娑堟鍦ㄨ繘琛岀殑璇锋眰
- let isRequestCancelled = false;
+// 褰撳墠浠诲姟淇℃伅
+const currentScanningTask = ref(null);
+const infoData = ref(null);
- const pagesPames = reactive({
- size: 10,
- current: 1,
- });
+// 涓婁紶鐩稿叧鐘舵��
+const showUploadDialog = ref(false);
+const uploadFiles = ref([]);
+const uploading = ref(false);
+const uploadProgress = ref(0);
+const number = ref(0);
- const loadMoreStatus = computed(() => {
- if (loading.value) {
- return "loading";
- }
- if (noMore.value) {
- return "noMore";
- }
- return "more";
- });
- const totalSize = ref(0);
- const noMore = computed(() => {
- return taskTableData.value.length >= totalSize.value;
- });
- const loading = ref(false);
+// 寮傚父鐘舵��
+const hasException = ref(null);
+// 寮傚父鎻忚堪
+const exceptionDesc = ref("");
- const reloadPage = () => {
- pagesPames.current = 1;
- taskTableData.value = [];
- getList();
- };
- const loadPage = () => {
- if (noMore.value || loading.value) return;
- pagesPames.current += 1;
- getList();
- };
+// 鏌ョ湅闄勪欢鐩稿叧鐘舵��
+const showAttachmentDialog = ref(false);
+const currentViewTask = ref(null);
+const attachmentList = ref([]);
- // 鐢熷懡鍛ㄦ湡
- onMounted(() => {
- // 寤惰繜鍒濆鍖栵紝纭繚DOM宸叉覆鏌�
- // nextTick(() => {
- // getList()
- // })
- });
+// 瑙嗛棰勮鐩稿叧鐘舵��
+const showVideoDialog = ref(false);
+const currentVideoFile = ref(null);
- onReachBottom(() => {
- loadPage();
- });
- onPullDownRefresh(() => {
- reloadPage();
- uni.stopPullDownRefresh();
- });
+// 涓婁紶閰嶇疆
+const uploadConfig = {
+ action: "/file/upload",
+ limit: 10,
+ fileSize: 50,
+ fileType: ["jpg", "jpeg", "png", "mp4", "mov"],
+ maxVideoDuration: 60,
+};
- onShow(() => {
- // 椤甸潰鏄剧ず鏃跺埛鏂版暟鎹�
- reloadPage();
- });
+const uploadFileUrl = computed(() => {
+ const baseUrl = config.baseUrl;
+ return baseUrl + uploadConfig.action;
+});
- // 缁勪欢閿�姣佹椂鐨勬竻鐞�
- onUnmounted(() => {
- // 璁剧疆鍙栨秷鏍囧織锛岄樆姝㈠悗缁殑寮傛鎿嶄綔
- isRequestCancelled = true;
+let isRequestCancelled = false;
- // 鍏抽棴涓婁紶寮圭獥
- if (showUploadDialog.value) {
- showUploadDialog.value = false;
- }
- });
+const pagesPames = reactive({
+ size: 10,
+ current: 1,
+});
- // 杩斿洖涓婁竴椤�
- const goBack = () => {
- uni.navigateBack();
- };
+const loadMoreStatus = computed(() => {
+ if (loading.value) {
+ return "loading";
+ }
+ if (noMore.value) {
+ return "noMore";
+ }
+ return "more";
+});
+const totalSize = ref(0);
+const noMore = computed(() => {
+ return taskTableData.value.length >= totalSize.value;
+});
+const loading = ref(false);
- // 鑾峰彇鍒楄〃鏁版嵁
- const getList = () => {
- // 鏄剧ず鍔犺浇鎻愮ず
- // showLoadingToast('鍔犺浇涓�...')
+const reloadPage = () => {
+ pagesPames.current = 1;
+ taskTableData.value = [];
+ getList();
+};
+const loadPage = () => {
+ if (noMore.value || loading.value) return;
+ pagesPames.current += 1;
+ getList();
+};
- // 璁剧疆鍙栨秷鏍囧織
- isRequestCancelled = false;
- loading.value = true;
- inspectionTaskList({ ...pagesPames })
- .then(res => {
- // 妫�鏌ョ粍浠舵槸鍚﹁繕瀛樺湪涓旇姹傛湭琚彇娑�
- if (!isRequestCancelled) {
- // 澶勭悊涓嶅悓鐨勬暟鎹粨鏋�
- let records = [];
- if (res && res.data) {
- // 灏濊瘯澶氱鍙兘鐨勬暟鎹粨鏋�
- totalSize.value = res.data.total;
- if (Array.isArray(res.data.records)) {
- records = res.data.records;
- } else if (Array.isArray(res.data.rows)) {
- records = res.data.rows;
- } else if (Array.isArray(res.data)) {
- records = res.data;
- } else if (Array.isArray(res.data.list)) {
- records = res.data.list;
- }
- }
+onMounted(() => { });
- if (records.length > 0) {
- taskTableData.value = [
- ...taskTableData.value,
- ...records.map(record => {
- record.fileStatus = getFileStatus(record);
- return record;
- }),
- ];
- } else {
- taskTableData.value = [];
- uni.showToast({
- title: "鏆傛棤宸℃浠诲姟鏁版嵁",
- icon: "none",
- });
- }
- }
- loading.value = false;
- // 鍏抽棴鍔犺浇鎻愮ず
- // closeToast()
- })
- .catch(err => {
- // 妫�鏌ョ粍浠舵槸鍚﹁繕瀛樺湪涓旇姹傛湭琚彇娑�
- if (!isRequestCancelled) {
- taskTableData.value = [];
- // 娣诲姞閿欒鎻愮ず
- uni.showToast({
- title: "鑾峰彇鏁版嵁澶辫触",
- icon: "error",
- });
- }
- loading.value = false;
- // 鍏抽棴鍔犺浇鎻愮ず
- // closeToast()
- });
- };
+onReachBottom(() => {
+ loadPage();
+});
+onPullDownRefresh(() => {
+ reloadPage();
+ uni.stopPullDownRefresh();
+});
- const getFileStatus = record => {
- let _beforeProduction =
- record.beforeProduction && record.beforeProduction.length;
- let _afterProduction =
- record.afterProduction && record.afterProduction.length;
- let _productionIssues =
- record.productionIssues && record.productionIssues.length;
- if (_beforeProduction && _afterProduction && _productionIssues) {
- return 2;
- } else if (_beforeProduction || _afterProduction || _productionIssues) {
- return 1;
- } else {
- return 0;
- }
- };
+onShow(() => {
+ reloadPage();
+});
- // 涓烘寚瀹氫换鍔″紑濮嬫壂鐮侊紙鐪熸満锛�
- const startScanForTask = async task => {
- try {
- currentScanningTask.value = task;
- uni.scanCode({
- success: res => {
- handleScanSuccess(res);
- },
- fail: err => {
- console.error("鎵爜澶辫触:", err);
- uni.showToast({
- title: "鎵爜澶辫触",
- icon: "error",
- });
- },
- });
- } catch (e) {
- console.error("鍚姩鎵爜澶辫触:", e);
- uni.showToast({
- title: "鍚姩鎵爜澶辫触",
- icon: "error",
- });
- }
- };
-
- // 鎵爜鎴愬姛澶勭悊锛氭牎楠屽悗鎵撳紑涓婁紶寮圭獥
- const handleScanSuccess = result => {
- try {
- // 瑙f瀽浜岀淮鐮佹暟鎹紝鎻愬彇deviceId
- let deviceId = "";
-
- if (result?.result && typeof result.result === "string") {
- if (result.result.includes("deviceId=")) {
- const match = result.result.match(/deviceId=(\d+)/);
- if (match && match[1]) deviceId = match[1];
- } else {
- try {
- const qrData = JSON.parse(result.result);
- deviceId = qrData.deviceId || qrData.qrCodeId || "";
- } catch (e) {
- deviceId = result.result;
- }
- }
- }
-
- if (!deviceId) {
- uni.showToast({ title: "鏈瘑鍒埌璁惧ID", icon: "error" });
- return;
- }
-
- const currentTaskId =
- currentScanningTask.value?.taskId || currentScanningTask.value?.id;
- if (!currentTaskId) {
- uni.showToast({ title: "浠诲姟淇℃伅缂哄け", icon: "error" });
- return;
- }
-
- if (deviceId === currentTaskId.toString()) {
- uni.showToast({ title: "璇嗗埆鎴愬姛", icon: "success" });
- openUploadDialog(currentScanningTask.value);
- } else {
- uni.showToast({ title: "璇锋壂鎻忔纭殑璁惧", icon: "error" });
- }
- } catch (error) {
- console.error("鎵爜缁撴灉澶勭悊澶辫触:", error);
- uni.showToast({
- title: error?.message || "鏁版嵁瑙f瀽澶辫触",
- icon: "error",
- });
- }
- };
-
- // 鎵撳紑涓婁紶寮圭獥
- 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 = () => {
+onUnmounted(() => {
+ isRequestCancelled = true;
+ if (showUploadDialog.value) {
showUploadDialog.value = false;
+ }
+});
+
+const goBack = () => {
+ uni.navigateBack();
+};
+
+const getList = () => {
+ isRequestCancelled = false;
+ loading.value = true;
+ inspectionTaskList({ ...pagesPames })
+ .then(res => {
+ if (!isRequestCancelled) {
+ let records = [];
+ if (res && res.data) {
+ totalSize.value = res.data.total;
+ if (Array.isArray(res.data.records)) {
+ records = res.data.records;
+ } else if (Array.isArray(res.data.rows)) {
+ records = res.data.rows;
+ } else if (Array.isArray(res.data)) {
+ records = res.data;
+ } else if (Array.isArray(res.data.list)) {
+ records = res.data.list;
+ }
+ }
+
+ if (records.length > 0) {
+ taskTableData.value = [
+ ...taskTableData.value,
+ ...records.map(record => {
+ record.fileStatus = getFileStatus(record);
+ return record;
+ }),
+ ];
+ } else {
+ taskTableData.value = [];
+ uni.showToast({
+ title: "鏆傛棤宸℃浠诲姟鏁版嵁",
+ icon: "none",
+ });
+ }
+ }
+ loading.value = false;
+ })
+ .catch(err => {
+ if (!isRequestCancelled) {
+ taskTableData.value = [];
+ uni.showToast({
+ title: "鑾峰彇鏁版嵁澶辫触",
+ icon: "error",
+ });
+ }
+ loading.value = false;
+ });
+};
+
+const getFileStatus = record => {
+ // 鏍规嵁鏄惁鏈夐檮浠跺垽鏂姸鎬�
+ let hasFiles = false;
+ if (record.commonFileList && record.commonFileList.length > 0) {
+ hasFiles = true;
+ }
+ if (record.commonFileListBefore && record.commonFileListBefore.length > 0) {
+ hasFiles = true;
+ }
+ if (record.commonFileListAfter && record.commonFileListAfter.length > 0) {
+ hasFiles = true;
+ }
+ return hasFiles ? 2 : 0;
+};
+
+const openUploadDialog = task => {
+ if (task) {
+ infoData.value = {
+ ...task,
+ taskId: task.taskId || task.id,
+ storageBlobDTO: [],
+ };
+ }
+ showUploadDialog.value = true;
+};
+
+const closeUploadDialog = () => {
+ showUploadDialog.value = false;
+ uploadFiles.value = [];
+ hasException.value = null;
+ exceptionDesc.value = "";
+ infoData.value = null;
+};
+
+const setExceptionStatus = status => {
+ hasException.value = status;
+ // 鍒囨崲鐘舵�佹椂娓呯┖鏂囦欢
+ if (status === false) {
uploadFiles.value = [];
- // 娓呯悊涓変釜鍒嗙被鐨勬暟鎹�
- beforeModelValue.value = [];
- afterModelValue.value = [];
- issueModelValue.value = [];
- currentUploadType.value = "before";
- hasException.value = null; // 閲嶇疆寮傚父鐘舵��
- infoData.value = null; // 娓呯悊浠诲姟鏁版嵁
- };
+ exceptionDesc.value = "";
+ }
+};
- // 鍒囨崲涓婁紶绫诲瀷
- const switchUploadType = type => {
- currentUploadType.value = type;
- };
+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: uploadFiles.value,
+ exceptionDesc: exceptionDesc.value,
+ };
- // 鑾峰彇褰撳墠鍒嗙被鐨勬枃浠跺垪琛�
- const getCurrentFiles = () => {
- switch (currentUploadType.value) {
- case "before":
- return beforeModelValue.value || [];
- case "after":
- return afterModelValue.value || [];
- case "issue":
- return issueModelValue.value || [];
- default:
- return [];
+ 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 getUploadTypeText = () => {
- switch (currentUploadType.value) {
- case "before":
- return "鐢熶骇鍓�";
- case "after":
- return "鐢熶骇涓�";
- case "issue":
- return "鐢熶骇鍚�";
- default:
- return "";
+ // 濡傛灉寮傚父鐘舵�侊紝妫�鏌ユ槸鍚︽湁鏂囦欢
+ if (hasException.value === true && uploadFiles.value.length === 0) {
+ uni.showToast({
+ title: "璇蜂笂浼犲紓甯哥収鐗囨垨瑙嗛",
+ icon: "none",
+ });
+ return;
}
- };
- // 澶勭悊涓婁紶鏂囦欢鏇存柊
- const handleUploadUpdate = files => {
- uploadFiles.value = files;
- };
+ showLoadingToast("鎻愪氦涓�...");
- // 璁剧疆寮傚父鐘舵��
- const setExceptionStatus = status => {
- hasException.value = status;
- };
+ // 鏀堕泦鎵�鏈夋枃浠�
+ let arr = [...uploadFiles.value];
- // 璺宠浆鍒版柊澧炴姤淇〉闈�
- const goToRepair = () => {
- try {
- // 瀛樺偍褰撳墠浠诲姟淇℃伅鍒版湰鍦板瓨鍌紝渚涙姤淇〉闈娇鐢�
- const taskInfo = {
+ // 涓存椂鏂囦欢ID鍒楄〃
+ let tempFileIds = [];
+ if (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;
+ // 濡傛灉瀛樺湪寮傚父锛屾坊鍔犲紓甯告弿杩�
+ if (hasException.value === true) {
+ infoData.value.inspectionRemark = exceptionDesc.value;
+ }
+
+ const result = await uploadInspectionTask({ ...infoData.value });
+
+ if (result && (result.code === 200 || result.success)) {
+ closeToast();
+ uni.showToast({
+ title: "鎻愪氦鎴愬姛",
+ icon: "success",
+ });
+
+ const currentHasException = hasException.value;
+ const taskInfoCopy = {
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,
- },
+ uploadedFiles: [...uploadFiles.value],
+ exceptionDesc: exceptionDesc.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",
+ if (currentHasException) {
+ uni.showModal({
+ title: "鎻愮ず",
+ content: "鏄惁鏂板鎶ヤ慨锛�",
+ success: function (res) {
+ if (res.confirm) {
+ uni.setStorageSync("repairTaskInfo", JSON.stringify(taskInfoCopy));
+ uni.navigateTo({
+ url: "/pages/equipmentManagement/repair/add",
+ });
+ }
+ setTimeout(() => {
+ reloadPage();
+ }, 500);
+ }
});
- 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();
-
- // 鍒锋柊鍒楄〃
+ } else {
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 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 = getFileAccessUrl(file);
- 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 isImageFile = file => {
- // 妫�鏌ontentType瀛楁
- if (file.contentType && file.contentType.startsWith("image/")) {
- return true;
- }
-
- // 妫�鏌ュ師鏈夌殑type瀛楁锛堟垨淇濈暀鐨勫獟浣撶被鍨嬶級
- if (file.type === "image" || file.mediaType === "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 isVideoFile = file => {
- if (!file) return false;
- if (file.type === "video" || file.mediaType === "video") return true;
- const name = file.bucketFilename || file.originalFilename || file.name || "";
- const ext = name.split(".").pop()?.toLowerCase();
- return ["mp4", "mov", "avi", "wmv", "mkv", "webm"].includes(ext);
- };
-
- // 鏂囦欢璁块棶鍩虹鍩燂紙鍚庣瑕佹眰鍓嶇紑锛�
- const filePreviewBase = config.fileUrl;
-
- const normalizeFileUrl = (rawUrl = "") => {
- let fileUrl = rawUrl || "";
- const javaApi = filePreviewBase;
- const localPrefixes = ["wxfile://", "file://", "content://", "blob:", "data:"];
-
- if (localPrefixes.some(prefix => fileUrl.startsWith(prefix))) {
- return fileUrl;
- }
-
- if (fileUrl && fileUrl.indexOf("\\") > -1) {
- const lowerPath = fileUrl.toLowerCase();
- const uploadPathIndex = lowerPath.indexOf("uploadpath");
-
- if (uploadPathIndex > -1) {
- fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/");
- } else {
- fileUrl = fileUrl.replace(/\\/g, "/");
- }
- }
- fileUrl = fileUrl.replace(/^\/?uploadPath/, "/profile");
-
- if (fileUrl && !fileUrl.startsWith("http")) {
- if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl;
- fileUrl = javaApi + fileUrl;
- }
-
- return fileUrl;
- };
-
- const getFileAccessUrl = (file = {}) => {
- if (file?.link) {
- if (String(file.link).startsWith("http")) return file.link;
- return normalizeFileUrl(file.link);
- }
- return normalizeFileUrl(file?.url || file?.downloadUrl || "");
- };
-
- // 棰勮闄勪欢
- const previewAttachment = file => {
- if (isImageFile(file)) {
- // 棰勮鍥剧墖
- const imageUrls = getCurrentViewAttachments()
- .filter(f => isImageFile(f))
- .map(f => getFileAccessUrl(f));
-
- uni.previewImage({
- urls: imageUrls,
- current: getFileAccessUrl(file),
- });
} else {
- // 棰勮瑙嗛 - 鏄剧ず瑙嗛鎾斁寮圭獥
- showVideoPreview(file);
+ closeToast();
+ uni.showToast({
+ title: result?.msg || result?.message || "鎻愪氦澶辫触",
+ icon: "error",
+ });
}
- };
+ } catch (error) {
+ console.error("鎻愪氦澶辫触:", error);
+ closeToast();
- // 鏄剧ず瑙嗛棰勮
- const showVideoPreview = file => {
- currentVideoFile.value = file;
- showVideoDialog.value = true;
- };
+ let errorMessage = "鎻愪氦澶辫触";
+ if (error.message) {
+ errorMessage = error.message;
+ } else if (error.msg) {
+ errorMessage = error.msg;
+ } else if (typeof error === "string") {
+ errorMessage = error;
+ }
- // 鍏抽棴瑙嗛棰勮
- const closeVideoPreview = () => {
- showVideoDialog.value = false;
- currentVideoFile.value = null;
- };
-
- // 瑙嗛鎾斁閿欒澶勭悊
- const handleVideoError = error => {
uni.showToast({
- title: "瑙嗛鎾斁澶辫触",
+ title: errorMessage,
icon: "error",
});
- };
+ }
+};
- // 鎷嶇収/鎷嶈棰戯紙鐪熸満浼樺厛鐢� chooseMedia锛涗笉鏀寔鍒欓檷绾э級
- const chooseMedia = type => {
- if (getCurrentFiles().length >= uploadConfig.limit) {
- uni.showToast({
- title: `鏈�澶氬彧鑳介�夋嫨${uploadConfig.limit}涓枃浠禶,
- icon: "none",
- });
- return;
+const startUploadForTask = async (task, type) => {
+ openUploadDialog(task);
+};
+
+const viewAttachments = async task => {
+ try {
+ currentViewTask.value = task;
+ attachmentList.value = [];
+
+ // 鏀堕泦鎵�鏈夐檮浠�
+ let allFiles = [];
+ if (task?.commonFileList) {
+ allFiles = allFiles.concat(task.commonFileList);
+ }
+ if (task?.commonFileListBefore) {
+ allFiles = allFiles.concat(task.commonFileListBefore);
+ }
+ if (task?.commonFileListAfter) {
+ allFiles = allFiles.concat(task.commonFileListAfter);
}
- const remaining = uploadConfig.limit - getCurrentFiles().length;
+ attachmentList.value = allFiles.map(file => ({
+ ...file,
+ name: file?.name || file?.originalFilename || file?.bucketFilename,
+ bucketFilename: file?.bucketFilename || file?.name,
+ originalFilename: file?.originalFilename || file?.name,
+ url: getFileAccessUrl(file),
+ downloadUrl: getFileAccessUrl(file),
+ size: file?.size || file?.byteSize,
+ }));
- // 浼樺厛锛歝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("鏈幏鍙栧埌鏂囦欢");
+ showAttachmentDialog.value = true;
+ } catch (error) {
+ uni.showToast({
+ title: "鑾峰彇闄勪欢澶辫触",
+ icon: "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;
- }
+const closeAttachmentDialog = () => {
+ showAttachmentDialog.value = false;
+ currentViewTask.value = null;
+ attachmentList.value = [];
+};
- // 闄嶇骇锛歝hooseImage / chooseVideo
- if (type === "video") {
- chooseVideo();
+const isImageFile = file => {
+ if (file.contentType && file.contentType.startsWith("image/")) {
+ return true;
+ }
+ if (file.type === "image" || file.mediaType === "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 isVideoFile = file => {
+ if (!file) return false;
+ if (file.type === "video" || file.mediaType === "video") return true;
+ const name = file.bucketFilename || file.originalFilename || file.name || "";
+ const ext = name.split(".").pop()?.toLowerCase();
+ return ["mp4", "mov", "avi", "wmv", "mkv", "webm"].includes(ext);
+};
+
+const filePreviewBase = config.fileUrl;
+
+const normalizeFileUrl = (rawUrl = "") => {
+ let fileUrl = rawUrl || "";
+ if (typeof fileUrl === "string") {
+ fileUrl = fileUrl.trim().replace(/^['"]|['"]$/g, "");
+ }
+ const javaApi = filePreviewBase;
+ const localPrefixes = ["wxfile://", "file://", "content://", "blob:", "data:"];
+
+ if (localPrefixes.some(prefix => fileUrl.startsWith(prefix))) {
+ return fileUrl;
+ }
+
+ if (fileUrl && fileUrl.indexOf("\\") > -1) {
+ const lowerPath = fileUrl.toLowerCase();
+ const uploadPathIndex = lowerPath.indexOf("uploadpath");
+ const prodIndex = lowerPath.indexOf("\\prod\\");
+
+ if (uploadPathIndex > -1) {
+ fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/");
+ } else if (prodIndex > -1) {
+ fileUrl = fileUrl
+ .substring(prodIndex + "\\prod\\".length)
+ .replace(/\\/g, "/");
} 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(),
- });
- },
- });
+ fileUrl = fileUrl.replace(/\\/g, "/");
}
- };
+ }
- // 鎷嶇収
- const chooseImage = () => {
- if (uploadFiles.value.length >= uploadConfig.limit) {
- uni.showToast({
- title: `鏈�澶氬彧鑳芥媿鎽�${uploadConfig.limit}涓枃浠禶,
- icon: "none",
- });
- return;
- }
+ const normalizedLower = String(fileUrl).toLowerCase();
+ const fileProdIdx = normalizedLower.indexOf("/file/prod/");
+ if (fileProdIdx > -1) {
+ fileUrl = `/profile/prod/${fileUrl.substring(fileProdIdx + "/file/prod/".length)}`;
+ }
+ const fileTempIdx = normalizedLower.indexOf("/file/temp/");
+ if (fileTempIdx > -1) {
+ fileUrl = `/profile/temp/${fileUrl.substring(fileTempIdx + "/file/temp/".length)}`;
+ }
+ if (/^\/?uploadPath/i.test(fileUrl)) {
+ fileUrl = fileUrl.replace(/^\/?uploadPath/i, "/profile");
+ }
+
+ if (fileUrl && !fileUrl.startsWith("http")) {
+ if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl;
+ fileUrl = javaApi + fileUrl;
+ }
+
+ return fileUrl;
+};
+
+const getFileAccessUrl = (file = {}) => {
+ if (file?.link) {
+ if (String(file.link).startsWith("http")) return file.link;
+ return normalizeFileUrl(file.link);
+ }
+ const remoteUrl = normalizeFileUrl(
+ file?.url ||
+ file?.downloadUrl ||
+ file?.tempPath ||
+ ""
+ );
+ if (remoteUrl) return remoteUrl;
+ if (file?._localPreviewUrl) return file._localPreviewUrl;
+ return normalizeFileUrl(file?.tempFilePath || file?.path || "");
+};
+
+const previewUploadedMedia = file => {
+ if (!file) return;
+ if (isImageFile(file)) {
+ const imageUrls = uploadFiles.value
+ .filter(f => isImageFile(f))
+ .map(f => getFileAccessUrl(f))
+ .filter(Boolean);
+ const current = getFileAccessUrl(file);
+ if (!imageUrls.length || !current) return;
+ uni.previewImage({
+ urls: imageUrls,
+ current,
+ });
+ return;
+ }
+ if (isVideoFile(file)) {
+ playVideoFile(file);
+ }
+};
+
+const previewAttachment = file => {
+ if (isImageFile(file)) {
+ const imageUrls = attachmentList.value
+ .filter(f => isImageFile(f))
+ .map(f => getFileAccessUrl(f));
+
+ uni.previewImage({
+ urls: imageUrls,
+ current: getFileAccessUrl(file),
+ });
+ } else {
+ playVideoFile(file);
+ }
+};
+
+const safeEncodeUrl = url => {
+ if (!url) return "";
+ if (!/^https?:\/\//i.test(url)) return url;
+ try {
+ return encodeURI(url);
+ } catch (e) {
+ return url;
+ }
+};
+
+const getPlayableVideoUrl = file => {
+ return safeEncodeUrl(getFileAccessUrl(file));
+};
+
+const getFallbackLocalVideoUrl = file => {
+ const local = file?._localPreviewUrl || file?.tempFilePath || file?.path || "";
+ return safeEncodeUrl(local);
+};
+
+const playVideoFile = file => {
+ const remoteSrc = getPlayableVideoUrl(file);
+ const localSrc = getFallbackLocalVideoUrl(file);
+ const src = remoteSrc || localSrc;
+ if (!src) {
+ uni.showToast({
+ title: "瑙嗛鍦板潃鏃犳晥",
+ icon: "none",
+ });
+ return;
+ }
+
+ showVideoPreview({
+ ...file,
+ _playUrl: src,
+ _playUrlLocal: localSrc,
+ _playUrlRemote: remoteSrc,
+ });
+};
+
+const showVideoPreview = file => {
+ currentVideoFile.value = file;
+ showVideoDialog.value = true;
+};
+
+const closeVideoPreview = () => {
+ showVideoDialog.value = false;
+ currentVideoFile.value = null;
+};
+
+const handleVideoError = () => {
+ const localUrl = currentVideoFile.value?._playUrlLocal;
+ const remoteUrl = currentVideoFile.value?._playUrlRemote;
+ const currentUrl = currentVideoFile.value?._playUrl;
+ if (remoteUrl && currentUrl !== remoteUrl) {
+ currentVideoFile.value = {
+ ...currentVideoFile.value,
+ _playUrl: remoteUrl,
+ };
+ uni.showToast({
+ title: "宸插垏鎹㈣繙绋嬭棰戦噸璇曟挱鏀�",
+ icon: "none",
+ });
+ return;
+ }
+ if (localUrl && currentUrl !== localUrl) {
+ currentVideoFile.value = {
+ ...currentVideoFile.value,
+ _playUrl: localUrl,
+ };
+ uni.showToast({
+ title: "宸插垏鎹㈡湰鍦拌棰戦噸璇曟挱鏀�",
+ icon: "none",
+ });
+ return;
+ }
+ uni.showToast({
+ title: "瑙嗛鎾斁澶辫触",
+ icon: "error",
+ });
+};
+
+const chooseMedia = type => {
+ if (uploadFiles.value.length >= uploadConfig.limit) {
+ uni.showToast({
+ title: `鏈�澶氬彧鑳介�夋嫨${uploadConfig.limit}涓枃浠禶,
+ icon: "none",
+ });
+ return;
+ }
+
+ const remaining = uploadConfig.limit - uploadFiles.value.length;
+
+ if (typeof uni.chooseMedia === "function") {
uni.chooseMedia({
- count: 1,
- mediaType: ["image", "video"],
+ count: Math.min(remaining, 1),
+ mediaType: [type || "image"],
sizeType: ["compressed", "original"],
sourceType: ["camera"],
success: res => {
try {
- if (!res.tempFiles || res.tempFiles.length === 0) {
- throw new Error("鏈幏鍙栧埌鍥剧墖鏂囦欢");
- }
+ const files = res?.tempFiles || [];
+ if (!files.length) 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",
+ 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);
});
- }
- },
- 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);
+ console.error("澶勭悊鎷嶆憚缁撴灉澶辫触:", e);
+ uni.showToast({ title: "澶勭悊鏂囦欢澶辫触", icon: "error" });
}
},
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;
+ console.error("鎷嶆憚澶辫触:", err);
+ uni.showToast({ title: "鎷嶆憚澶辫触", icon: "error" });
},
});
+ return;
+ }
- // 鐩戝惉涓婁紶杩涘害
- if (uploadTask && uploadTask.onProgressUpdate) {
- uploadTask.onProgressUpdate(res => {
- uploadProgress.value = res.progress;
- });
+ 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 removeFile = index => {
+ uni.showModal({
+ title: "纭鍒犻櫎",
+ content: "纭畾瑕佸垹闄よ繖涓枃浠跺悧锛�",
+ success: res => {
+ if (res.confirm) {
+ uploadFiles.value.splice(index, 1);
+ uni.showToast({
+ title: "鍒犻櫎鎴愬姛",
+ icon: "success",
+ });
+ }
+ },
+ });
+};
+
+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"];
}
- };
- // 涓婁紶澶辫触澶勭悊
- const handleUploadError = (message = "涓婁紶鏂囦欢澶辫触", showRetry = false) => {
- uploading.value = false;
- uploadProgress.value = 0;
+ if (fileExtension && expectedTypes.length > 0) {
+ const isAllowed = expectedTypes.some(
+ type => uploadConfig.fileType.includes(type) && type === fileExtension
+ );
- if (showRetry) {
- uni.showModal({
- title: "涓婁紶澶辫触",
- content: message + "锛屾槸鍚﹂噸璇曪紵",
- success: res => {
- if (res.confirm) {
- // 鐢ㄦ埛閫夋嫨閲嶈瘯锛岃繖閲屽彲浠ラ噸鏂拌Е鍙戜笂浼�
+ if (!isAllowed) {
+ uni.showToast({
+ title: `鏂囦欢鏍煎紡涓嶆敮鎸侊紝璇锋媿鎽� ${expectedTypes.join("/")} 鏍煎紡鐨勬枃浠禶,
+ icon: "none",
+ });
+ return false;
+ }
+ }
+ }
+
+ uploadFile(file);
+ return true;
+};
+
+const uploadFile = async file => {
+ uploading.value = true;
+ uploadProgress.value = 0;
+ number.value++;
+
+ const token = getToken();
+ if (!token) {
+ handleUploadError("鐢ㄦ埛鏈櫥褰�");
+ return;
+ }
+
+ const typeValue = 12; // 缁熶竴浣跨敤 type=12 琛ㄧず宸℃闄勪欢
+
+ uploadWithUniUploadFile(
+ file,
+ file.tempFilePath || file.path || "",
+ typeValue,
+ token
+ );
+};
+
+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 {
- uni.showToast({
- title: message,
- icon: "error",
- });
- }
+ } else {
+ handleUploadError(`鏈嶅姟鍣ㄩ敊璇紝鐘舵�佺爜: ${res.statusCode}`);
+ }
+ } catch (e) {
+ console.error("瑙f瀽鍝嶅簲澶辫触:", e);
+ 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 = "涓婁紶鏂囦欢澶辫触") => {
+ uploading.value = false;
+ uploadProgress.value = 0;
+ 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("涓婁紶鍝嶅簲鏁版嵁鏍煎紡閿欒");
+ return;
+ }
+
+ const fileData = {
+ ...file,
+ id: uploadedFile.id,
+ tempId: uploadedFile.tempId ?? uploadedFile.tempFileId ?? uploadedFile.id,
+ url: uploadedFile.url || uploadedFile.downloadUrl || uploadedFile.tempPath || file.tempFilePath || file.path,
+ tempPath: uploadedFile.tempPath || file.tempPath || "",
+ _localPreviewUrl: file.tempFilePath || file.path || "",
+ bucketFilename: uploadedFile.bucketFilename || uploadedFile.originalFilename || uploadedFile.originalName || file.name,
+ downloadUrl: uploadedFile.downloadUrl || uploadedFile.url,
+ size: uploadedFile.size || uploadedFile.byteSize || file.size,
+ createTime: uploadedFile.createTime || new Date().getTime(),
+ mediaType: file.type || uploadedFile.mediaType,
+ type: 20, // 缁熶竴浣跨敤 type=20
};
- // 涓婁紶鎴愬姛鍥炶皟
- const handleUploadSuccess = (res, file) => {
- console.log("涓婁紶鎴愬姛鍝嶅簲:", res);
+ uploadFiles.value.push(fileData);
+ number.value = 0;
+};
- // 澶勭悊涓嶅悓鐨勬暟鎹粨鏋勶細鍙兘鏄暟缁勶紝涔熷彲鑳芥槸鍗曚釜瀵硅薄
- 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(),
- mediaType: file.type || uploadedFile.mediaType,
- 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";
- };
+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>
- .inspection-upload-page {
- min-height: 100vh;
- background-color: #f5f5f5;
- }
+.inspection-upload-page {
+ min-height: 100vh;
+ background-color: #f5f5f5;
+}
- .table-section {
- padding: 15px;
- }
+.table-section {
+ padding: 15px;
+}
- .task-list {
- display: flex;
- flex-direction: column;
- gap: 12px;
- }
+.task-list {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
- .task-item {
- background: #fff;
- border-radius: 12px;
- padding: 15px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- transition: all 0.3s ease;
- }
+.task-item {
+ background: #fff;
+ border-radius: 12px;
+ padding: 15px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ transition: all 0.3s ease;
+}
- .task-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- margin-bottom: 12px;
- }
+.task-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ margin-bottom: 12px;
+}
- .task-info {
- flex: 1;
- display: flex;
- flex-direction: column;
- gap: 4px;
- }
+.task-info {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
- .task-name {
- font-size: 16px;
- font-weight: 600;
- color: #333;
- }
+.task-name {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
- .task-location {
- font-size: 14px;
- color: #666;
- }
+.task-location {
+ font-size: 14px;
+ color: #666;
+}
- .task-actions {
- display: flex;
- gap: 8px;
- }
+.task-actions {
+ display: flex;
+ gap: 8px;
+}
- .task-details {
- display: flex;
- flex-direction: column;
- gap: 6px;
- }
+.task-details {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
- .detail-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
+.detail-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
- .detail-label {
- font-size: 12px;
- color: #999;
- }
+.detail-label {
+ font-size: 12px;
+ color: #999;
+}
- .detail-value {
- font-size: 12px;
- color: #666;
- font-weight: 500;
- }
+.detail-value {
+ font-size: 12px;
+ color: #666;
+ font-weight: 500;
+}
- .no-data {
- text-align: center;
- padding: 40px 20px;
- color: #999;
- font-size: 14px;
- }
+.no-data {
+ text-align: center;
+ padding: 40px 20px;
+ color: #999;
+ font-size: 14px;
+}
- /* 鎵爜寮圭獥鏍峰紡 */
- .qr-scan-overlay {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.8);
- z-index: 9999;
- display: flex;
- align-items: center;
- justify-content: center;
- }
+.custom-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ z-index: 10000;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20px;
+}
- .qr-scan-container {
- width: 90vw;
- max-width: 400px;
- background: #fff;
- border-radius: 12px;
- padding: 20px;
- position: relative;
- }
+.custom-modal-container {
+ width: 100%;
+ max-width: 500px;
+ max-height: 80vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
- .scan-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 15px;
- }
+.upload-popup-content {
+ background: #fff;
+ border-radius: 12px;
+ width: 100%;
+ min-height: 300px;
+ max-height: 80vh;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
+}
- .scan-title {
- font-size: 18px;
- font-weight: 600;
- color: #333;
- }
+.upload-popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ border-bottom: 1px solid #eee;
+}
- .qr-camera {
- width: 100%;
- height: 300px;
- border-radius: 8px;
- overflow: hidden;
- margin-bottom: 15px;
- }
+.upload-popup-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
- .scan-frame-wrapper {
- position: relative;
- display: flex;
- flex-direction: column;
- align-items: center;
- }
+.upload-popup-body {
+ flex: 1;
+ padding: 20px;
+ overflow-y: auto;
+}
- .scan-frame {
- width: 200px;
- height: 200px;
- border: 2px solid #409eff;
- border-radius: 8px;
- position: relative;
- }
+.upload-popup-footer {
+ display: flex;
+ justify-content: flex-end;
+ padding: 15px 20px;
+ border-top: 1px solid #eee;
+ gap: 10px;
+}
- .scan-frame::before,
- .scan-frame::after {
- content: "";
- position: absolute;
- width: 20px;
- height: 20px;
- border: 2px solid #409eff;
- }
+.upload-buttons {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 15px;
+}
- .scan-frame::before {
- top: -2px;
- left: -2px;
- border-right: none;
- border-bottom: none;
- }
+.file-list {
+ margin-top: 15px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
- .scan-frame::after {
- bottom: -2px;
- right: -2px;
- border-left: none;
- border-top: none;
- }
+.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;
+}
- .scan-tip {
- margin-top: 10px;
- font-size: 14px;
- color: #666;
- text-align: center;
- }
+.file-preview-container {
+ position: relative;
+ margin-bottom: 8px;
+}
- /* 鑷畾涔夋ā鎬佹鏍峰紡 */
- .custom-modal-overlay {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.5);
- z-index: 10000;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 20px;
- }
+.file-preview {
+ width: 80px;
+ height: 80px;
+ border-radius: 8px;
+ object-fit: cover;
+ border: 2px solid #f0f0f0;
+}
- .custom-modal-container {
- width: 100%;
- max-width: 500px;
- max-height: 80vh;
- display: flex;
- align-items: center;
- justify-content: center;
- }
+.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;
+}
- /* 涓婁紶寮圭獥鏍峰紡 */
- .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);
- }
+.video-text {
+ font-size: 12px;
+ color: #666;
+ margin-top: 4px;
+}
- .upload-popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px 20px;
- border-bottom: 1px solid #eee;
- }
+.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;
+}
- .upload-popup-title {
- font-size: 16px;
- font-weight: 600;
- color: #333;
- }
+.file-info {
+ text-align: center;
+ width: 100%;
+}
- .upload-popup-body {
- flex: 1;
- padding: 20px;
- overflow-y: auto;
- }
+.file-name {
+ font-size: 12px;
+ color: #333;
+ font-weight: 500;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100px;
+}
- .upload-popup-footer {
- display: flex;
- justify-content: flex-end;
- padding: 15px 20px;
- border-top: 1px solid #eee;
- gap: 10px;
- }
+.file-size {
+ font-size: 10px;
+ color: #999;
+ margin-top: 2px;
+ display: block;
+}
- /* 绠�鍖栦笂浼犵粍浠舵牱寮� */
- .simple-upload-area {
- padding: 15px;
- }
+.empty-state {
+ text-align: center;
+ padding: 40px 20px;
+ color: #999;
+ font-size: 14px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ border: 2px dashed #ddd;
+}
- .upload-buttons {
- display: flex;
- gap: 10px;
- margin-bottom: 15px;
- }
+.upload-progress {
+ margin: 15px 0;
+ padding: 0 10px;
+}
- .file-list {
- margin-top: 15px;
- display: flex;
- flex-wrap: wrap;
- gap: 12px;
- }
+.exception-section {
+ margin-bottom: 20px;
+ padding: 15px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ border: 1px solid #e9ecef;
+}
- .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;
- }
+.section-title {
+ display: block;
+ font-size: 14px;
+ font-weight: 600;
+ color: #333;
+ margin-bottom: 12px;
+}
- .file-item:hover {
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
- transform: translateY(-2px);
- }
+.exception-options {
+ display: flex;
+ gap: 12px;
+}
- .file-preview-container {
- position: relative;
- margin-bottom: 8px;
- }
+.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;
+}
- .file-preview {
- width: 80px;
- height: 80px;
- border-radius: 8px;
- object-fit: cover;
- border: 2px solid #f0f0f0;
- }
+.exception-option.active {
+ border-color: #409eff;
+ background: #f0f8ff;
+ color: #409eff;
+ font-weight: 500;
+}
- .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;
- }
+.exception-desc-section {
+ margin-top: 15px;
+}
- .video-text {
- font-size: 12px;
- color: #666;
- margin-top: 4px;
- }
+.normal-tip {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 15px;
+ background: #f6ffed;
+ border: 1px solid #b7eb8f;
+ border-radius: 8px;
+}
- .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;
- }
+.tip-text {
+ font-size: 14px;
+ color: #52c41a;
+}
- /* 缁熻淇℃伅鏍峰紡 */
- .upload-summary {
- margin-top: 15px;
- padding: 10px;
- background: #f8f9fa;
- border-radius: 6px;
- border-left: 3px solid #409eff;
- }
+.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;
- }
+.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);
- }
+.media-upload-section {
+ margin-bottom: 15px;
+}
- .attachment-popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px 20px;
- border-bottom: 1px solid #eee;
- background: #f8f9fa;
- }
+.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-title {
- font-size: 16px;
- font-weight: 600;
- color: #333;
- }
+.detail-info-section {
+ padding: 10px;
+ background-color: #fff2f0;
+ border: 1px solid #ffccc7;
+ border-radius: 8px;
+ margin-bottom: 15px;
+}
- .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;
- }
+.info-label {
+ font-size: 14px;
+ font-weight: 600;
+ color: #ff4d4f;
+}
- .close-btn-attachment:hover {
- background: #e9ecef;
- transform: scale(1.1);
- }
+.info-value {
+ font-size: 14px;
+ color: #ff4d4f;
+ margin-top: 5px;
+ display: block;
+}
- .attachment-popup-body {
- flex: 1;
- padding: 15px 20px;
- overflow-y: auto;
- }
+.attachment-popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ border-bottom: 1px solid #eee;
+ background: #f8f9fa;
+}
- .attachment-tabs {
- display: flex;
- background: #f8f9fa;
- border-radius: 8px;
- margin-bottom: 15px;
- padding: 4px;
- }
+.attachment-popup-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
- .attachment-content {
- min-height: 200px;
- }
+.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;
+}
- .attachment-list {
- display: flex;
- flex-wrap: wrap;
- gap: 12px;
- }
+.attachment-popup-body {
+ flex: 1;
+ padding: 15px 20px;
+ overflow-y: auto;
+}
- .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-content {
+ min-height: 200px;
+}
- .attachment-item:hover {
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
- transform: translateY(-2px);
- }
+.attachment-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
- .attachment-preview-container {
- margin-bottom: 8px;
- }
+.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-preview {
- width: 80px;
- height: 80px;
- border-radius: 8px;
- object-fit: cover;
- border: 2px solid #f0f0f0;
- }
+.attachment-preview-container {
+ margin-bottom: 8px;
+}
- .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-preview {
+ width: 80px;
+ height: 80px;
+ border-radius: 8px;
+ object-fit: cover;
+ border: 2px solid #f0f0f0;
+}
- .attachment-info {
- text-align: center;
- width: 100%;
- }
+.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-name {
- font-size: 12px;
- color: #333;
- font-weight: 500;
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 80px;
- }
+.attachment-info {
+ text-align: center;
+ width: 100%;
+}
- .attachment-size {
- font-size: 10px;
- color: #999;
- margin-top: 2px;
- display: block;
- }
+.attachment-name {
+ font-size: 12px;
+ color: #333;
+ font-weight: 500;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 80px;
+}
- .attachment-empty {
- text-align: center;
- padding: 60px 20px;
- color: #999;
- font-size: 14px;
- background: #f8f9fa;
- border-radius: 8px;
- border: 2px dashed #ddd;
- }
+.attachment-size {
+ font-size: 10px;
+ color: #999;
+ margin-top: 2px;
+ display: block;
+}
- /* 瑙嗛棰勮寮圭獥鏍峰紡 */
- .video-modal-overlay {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.8);
- z-index: 10001;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 20px;
- }
+.attachment-empty {
+ text-align: center;
+ padding: 60px 20px;
+ color: #999;
+ font-size: 14px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ border: 2px dashed #ddd;
+}
- .video-modal-container {
- width: 90%;
- max-width: 800px;
- max-height: 80vh;
- background: #000;
- border-radius: 12px;
- overflow: hidden;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
- }
+.video-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.8);
+ z-index: 10001;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20px;
+}
- .video-modal-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px 20px;
- background: rgba(0, 0, 0, 0.7);
- color: #fff;
- }
+.video-modal-container {
+ width: 90%;
+ max-width: 800px;
+ max-height: 80vh;
+ background: #000;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
+}
- .video-modal-title {
- font-size: 16px;
- font-weight: 500;
- color: #fff;
- }
+.video-modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ background: rgba(0, 0, 0, 0.7);
+ color: #fff;
+}
- .close-btn-video {
- width: 28px;
- height: 28px;
- border-radius: 50%;
- background: rgba(255, 255, 255, 0.2);
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: all 0.3s ease;
- }
+.video-modal-title {
+ font-size: 16px;
+ font-weight: 500;
+ color: #fff;
+}
- .close-btn-video:hover {
- background: rgba(255, 255, 255, 0.3);
- transform: scale(1.1);
- }
+.close-btn-video {
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background: rgba(255, 255, 255, 0.2);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
- .video-modal-body {
- position: relative;
- background: #000;
- }
+.video-modal-body {
+ position: relative;
+ background: #000;
+}
- .video-player {
- width: 100%;
- height: auto;
- max-height: 60vh;
- display: block;
- }
-</style>
\ No newline at end of file
+.video-player {
+ width: 100%;
+ height: 56vh;
+ min-height: 260px;
+ max-height: 60vh;
+ display: block;
+ object-fit: contain;
+}
+</style>
--
Gitblit v1.9.3