Files
gao-customer-h5/src/components/mediaSelector/MediaSelectorItem.vue
T

146 lines
2.6 KiB
Vue

<template>
<div class="item">
<t-button variant="text" class="preview-trigger" @click="emit('preview')">
<div v-if="isVideoItem(item)" class="video-thumbnail">
<t-image
v-if="getMediaThumbnailURL(item)"
class="image"
:src="getMediaThumbnailURL(item)"
:alt="getAttachTypeText(item.attachType)"
fit="cover"
/>
<video
v-else
:src="getMediaPreviewURL(item)"
muted
playsinline
preload="metadata"
/>
<span class="video-play" aria-hidden="true">▶</span>
</div>
<t-image
v-else
class="image"
:src="item.url"
:alt="getAttachTypeText(item.attachType)"
fit="cover"
/>
</t-button>
<div
v-if="showTypeLabel"
class="type-label white glass-black clip-text"
v-text="getAttachTypeText(item.attachType)"
/>
<t-button
v-if="showRemove && removable"
theme="danger"
class="remove"
shape="circle"
size="extra-small"
@click="emit('remove')"
>
<t-icon name="close" size="1rem" />
</t-button>
</div>
</template>
<script setup lang="ts">
import type { PhotoItem } from "@/types/Photo.ts";
import {
getAttachTypeText,
getMediaPreviewURL,
getMediaThumbnailURL,
isVideoItem
} from "./utils";
interface Props {
item: PhotoItem;
removable: boolean;
showRemove: boolean;
showTypeLabel: boolean;
}
defineProps<Props>();
const emit = defineEmits<{
preview: [];
remove: [];
}>();
</script>
<style scoped lang="less">
.item {
width: 5.5rem;
height: 5.5rem;
flex: 0 0 5.5rem;
position: relative;
overflow: hidden;
border-radius: 1rem;
.preview-trigger {
padding: 0;
border: 0;
width: 100%;
height: 100%;
display: block;
cursor: pointer;
background: transparent;
.image {
height: 100%;
}
.video-thumbnail {
width: 100%;
height: 100%;
position: relative;
background: #0f172a;
video {
width: 100%;
height: 100%;
object-fit: cover;
}
.video-play {
inset: 50% auto auto 50%;
width: 2rem;
height: 2rem;
color: #fff;
position: absolute;
display: flex;
font-size: 1.125rem;
align-items: center;
justify-content: center;
background: rgba(15, 23, 42, .68);
border-radius: 50%;
transform: translate(-50%, -50%);
}
}
}
.type-label {
width: 100%;
bottom: 0;
padding: .125rem .5rem;
position: absolute;
overflow: hidden;
font-size: .875rem;
text-align: center;
line-height: 1.2;
border-radius: 0 0 1rem 1rem;
pointer-events: none;
}
.remove {
top: .375rem;
right: .375rem;
position: absolute;
:deep(.t-button__content) {
display: flex;
align-items: center;
}
}
}
</style>