Remove the unused box-sizing.scss stylesheet and its import from the main SCSS index file. Update all Vue component template class references from the custom border-box class to the native box-border utility class to eliminate redundant custom CSS and align with the project's utility class conventions.
120 lines
3.2 KiB
Vue
120 lines
3.2 KiB
Vue
<template>
|
|
<view class="w-full bg-white box-border border-ff overflow-hidden rounded-20 flex flex-col">
|
|
<!-- 占位撑开 -->
|
|
<view class="w-vw"></view>
|
|
|
|
<view class="aigc-photo-card relative rounded-24 overflow-hidden w-full"
|
|
:class="{ 'is-disabled': disabled, 'is-empty': !videoUrl }" @click="handleAction">
|
|
<video v-if="videoUrl" :id="videoId" class="aigc-photo-card__video block w-full" :src="videoUrl" :poster="poster"
|
|
:controls="!disabled" :show-center-play-btn="!disabled" :show-play-btn="!disabled"
|
|
:show-fullscreen-btn="!disabled" :enable-progress-gesture="!disabled" :direction="fullscreenDirection"
|
|
object-fit="cover" @click.stop @play="handlePlay" @fullscreenchange="handleFullScreenChange"
|
|
@error="handleError" />
|
|
<view v-if="videoUrl && !disabled"
|
|
class="aigc-photo-card__fullscreen flex flex-items-center flex-justify-center color-white font-size-12"
|
|
@click.stop="requestFullScreen">
|
|
全屏
|
|
</view>
|
|
<view v-if="!videoUrl"
|
|
class="aigc-photo-card__empty flex flex-items-center flex-justify-center color-white font-size-14">
|
|
视频地址为空
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, getCurrentInstance } from "vue";
|
|
|
|
const props = defineProps({
|
|
toolCall: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
data: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["select", "action", "play", "fullscreenchange", "error"]);
|
|
const instance = getCurrentInstance();
|
|
const videoId = `aigc-video-${Math.random().toString(36).slice(2, 10)}`;
|
|
|
|
const cardData = computed(() => ({
|
|
...props.data,
|
|
...(props.toolCall?.componentNameParams || {}),
|
|
}));
|
|
|
|
const videoUrl = computed(
|
|
() => cardData.value.videoUrl || cardData.value.url || cardData.value.src || ""
|
|
);
|
|
|
|
const poster = computed(
|
|
() => cardData.value.poster || cardData.value.cover || cardData.value.coverUrl || ""
|
|
);
|
|
|
|
const title = computed(() => cardData.value.title || cardData.value.name || "");
|
|
|
|
const fullscreenDirection = computed(
|
|
() => cardData.value.fullscreenDirection ?? cardData.value.direction ?? 90
|
|
);
|
|
|
|
const eventPayload = computed(() => {
|
|
if (props.toolCall && Object.keys(props.toolCall).length > 0) {
|
|
return {
|
|
...props.toolCall,
|
|
componentNameParams: cardData.value,
|
|
};
|
|
}
|
|
return cardData.value;
|
|
});
|
|
|
|
const handleAction = () => {
|
|
if (props.disabled) return;
|
|
emit("select", eventPayload.value);
|
|
emit("action", eventPayload.value);
|
|
};
|
|
|
|
const handlePlay = () => {
|
|
if (props.disabled) return;
|
|
emit("play", eventPayload.value);
|
|
};
|
|
|
|
const requestFullScreen = () => {
|
|
if (!videoUrl.value || props.disabled) return;
|
|
|
|
const videoContext = uni.createVideoContext(
|
|
videoId,
|
|
instance?.proxy || instance
|
|
);
|
|
videoContext?.play?.();
|
|
videoContext?.requestFullScreen?.({
|
|
direction: Number(fullscreenDirection.value),
|
|
});
|
|
};
|
|
|
|
const handleFullScreenChange = (event) => {
|
|
emit("fullscreenchange", {
|
|
event,
|
|
data: eventPayload.value,
|
|
});
|
|
};
|
|
|
|
const handleError = (event) => {
|
|
emit("error", {
|
|
event,
|
|
data: eventPayload.value,
|
|
});
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import "./styles/index.scss";
|
|
</style>
|