mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-08-06 10:57:25 +08:00
- 将多个组件转换为 `<script setup>` 语法,提升可读性和性能 - 优化状态管理和事件处理逻辑,简化代码结构 - 更新样式和布局以适应新组件结构 - 添加新功能和修复已知问题,提升用户体验
170 lines
3.8 KiB
Vue
170 lines
3.8 KiB
Vue
<template>
|
|
<div class="layout" :style="wrapperStyle">
|
|
<div class="video-shell" :style="boxStyle">
|
|
<div
|
|
class="video-ratio"
|
|
:style="{ paddingBottom: aspectPadding + '%' }"
|
|
>
|
|
<div class="video-ratio-inner">
|
|
<video
|
|
v-if="item.videoUrl"
|
|
class="video-media"
|
|
:src="item.videoUrl"
|
|
:poster="item.poster"
|
|
:autoplay="!!item.autoplay"
|
|
:controls="true"
|
|
object-fit="cover"
|
|
/>
|
|
<image
|
|
v-else-if="item.poster"
|
|
class="video-media"
|
|
:src="item.poster"
|
|
mode="aspectFill"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
|
|
const props = defineProps<{ res: any }>();
|
|
|
|
const DEFAULT_VIDEO_STYLE = {
|
|
bgType: "color",
|
|
bgColorStart: "#F5F5F5",
|
|
bgColorEnd: "#F5F5F5",
|
|
bgGradientDir: "horizontal",
|
|
bgRadius: 0,
|
|
bottomBgColor: "#F5F5F5",
|
|
bgImage: "",
|
|
margin: 0,
|
|
padding: 0,
|
|
borderShow: false,
|
|
borderStyle: "solid",
|
|
borderWidth: 1,
|
|
borderColor: "#e5e5e5",
|
|
shadowShow: false,
|
|
shadowColor: "rgba(0,0,0,0.1)",
|
|
shadowX: 0,
|
|
shadowY: 0,
|
|
shadowBlur: 10,
|
|
shadowSpread: 0,
|
|
};
|
|
|
|
const ASPECT_RATIO_MAP: Record<string, number> = {
|
|
"16:9": 56.25,
|
|
"4:3": 75,
|
|
"1:1": 100,
|
|
};
|
|
|
|
function ensureVideoItem(item: any) {
|
|
if (!item.aspectRatio) item.aspectRatio = "16:9";
|
|
if (!item.style) {
|
|
item.style = { ...DEFAULT_VIDEO_STYLE };
|
|
return;
|
|
}
|
|
Object.keys(DEFAULT_VIDEO_STYLE).forEach((key) => {
|
|
if (item.style[key] === undefined) {
|
|
item.style[key] = DEFAULT_VIDEO_STYLE[key as keyof typeof DEFAULT_VIDEO_STYLE];
|
|
}
|
|
});
|
|
}
|
|
|
|
function getVideoGradient(style: any) {
|
|
const start = style.bgColorStart || "#F5F5F5";
|
|
const end = style.bgColorEnd || start;
|
|
const colors = `${start}, ${end}`;
|
|
const dirMap: Record<string, string> = {
|
|
horizontal: `linear-gradient(to right, ${colors})`,
|
|
vertical: `linear-gradient(to bottom, ${colors})`,
|
|
skewLeft: `linear-gradient(135deg, ${colors})`,
|
|
skewRight: `linear-gradient(45deg, ${colors})`,
|
|
};
|
|
return dirMap[style.bgGradientDir] || dirMap.horizontal;
|
|
}
|
|
|
|
const item = computed(() => {
|
|
const data = props.res.list[0] || {};
|
|
ensureVideoItem(data);
|
|
return data;
|
|
});
|
|
|
|
const wrapperStyle = computed(() => {
|
|
const style = item.value.style;
|
|
return {
|
|
margin: `${style.margin || 0}px`,
|
|
padding: `${style.padding || 0}px`,
|
|
background: style.bottomBgColor || "#F5F5F5",
|
|
boxSizing: "border-box",
|
|
};
|
|
});
|
|
|
|
const boxStyle = computed(() => {
|
|
const style = item.value.style;
|
|
const box: Record<string, string> = {
|
|
borderRadius: `${style.bgRadius || 0}px`,
|
|
overflow: "hidden",
|
|
position: "relative",
|
|
width: "100%",
|
|
};
|
|
|
|
if (style.bgType === "image" && style.bgImage) {
|
|
box.backgroundImage = `url(${style.bgImage})`;
|
|
box.backgroundSize = "cover";
|
|
box.backgroundPosition = "center";
|
|
} else {
|
|
box.background = getVideoGradient(style);
|
|
}
|
|
|
|
if (style.borderShow) {
|
|
box.border = `${style.borderWidth || 1}px ${style.borderStyle || "solid"} ${
|
|
style.borderColor || "#e5e5e5"
|
|
}`;
|
|
}
|
|
|
|
if (style.shadowShow) {
|
|
box.boxShadow = `${style.shadowX || 0}px ${style.shadowY || 0}px ${
|
|
style.shadowBlur || 10
|
|
}px ${style.shadowSpread || 0}px ${style.shadowColor || "rgba(0,0,0,0.1)"}`;
|
|
}
|
|
|
|
return box;
|
|
});
|
|
|
|
const aspectPadding = computed(
|
|
() => ASPECT_RATIO_MAP[item.value.aspectRatio] || ASPECT_RATIO_MAP["16:9"]
|
|
);
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
@import "./tpl.scss";
|
|
|
|
.layout {
|
|
padding: 0;
|
|
margin: 0;
|
|
background: transparent;
|
|
}
|
|
|
|
.video-shell {
|
|
width: 100%;
|
|
}
|
|
|
|
.video-ratio {
|
|
width: 100%;
|
|
height: 0;
|
|
position: relative;
|
|
}
|
|
|
|
.video-ratio-inner {
|
|
position: absolute;
|
|
inset: 0;
|
|
}
|
|
|
|
.video-media {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
}
|
|
</style>
|