From ec00255aab24865cd785e181704e502354b9c8f6 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期五, 13 三月 2026 13:52:49 +0800
Subject: [PATCH] Merge branch 'dev_KT' of http://114.132.189.42:9002/r/product-inventory-APP-before into dev_KT
---
src/pages/inspectionManagement/components/viewFiles.vue | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 296 insertions(+), 0 deletions(-)
diff --git a/src/pages/inspectionManagement/components/viewFiles.vue b/src/pages/inspectionManagement/components/viewFiles.vue
new file mode 100644
index 0000000..f39d9a4
--- /dev/null
+++ b/src/pages/inspectionManagement/components/viewFiles.vue
@@ -0,0 +1,296 @@
+<template>
+ <u-popup :show="dialogVisitable"
+ mode="bottom"
+ :round="16"
+ @close="cancel">
+ <view class="popup-content">
+ <view class="popup-header">
+ <text class="popup-title">鏌ョ湅闄勪欢</text>
+ <view class="close-icon"
+ @click="cancel">
+ <u-icon name="close"
+ size="14"
+ color="#666" />
+ </view>
+ </view>
+ <view class="popup-body">
+ <view class="tabs">
+ <view v-for="tab in tabs"
+ :key="tab.key"
+ class="tab-item"
+ :class="{ active: currentType === tab.key }"
+ @click="currentType = tab.key">
+ {{ tab.label }} ({{ getCurrentList(tab.key).length }})
+ </view>
+ </view>
+ <view class="file-list"
+ v-if="getCurrentList(currentType).length">
+ <view v-for="(file, index) in getCurrentList(currentType)"
+ :key="index"
+ class="file-item"
+ @click="previewFile(file)">
+ <image v-if="isImageFile(file)"
+ :src="file.url"
+ class="thumb"
+ mode="aspectFill" />
+ <view v-else
+ class="video-thumb">
+ <u-icon name="video"
+ size="28"
+ color="#1677ff" />
+ <text class="video-text">瑙嗛</text>
+ </view>
+ <text class="name">{{ file.name || "闄勪欢" }}</text>
+ </view>
+ </view>
+ <view v-else
+ class="empty">
+ <text>鏆傛棤闄勪欢</text>
+ </view>
+ </view>
+ </view>
+ </u-popup>
+ <u-popup :show="showVideoPopup"
+ mode="center"
+ :round="10"
+ @close="closeVideoPopup">
+ <view class="video-container">
+ <video :src="videoUrl"
+ controls
+ autoplay
+ class="video-player" />
+ </view>
+ </u-popup>
+</template>
+
+<script setup>
+ import { ref } from "vue";
+ import config from "@/config";
+
+ const dialogVisitable = ref(false);
+ const currentType = ref("before");
+ const showVideoPopup = ref(false);
+ const videoUrl = ref("");
+ const filesMap = ref({
+ before: [],
+ after: [],
+ issue: [],
+ });
+
+ const tabs = [
+ { key: "before", label: "鐢熶骇鍓�" },
+ { key: "after", label: "鐢熶骇涓�" },
+ { key: "issue", label: "鐢熶骇鍚�" },
+ ];
+
+ const normalizeUrl = raw => {
+ if (!raw) return "";
+ const url = String(raw).trim();
+ if (!url) return "";
+ if (/^https?:\/\//i.test(url)) return url;
+ if (url.startsWith("/")) return `${config.fileUrl}${url}`;
+ 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 `${config.fileUrl}/${relative}`;
+ }
+ return normalized;
+ }
+ return `${config.fileUrl}/${url.replace(/^\//, "")}`;
+ };
+
+ const isImageFile = file => {
+ if (file?.contentType?.startsWith("image/")) return true;
+ const name = String(file?.name || file?.bucketFilename || "").toLowerCase();
+ return /\.(jpg|jpeg|png|gif|bmp|webp)$/.test(name);
+ };
+
+ const normalizeFile = (file, type) => ({
+ ...file,
+ type,
+ url: normalizeUrl(file?.url || file?.downloadUrl),
+ name: file?.originalFilename || file?.bucketFilename || file?.name,
+ });
+
+ const getCurrentList = type => filesMap.value[type] || [];
+
+ const previewFile = file => {
+ if (isImageFile(file)) {
+ const urls = getCurrentList(currentType.value)
+ .filter(item => isImageFile(item))
+ .map(item => item.url);
+ uni.previewImage({
+ urls,
+ current: file.url,
+ });
+ return;
+ }
+ videoUrl.value = file.url;
+ showVideoPopup.value = true;
+ };
+
+ const closeVideoPopup = () => {
+ showVideoPopup.value = false;
+ videoUrl.value = "";
+ };
+
+ const openDialog = row => {
+ const allList = Array.isArray(row?.commonFileList) ? row.commonFileList : [];
+ const beforeList = Array.isArray(row?.commonFileListBefore)
+ ? row.commonFileListBefore
+ : allList.filter(item => item?.type === 10);
+ const afterList = Array.isArray(row?.commonFileListAfter)
+ ? row.commonFileListAfter
+ : allList.filter(item => item?.type === 11);
+ const issueList = Array.isArray(row?.commonFileListIssue)
+ ? row.commonFileListIssue
+ : allList.filter(item => item?.type === 12);
+ filesMap.value = {
+ before: beforeList.map(item => normalizeFile(item, "before")).filter(item => item.url),
+ after: afterList.map(item => normalizeFile(item, "after")).filter(item => item.url),
+ issue: issueList.map(item => normalizeFile(item, "issue")).filter(item => item.url),
+ };
+ currentType.value = "before";
+ dialogVisitable.value = true;
+ };
+
+ const cancel = () => {
+ dialogVisitable.value = false;
+ closeVideoPopup();
+ filesMap.value = {
+ before: [],
+ after: [],
+ issue: [],
+ };
+ };
+
+ defineExpose({ openDialog });
+</script>
+
+<style scoped lang="scss">
+ .popup-content {
+ width: 100vw;
+ max-height: 82vh;
+ background: #fff;
+ border-radius: 24rpx 24rpx 0 0;
+ overflow: hidden;
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+
+ .popup-header {
+ padding: 24rpx 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ text-align: center;
+ position: relative;
+ }
+
+ .popup-title {
+ font-size: 32rpx;
+ color: #1f1f1f;
+ font-weight: 600;
+ }
+
+ .popup-body {
+ padding: 20rpx 20rpx 26rpx;
+ max-height: 68vh;
+ overflow-y: auto;
+ }
+
+ .tabs {
+ display: flex;
+ background: #f4f5f8;
+ border-radius: 12rpx;
+ padding: 6rpx;
+ margin-bottom: 20rpx;
+ }
+
+ .tab-item {
+ flex: 1;
+ text-align: center;
+ padding: 12rpx 0;
+ color: #666;
+ font-size: 24rpx;
+ border-radius: 10rpx;
+ }
+
+ .tab-item.active {
+ background: #1677ff;
+ color: #fff;
+ font-weight: 600;
+ }
+
+ .file-list {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 16rpx;
+ }
+
+ .file-item {
+ background: #fafafa;
+ border-radius: 12rpx;
+ padding: 10rpx;
+ }
+
+ .thumb {
+ width: 100%;
+ height: 180rpx;
+ border-radius: 8rpx;
+ }
+
+ .video-thumb {
+ width: 100%;
+ height: 180rpx;
+ border-radius: 8rpx;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: #edf3ff;
+ }
+
+ .video-text {
+ font-size: 22rpx;
+ color: #1677ff;
+ margin-top: 6rpx;
+ }
+
+ .name {
+ margin-top: 8rpx;
+ font-size: 22rpx;
+ color: #333;
+ display: block;
+ word-break: break-all;
+ }
+
+ .empty {
+ text-align: center;
+ color: #999;
+ padding: 40rpx 0;
+ }
+
+ .video-container {
+ width: 94vw;
+ background: #000;
+ }
+
+ .video-player {
+ width: 94vw;
+ height: 55vw;
+ }
+
+ .close-icon {
+ position: absolute;
+ right: 24rpx;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 44rpx;
+ height: 44rpx;
+ border-radius: 50%;
+ background: #f5f5f5;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+</style>
--
Gitblit v1.9.3