195 lines
3.7 KiB
Vue
195 lines
3.7 KiB
Vue
<template>
|
||
<view v-if="items.length" class="dm-root">
|
||
<view class="dm-title-row">
|
||
<text class="dm-title">服务过程</text>
|
||
<text class="dm-sub">{{ items.length }} 段素材</text>
|
||
</view>
|
||
<view class="dm-grid">
|
||
<view
|
||
v-for="(it, idx) in displayItems"
|
||
:key="idx"
|
||
class="dm-cell"
|
||
@click="onCell(it, idx)"
|
||
>
|
||
<image
|
||
v-if="it.mediaType !== 'video'"
|
||
class="dm-thumb"
|
||
:src="it.url"
|
||
mode="aspectFill"
|
||
/>
|
||
<view v-else class="dm-video-wrap">
|
||
<view class="dm-video-ph"></view>
|
||
<view class="dm-play">
|
||
<text class="dm-play-icon">▶</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- H5:全屏遮罩播放;小程序原生 video 在 fixed 遮罩内易触发渲染层异常,改跳转播放页 -->
|
||
<!-- #ifdef H5 -->
|
||
<view v-if="videoPreviewUrl" class="dm-video-overlay" @click="closeVideo">
|
||
<view class="dm-video-box" @click.stop>
|
||
<video
|
||
class="dm-video"
|
||
:src="videoPreviewUrl"
|
||
controls
|
||
autoplay
|
||
/>
|
||
<text class="dm-close">关闭</text>
|
||
</view>
|
||
</view>
|
||
<!-- #endif -->
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed } from 'vue'
|
||
|
||
const props = defineProps({
|
||
items: {
|
||
type: Array,
|
||
default: () => []
|
||
}
|
||
})
|
||
|
||
const videoPreviewUrl = ref('')
|
||
|
||
const displayItems = computed(() => props.items.slice(0, 9))
|
||
|
||
const imageUrls = computed(() =>
|
||
displayItems.value.filter((i) => i.mediaType !== 'video').map((i) => i.url)
|
||
)
|
||
|
||
function onCell(it, idx) {
|
||
if (it.mediaType === 'video') {
|
||
// #ifdef H5
|
||
videoPreviewUrl.value = it.url
|
||
// #endif
|
||
// #ifndef H5
|
||
uni.navigateTo({
|
||
url: `/pages/video-player/videoPlayer?url=${encodeURIComponent(it.url)}`
|
||
})
|
||
// #endif
|
||
return
|
||
}
|
||
const urls = imageUrls.value
|
||
if (!urls.length) return
|
||
const current = it.url
|
||
uni.previewImage({
|
||
urls,
|
||
current
|
||
})
|
||
}
|
||
|
||
function closeVideo() {
|
||
videoPreviewUrl.value = ''
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.dm-root {
|
||
margin-top: 2px;
|
||
}
|
||
.dm-title-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
margin-bottom: 10px;
|
||
}
|
||
.dm-title {
|
||
font-size: 15px;
|
||
font-weight: 700;
|
||
color: #1f2937;
|
||
}
|
||
.dm-sub {
|
||
font-size: 12px;
|
||
color: #94a3b8;
|
||
}
|
||
.dm-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 6px;
|
||
}
|
||
.dm-cell {
|
||
aspect-ratio: 1;
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
background: #f1f5f9;
|
||
border: 1px solid #e8edf4;
|
||
}
|
||
.dm-thumb {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: block;
|
||
}
|
||
.dm-video-wrap {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.dm-video-ph {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: linear-gradient(145deg, #1e293b 0%, #334155 100%);
|
||
}
|
||
.dm-play {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: rgba(15, 23, 42, 0.25);
|
||
}
|
||
.dm-play-icon {
|
||
width: 36px;
|
||
height: 36px;
|
||
line-height: 36px;
|
||
text-align: center;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
color: #16a34a;
|
||
font-size: 14px;
|
||
padding-left: 3px;
|
||
}
|
||
.dm-video-overlay {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
z-index: 10000;
|
||
background: rgba(15, 23, 42, 0.75);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20px;
|
||
box-sizing: border-box;
|
||
}
|
||
.dm-video-box {
|
||
width: 100%;
|
||
max-width: 400px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
.dm-video {
|
||
width: 100%;
|
||
max-height: 70vh;
|
||
border-radius: 12px;
|
||
background: #000;
|
||
}
|
||
.dm-close {
|
||
color: #fff;
|
||
font-size: 14px;
|
||
padding: 8px 20px;
|
||
}
|
||
</style>
|