feat: support ticket home video cover
This commit is contained in:
@@ -1,7 +1,27 @@
|
||||
<template>
|
||||
<view class="h-screen overflow-hidden bg-[#06111f] flex flex-col">
|
||||
<view class="relative z-0 h-[43vh] shrink-0 overflow-hidden bg-[#173a34]">
|
||||
<image class="absolute inset-0 h-full w-full" :src="homeData.coverImage" mode="aspectFill" />
|
||||
<video
|
||||
v-if="homeData.coverImage && isMp4Video(homeData.coverImage)"
|
||||
class="absolute inset-0 h-full w-full"
|
||||
:src="homeData.coverImage"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
:controls="false"
|
||||
:show-center-play-btn="false"
|
||||
:show-play-btn="false"
|
||||
:show-fullscreen-btn="false"
|
||||
:show-mute-btn="false"
|
||||
:enable-progress-gesture="false"
|
||||
object-fit="cover"
|
||||
/>
|
||||
<image
|
||||
v-else-if="homeData.coverImage"
|
||||
class="absolute inset-0 h-full w-full"
|
||||
:src="homeData.coverImage"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="absolute inset-0 bg-[linear-gradient(180deg,rgba(6,17,31,0.15)_18%,rgba(6,17,31,0.1)_45%,rgba(6,17,31,0.92)_100%)]" />
|
||||
|
||||
<view class="absolute inset-x-0 top-0 z-20">
|
||||
@@ -151,6 +171,11 @@ const instance = getCurrentInstance()
|
||||
const scenicMetaText = computed(() =>
|
||||
[props.homeData.levelText, props.homeData.subtitle].filter(Boolean).join('|')
|
||||
)
|
||||
const isMp4Video = (url) => {
|
||||
if (typeof url !== 'string') return false
|
||||
const resourcePath = url.trim().split(/[?#]/)[0]
|
||||
return resourcePath.toLowerCase().endsWith('.mp4')
|
||||
}
|
||||
const isActiveGroup = (groupId) =>
|
||||
String(groupId) === String(activeGroupId.value)
|
||||
const productsForGroup = (group) =>
|
||||
|
||||
@@ -117,6 +117,27 @@ test("TicketHome consumes scenic home response fields directly", async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("TicketHome renders MP4 cover images as background videos", async () => {
|
||||
const source = await readTicketFile("components/TicketHome.vue");
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/<video\s+v-if="homeData\.coverImage && isMp4Video\(homeData\.coverImage\)"/
|
||||
);
|
||||
assert.match(source, /autoplay\s+loop\s+muted/);
|
||||
assert.match(source, /:controls="false"/);
|
||||
assert.match(source, /:show-center-play-btn="false"/);
|
||||
assert.match(source, /:show-play-btn="false"/);
|
||||
assert.match(source, /:show-fullscreen-btn="false"/);
|
||||
assert.match(source, /:show-mute-btn="false"/);
|
||||
assert.match(source, /:enable-progress-gesture="false"/);
|
||||
assert.match(source, /object-fit="cover"/);
|
||||
assert.match(source, /<image\s+v-else-if="homeData\.coverImage"/);
|
||||
assert.match(source, /const isMp4Video = \(url\) =>/);
|
||||
assert.match(source, /url\.trim\(\)\.split\(\/\[\?\#\]\/\)\[0\]/);
|
||||
assert.match(source, /toLowerCase\(\)\.endsWith\('\.mp4'\)/);
|
||||
});
|
||||
|
||||
test("product detail is an independent prototype-aligned page", async () => {
|
||||
const indexPage = await readTicketFile("index.vue");
|
||||
const detailPage = await readTicketFile("product-detail.vue");
|
||||
|
||||
Reference in New Issue
Block a user