<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 style="display: flex; flex-wrap: wrap;">
|
<img v-for="(item, index) in beforeProductionImgs" :key="index"
|
@click="showMedia(beforeProductionImgs, index, 'image')"
|
:src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
|
</div>
|
|
<!-- 视频列表 -->
|
<div style="display: flex; flex-wrap: wrap;">
|
<div
|
v-for="(videoUrl, index) in beforeProductionVideos"
|
:key="index"
|
@click="showMedia(beforeProductionVideos, index, 'video')"
|
style="position: relative; margin: 10px; cursor: pointer;"
|
>
|
<div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
|
<img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
|
</div>
|
<div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 生产后 -->
|
<div class="form-container">
|
<div class="title">生产后</div>
|
|
<!-- 图片列表 -->
|
<div style="display: flex; flex-wrap: wrap;">
|
<img v-for="(item, index) in afterProductionImgs" :key="index"
|
@click="showMedia(afterProductionImgs, index, 'image')"
|
:src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
|
</div>
|
|
<!-- 视频列表 -->
|
<div style="display: flex; flex-wrap: wrap;">
|
<div
|
v-for="(videoUrl, index) in afterProductionVideos"
|
:key="index"
|
@click="showMedia(afterProductionVideos, index, 'video')"
|
style="position: relative; margin: 10px; cursor: pointer;"
|
>
|
<div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
|
<img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
|
</div>
|
<div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 生产问题 -->
|
<div class="form-container">
|
<div class="title">生产问题</div>
|
|
<!-- 图片列表 -->
|
<div style="display: flex; flex-wrap: wrap;">
|
<img v-for="(item, index) in productionIssuesImgs" :key="index"
|
@click="showMedia(productionIssuesImgs, index, 'image')"
|
:src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
|
</div>
|
|
<!-- 视频列表 -->
|
<div style="display: flex; flex-wrap: wrap;">
|
<div
|
v-for="(videoUrl, index) in productionIssuesVideos"
|
:key="index"
|
@click="showMedia(productionIssuesVideos, index, 'video')"
|
style="position: relative; margin: 10px; cursor: pointer;"
|
>
|
<div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
|
<img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
|
</div>
|
<div style="text-align: center; font-size: 12px; color: #666;">点击播放</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"
|
></vue-easy-lightbox>
|
|
<!-- 视频 -->
|
<div v-else-if="mediaType === 'video'" style="position: relative;">
|
<Video
|
:src="mediaList[currentMediaIndex]"
|
autoplay
|
controls
|
style="max-width: 90vw; max-height: 80vh;"
|
/>
|
</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'); // image | video
|
|
// 处理每一类数据:分离图片和视频
|
function processItems(items) {
|
const images = [];
|
const videos = [];
|
items.forEach(item => {
|
if (item.contentType?.startsWith('image/')) {
|
images.push(item.url);
|
} else if (item.contentType?.startsWith('video/')) {
|
videos.push(item.url);
|
}
|
});
|
return { images, videos };
|
}
|
|
// 打开弹窗并加载数据
|
const openDialog = async (row) => {
|
const { images: beforeImgs, videos: beforeVids } = processItems(row.beforeProduction);
|
const { images: afterImgs, videos: afterVids } = processItems(row.afterProduction);
|
const { images: issueImgs, videos: issueVids } = processItems(row.productionIssues);
|
|
beforeProductionImgs.value = beforeImgs;
|
beforeProductionVideos.value = beforeVids;
|
|
afterProductionImgs.value = afterImgs;
|
afterProductionVideos.value = afterVids;
|
|
productionIssuesImgs.value = issueImgs;
|
productionIssuesVideos.value = issueVids;
|
|
dialogVisitable.value = true;
|
};
|
|
// 显示媒体(图片 or 视频)
|
function showMedia(mediaArray, index, type) {
|
mediaList.value = mediaArray;
|
currentMediaIndex.value = index;
|
mediaType.value = type;
|
isMediaViewerVisible.value = true;
|
}
|
|
// 关闭媒体查看器
|
function 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-viewer-overlay {
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 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;
|
}
|
</style>
|