This commit is contained in:
2025-05-10 15:59:02 +08:00
parent d6b32af2b2
commit 396fd4b934
21 changed files with 662 additions and 83 deletions

View File

@@ -1,9 +1,11 @@
<script setup>
import {ref} from "vue";
import {Modal} from "@arco-design/web-vue";
import {determineMediaType} from "../../utils/index.js";
import Plyr from "../Plyr/Plyr.vue";
const emits = defineEmits(['delete']);
const {width, height, aspect} = defineProps({
const {width, height, aspect, hideDelete, src} = defineProps({
width: {
type: String,
default: '80px'
@@ -15,6 +17,14 @@ const {width, height, aspect} = defineProps({
aspect: {
type: Boolean,
default: false,
},
hideDelete: {
type: Boolean,
default: false,
},
src: {
type: String,
default: "",
}
});
const previewVisible = ref(false);
@@ -33,28 +43,61 @@ const deleteImage = () => {
<template>
<div class="x-image-box" :style="{aspectRatio: aspect ? '1 / 1' : ''}">
<a-image
v-if="determineMediaType(src) === 'Image'"
fit="contain"
v-model:preview-visible="previewVisible"
@preview-visible-change="(v)=>previewVisible=v"
v-bind="$attrs"
:src="src"
:width="width"
:height="height">
</a-image>
<video class="video" v-else-if="determineMediaType(src) === 'Video'" :src="src">
</video>
<transition name="fade">
<div class="video-preview-mask" v-if="determineMediaType(src) === 'Video' && previewVisible"
@click="previewVisible=false">
<plyr :src="src" @click.stop></plyr>
</div>
</transition>
<div class="mask">
<icon-eye @click="previewVisible=true" class="icon" style="color: #fff"/>
<icon-delete @click="deleteImage" class="icon" style="color: #fff"/>
<icon-delete @click="deleteImage" v-if="!hideDelete" class="icon" style="color: #fff"/>
</div>
</div>
</template>
<style scoped lang="scss">
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
position: relative;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
position: absolute;
}
.x-image-box {
@apply cursor-pointer relative box-border rounded-[6px] overflow-hidden;
outline: 1px solid #E5E6EB;
width: v-bind(width);
height: v-bind(height);
.video {
width: v-bind(width);
height: v-bind(height);
object-fit: contain;
}
.video-preview-mask {
@apply size-full fixed z-[999] left-0 top-0 bg-[rgba(0,0,0,.6)] flex justify-center items-center;
}
&:hover .mask {
background-color: rgba(0, 0, 0, .4);

View File

@@ -0,0 +1,44 @@
<script setup>
const {list, size} = defineProps({
list: {
type: Array,
default: []
},
size: {
type: String,
default: "40px"
}
});
</script>
<template>
<div class="x-image-small-list">
<a-image :width="size" :height="size" :src="list[0]" v-bind="$attrs"></a-image>
<div class="x-image-small-list-mask" v-if="list.length > 1">
+{{ list.length - 1 }}
</div>
</div>
</template>
<style scoped lang="scss">
.x-image-small-list {
width: v-bind(size);
height: v-bind(size);
overflow: hidden;
position: relative;
border-radius: 6px;
.x-image-small-list-mask {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, .3);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>