<template>
|
<view>
|
<!-- 弹窗 -->
|
<u-popup
|
v-model="dialogVisitable"
|
mode="center"
|
width="90%"
|
height="80%"
|
border-radius="20"
|
@close="cancel"
|
>
|
<view class="popup-content">
|
<view class="popup-header">
|
<text class="popup-title">查看附件</text>
|
<u-icon
|
name="close"
|
size="24"
|
color="#999"
|
@click="cancel"
|
></u-icon>
|
</view>
|
|
<view class="upload-container">
|
<view class="form-container">
|
<view class="title">巡检附件</view>
|
|
<!-- 图片列表 -->
|
<view v-if="beforeProductionImgs.length > 0" class="media-section">
|
<view class="section-title">图片</view>
|
<view class="image-grid">
|
<view
|
v-for="(item, index) in beforeProductionImgs"
|
:key="index"
|
class="image-item"
|
@click="previewImage(item, index)"
|
>
|
<image
|
:src="item"
|
mode="aspectFill"
|
class="image-preview"
|
/>
|
</view>
|
</view>
|
</view>
|
|
<!-- 视频列表 -->
|
<view v-if="beforeProductionVideos.length > 0" class="media-section">
|
<view class="section-title">视频</view>
|
<view class="video-grid">
|
<view
|
v-for="(videoUrl, index) in beforeProductionVideos"
|
:key="index"
|
class="video-item"
|
@click="previewVideo(videoUrl)"
|
>
|
<view class="video-preview">
|
<u-icon name="play-circle-fill" size="40" color="#fff"></u-icon>
|
</view>
|
<view class="video-tip">点击播放</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 空状态 -->
|
<view v-if="beforeProductionImgs.length === 0 && beforeProductionVideos.length === 0" class="empty-state">
|
<u-empty
|
mode="data"
|
text="暂无附件"
|
:iconSize="60"
|
></u-empty>
|
</view>
|
</view>
|
</view>
|
</view>
|
</u-popup>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref } from 'vue'
|
|
// 控制弹窗显示
|
const dialogVisitable = ref(false)
|
// 图片数组
|
const beforeProductionImgs = ref([])
|
// 视频数组
|
const beforeProductionVideos = ref([])
|
|
// 打开弹窗并加载数据
|
const openDialog = async (row) => {
|
console.log('打开附件查看弹窗,数据:', row)
|
|
// 处理数据,分离图片和视频
|
const { images: beforeImgs, videos: beforeVids } = processItems(row.storageBlobDTO || [])
|
|
beforeProductionImgs.value = beforeImgs
|
beforeProductionVideos.value = beforeVids
|
dialogVisitable.value = true
|
}
|
|
// 预览图片
|
const previewImage = (url, index) => {
|
uni.previewImage({
|
urls: beforeProductionImgs.value,
|
current: index,
|
fail: (err) => {
|
console.error('图片预览失败:', err)
|
uni.showToast({
|
title: '图片预览失败',
|
icon: 'error'
|
})
|
}
|
})
|
}
|
|
// 预览视频
|
const previewVideo = (url) => {
|
uni.previewVideo({
|
sources: [{
|
src: url
|
}],
|
fail: (err) => {
|
console.error('视频预览失败:', err)
|
uni.showToast({
|
title: '视频预览失败',
|
icon: 'error'
|
})
|
}
|
})
|
}
|
|
// 表单关闭方法
|
const cancel = () => {
|
dialogVisitable.value = false
|
// 重置数据
|
beforeProductionImgs.value = []
|
beforeProductionVideos.value = []
|
}
|
|
// 处理每一类数据:分离图片和视频
|
function processItems(items) {
|
if (!items || !Array.isArray(items)) {
|
return { images: [], videos: [] }
|
}
|
|
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 }
|
}
|
|
// 暴露方法给父组件
|
defineExpose({ openDialog })
|
</script>
|
|
<style scoped lang="scss">
|
.popup-content {
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.popup-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 20px;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.popup-title {
|
font-size: 18px;
|
font-weight: 600;
|
color: #333;
|
}
|
|
.upload-container {
|
flex: 1;
|
padding: 20px;
|
overflow-y: auto;
|
}
|
|
.form-container {
|
width: 100%;
|
}
|
|
.title {
|
font-size: 16px;
|
color: #1890ff;
|
line-height: 24px;
|
font-weight: 600;
|
padding-left: 12px;
|
position: relative;
|
margin: 0 0 20px 0;
|
|
&::before {
|
content: "";
|
position: absolute;
|
left: 0;
|
top: 4px;
|
width: 4px;
|
height: 16px;
|
background-color: #1890ff;
|
border-radius: 2px;
|
}
|
}
|
|
.media-section {
|
margin-bottom: 30px;
|
}
|
|
.section-title {
|
font-size: 14px;
|
color: #666;
|
margin-bottom: 15px;
|
font-weight: 500;
|
}
|
|
.image-grid {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 10px;
|
}
|
|
.image-item {
|
width: 100px;
|
height: 100px;
|
border-radius: 8px;
|
overflow: hidden;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.image-preview {
|
width: 100%;
|
height: 100%;
|
}
|
|
.video-grid {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 15px;
|
}
|
|
.video-item {
|
width: 160px;
|
height: 90px;
|
border-radius: 8px;
|
overflow: hidden;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.video-preview {
|
width: 100%;
|
height: 100%;
|
background-color: #333;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
position: relative;
|
}
|
|
.video-tip {
|
position: absolute;
|
bottom: 5px;
|
left: 50%;
|
transform: translateX(-50%);
|
font-size: 12px;
|
color: #fff;
|
background-color: rgba(0, 0, 0, 0.6);
|
padding: 2px 8px;
|
border-radius: 4px;
|
}
|
|
.empty-state {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
height: 200px;
|
}
|
</style>
|