<template>
|
<div>
|
<el-dialog title="查看附件" v-model="dialogVisitable" width="800px" @close="cancel">
|
<div class="upload-container">
|
<div class="form-container">
|
<div class="title">生产前</div>
|
|
<div class="media-list">
|
<img
|
v-for="(item, index) in beforeProductionImgs"
|
:key="`before-img-${index}`"
|
:src="item"
|
alt=""
|
class="media-image"
|
@click="showMedia(beforeProductionImgs, index, 'image')"
|
/>
|
</div>
|
|
<div class="media-list">
|
<div
|
v-for="(videoUrl, index) in beforeProductionVideos"
|
:key="`before-video-${index}`"
|
class="video-item"
|
@click="showMedia(beforeProductionVideos, index, 'video')"
|
>
|
<div class="video-thumb">
|
<img src="@/assets/images/video.png" alt="播放" class="video-icon" />
|
</div>
|
<div class="video-text">点击播放</div>
|
</div>
|
</div>
|
</div>
|
|
<div class="form-container">
|
<div class="title">生产中</div>
|
|
<div class="media-list">
|
<img
|
v-for="(item, index) in afterProductionImgs"
|
:key="`during-img-${index}`"
|
:src="item"
|
alt=""
|
class="media-image"
|
@click="showMedia(afterProductionImgs, index, 'image')"
|
/>
|
</div>
|
|
<div class="media-list">
|
<div
|
v-for="(videoUrl, index) in afterProductionVideos"
|
:key="`during-video-${index}`"
|
class="video-item"
|
@click="showMedia(afterProductionVideos, index, 'video')"
|
>
|
<div class="video-thumb">
|
<img src="@/assets/images/video.png" alt="播放" class="video-icon" />
|
</div>
|
<div class="video-text">点击播放</div>
|
</div>
|
</div>
|
</div>
|
|
<div class="form-container">
|
<div class="title">生产后</div>
|
|
<div class="media-list">
|
<img
|
v-for="(item, index) in productionIssuesImgs"
|
:key="`after-img-${index}`"
|
:src="item"
|
alt=""
|
class="media-image"
|
@click="showMedia(productionIssuesImgs, index, 'image')"
|
/>
|
</div>
|
|
<div class="media-list">
|
<div
|
v-for="(videoUrl, index) in productionIssuesVideos"
|
:key="`after-video-${index}`"
|
class="video-item"
|
@click="showMedia(productionIssuesVideos, index, 'video')"
|
>
|
<div class="video-thumb">
|
<img src="@/assets/images/video.png" alt="播放" class="video-icon" />
|
</div>
|
<div class="video-text">点击播放</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-dialog>
|
|
<div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer">
|
<div class="media-viewer-content" @click.stop>
|
<vue-easy-lightbox
|
v-if="mediaType === 'image'"
|
:visible="isMediaViewerVisible"
|
:imgs="mediaList"
|
:index="currentMediaIndex"
|
@hide="closeMediaViewer"
|
/>
|
|
<div v-else-if="mediaType === 'video'" class="video-player-wrap">
|
<video :src="mediaList[currentMediaIndex]" autoplay controls class="video-player" />
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref } from "vue";
|
import VueEasyLightbox from "vue-easy-lightbox";
|
|
const dialogVisitable = ref(false);
|
|
const beforeProductionImgs = ref([]);
|
const afterProductionImgs = ref([]);
|
const productionIssuesImgs = ref([]);
|
|
const beforeProductionVideos = ref([]);
|
const afterProductionVideos = ref([]);
|
const productionIssuesVideos = ref([]);
|
|
const isMediaViewerVisible = ref(false);
|
const currentMediaIndex = ref(0);
|
const mediaList = ref([]);
|
const mediaType = ref("image");
|
|
const processFileUrl = fileUrl => {
|
if (!fileUrl) return "";
|
|
let currentUrl = String(fileUrl);
|
if (currentUrl.includes("\\")) {
|
const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
|
if (uploadsIndex > -1) {
|
currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
|
} else {
|
const fileName = currentUrl.split("\\").pop();
|
currentUrl = `/uploads/${fileName}`;
|
}
|
}
|
|
if (currentUrl && !currentUrl.startsWith("http")) {
|
if (!currentUrl.startsWith("/")) {
|
currentUrl = `/${currentUrl}`;
|
}
|
currentUrl = __BASE_API__ + currentUrl;
|
}
|
|
return currentUrl;
|
};
|
|
const processItems = items => {
|
const images = [];
|
const videos = [];
|
|
if (!Array.isArray(items)) {
|
return { images, videos };
|
}
|
|
items.forEach(item => {
|
if (!item) return;
|
|
const fileUrl = processFileUrl(
|
item.previewURL || item.url || item.downloadUrl || item.path || ""
|
);
|
const contentType = String(item.contentType || "").toLowerCase();
|
|
if (!fileUrl) return;
|
|
if (contentType.startsWith("video/")) {
|
videos.push(fileUrl);
|
return;
|
}
|
|
images.push(fileUrl);
|
});
|
|
return { images, videos };
|
};
|
|
const openDialog = row => {
|
const { images: beforeImgs, videos: beforeVids } = processItems(
|
row.commonFileListBeforeVO || []
|
);
|
const { images: afterImgs, videos: afterVids } = processItems(
|
row.commonFileListVO || []
|
);
|
const { images: issueImgs, videos: issueVids } = processItems(
|
row.commonFileListAfterVO || []
|
);
|
|
beforeProductionImgs.value = beforeImgs;
|
beforeProductionVideos.value = beforeVids;
|
afterProductionImgs.value = afterImgs;
|
afterProductionVideos.value = afterVids;
|
productionIssuesImgs.value = issueImgs;
|
productionIssuesVideos.value = issueVids;
|
dialogVisitable.value = true;
|
};
|
|
const showMedia = (items, index, type) => {
|
mediaList.value = items;
|
currentMediaIndex.value = index;
|
mediaType.value = type;
|
isMediaViewerVisible.value = true;
|
};
|
|
const closeMediaViewer = () => {
|
isMediaViewerVisible.value = false;
|
mediaList.value = [];
|
mediaType.value = "image";
|
};
|
|
const cancel = () => {
|
dialogVisitable.value = false;
|
};
|
|
defineExpose({ openDialog });
|
</script>
|
|
<style scoped lang="scss">
|
.upload-container {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
padding: 20px;
|
border: 1px solid #dcdfe6;
|
box-sizing: border-box;
|
|
.form-container {
|
flex: 1;
|
width: 100%;
|
margin-bottom: 20px;
|
}
|
}
|
|
.title {
|
font-size: 14px;
|
color: #165dff;
|
line-height: 20px;
|
font-weight: 600;
|
padding-left: 10px;
|
position: relative;
|
margin: 6px 0;
|
|
&::before {
|
content: "";
|
position: absolute;
|
left: 0;
|
top: 3px;
|
width: 4px;
|
height: 14px;
|
background-color: #165dff;
|
}
|
}
|
|
.media-list {
|
display: flex;
|
flex-wrap: wrap;
|
}
|
|
.media-image {
|
max-width: 100px;
|
height: 100px;
|
margin: 5px;
|
cursor: pointer;
|
}
|
|
.video-item {
|
position: relative;
|
margin: 10px;
|
cursor: pointer;
|
}
|
|
.video-thumb {
|
width: 160px;
|
height: 90px;
|
background-color: #333;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.video-icon {
|
width: 30px;
|
height: 30px;
|
opacity: 0.8;
|
}
|
|
.video-text {
|
text-align: center;
|
font-size: 12px;
|
color: #666;
|
}
|
|
.media-viewer-overlay {
|
position: fixed;
|
inset: 0;
|
background-color: rgba(0, 0, 0, 0.8);
|
z-index: 9999;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.media-viewer-content {
|
position: relative;
|
max-width: 90vw;
|
max-height: 90vh;
|
overflow: hidden;
|
}
|
|
.video-player-wrap {
|
position: relative;
|
}
|
|
.video-player {
|
max-width: 90vw;
|
max-height: 80vh;
|
}
|
</style>
|