Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
飞
飞鹤小程序
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
FH
飞鹤小程序
Commits
9c3b2110
Commit
9c3b2110
authored
Nov 06, 2025
by
zhangchenchen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 小程序预览功能
parent
0c59f9d5
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1665 additions
and
1492 deletions
+1665
-1492
Brand.vue
views/Brand.vue
+1665
-1492
No files found.
views/Brand.vue
View file @
9c3b2110
<
template
>
<view
class=
"brand-container"
>
<view
class=
"content"
>
<swiper
id=
"firstScreen"
class=
"swiper banner"
:current=
"swiperIndex"
@
animationfinish=
"intervalChange"
circular
:indicator-dots=
"indicatorDots"
:autoplay=
"autoplay"
:interval=
"interval"
:duration=
"duration"
:indicator-color=
"indicatorColor"
:indicator-active-color=
"indicatoractiveColor"
>
<swiper-item
v-for=
"(item, index) in swiperList"
:key=
"index"
>
<view
class=
"swiper-item banneritem"
>
<image
:data-log=
"
{
xcxClick: '品牌故事-首屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: `背景图-${swiperNameList[index]}`
}" :data-comlog="{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '品牌故事页banner',
componentContent: item.title || ''
}" :data-link="item.link" @tap="jumpLink(item.link, item.videoUrl, $event)" class="b-img"
:src="item?.url?.indexOf('http') === 0 ? item.url : $baseUrl + item.url">
</image>
</view>
</swiper-item>
</swiper>
<view
class=
"swiperbox"
>
<view
class=
"iconbox"
>
<!--
<image
:data-log=
"
{
<view
class=
"brand-container"
>
<view
class=
"content"
>
<swiper
id=
"firstScreen"
class=
"swiper banner"
:current=
"swiperIndex"
@
animationfinish=
"intervalChange"
circular
:indicator-dots=
"indicatorDots"
:autoplay=
"autoplay"
:interval=
"interval"
:duration=
"duration"
:indicator-color=
"indicatorColor"
:indicator-active-color=
"indicatoractiveColor"
>
<swiper-item
v-for=
"(item, index) in swiperList"
:key=
"index"
>
<view
class=
"swiper-item banneritem"
>
<image
:data-log=
"
{
xcxClick: '品牌故事-首屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: `背景图-${swiperNameList[index]}`,
}"
:data-comlog="{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '品牌故事页banner',
componentContent: item.title || '',
}"
:data-link="item.link"
@tap="jumpLink(item.link, item.videoUrl, $event)"
class="b-img"
:src="item?.url?.indexOf('http') === 0 ? item.url : $baseUrl + item.url"
>
</image>
</view>
</swiper-item>
</swiper>
<view
class=
"swiperbox"
>
<view
class=
"iconbox"
>
<!--
<image
:data-log=
"
{
xcxClick: '品牌故事-首屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: `按钮-${swiperNameList[index]}`
}" @tap="jumpSwiper(index, $event)" class="icon"
:src="swiperIndex === index ? $baseUrl + icon.activeUrl : $baseUrl + icon.baseUrl"
v-for="(icon, index) in swiperIconList" :key="index">
</image>
-->
<image
:src=
"$baseUrl + 'brandpage/indicatorDotsBg.png'"
class=
"indicatorDotsBg"
></image>
<view
class=
"indicatorDots"
>
<template
class=
"dotbox"
v-for=
"(item, index) in swiperIconList"
:key=
"index"
>
<view
class=
"dot"
:class=
"swiperIndex === index ? 'dot-active' : 'dot-normal'"
>
</view>
</
template
>
<text
class=
"dotText"
>
{{ swiperIconList[swiperIndex]?.text.length > 7 ?
swiperIconList[swiperIndex]?.text.substring(0, 7) + '...' :
swiperIconList[swiperIndex]?.text }}
</text>
</view>
</view>
</view>
<view
class=
"swiper-mask"
>
<image
class=
"swiper-mask-img"
:src=
"$baseUrl + 'homepage/home_format_v2.png'"
></image>
</view>
<view
class=
"videoposterbox"
v-if=
"video1Channel.videoUrl || (video1Channel.finderUserName && video1Channel.feedId)"
>
<video
v-if=
"video1Channel.videoUrl"
ref=
"brandVideo1Ref"
id=
"brandVideo1"
class=
"videoposter"
:src=
"video1Channel.videoUrl?.indexOf('http') === 0 ? video1Channel.videoUrl : $baseUrl + video1Channel.videoUrl"
:autoplay=
"false"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: '腰部品牌Video'
}"
:poster=
"video1Channel.posterUrl?.indexOf('http') === 0 ? video1Channel.posterUrl : $baseUrl + video1Channel.posterUrl"
object-fit=
"cover"
@
loadedmetadata=
"onVideoLoadedMeta"
@
play=
"onVideo1Play"
@
ended=
"onVideo1Ended"
></video>
<image
v-else
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: '腰部品牌Video'
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '品牌故事视频',
componentContent: video1Channel.title || ''
}"
@
tap=
"openChannel(video1Channel, $event)"
class=
"videoposter"
:src=
"video1Channel.posterUrl?.indexOf('http') === 0 ? video1Channel.posterUrl : $baseUrl + video1Channel.posterUrl"
>
</image>
<view
class=
"videoposterboxtitle"
v-if=
"showVideo1Title"
>
{{ video1Channel.title || "" }}
</view>
</view>
<view
id=
"secondScreen"
class=
"productcontai"
v-if=
"productTabList.length > 0 && productInfoList.length > 0"
>
<text
class=
"maintitle"
>
{{ erqiPeizhi.title1 }}
</text>
<scroll-view
class=
"listbox"
scroll-x=
"true"
show-scrollbar=
"false"
:scroll-into-view=
"'tab-' + channelTabIndex"
:scroll-with-animation=
"true"
>
<view
class=
"tab-container"
>
<view
@
tap=
"channelTabHandler(index, $event)"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-次屏页面',
buttonName: `${item}`
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤产品家族',
componentContent: '产品家族切换分类-' + item
}"
:class=
"channelTabIndex === index ? 'tabitem tabActive' : 'tabitem'"
v-for=
"(item, index) in productTabList"
:key=
"index"
:id=
"'tab-' + index"
>
{{ item }}
</view>
</view>
</scroll-view>
<scroll-view
v-if=
"productInfoList.length > 0"
class=
"productbox"
scroll-x=
"true"
show-scrollbar=
"false"
>
<view
class=
"product-grid"
>
<view
class=
"product-row"
>
<view
class=
"infobox"
:key=
"'top-' + index"
v-for=
"(infoItem, index) in productInfoList[channelTabIndex].filter((item, i) => i % 2 === 0)"
:style=
"{
background: `url(${$baseUrl}brandpage/infoBoxBg.png) no-repeat center/contain`
}"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-次屏页面',
buttonName: `${productTabList[channelTabIndex] + '中的' + infoItem.title}+'商品'`
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤产品家族',
componentContent: '产品家族商品-' + infoItem.desc
}"
@
tap=
"jumpProduct(infoItem, $event)"
>
<view
class=
"flexbox"
>
<view
class=
"infotitle"
>
{{ infoItem.title }}
</view>
<image
class=
"infoimg"
:src=
"infoItem.bgUrl?.indexOf('http') === 0 ? infoItem.bgUrl : $baseUrl + infoItem.bgUrl"
>
</image>
</view>
<view
class=
"infodesc"
>
{{ infoItem.desc }}
</view>
</view>
</view>
<view
class=
"product-row"
>
<view
class=
"infobox"
:key=
"'bottom-' + index"
v-for=
"(infoItem, index) in productInfoList[channelTabIndex].filter((item, i) => i % 2 === 1)"
:style=
"{
background: `url(${$baseUrl}brandpage/infoBoxBg.png) no-repeat center/contain`
}"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-次屏页面',
buttonName: `${productTabList[channelTabIndex] + '中的' + infoItem.title}+'商品'`
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤产品家族',
componentContent: '产品家族商品-' + infoItem.desc
}"
@
tap=
"jumpProduct(infoItem, $event)"
>
<view
class=
"flexbox"
>
<view
class=
"infotitle"
>
{{ infoItem.title }}
</view>
<image
class=
"infoimg"
:src=
"infoItem.bgUrl?.indexOf('http') === 0 ? infoItem.bgUrl : $baseUrl + infoItem.bgUrl"
>
</image>
</view>
<view
class=
"infodesc"
>
{{ infoItem.desc }}
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<view
class=
"videoposterbox"
v-if=
"video2Channel.videoUrl || (video2Channel.finderUserName && video2Channel.feedId)"
>
<video
v-if=
"video2Channel.videoUrl"
ref=
"brandVideo2Ref"
id=
"brandVideo2"
class=
"videoposter"
:src=
"video2Channel.videoUrl?.indexOf('http') === 0 ? video2Channel.videoUrl : $baseUrl + video2Channel.videoUrl"
:autoplay=
"false"
object-fit=
"cover"
@
loadedmetadata=
"onVideoLoadedMeta"
@
play=
"onVideo2Play"
:poster=
"video2Channel.posterUrl?.indexOf('http') === 0 ? video2Channel.posterUrl : $baseUrl + video2Channel.posterUrl"
@
ended=
"onVideo2Ended"
></video>
<image
v-else
class=
"videoposter"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '品牌故事视频',
componentContent: video2Channel.title || ''
}"
@
tap=
"openChannel(video2Channel, $event)"
:src=
"video2Channel.posterUrl?.indexOf('http') === 0 ? video2Channel.posterUrl : $baseUrl + video2Channel.posterUrl"
>
</image>
<view
class=
"videoposterboxtitle"
v-if=
"showVideo2Title"
>
{{ video2Channel.title || "" }}
</view>
</view>
<view
id=
"thirdScreen"
class=
"ipbox"
v-if=
"erqiPeizhi.appId1 && erqiPeizhi.appId2"
:style=
"{ background: `url(${$baseUrl}brandpage/hexiaofeiBg.png) no-repeat center/contain` }"
>
<!-- <store-product appid="wx1ad0903b95889ea1" product-id="10000239570622" custom-content="true"> -->
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `全家形象`
}"
class=
"iphexiaofei"
@
tap=
"jumpLink(erqiPeizhi.link, erqiPeizhi.videoUrl, $event)"
:src=
"erqiPeizhi.iphexiaofeiUrl"
>
</image>
<!-- </store-product> -->
<view
class=
"ipcard"
>
<view
class=
"title"
>
{{ erqiPeizhi.title2 }}
<!-- <view class="t1">鹤小飞一家</view> -->
</view>
<view
class=
"desc"
>
{{ ipDesc }}
</view>
<view
class=
"ipflex"
>
<view
class=
"ipbg ip1"
id=
"ip1"
@
tap=
"ipTapEvent(1, $event)"
>
<store-product
:appid=
"erqiPeizhi.appId1"
:product-id=
"erqiPeizhi.productId1"
custom-content=
"true"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[0]}`
}"
:src=
"erqiPeizhi.ipImg1?.indexOf('http') === 0 ? erqiPeizhi.ipImg1 : $baseUrl + erqiPeizhi.ipImg1"
class=
"ip1"
>
</image>
</store-product>
</view>
<view
class=
"ipright"
>
<view
class=
"ipbg ip2"
id=
"ip2"
@
tap=
"ipTapEvent(2, $event)"
>
<store-product
:appid=
"erqiPeizhi.appId2"
:product-id=
"erqiPeizhi.productId2"
custom-content=
"true"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[1]}`
}"
:src=
"erqiPeizhi.ipImg2?.indexOf('http') === 0 ? erqiPeizhi.ipImg2 : $baseUrl + erqiPeizhi.ipImg2"
>
</image>
</store-product>
</view>
<view
style=
"display: flex;justify-content: space-between;margin-top: 20rpx;"
>
<view
class=
"ipbg ip3"
id=
"ip3"
@
tap=
"ipTapEvent(3, $event)"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[2]}`
}"
@
tap=
"showPopup(0, $event)"
:src=
"erqiPeizhi.ipImg3?.indexOf('http') === 0 ? erqiPeizhi.ipImg3 : $baseUrl + erqiPeizhi.ipImg3"
>
</image>
</view>
<view
class=
"ipbg ip4"
id=
"ip4"
@
tap=
"ipTapEvent(4, $event)"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[3]}`
}"
@
tap=
"showPopup(2, $event)"
:src=
"erqiPeizhi.ipImg4?.indexOf('http') === 0 ? erqiPeizhi.ipImg4 : $baseUrl + erqiPeizhi.ipImg4"
>
</image>
</view>
</view>
</view>
</view>
</view>
</view>
<view
v-if=
"esgInfoList.length > 0"
class=
"esgbox"
>
<text
class=
"maintitle"
>
{{ erqiPeizhi.title3 }}
</text>
<!-- <text class="subtitle">关注祖国下一代的营养、教育和陪伴</text> -->
<view
class=
"channelscroll"
>
<view
class=
"box"
>
<view
class=
"infobox"
:key=
"index"
v-for=
"(infoItem, index) in esgInfoList"
:id=
"'esg' + (index + 1)"
:style=
"{ background: `url(${$baseUrl}brandpage/esgItemBg.png) no-repeat center/505rpx 638rpx` }"
:data-log=
"{
xcxClick: `品牌故事-三屏页面点击`,
pageName: `品牌故事-三屏页面ESG点击`,
buttonName: `${index + 1}-${infoItem.desc}`
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤ESG',
componentContent: infoItem.desc
}"
@
tap=
"jumpLink(infoItem.link, infoItem.videoUrl, $event)"
>
<image
class=
"infoimg imgRaduis"
:src=
"infoItem.bgUrl?.indexOf('http') === 0 ? infoItem.bgUrl : $baseUrl + infoItem.bgUrl"
>
</image>
<view
class=
"infotitle"
>
{{ infoItem.desc }}
</view>
<view
class=
"infodesc"
>
{{ infoItem.desc2 }}
</view>
</view>
</view>
</view>
</view>
</view>
<view>
<!-- 普通弹窗 -->
<uni-popup
:is-mask-click=
"false"
:safe-area=
"false"
ref=
"popup"
background-color=
"#fff"
border-radius=
"48rpx"
>
<view
v-if=
"qrInfoObj !== null"
class=
"popup-content"
>
<image
class=
"btnclose"
@
tap=
"closePop"
:src=
"$baseUrl + 'homepage/btnclose.png'"
></image>
<view
class=
"title"
>
{{ qrInfoObj.title }}
</view>
<rich-text
class=
"desc"
:nodes=
"qrInfoObj.desc"
>
</rich-text>
<image
:show-menu-by-longpress=
"true"
class=
"qrcode"
:src=
"$baseUrl + qrInfoObj.qrUrl"
></image>
<image
@
tap=
"downloadHandler($baseUrl + qrInfoObj.qrUrl)"
class=
"btndownload"
:src=
"$baseUrl + 'homepage/btn_download.png'"
></image>
</view>
<view
v-else
class=
"popup-content"
style=
"height: 899rpx;"
>
<image
class=
"xingmahui"
:src=
"$baseUrl + 'brandpage/hexiaofei.png'"
></image>
<image
class=
"btnclose"
@
tap=
"closePop"
:src=
"$baseUrl + 'homepage/btnclose.png'"
></image>
</view>
</uni-popup>
</view>
<view
v-if=
"showVideo"
class=
"video-popup"
>
<video
:src=
"currentVideoUrl"
controls
autoplay
:style=
"{ width: videoWidth + 'px', height: videoHeight + 'px' }"
@
loadedmetadata=
"onVideoLoadedMeta"
@
play=
"onVideoPlay"
></video>
<view
class=
"close-btn-bottom"
@
tap=
"closeVideo"
>
×
</view>
</view>
</view>
<image
:src=
"$baseUrl + 'brandpage/indicatorDotsBg.png'"
class=
"indicatorDotsBg"
></image>
<view
class=
"indicatorDots"
>
<template
class=
"dotbox"
v-for=
"(item, index) in swiperIconList"
:key=
"index"
>
<view
class=
"dot"
:class=
"swiperIndex === index ? 'dot-active' : 'dot-normal'"
>
</view>
</
template
>
<text
class=
"dotText"
>
{{
swiperIconList[swiperIndex]?.text.length > 7
? swiperIconList[swiperIndex]?.text.substring(0, 7) + '...'
: swiperIconList[swiperIndex]?.text
}}
</text>
</view>
</view>
</view>
<view
class=
"swiper-mask"
>
<image
class=
"swiper-mask-img"
:src=
"$baseUrl + 'homepage/home_format_v2.png'"
></image>
</view>
<view
class=
"videoposterbox"
v-if=
"video1Channel.videoUrl || (video1Channel.finderUserName && video1Channel.feedId)"
>
<video
v-if=
"video1Channel.videoUrl"
ref=
"brandVideo1Ref"
id=
"brandVideo1"
class=
"videoposter"
:src=
"
video1Channel.videoUrl?.indexOf('http') === 0
? video1Channel.videoUrl
: $baseUrl + video1Channel.videoUrl
"
:autoplay=
"false"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: '腰部品牌Video',
}"
:poster=
"
video1Channel.posterUrl?.indexOf('http') === 0
? video1Channel.posterUrl
: $baseUrl + video1Channel.posterUrl
"
object-fit=
"cover"
@
loadedmetadata=
"onVideoLoadedMeta"
@
play=
"onVideo1Play"
@
ended=
"onVideo1Ended"
></video>
<image
v-else
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-首屏页面',
buttonName: '腰部品牌Video',
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '品牌故事视频',
componentContent: video1Channel.title || '',
}"
@
tap=
"openChannel(video1Channel, $event)"
class=
"videoposter"
:src=
"
video1Channel.posterUrl?.indexOf('http') === 0
? video1Channel.posterUrl
: $baseUrl + video1Channel.posterUrl
"
>
</image>
<view
class=
"videoposterboxtitle"
v-if=
"showVideo1Title"
>
{{ video1Channel.title || '' }}
</view>
</view>
<!-- 产品家族 -->
<view
id=
"secondScreen"
class=
"productcontai"
v-if=
"productTabList.length > 0 && productInfoList.length > 0"
>
<text
class=
"maintitle"
>
{{ erqiPeizhi.title1 }}
</text>
<!-- tab容器 -->
<scroll-view
class=
"listbox"
scroll-x=
"true"
show-scrollbar=
"false"
:scroll-into-view=
"'tab-' + channelTabIndex"
:scroll-with-animation=
"true"
>
<view
class=
"tab-container"
>
<view
@
tap=
"channelTabHandler(index, $event)"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-次屏页面',
buttonName: `${item}`,
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤产品家族',
componentContent: '产品家族切换分类-' + item,
}"
:class=
"channelTabIndex === index ? 'tabitem tabActive' : 'tabitem'"
v-for=
"(item, index) in productTabList"
:key=
"index"
:id=
"'tab-' + index"
>
{{ item }}
</view>
</view>
</scroll-view>
<!-- 内容 -->
<scroll-view
v-if=
"productInfoList.length > 0"
class=
"productbox"
scroll-x=
"true"
show-scrollbar=
"false"
>
<view
class=
"product-grid"
>
<view
class=
"product-row"
>
<view
class=
"infobox"
:key=
"'top-' + index"
v-for=
"(infoItem, index) in productInfoList[channelTabIndex].filter((item, i) => i % 2 === 0)"
:style=
"{
background: `url(${$baseUrl}brandpage/infoBoxBg.png) no-repeat center/contain`,
}"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-次屏页面',
buttonName: `${productTabList[channelTabIndex] + '中的' + infoItem.title}+'商品'`,
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤产品家族',
componentContent: '产品家族商品-' + infoItem.desc,
}"
@
tap=
"jumpProduct(infoItem, $event)"
>
<view
class=
"flexbox"
>
<view
class=
"infotitle"
>
{{ infoItem.title }}
</view>
<image
class=
"infoimg"
:src=
"infoItem.bgUrl?.indexOf('http') === 0 ? infoItem.bgUrl : $baseUrl + infoItem.bgUrl"
>
</image>
</view>
<view
class=
"infodesc"
>
{{ infoItem.desc }}
</view>
</view>
</view>
<view
class=
"product-row"
>
<view
class=
"infobox"
:key=
"'bottom-' + index"
v-for=
"(infoItem, index) in productInfoList[channelTabIndex].filter((item, i) => i % 2 === 1)"
:style=
"{
background: `url(${$baseUrl}brandpage/infoBoxBg.png) no-repeat center/contain`,
}"
:data-log=
"{
xcxClick: '品牌故事-次屏页面点击',
pageName: '品牌故事-次屏页面',
buttonName: `${productTabList[channelTabIndex] + '中的' + infoItem.title}+'商品'`,
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤产品家族',
componentContent: '产品家族商品-' + infoItem.desc,
}"
@
tap=
"jumpProduct(infoItem, $event)"
>
<view
class=
"flexbox"
>
<view
class=
"infotitle"
>
{{ infoItem.title }}
</view>
<image
class=
"infoimg"
:src=
"infoItem.bgUrl?.indexOf('http') === 0 ? infoItem.bgUrl : $baseUrl + infoItem.bgUrl"
>
</image>
</view>
<view
class=
"infodesc"
>
{{ infoItem.desc }}
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<!-- 视频 -->
<view
class=
"videoposterbox"
v-if=
"video2Channel.videoUrl || (video2Channel.finderUserName && video2Channel.feedId)"
>
<video
v-if=
"video2Channel.videoUrl"
ref=
"brandVideo2Ref"
id=
"brandVideo2"
class=
"videoposter"
:src=
"
video2Channel.videoUrl?.indexOf('http') === 0
? video2Channel.videoUrl
: $baseUrl + video2Channel.videoUrl
"
:autoplay=
"false"
object-fit=
"cover"
@
loadedmetadata=
"onVideoLoadedMeta"
@
play=
"onVideo2Play"
:poster=
"
video2Channel.posterUrl?.indexOf('http') === 0
? video2Channel.posterUrl
: $baseUrl + video2Channel.posterUrl
"
@
ended=
"onVideo2Ended"
></video>
<image
v-else
class=
"videoposter"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '品牌故事视频',
componentContent: video2Channel.title || '',
}"
@
tap=
"openChannel(video2Channel, $event)"
:src=
"
video2Channel.posterUrl?.indexOf('http') === 0
? video2Channel.posterUrl
: $baseUrl + video2Channel.posterUrl
"
>
</image>
<view
class=
"videoposterboxtitle"
v-if=
"showVideo2Title"
>
{{ video2Channel.title || '' }}
</view>
</view>
<!-- 鹤小飞一家 -->
<view
id=
"thirdScreen"
class=
"ipbox"
v-if=
"erqiPeizhi.appId1 && erqiPeizhi.appId2"
:style=
"{ background: `url(${$baseUrl}brandpage/hexiaofeiBg.png) no-repeat center/contain` }"
>
<!-- <store-product appid="wx1ad0903b95889ea1" product-id="10000239570622" custom-content="true"> -->
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `全家形象`,
}"
class=
"iphexiaofei"
@
tap=
"jumpLink(erqiPeizhi.link, erqiPeizhi.videoUrl, $event)"
:src=
"erqiPeizhi.iphexiaofeiUrl"
>
</image>
<!-- </store-product> -->
<view
class=
"ipcard"
>
<!-- 标题 -->
<view
class=
"title"
>
{{ erqiPeizhi.title2 }}
</view>
<!-- 描述 -->
<view
class=
"desc"
>
{{ ipDesc }}
</view>
<!-- 商品 -->
<view
class=
"ipflex"
>
<!-- 竖版商品 -->
<view
class=
"ipbg ip1"
id=
"ip1"
@
tap=
"ipTapEvent(1, $event)"
>
<store-product
:appid=
"erqiPeizhi.appId1"
:product-id=
"erqiPeizhi.productId1"
custom-content=
"true"
>
<view
class=
"ipcontainer"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[0]}`,
}"
:src=
"
erqiPeizhi.ipImg1?.indexOf('http') === 0
? erqiPeizhi.ipImg1
: $baseUrl + erqiPeizhi.ipImg1
"
class=
"ip1"
>
</image>
<view
class=
"ipcontext"
>
<view
class=
"ipcontext-title"
>
{{ '竖版标题' }}
</view>
<view
class=
"ipcontext-desc"
>
{{ '竖版描述' }}
</view>
</view>
</view>
</store-product>
</view>
<view
class=
"ipright"
>
<!-- 横版商品 -->
<view
class=
"ipbg ip2"
id=
"ip2"
@
tap=
"ipTapEvent(2, $event)"
>
<store-product
:appid=
"erqiPeizhi.appId2"
:product-id=
"erqiPeizhi.productId2"
custom-content=
"true"
>
<view
class=
"ipcontainer"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[1]}`,
}"
:src=
"
erqiPeizhi.ipImg2?.indexOf('http') === 0
? erqiPeizhi.ipImg2
: $baseUrl + erqiPeizhi.ipImg2
"
>
</image>
<view
class=
"ipcontext"
>
<view
class=
"ipcontext-title"
>
{{ '横版标题' }}
</view>
<view
class=
"ipcontext-desc"
>
{{ '横版描述' }}
</view>
</view>
</view>
</store-product>
</view>
<view
style=
"display: flex; justify-content: space-between; margin-top: 20rpx"
>
<!-- 视频号 -->
<view
class=
"ipbg ip3"
id=
"ip3"
@
tap=
"ipTapEvent(3, $event)"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[2]}`,
}"
@
tap=
"showPopup(0, $event)"
:src=
"
erqiPeizhi.ipImg3?.indexOf('http') === 0
? erqiPeizhi.ipImg3
: $baseUrl + erqiPeizhi.ipImg3
"
>
</image>
</view>
<!-- 小红书 -->
<view
class=
"ipbg ip4"
id=
"ip4"
@
tap=
"ipTapEvent(4, $event)"
>
<image
:data-log=
"{
xcxClick: '品牌故事-三屏页面点击',
pageName: '品牌故事-三屏页面',
buttonName: `${hexiaofeiNameList[3]}`,
}"
@
tap=
"showPopup(2, $event)"
:src=
"
erqiPeizhi.ipImg4?.indexOf('http') === 0
? erqiPeizhi.ipImg4
: $baseUrl + erqiPeizhi.ipImg4
"
>
</image>
</view>
</view>
</view>
</view>
</view>
</view>
<view
v-if=
"esgInfoList.length > 0"
class=
"esgbox"
>
<text
class=
"maintitle"
>
{{ erqiPeizhi.title3 }}
</text>
<!-- <text class="subtitle">关注祖国下一代的营养、教育和陪伴</text> -->
<view
class=
"channelscroll"
>
<view
class=
"box"
>
<view
class=
"infobox"
:key=
"index"
v-for=
"(infoItem, index) in esgInfoList"
:id=
"'esg' + (index + 1)"
:style=
"{
background: `url(${$baseUrl}brandpage/esgItemBg.png) no-repeat center/505rpx 638rpx`,
}"
:data-log=
"{
xcxClick: `品牌故事-三屏页面点击`,
pageName: `品牌故事-三屏页面ESG点击`,
buttonName: `${index + 1}-${infoItem.desc}`,
}"
:data-comlog=
"{
xcxComponentClick: 'true',
pageName: '品牌故事页',
componentName: '飞鹤ESG',
componentContent: infoItem.desc,
}"
@
tap=
"jumpLink(infoItem.link, infoItem.videoUrl, $event)"
>
<image
class=
"infoimg imgRaduis"
:src=
"infoItem.bgUrl?.indexOf('http') === 0 ? infoItem.bgUrl : $baseUrl + infoItem.bgUrl"
>
</image>
<view
class=
"infotitle"
>
{{ infoItem.desc }}
</view>
<view
class=
"infodesc"
>
{{ infoItem.desc2 }}
</view>
</view>
</view>
</view>
</view>
</view>
<view>
<!-- 普通弹窗 -->
<uni-popup
:is-mask-click=
"false"
:safe-area=
"false"
ref=
"popup"
background-color=
"#fff"
border-radius=
"48rpx"
>
<view
v-if=
"qrInfoObj !== null"
class=
"popup-content"
>
<image
class=
"btnclose"
@
tap=
"closePop"
:src=
"$baseUrl + 'homepage/btnclose.png'"
></image>
<view
class=
"title"
>
{{ qrInfoObj.title }}
</view>
<rich-text
class=
"desc"
:nodes=
"qrInfoObj.desc"
>
</rich-text>
<image
:show-menu-by-longpress=
"true"
class=
"qrcode"
:src=
"$baseUrl + qrInfoObj.qrUrl"
></image>
<image
@
tap=
"downloadHandler($baseUrl + qrInfoObj.qrUrl)"
class=
"btndownload"
:src=
"$baseUrl + 'homepage/btn_download.png'"
></image>
</view>
<view
v-else
class=
"popup-content"
style=
"height: 899rpx"
>
<image
class=
"xingmahui"
:src=
"$baseUrl + 'brandpage/hexiaofei.png'"
></image>
<image
class=
"btnclose"
@
tap=
"closePop"
:src=
"$baseUrl + 'homepage/btnclose.png'"
></image>
</view>
</uni-popup>
</view>
<view
v-if=
"showVideo"
class=
"video-popup"
>
<video
:src=
"currentVideoUrl"
controls
autoplay
:style=
"{ width: videoWidth + 'px', height: videoHeight + 'px' }"
@
loadedmetadata=
"onVideoLoadedMeta"
@
play=
"onVideoPlay"
></video>
<view
class=
"close-btn-bottom"
@
tap=
"closeVideo"
>
×
</view>
</view>
</view>
</template>
<
script
>
import
{
fetchBrandJSON
}
from
'../api/brand'
;
import
{
jump
,
JumpType
}
from
'../utils'
;
import
md
from
'../md'
;
...
...
@@ -317,1203 +494,1199 @@ import ExposureTracker from '../utils/exposure';
// 定义需要曝光检测的元素配置
const
EXPOSURE_CONFIGS
=
[
{
id
:
'firstScreen'
,
logParams
:
{
xcxPage
:
'品牌故事-首屏页面浏览'
,
pageName
:
'品牌故事-首屏页面'
}
},
// 可以添加更多需要曝光检测的元素配置
{
id
:
'secondScreen'
,
logParams
:
{
xcxPage
:
'品牌故事-首屏页面浏览'
,
pageName
:
'品牌故事-次屏页面'
}
},
{
id
:
'thirdScreen'
,
logParams
:
{
xcxPage
:
'品牌故事-首屏页面浏览'
,
pageName
:
'品牌故事-三屏页面'
}
}
{
id
:
'firstScreen'
,
logParams
:
{
xcxPage
:
'品牌故事-首屏页面浏览'
,
pageName
:
'品牌故事-首屏页面'
,
},
},
// 可以添加更多需要曝光检测的元素配置
{
id
:
'secondScreen'
,
logParams
:
{
xcxPage
:
'品牌故事-首屏页面浏览'
,
pageName
:
'品牌故事-次屏页面'
,
},
},
{
id
:
'thirdScreen'
,
logParams
:
{
xcxPage
:
'品牌故事-首屏页面浏览'
,
pageName
:
'品牌故事-三屏页面'
,
},
},
];
export
default
{
beforeDestroy
()
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
resetAllExposure
();
}
this
.
stopAllVideos
();
},
deactivated
()
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
resetAllExposure
();
}
this
.
stopAllVideos
();
},
props
:
{
scrollTop
:
{
type
:
Number
,
default
:
0
}
},
watch
:
{
scrollTop
:
{
handler
(
newVal
)
{
this
.
checkExposure
(
newVal
);
}
}
},
data
()
{
return
{
popType
:
'bottom'
,
swiperList
:
[],
erqiPeizhi
:
{},
indicatorDots
:
false
,
autoplay
:
true
,
interval
:
4000
,
duration
:
500
,
indicatoractiveColor
:
"#a6a0a1"
,
indicatorColor
:
"rgba(255, 255, 255, 1)"
,
channelTabIndex
:
0
,
productTabList
:
[],
productInfoList
:
[],
swiperIconList
:
[],
swiperIndex
:
0
,
ipDesc
:
''
,
esgInfoList
:
[],
qrInfoList
:
[],
qrInfoObj
:
null
,
popupIndex
:
0
,
showVideo
:
false
,
testVideoUrl
:
''
,
channel
:
{},
videoWidth
:
375
,
videoHeight
:
210
,
swiperNameList
:
[
"北纬47°入口"
,
"自有牧场入口"
,
"工厂预约入口"
],
hexiaofeiNameList
:
[
"主要竖屏商品"
,
"主要横屏商品"
,
"视频号"
,
"小红书"
],
exposureTracker
:
null
,
video1Channel
:
{},
video2Channel
:
{},
currentPlayingVideo
:
null
,
// 当前正在播放的视频标识
videoContexts
:
{},
// 存储视频上下文,使用id作为key
ipExStr
:
[
'鹤小飞商品'
,
'鹤小飞商品'
,
'鹤小飞'
,
'鹤小飞'
],
showVideo1Title
:
true
,
// 控制视频1标题显示
showVideo2Title
:
true
,
// 控制视频2标题显示
}
},
mounted
()
{
this
.
initBrandInfo
();
// 初始化视频上下文
this
.
initVideoContexts
();
// 初始化曝光检测工具
this
.
exposureTracker
=
new
ExposureTracker
(
this
);
this
.
exposureTracker
.
addExposureElements
(
EXPOSURE_CONFIGS
);
// 初始检查曝光
this
.
$nextTick
(()
=>
{
this
.
checkExposure
(
this
.
scrollTop
);
});
},
methods
:
{
async
initBrandInfo
()
{
const
{
data
}
=
await
fetchBrandJSON
();
if
(
data
)
{
this
.
swiperList
=
data
.
swiperList
||
[{
"title"
:
"默认图"
,
"url"
:
this
.
$baseUrl
+
"homepage/brandSwiperDefaultBg.png"
}];
this
.
erqiPeizhi
=
data
.
erqiPeizhi
;
this
.
productTabList
=
data
.
productTabList
||
[];
this
.
productInfoList
=
data
.
product
||
[];
this
.
esgInfoList
=
data
.
esgInfoList
[
0
]
||
[];
this
.
qrInfoList
=
data
.
qrInfoList
;
this
.
ipDesc
=
data
.
ipDesc
;
this
.
swiperIconList
=
data
.
swiperIconList
||
[{
activeUrl
:
this
.
$baseUrl
+
"homepage/brandSwiperDefaultBg.png"
,
baseUrl
:
this
.
$baseUrl
+
"homepage/brandSwiperDefaultBg.png"
,
text
:
"默认图"
}];
this
.
testVideoUrl
=
data
.
videoUrl
;
if
(
data
.
videoUrl
.
indexOf
(
'http'
)
===
-
1
)
{
data
.
videoUrl
=
this
.
$baseUrl
+
data
.
videoUrl
;
}
this
.
currentVideoUrl
=
data
.
videoUrl
;
this
.
video1Channel
=
data
.
video1Channel
;
this
.
video2Channel
=
data
.
video2Channel
;
this
.
initExposure
();
}
},
initExposure
()
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"品牌故事页banner"
,
componentContent
:
this
.
swiperList
[
0
]?.
title
||
''
});
this
.
productTabList
.
forEach
((
item
,
index
)
=>
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"飞鹤产品家族"
,
componentContent
:
"产品家族切换分类-"
+
item
});
})
if
(
this
.
productInfoList
.
length
>
0
&&
this
.
productInfoList
[
0
]?.
length
>
0
)
{
this
.
productInfoList
[
0
]?.
forEach
((
item
,
index
)
=>
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"飞鹤产品家族"
,
componentContent
:
"产品家族商品-"
+
item
.
shareTitle
});
})
}
this
.
ipExStr
.
forEach
((
item
,
index
)
=>
{
this
.
exposureTracker
.
addExposureElement
({
id
:
'ip'
+
(
index
+
1
),
logParams
:
{
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"鹤小飞"
,
componentContent
:
item
+
'-'
+
this
.
erqiPeizhi
[
'ipTitle'
+
(
index
+
1
)]
}
})
})
this
.
esgInfoList
.
forEach
((
item
,
index
)
=>
{
this
.
exposureTracker
.
addExposureElement
({
id
:
'esg'
+
(
index
+
1
),
logParams
:
{
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"飞鹤ESG"
,
componentContent
:
item
.
desc
}
})
})
this
.
exposureTracker
.
addExposureElements
([
{
id
:
'brandVideo1'
,
logParams
:
{
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video1Channel
.
title
||
''
}
},
{
id
:
'brandVideo2'
,
logParams
:
{
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video2Channel
.
title
||
''
}
}
])
},
ipTapEvent
(
index
,
evt
)
{
md
.
sensorComponentLogTake
({
xcxComponentClick
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"鹤小飞"
,
componentContent
:
this
.
ipExStr
[
index
]
+
'-'
+
this
.
erqiPeizhi
[
'ipTitle'
+
index
]
});
},
intervalChange
(
e
)
{
this
.
swiperIndex
=
e
.
target
.
current
;
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"品牌故事页banner"
,
componentContent
:
this
.
swiperList
[
e
.
target
.
current
]?.
title
||
''
});
},
jumpSwiper
(
_index
,
evt
)
{
//点indicator切换图片
if
(
evt
)
{
md
.
sensorLog
(
evt
);
}
this
.
swiperIndex
=
_index
;
},
jumpLink
(
_link
,
videoUrl
,
evt
)
{
console
.
log
(
'jumpLink1111111:'
,
_link
,
videoUrl
);
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
}
}
// console.log(_link)
// uni.navigateTo({
// url: "/pages/product/product?id=1-1"
// })
if
(
videoUrl
)
{
// 弹出视频
this
.
currentVideoUrl
=
videoUrl
;
this
.
showVideo
=
true
;
return
;
// 视频弹窗出现后,video标签的autoplay会自动播放
}
else
if
(
_link
)
{
// 其他跳转逻辑
jump
(
_link
);
}
},
jumpProduct
(
item
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
}
}
const
{
productId
,
skuId
,
contentImg
,
contentImgLen
,
shareTitle
,
shareImg
,
title
,
link
,
entrySource
}
=
item
;
const
tabName
=
this
.
productTabList
[
this
.
channelTabIndex
];
if
(
productId
&&
skuId
&&
entrySource
)
{
const
url
=
`subPackages/shopMainProcess/product/index?productId=
${
productId
}
&skuId=
${
skuId
}
&entrySource=
${
entrySource
}
`
;
const
type
=
JumpType
.
MINI
;
const
extra
=
{
appId
:
'wx4205ec55b793245e'
,
//星妈优选小程序
extraData
:
{},
envVersion
:
'release'
,
embedded
:
true
,
};
jump
({
type
:
type
,
url
:
url
,
extra
:
extra
})
}
else
{
jump
(
link
)
// console.warn("/pages/product/product?productId=" + productId + "&skuId=" + skuId + "&contentImg=" + contentImg + "&contentImgLen=" + contentImgLen + "&shareTitle=" + shareTitle + "&shareImg=" + shareImg + "&tabName=" + tabName + "&title=" + title)
// uni.navigateTo({
// url: "/pages/product/product?productId=" + productId + "&skuId=" + skuId + "&contentImg=" + contentImg + "&contentImgLen=" + contentImgLen + "&shareTitle=" + shareTitle + "&shareImg=" + shareImg + "&tabName=" + tabName + "&title=" + title
// })
}
},
channelTabHandler
(
_index
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
this
.
productInfoList
[
_index
]?.
forEach
((
item
,
index
)
=>
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
"true"
,
pageName
:
"品牌故事页"
,
componentName
:
"飞鹤产品家族"
,
componentContent
:
"产品家族商品-"
+
item
.
shareTitle
});
})
}
}
this
.
channelTabIndex
=
_index
;
// 自动滚动到选中的tab
this
.
$nextTick
(()
=>
{
const
scrollView
=
uni
.
createSelectorQuery
().
select
(
'.listbox'
);
if
(
scrollView
)
{
scrollView
.
scrollOffset
((
res
)
=>
{
// 这里可以添加额外的滚动逻辑
}).
exec
();
}
});
},
showPopup
(
_index
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
}
this
.
popupIndex
=
_index
;
if
(
_index
<
2
)
{
this
.
qrInfoObj
=
this
.
qrInfoList
[
_index
];
md
.
sensorLogTake
({
xcxPage
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
pageName
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
});
}
else
{
this
.
qrInfoObj
=
null
;
md
.
sensorLogTake
({
xcxPage
:
`品牌故事-鹤小飞家族小红书二维码半屏`
,
pageName
:
`品牌故事-鹤小飞家族小红书二维码半屏`
,
});
}
this
.
$refs
.
popup
.
open
(
this
.
popType
);
},
closePop
()
{
this
.
$refs
.
popup
.
close
();
},
downloadHandler
(
imgurl
)
{
md
.
sensorLogTake
({
xcxClick
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
pageName
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
buttonName
:
`下载二维码`
});
uni
.
downloadFile
({
url
:
imgurl
,
success
:
(
downloadRes
)
=>
{
if
(
downloadRes
.
statusCode
===
200
)
{
uni
.
saveImageToPhotosAlbum
({
filePath
:
downloadRes
.
tempFilePath
,
success
:
(
res
)
=>
{
uni
.
showToast
({
title
:
'保存成功'
,
icon
:
'success'
});
},
fail
:
(
err
)
=>
{
uni
.
showToast
({
title
:
'保存失败'
,
icon
:
'none'
});
}
});
}
else
{
uni
.
showToast
({
title
:
'下载失败'
,
icon
:
'none'
});
}
},
fail
:
(
err
)
=>
{
uni
.
showToast
({
title
:
'下载失败'
,
icon
:
'none'
});
}
});
},
showVideoHandler
()
{
this
.
currentVideoUrl
=
this
.
testVideoUrl
;
this
.
showVideo
=
true
;
},
closeVideo
()
{
this
.
showVideo
=
false
;
this
.
currentVideoUrl
=
''
;
// 如果弹窗视频是当前播放的视频,清除播放状态
if
(
this
.
currentPlayingVideo
===
'popupVideo'
)
{
this
.
currentPlayingVideo
=
null
;
}
},
openChannel
(
videoChannel
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
}
}
const
finderUserName
=
videoChannel
.
finderUserName
;
const
feedId
=
videoChannel
.
feedId
;
uni
.
openChannelsActivity
({
finderUserName
,
feedId
,
success
:
res
=>
{
console
.
log
(
'跳转成功'
,
res
);
},
fail
:
err
=>
{
console
.
log
(
'跳转失败'
,
err
);
}
});
},
previewImage
(
url
)
{
uni
.
previewImage
({
urls
:
[
url
],
// 预览当前图片
current
:
url
// 当前显示的图片
});
},
onVideoLoadedMeta
(
e
)
{
const
{
width
,
height
}
=
e
.
detail
;
const
pageWidth
=
uni
.
upx2px
(
750
);
const
ratio
=
height
/
width
;
this
.
videoWidth
=
pageWidth
;
this
.
videoHeight
=
pageWidth
;
// pageWidth * ratio;
},
checkExposure
(
scrollTop
)
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
checkExposure
(
scrollTop
);
}
},
resetExposure
()
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
resetAllExposure
();
}
},
// 初始化视频上下文
initVideoContexts
()
{
this
.
$nextTick
(()
=>
{
const
videoIds
=
[
'brandVideo1'
,
'brandVideo2'
];
videoIds
.
forEach
(
id
=>
{
try
{
// 使用id创建视频上下文
this
.
videoContexts
[
id
]
=
uni
.
createVideoContext
(
id
,
this
);
console
.
log
(
'视频上下文已创建:'
,
id
);
}
catch
(
error
)
{
console
.
error
(
'创建视频上下文失败:'
,
id
,
error
);
}
});
});
},
onVideoPlay
()
{
console
.
log
(
'视频播放'
);
this
.
handleVideoPlay
(
'brandVideo1'
);
this
.
handleVideoPlay
(
'brandVideo2'
);
},
// 视频1播放事件
onVideo1Play
()
{
const
evt
=
{
currentTarget
:
{
dataset
:
{
log
:
{
xcxClick
:
'品牌故事-次屏页面点击'
,
pageName
:
'品牌故事-首屏页面'
,
buttonName
:
'腰部品牌Video'
}
}
}
}
md
.
sensorLog
(
evt
);
md
.
sensorComponentLogTake
({
xcxComponentClick
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video1Channel
.
title
||
''
});
console
.
log
(
'视频1开始播放'
);
this
.
showVideo1Title
=
false
;
// 隐藏标题
this
.
handleVideoPlay
(
'brandVideo1'
);
},
// 视频2播放事件
onVideo2Play
()
{
const
evt
=
{
currentTarget
:
{
dataset
:
{
log
:
{
xcxClick
:
'小程序页面点击事件'
,
pageName
:
'品牌故事-次屏页面'
,
buttonName
:
'视频'
}
}
}
}
md
.
sensorLog
(
evt
);
md
.
sensorComponentLogTake
({
xcxComponentClick
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video2Channel
.
title
||
''
});
console
.
log
(
'视频2开始播放'
);
this
.
showVideo2Title
=
false
;
// 隐藏标题
this
.
handleVideoPlay
(
'brandVideo2'
);
},
// 视频1播放结束事件
onVideo1Ended
()
{
console
.
log
(
'视频1播放结束'
);
this
.
showVideo1Title
=
true
;
// 显示标题
// 恢复展示海报(自动生效,因为video组件播放结束后会显示poster)
if
(
this
.
currentPlayingVideo
===
'brandVideo1'
)
{
this
.
currentPlayingVideo
=
null
;
}
// 重置视频src来进行初始化
const
videoId
=
'brandVideo1'
;
if
(
this
.
videoContexts
[
videoId
])
{
try
{
// 保存原始URL
const
originalUrl
=
this
.
video1Channel
.
videoUrl
;
// 先设置为空字符串来重置
this
.
videoContexts
[
videoId
].
src
=
''
;
// 延迟一小段时间后恢复原始URL,以确保重置生效
setTimeout
(()
=>
{
if
(
this
.
videoContexts
[
videoId
])
{
this
.
videoContexts
[
videoId
].
src
=
originalUrl
.
indexOf
(
'http'
)
===
0
?
originalUrl
:
this
.
$baseUrl
+
originalUrl
;
}
},
100
);
console
.
log
(
'视频1已重置初始化'
);
}
catch
(
error
)
{
console
.
error
(
'重置视频1失败:'
,
error
);
}
}
},
// 视频2播放结束事件
onVideo2Ended
()
{
console
.
log
(
'视频2播放结束'
);
this
.
showVideo2Title
=
true
;
// 显示标题
// 恢复展示海报(自动生效,因为video组件播放结束后会显示poster)
if
(
this
.
currentPlayingVideo
===
'brandVideo2'
)
{
this
.
currentPlayingVideo
=
null
;
}
// 重置视频src来进行初始化
const
videoId
=
'brandVideo2'
;
if
(
this
.
videoContexts
[
videoId
])
{
console
.
warn
(
'视频上下文已存在:'
,
videoId
);
try
{
// 保存原始URL
const
originalUrl
=
this
.
video2Channel
.
videoUrl
;
// 先设置为空字符串来重置
this
.
videoContexts
[
videoId
].
src
=
''
;
// 延迟一小段时间后恢复原始URL,以确保重置生效
// setTimeout(() => {
// if (this.videoContexts[videoId]) {
// this.videoContexts[videoId].src = originalUrl.indexOf('http') === 0 ? originalUrl : this.$baseUrl + originalUrl;
// }
// }, 100);
console
.
log
(
'视频2已重置初始化'
);
}
catch
(
error
)
{
console
.
error
(
'重置视频2失败:'
,
error
);
}
}
},
// 处理视频播放(互斥逻辑)
handleVideoPlay
(
videoId
)
{
console
.
log
(
'处理视频播放:'
,
videoId
,
'当前播放视频:'
,
this
.
currentPlayingVideo
);
// 如果有其他视频正在播放,先暂停它
if
(
this
.
currentPlayingVideo
&&
this
.
currentPlayingVideo
!==
videoId
)
{
console
.
log
(
'暂停其他视频:'
,
this
.
currentPlayingVideo
);
this
.
stopVideo
(
this
.
currentPlayingVideo
);
}
// 设置当前播放的视频
this
.
currentPlayingVideo
=
videoId
;
},
// 处理视频暂停
handleVideoPause
(
videoId
)
{
console
.
log
(
'处理视频暂停:'
,
videoId
,
'当前播放视频:'
,
this
.
currentPlayingVideo
);
// 如果暂停的视频是当前播放的视频,清除播放状态
if
(
this
.
currentPlayingVideo
===
videoId
)
{
this
.
currentPlayingVideo
=
null
;
}
},
// 暂停指定的视频
stopVideo
(
videoId
)
{
console
.
log
(
'尝试暂停视频:'
,
videoId
);
// 如果上下文不存在,尝试创建
if
(
!
this
.
videoContexts
[
videoId
])
{
try
{
this
.
videoContexts
[
videoId
]
=
uni
.
createVideoContext
(
videoId
,
this
);
console
.
log
(
'延迟创建视频上下文:'
,
videoId
);
}
catch
(
error
)
{
console
.
error
(
'延迟创建视频上下文失败:'
,
videoId
,
error
);
return
;
}
}
if
(
this
.
videoContexts
[
videoId
])
{
try
{
this
.
videoContexts
[
videoId
].
pause
();
console
.
log
(
'视频已暂停 (通过上下文):'
,
videoId
);
}
catch
(
error
)
{
console
.
error
(
'暂停视频失败 (通过上下文):'
,
videoId
,
error
);
}
}
},
// 暂停所有视频
stopAllVideos
()
{
console
.
log
(
'暂停所有视频'
);
const
videoIds
=
[
'brandVideo1'
,
'brandVideo2'
];
videoIds
.
forEach
(
id
=>
{
this
.
stopVideo
(
id
);
});
this
.
currentPlayingVideo
=
null
;
},
//跳转微店
// 商品ID
// 10000239356280
// 商品ID
// 10000239570622
}
}
beforeDestroy
()
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
resetAllExposure
();
}
this
.
stopAllVideos
();
},
deactivated
()
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
resetAllExposure
();
}
this
.
stopAllVideos
();
},
props
:
{
scrollTop
:
{
type
:
Number
,
default
:
0
,
},
},
watch
:
{
scrollTop
:
{
handler
(
newVal
)
{
this
.
checkExposure
(
newVal
);
},
},
},
data
()
{
return
{
popType
:
'bottom'
,
swiperList
:
[],
erqiPeizhi
:
{},
indicatorDots
:
false
,
autoplay
:
true
,
interval
:
4000
,
duration
:
500
,
indicatoractiveColor
:
'#a6a0a1'
,
indicatorColor
:
'rgba(255, 255, 255, 1)'
,
channelTabIndex
:
0
,
productTabList
:
[],
productInfoList
:
[],
swiperIconList
:
[],
swiperIndex
:
0
,
ipDesc
:
''
,
esgInfoList
:
[],
qrInfoList
:
[],
qrInfoObj
:
null
,
popupIndex
:
0
,
showVideo
:
false
,
testVideoUrl
:
''
,
channel
:
{},
videoWidth
:
375
,
videoHeight
:
210
,
swiperNameList
:
[
'北纬47°入口'
,
'自有牧场入口'
,
'工厂预约入口'
],
hexiaofeiNameList
:
[
'主要竖屏商品'
,
'主要横屏商品'
,
'视频号'
,
'小红书'
],
exposureTracker
:
null
,
video1Channel
:
{},
video2Channel
:
{},
currentPlayingVideo
:
null
,
// 当前正在播放的视频标识
videoContexts
:
{},
// 存储视频上下文,使用id作为key
ipExStr
:
[
'鹤小飞商品'
,
'鹤小飞商品'
,
'鹤小飞'
,
'鹤小飞'
],
showVideo1Title
:
true
,
// 控制视频1标题显示
showVideo2Title
:
true
,
// 控制视频2标题显示
};
},
mounted
()
{
this
.
initBrandInfo
();
// 初始化视频上下文
this
.
initVideoContexts
();
// 初始化曝光检测工具
this
.
exposureTracker
=
new
ExposureTracker
(
this
);
this
.
exposureTracker
.
addExposureElements
(
EXPOSURE_CONFIGS
);
// 初始检查曝光
this
.
$nextTick
(()
=>
{
this
.
checkExposure
(
this
.
scrollTop
);
});
},
methods
:
{
async
initBrandInfo
()
{
const
{
data
}
=
await
fetchBrandJSON
();
if
(
data
)
{
this
.
swiperList
=
data
.
swiperList
||
[
{
title
:
'默认图'
,
url
:
this
.
$baseUrl
+
'homepage/brandSwiperDefaultBg.png'
,
},
];
this
.
erqiPeizhi
=
data
.
erqiPeizhi
;
this
.
productTabList
=
data
.
productTabList
||
[];
this
.
productInfoList
=
data
.
product
||
[];
this
.
esgInfoList
=
data
.
esgInfoList
[
0
]
||
[];
this
.
qrInfoList
=
data
.
qrInfoList
;
this
.
ipDesc
=
data
.
ipDesc
;
this
.
swiperIconList
=
data
.
swiperIconList
||
[
{
activeUrl
:
this
.
$baseUrl
+
'homepage/brandSwiperDefaultBg.png'
,
baseUrl
:
this
.
$baseUrl
+
'homepage/brandSwiperDefaultBg.png'
,
text
:
'默认图'
,
},
];
this
.
testVideoUrl
=
data
.
videoUrl
;
if
(
data
.
videoUrl
.
indexOf
(
'http'
)
===
-
1
)
{
data
.
videoUrl
=
this
.
$baseUrl
+
data
.
videoUrl
;
}
this
.
currentVideoUrl
=
data
.
videoUrl
;
this
.
video1Channel
=
data
.
video1Channel
;
this
.
video2Channel
=
data
.
video2Channel
;
this
.
initExposure
();
}
},
initExposure
()
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事页banner'
,
componentContent
:
this
.
swiperList
[
0
]?.
title
||
''
,
});
this
.
productTabList
.
forEach
((
item
,
index
)
=>
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'飞鹤产品家族'
,
componentContent
:
'产品家族切换分类-'
+
item
,
});
});
if
(
this
.
productInfoList
.
length
>
0
&&
this
.
productInfoList
[
0
]?.
length
>
0
)
{
this
.
productInfoList
[
0
]?.
forEach
((
item
,
index
)
=>
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'飞鹤产品家族'
,
componentContent
:
'产品家族商品-'
+
item
.
shareTitle
,
});
});
}
this
.
ipExStr
.
forEach
((
item
,
index
)
=>
{
this
.
exposureTracker
.
addExposureElement
({
id
:
'ip'
+
(
index
+
1
),
logParams
:
{
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'鹤小飞'
,
componentContent
:
item
+
'-'
+
this
.
erqiPeizhi
[
'ipTitle'
+
(
index
+
1
)],
},
});
});
this
.
esgInfoList
.
forEach
((
item
,
index
)
=>
{
this
.
exposureTracker
.
addExposureElement
({
id
:
'esg'
+
(
index
+
1
),
logParams
:
{
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'飞鹤ESG'
,
componentContent
:
item
.
desc
,
},
});
});
this
.
exposureTracker
.
addExposureElements
([
{
id
:
'brandVideo1'
,
logParams
:
{
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video1Channel
.
title
||
''
,
},
},
{
id
:
'brandVideo2'
,
logParams
:
{
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video2Channel
.
title
||
''
,
},
},
]);
},
ipTapEvent
(
index
,
evt
)
{
md
.
sensorComponentLogTake
({
xcxComponentClick
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'鹤小飞'
,
componentContent
:
this
.
ipExStr
[
index
]
+
'-'
+
this
.
erqiPeizhi
[
'ipTitle'
+
index
],
});
},
intervalChange
(
e
)
{
this
.
swiperIndex
=
e
.
target
.
current
;
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事页banner'
,
componentContent
:
this
.
swiperList
[
e
.
target
.
current
]?.
title
||
''
,
});
},
jumpSwiper
(
_index
,
evt
)
{
//点indicator切换图片
if
(
evt
)
{
md
.
sensorLog
(
evt
);
}
this
.
swiperIndex
=
_index
;
},
jumpLink
(
_link
,
videoUrl
,
evt
)
{
console
.
log
(
'jumpLink1111111:'
,
_link
,
videoUrl
);
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
}
}
// console.log(_link)
// uni.navigateTo({
// url: "/pages/product/product?id=1-1"
// })
if
(
videoUrl
)
{
// 弹出视频
this
.
currentVideoUrl
=
videoUrl
;
this
.
showVideo
=
true
;
return
;
// 视频弹窗出现后,video标签的autoplay会自动播放
}
else
if
(
_link
)
{
// 其他跳转逻辑
jump
(
_link
);
}
},
jumpProduct
(
item
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
}
}
const
{
productId
,
skuId
,
contentImg
,
contentImgLen
,
shareTitle
,
shareImg
,
title
,
link
,
entrySource
}
=
item
;
const
tabName
=
this
.
productTabList
[
this
.
channelTabIndex
];
if
(
productId
&&
skuId
&&
entrySource
)
{
const
url
=
`subPackages/shopMainProcess/product/index?productId=
${
productId
}
&skuId=
${
skuId
}
&entrySource=
${
entrySource
}
`
;
const
type
=
JumpType
.
MINI
;
const
extra
=
{
appId
:
'wx4205ec55b793245e'
,
//星妈优选小程序
extraData
:
{},
envVersion
:
'release'
,
embedded
:
true
,
};
jump
({
type
:
type
,
url
:
url
,
extra
:
extra
,
});
}
else
{
jump
(
link
);
// console.warn("/pages/product/product?productId=" + productId + "&skuId=" + skuId + "&contentImg=" + contentImg + "&contentImgLen=" + contentImgLen + "&shareTitle=" + shareTitle + "&shareImg=" + shareImg + "&tabName=" + tabName + "&title=" + title)
// uni.navigateTo({
// url: "/pages/product/product?productId=" + productId + "&skuId=" + skuId + "&contentImg=" + contentImg + "&contentImgLen=" + contentImgLen + "&shareTitle=" + shareTitle + "&shareImg=" + shareImg + "&tabName=" + tabName + "&title=" + title
// })
}
},
channelTabHandler
(
_index
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
this
.
productInfoList
[
_index
]?.
forEach
((
item
,
index
)
=>
{
md
.
sensorComponentLogTake
({
xcxComponentExposure
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'飞鹤产品家族'
,
componentContent
:
'产品家族商品-'
+
item
.
shareTitle
,
});
});
}
}
this
.
channelTabIndex
=
_index
;
// 自动滚动到选中的tab
this
.
$nextTick
(()
=>
{
const
scrollView
=
uni
.
createSelectorQuery
().
select
(
'.listbox'
);
if
(
scrollView
)
{
scrollView
.
scrollOffset
((
res
)
=>
{
// 这里可以添加额外的滚动逻辑
})
.
exec
();
}
});
},
showPopup
(
_index
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
}
this
.
popupIndex
=
_index
;
if
(
_index
<
2
)
{
this
.
qrInfoObj
=
this
.
qrInfoList
[
_index
];
md
.
sensorLogTake
({
xcxPage
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
pageName
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
});
}
else
{
this
.
qrInfoObj
=
null
;
md
.
sensorLogTake
({
xcxPage
:
`品牌故事-鹤小飞家族小红书二维码半屏`
,
pageName
:
`品牌故事-鹤小飞家族小红书二维码半屏`
,
});
}
this
.
$refs
.
popup
.
open
(
this
.
popType
);
},
closePop
()
{
this
.
$refs
.
popup
.
close
();
},
downloadHandler
(
imgurl
)
{
md
.
sensorLogTake
({
xcxClick
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
pageName
:
`品牌故事-鹤小飞家族
${
this
.
qrInfoObj
.
title
}
二维码半屏`
,
buttonName
:
`下载二维码`
,
});
uni
.
downloadFile
({
url
:
imgurl
,
success
:
(
downloadRes
)
=>
{
if
(
downloadRes
.
statusCode
===
200
)
{
uni
.
saveImageToPhotosAlbum
({
filePath
:
downloadRes
.
tempFilePath
,
success
:
(
res
)
=>
{
uni
.
showToast
({
title
:
'保存成功'
,
icon
:
'success'
,
});
},
fail
:
(
err
)
=>
{
uni
.
showToast
({
title
:
'保存失败'
,
icon
:
'none'
,
});
},
});
}
else
{
uni
.
showToast
({
title
:
'下载失败'
,
icon
:
'none'
,
});
}
},
fail
:
(
err
)
=>
{
uni
.
showToast
({
title
:
'下载失败'
,
icon
:
'none'
,
});
},
});
},
showVideoHandler
()
{
this
.
currentVideoUrl
=
this
.
testVideoUrl
;
this
.
showVideo
=
true
;
},
closeVideo
()
{
this
.
showVideo
=
false
;
this
.
currentVideoUrl
=
''
;
// 如果弹窗视频是当前播放的视频,清除播放状态
if
(
this
.
currentPlayingVideo
===
'popupVideo'
)
{
this
.
currentPlayingVideo
=
null
;
}
},
openChannel
(
videoChannel
,
evt
)
{
if
(
evt
)
{
md
.
sensorLog
(
evt
);
if
(
evt
.
currentTarget
.
dataset
.
comlog
)
{
md
.
sensorComponentLogTake
(
evt
.
currentTarget
.
dataset
.
comlog
);
}
}
const
finderUserName
=
videoChannel
.
finderUserName
;
const
feedId
=
videoChannel
.
feedId
;
uni
.
openChannelsActivity
({
finderUserName
,
feedId
,
success
:
(
res
)
=>
{
console
.
log
(
'跳转成功'
,
res
);
},
fail
:
(
err
)
=>
{
console
.
log
(
'跳转失败'
,
err
);
},
});
},
previewImage
(
url
)
{
uni
.
previewImage
({
urls
:
[
url
],
// 预览当前图片
current
:
url
,
// 当前显示的图片
});
},
onVideoLoadedMeta
(
e
)
{
const
{
width
,
height
}
=
e
.
detail
;
const
pageWidth
=
uni
.
upx2px
(
750
);
const
ratio
=
height
/
width
;
this
.
videoWidth
=
pageWidth
;
this
.
videoHeight
=
pageWidth
;
// pageWidth * ratio;
},
checkExposure
(
scrollTop
)
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
checkExposure
(
scrollTop
);
}
},
resetExposure
()
{
if
(
this
.
exposureTracker
)
{
this
.
exposureTracker
.
resetAllExposure
();
}
},
// 初始化视频上下文
initVideoContexts
()
{
this
.
$nextTick
(()
=>
{
const
videoIds
=
[
'brandVideo1'
,
'brandVideo2'
];
videoIds
.
forEach
((
id
)
=>
{
try
{
// 使用id创建视频上下文
this
.
videoContexts
[
id
]
=
uni
.
createVideoContext
(
id
,
this
);
console
.
log
(
'视频上下文已创建:'
,
id
);
}
catch
(
error
)
{
console
.
error
(
'创建视频上下文失败:'
,
id
,
error
);
}
});
});
},
onVideoPlay
()
{
console
.
log
(
'视频播放'
);
this
.
handleVideoPlay
(
'brandVideo1'
);
this
.
handleVideoPlay
(
'brandVideo2'
);
},
// 视频1播放事件
onVideo1Play
()
{
const
evt
=
{
currentTarget
:
{
dataset
:
{
log
:
{
xcxClick
:
'品牌故事-次屏页面点击'
,
pageName
:
'品牌故事-首屏页面'
,
buttonName
:
'腰部品牌Video'
,
},
},
},
};
md
.
sensorLog
(
evt
);
md
.
sensorComponentLogTake
({
xcxComponentClick
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video1Channel
.
title
||
''
,
});
console
.
log
(
'视频1开始播放'
);
this
.
showVideo1Title
=
false
;
// 隐藏标题
this
.
handleVideoPlay
(
'brandVideo1'
);
},
// 视频2播放事件
onVideo2Play
()
{
const
evt
=
{
currentTarget
:
{
dataset
:
{
log
:
{
xcxClick
:
'小程序页面点击事件'
,
pageName
:
'品牌故事-次屏页面'
,
buttonName
:
'视频'
,
},
},
},
};
md
.
sensorLog
(
evt
);
md
.
sensorComponentLogTake
({
xcxComponentClick
:
'true'
,
pageName
:
'品牌故事页'
,
componentName
:
'品牌故事视频'
,
componentContent
:
this
.
video2Channel
.
title
||
''
,
});
console
.
log
(
'视频2开始播放'
);
this
.
showVideo2Title
=
false
;
// 隐藏标题
this
.
handleVideoPlay
(
'brandVideo2'
);
},
// 视频1播放结束事件
onVideo1Ended
()
{
console
.
log
(
'视频1播放结束'
);
this
.
showVideo1Title
=
true
;
// 显示标题
// 恢复展示海报(自动生效,因为video组件播放结束后会显示poster)
if
(
this
.
currentPlayingVideo
===
'brandVideo1'
)
{
this
.
currentPlayingVideo
=
null
;
}
// 重置视频src来进行初始化
const
videoId
=
'brandVideo1'
;
if
(
this
.
videoContexts
[
videoId
])
{
try
{
// 保存原始URL
const
originalUrl
=
this
.
video1Channel
.
videoUrl
;
// 先设置为空字符串来重置
this
.
videoContexts
[
videoId
].
src
=
''
;
// 延迟一小段时间后恢复原始URL,以确保重置生效
setTimeout
(()
=>
{
if
(
this
.
videoContexts
[
videoId
])
{
this
.
videoContexts
[
videoId
].
src
=
originalUrl
.
indexOf
(
'http'
)
===
0
?
originalUrl
:
this
.
$baseUrl
+
originalUrl
;
}
},
100
);
console
.
log
(
'视频1已重置初始化'
);
}
catch
(
error
)
{
console
.
error
(
'重置视频1失败:'
,
error
);
}
}
},
// 视频2播放结束事件
onVideo2Ended
()
{
console
.
log
(
'视频2播放结束'
);
this
.
showVideo2Title
=
true
;
// 显示标题
// 恢复展示海报(自动生效,因为video组件播放结束后会显示poster)
if
(
this
.
currentPlayingVideo
===
'brandVideo2'
)
{
this
.
currentPlayingVideo
=
null
;
}
// 重置视频src来进行初始化
const
videoId
=
'brandVideo2'
;
if
(
this
.
videoContexts
[
videoId
])
{
console
.
warn
(
'视频上下文已存在:'
,
videoId
);
try
{
// 保存原始URL
const
originalUrl
=
this
.
video2Channel
.
videoUrl
;
// 先设置为空字符串来重置
this
.
videoContexts
[
videoId
].
src
=
''
;
// 延迟一小段时间后恢复原始URL,以确保重置生效
// setTimeout(() => {
// if (this.videoContexts[videoId]) {
// this.videoContexts[videoId].src = originalUrl.indexOf('http') === 0 ? originalUrl : this.$baseUrl + originalUrl;
// }
// }, 100);
console
.
log
(
'视频2已重置初始化'
);
}
catch
(
error
)
{
console
.
error
(
'重置视频2失败:'
,
error
);
}
}
},
// 处理视频播放(互斥逻辑)
handleVideoPlay
(
videoId
)
{
console
.
log
(
'处理视频播放:'
,
videoId
,
'当前播放视频:'
,
this
.
currentPlayingVideo
);
// 如果有其他视频正在播放,先暂停它
if
(
this
.
currentPlayingVideo
&&
this
.
currentPlayingVideo
!==
videoId
)
{
console
.
log
(
'暂停其他视频:'
,
this
.
currentPlayingVideo
);
this
.
stopVideo
(
this
.
currentPlayingVideo
);
}
// 设置当前播放的视频
this
.
currentPlayingVideo
=
videoId
;
},
// 处理视频暂停
handleVideoPause
(
videoId
)
{
console
.
log
(
'处理视频暂停:'
,
videoId
,
'当前播放视频:'
,
this
.
currentPlayingVideo
);
// 如果暂停的视频是当前播放的视频,清除播放状态
if
(
this
.
currentPlayingVideo
===
videoId
)
{
this
.
currentPlayingVideo
=
null
;
}
},
// 暂停指定的视频
stopVideo
(
videoId
)
{
console
.
log
(
'尝试暂停视频:'
,
videoId
);
// 如果上下文不存在,尝试创建
if
(
!
this
.
videoContexts
[
videoId
])
{
try
{
this
.
videoContexts
[
videoId
]
=
uni
.
createVideoContext
(
videoId
,
this
);
console
.
log
(
'延迟创建视频上下文:'
,
videoId
);
}
catch
(
error
)
{
console
.
error
(
'延迟创建视频上下文失败:'
,
videoId
,
error
);
return
;
}
}
if
(
this
.
videoContexts
[
videoId
])
{
try
{
this
.
videoContexts
[
videoId
].
pause
();
console
.
log
(
'视频已暂停 (通过上下文):'
,
videoId
);
}
catch
(
error
)
{
console
.
error
(
'暂停视频失败 (通过上下文):'
,
videoId
,
error
);
}
}
},
// 暂停所有视频
stopAllVideos
()
{
console
.
log
(
'暂停所有视频'
);
const
videoIds
=
[
'brandVideo1'
,
'brandVideo2'
];
videoIds
.
forEach
((
id
)
=>
{
this
.
stopVideo
(
id
);
});
this
.
currentPlayingVideo
=
null
;
},
//跳转微店
// 商品ID
// 10000239356280
// 商品ID
// 10000239570622
},
};
</
script
>
<
style
lang=
"less"
scoped
>
@import '@/common.less';
.brand-container {
background-color: #fff;
.content {
padding-bottom: 200rpx;
.banner {
height: 1250rpx;
.banneritem {
width: 750rpx;
height: 1250rpx;
.b-img {
width: 100%;
height: 100%;
}
}
}
.swiperbox {
position: absolute;
top: 1002rpx;
width: 196rpx;
left: 50%;
transform: translateX(-50%);
.iconbox {
width: 100%;
display: flex;
justify-content: space-between;
position: relative;
.icon {
width: 200rpx;
height: 200rpx;
}
.indicatorDotsBg {
position: absolute;
width: 196rpx;
height: 77rpx;
}
.indicatorDots {
// margin-left: 19rpx;
margin-top: 21rpx;
display: flex;
align-items: center;
justify-content: center;
width: 196rpx;
height: 10rpx;
position: relative;
.dot {
// transition: all 0.3s ease;
cursor: pointer;
}
.dot-active {
width: 26rpx;
height: 10rpx;
border-radius: 5rpx;
background-color: #ffffff;
margin-right: 5rpx;
margin-left: 5rpx;
}
.dot-normal {
width: 10rpx;
height: 10rpx;
border-radius: 5rpx;
margin-right: 5rpx;
margin-left: 5rpx;
background-color: rgba(255, 255, 255, 0.6);
}
.dotText {
margin-top: 56rpx;
position: absolute;
font-size: 17rpx;
color: #fff;
text-align: center;
font-weight: bold;
width: 196rpx;
// top: 50%;
// transform: translateY(-50%);
pointer-events: none;
}
}
}
}
.swiper-mask {
position: absolute;
left: 0;
width: 750rpx;
height: 192rpx;
z-index: 1;
top: 1061rpx;
pointer-events: none;
.swiper-mask-img {
width: 100%;
height: 100%;
}
}
.videoposterbox {
width: 640rpx;
height: 360rpx;
margin-left: 55rpx;
margin-top: 32rpx;
overflow: hidden;
border-radius: 24rpx;
.videoposter {
width: 100%;
height: 100%;
border-radius: 24rpx;
object-fit: cover;
}
.videoposterboxtitle {
font-size: 28rpx;
color: #ffffff;
font-weight: 500;
margin-left: 20rpx;
line-height: 1.4;
margin-top: -56rpx;
z-index: 0;
position: relative;
// padding: 8rpx 16rpx;
// background-color: rgba(0, 0, 0, 0.5);
border-radius: 8rpx;
width: 476rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.productcontai {
margin-top: 32rpx;
margin-left: 32rpx;
.maintitle {
color: @color-black-deep;
font-size: 38rpx;
font-weight: bold;
display: block;
margin-left: 5rpx;
}
.subtitle {
color: @color-black-deep;
font-size: 24rpx;
margin-top: 10rpx;
margin-left: 5rpx;
}
.listbox {
margin-top: 15rpx;
width: 686rpx;
white-space: nowrap;
.tab-container {
display: flex;
align-items: center;
padding: 0 20rpx;
min-width: 100%;
.tabitem {
color: @color-black-deep;
background-color: #e9edf1;
padding: 15rpx 20rpx;
font-size: 22rpx;
margin-right: 15rpx;
border-radius: 30rpx;
flex-shrink: 0;
white-space: nowrap;
transition: all 0.3s ease;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&:active {
transform: scale(0.95);
}
}
.tabActive {
color: white;
background-color: @color-gold-main;
box-shadow: 0 2rpx 8rpx rgba(211, 163, 88, 0.3);
}
}
}
.productbox {
width: 686rpx;
height: 545rpx;
overflow-x: auto;
margin-top: 30rpx;
.product-grid {
display: flex;
flex-direction: column;
height: 100%;
width: max-content;
.product-row {
display: flex;
flex-direction: row;
height: 50%;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.infobox {
margin-right: 20rpx;
flex-shrink: 0;
&:last-child {
margin-right: 0;
}
}
}
}
.infobox {
width: 273rpx;
height: 263rpx;
background-color: white;
border-radius: 24rpx;
// margin-top: 32rpx;
.flexbox {
display: flex;
margin-top: 25rpx;
align-items: center;
justify-content: center;
.infotitle {
font-size: 36rpx;
font-weight: 400;
width: 100rpx;
color: @color-black-deep;
margin-left: 15rpx; //一点偏移量
text-align: center;
}
.infoimg {
width: 150rpx;
height: 150rpx;
}
}
.infodesc {
display: flex;
justify-content: center;
align-items: center;
font-size: 24rpx;
color: @color-black-deep;
width: 273rpx;
text-align: center;
height: 90rpx;
white-space: pre-wrap;
}
}
}
}
.ipbox {
width: 674rpx;
height: 922rpx;
position: relative;
left: 36rpx;
border-radius: 24rpx;
background-color: white;
top: 50rpx;
.iphexiaofei {
width: 374rpx;
height: 298rpx;
position: absolute;
top: 15rpx;
left: 165rpx;
}
.ipcard {
position: absolute;
padding: 15rpx;
top: 313rpx;
.title {
display: flex;
font-size: 36rpx;
color: @color-black-deep;
font-weight: bold;
.t1 {
color: @color-black-deep;
}
}
.desc {
margin-top: 20rpx;
white-space: pre-wrap;
font-size: 24rpx;
color: @color-black-deep;
}
.ipflex {
display: flex;
justify-content: space-between;
margin-top: 30rpx;
.ipbg {
border-radius: 24rpx;
background-color: @color-gray-light;
display: flex;
justify-content: center;
align-items: center;
}
.ip1 {
width: 288rpx;
height: 380rpx;
overflow: hidden;
image {
width: 288*0.8rpx;
height: 380*0.8rpx;
}
}
.ip2 {
width: 342rpx;
height: 201rpx;
image {
width: 342*0.75rpx;
height: 201*0.75rpx;
}
}
.ip3 {
width: 160rpx;
height: 160rpx;
image {
width: 70rpx;
height: 97rpx;
}
}
.ip4 {
width: 160rpx;
height: 160rpx;
image {
width: 88rpx;
height: 92rpx;
}
}
}
}
}
.esgbox {
margin-top: 128rpx;
margin-left: 32rpx;
.maintitle {
color: @color-black-deep;
font-size: 38rpx;
font-weight: bold;
display: block;
margin-left: 5rpx;
}
.subtitle {
color: @color-black-deep;
font-size: 24rpx;
margin-top: 10rpx;
margin-left: 5rpx;
}
.listbox {
display: flex;
margin-top: 10rpx;
.tabitem {
color: @color-black-deep;
background-color: #e9edf1;
padding: 15rpx;
font-size: 22rpx;
margin-right: 15rpx;
border-radius: 30rpx;
}
.tabActive {
color: white;
background-color: @color-gold-main;
}
}
.channelscroll {
width: 718rpx;
overflow-x: scroll;
margin-top: 32rpx;
// margin-left: -32rpx;
.box {
display: flex;
.infobox {
margin-left: 0rpx;
margin-right: 30rpx;
width: 503rpx;
height: 638rpx;
.infoimg {
width: 500rpx;
height: 400rpx;
}
.imgRaduis {
border-radius: 24rpx 24rpx 0 0;
}
.infotitle {
color: @color-gold-main;
font-size: 32rpx;
text-align: left;
font-weight: bold;
margin-top: 10rpx;
margin-left: 20rpx;
}
.infodesc {
font-size: 24rpx;
color: black;
margin-top: 10rpx;
padding-right: 40rpx;
margin-left: 20rpx;
}
}
}
}
}
}
.popup-content {
width: 750rpx;
height: 812rpx;
border-top-left-radius: 48rpx;
border-top-right-radius: 48rpx;
position: relative;
.btnclose {
width: 70rpx;
height: 70rpx;
position: absolute;
top: 36rpx;
right: 32rpx;
}
.xingmahui {
width: 750rpx;
height: 100%;
position: absolute;
bottom: 0;
}
.title {
position: absolute;
top: 47rpx;
left: 32rpx;
font-size: 36rpx;
color: @color-black-deep;
font-weight: bold;
}
.desc {
position: absolute;
top: 108rpx;
left: 32rpx;
font-size: 28rpx;
color: @color-black-medium;
font-weight: bold;
}
.qrcode {
width: 340rpx;
height: 340rpx;
position: absolute;
top: 220rpx;
left: 205rpx;
}
.btndownload {
width: 286rpx;
height: 89rpx;
position: absolute;
top: 630rpx;
left: 232rpx;
}
}
.video-popup {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 9999;
}
.close-btn-bottom {
margin: 32rpx auto 0 auto;
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-size: 44rpx;
line-height: 64rpx;
text-align: center;
z-index: 10001;
display: flex;
align-items: center;
justify-content: center;
}
background-color: #fff;
.content {
padding-bottom: 200rpx;
.banner {
height: 1250rpx;
.banneritem {
width: 750rpx;
height: 1250rpx;
.b-img {
width: 100%;
height: 100%;
}
}
}
.swiperbox {
position: absolute;
top: 1002rpx;
width: 196rpx;
left: 50%;
transform: translateX(-50%);
.iconbox {
width: 100%;
display: flex;
justify-content: space-between;
position: relative;
.icon {
width: 200rpx;
height: 200rpx;
}
.indicatorDotsBg {
position: absolute;
width: 196rpx;
height: 77rpx;
}
.indicatorDots {
// margin-left: 19rpx;
margin-top: 21rpx;
display: flex;
align-items: center;
justify-content: center;
width: 196rpx;
height: 10rpx;
position: relative;
.dot {
// transition: all 0.3s ease;
cursor: pointer;
}
.dot-active {
width: 26rpx;
height: 10rpx;
border-radius: 5rpx;
background-color: #ffffff;
margin-right: 5rpx;
margin-left: 5rpx;
}
.dot-normal {
width: 10rpx;
height: 10rpx;
border-radius: 5rpx;
margin-right: 5rpx;
margin-left: 5rpx;
background-color: rgba(255, 255, 255, 0.6);
}
.dotText {
margin-top: 56rpx;
position: absolute;
font-size: 17rpx;
color: #fff;
text-align: center;
font-weight: bold;
width: 196rpx;
// top: 50%;
// transform: translateY(-50%);
pointer-events: none;
}
}
}
}
.swiper-mask {
position: absolute;
left: 0;
width: 750rpx;
height: 192rpx;
z-index: 1;
top: 1061rpx;
pointer-events: none;
.swiper-mask-img {
width: 100%;
height: 100%;
}
}
.videoposterbox {
width: 640rpx;
height: 360rpx;
margin-left: 55rpx;
margin-top: 32rpx;
overflow: hidden;
border-radius: 24rpx;
.videoposter {
width: 100%;
height: 100%;
border-radius: 24rpx;
object-fit: cover;
}
.videoposterboxtitle {
font-size: 28rpx;
color: #ffffff;
font-weight: 500;
margin-left: 20rpx;
line-height: 1.4;
margin-top: -56rpx;
z-index: 0;
position: relative;
// padding: 8rpx 16rpx;
// background-color: rgba(0, 0, 0, 0.5);
border-radius: 8rpx;
width: 476rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.productcontai {
margin-top: 32rpx;
margin-left: 32rpx;
.maintitle {
color: @color-black-deep;
font-size: 38rpx;
font-weight: bold;
display: block;
margin-left: 5rpx;
}
.subtitle {
color: @color-black-deep;
font-size: 24rpx;
margin-top: 10rpx;
margin-left: 5rpx;
}
.listbox {
margin-top: 15rpx;
width: 686rpx;
white-space: nowrap;
.tab-container {
display: flex;
align-items: center;
padding: 0 20rpx;
min-width: 100%;
.tabitem {
color: @color-black-deep;
background-color: #e9edf1;
padding: 15rpx 20rpx;
font-size: 22rpx;
margin-right: 15rpx;
border-radius: 30rpx;
flex-shrink: 0;
white-space: nowrap;
transition: all 0.3s ease;
cursor: pointer;
&:last-child {
margin-right: 0;
}
&:active {
transform: scale(0.95);
}
}
.tabActive {
color: white;
background-color: @color-gold-main;
box-shadow: 0 2rpx 8rpx rgba(211, 163, 88, 0.3);
}
}
}
.productbox {
width: 686rpx;
height: 545rpx;
overflow-x: auto;
margin-top: 30rpx;
.product-grid {
display: flex;
flex-direction: column;
height: 100%;
width: max-content;
.product-row {
display: flex;
flex-direction: row;
height: 50%;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.infobox {
margin-right: 20rpx;
flex-shrink: 0;
&:last-child {
margin-right: 0;
}
}
}
}
.infobox {
width: 273rpx;
height: 263rpx;
background-color: white;
border-radius: 24rpx;
// margin-top: 32rpx;
.flexbox {
display: flex;
margin-top: 25rpx;
align-items: center;
justify-content: center;
.infotitle {
font-size: 36rpx;
font-weight: 400;
width: 100rpx;
color: @color-black-deep;
margin-left: 15rpx; //一点偏移量
text-align: center;
}
.infoimg {
width: 150rpx;
height: 150rpx;
}
}
.infodesc {
display: flex;
justify-content: center;
align-items: center;
font-size: 24rpx;
color: @color-black-deep;
width: 273rpx;
text-align: center;
height: 90rpx;
white-space: pre-wrap;
}
}
}
}
.ipbox {
width: 674rpx;
height: 922rpx;
position: relative;
left: 36rpx;
border-radius: 24rpx;
background-color: white;
top: 50rpx;
.iphexiaofei {
width: 374rpx;
height: 298rpx;
position: absolute;
top: 15rpx;
left: 165rpx;
}
.ipcard {
position: absolute;
padding: 15rpx;
top: 313rpx;
.title {
display: flex;
font-size: 36rpx;
color: @color-black-deep;
font-weight: bold;
.t1 {
color: @color-black-deep;
}
}
.desc {
margin-top: 20rpx;
white-space: pre-wrap;
font-size: 24rpx;
color: @color-black-deep;
}
.ipcontainer {
position: relative;
image,.ipcontext {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
}
.ipflex {
display: flex;
justify-content: space-between;
margin-top: 30rpx;
.ipbg {
border-radius: 24rpx;
background-color: @color-gray-light;
display: flex;
justify-content: center;
align-items: center;
}
.ip1 {
width: 288rpx;
height: 380rpx;
overflow: hidden;
.ipcontainer{
width: 288 * 0.8rpx;
height: 380 * 0.8rpx;
}
image {
width: 288 * 0.8rpx;
height: 380 * 0.8rpx;
}
}
.ip2 {
width: 342rpx;
height: 201rpx;
.ipcontainer{
width: 342 * 0.75rpx;
height: 201 * 0.75rpx;
}
image {
width: 342 * 0.75rpx;
height: 201 * 0.75rpx;
}
}
.ip3 {
width: 160rpx;
height: 160rpx;
image {
width: 70rpx;
height: 97rpx;
}
}
.ip4 {
width: 160rpx;
height: 160rpx;
image {
width: 88rpx;
height: 92rpx;
}
}
}
}
}
.esgbox {
margin-top: 128rpx;
margin-left: 32rpx;
.maintitle {
color: @color-black-deep;
font-size: 38rpx;
font-weight: bold;
display: block;
margin-left: 5rpx;
}
.subtitle {
color: @color-black-deep;
font-size: 24rpx;
margin-top: 10rpx;
margin-left: 5rpx;
}
.listbox {
display: flex;
margin-top: 10rpx;
.tabitem {
color: @color-black-deep;
background-color: #e9edf1;
padding: 15rpx;
font-size: 22rpx;
margin-right: 15rpx;
border-radius: 30rpx;
}
.tabActive {
color: white;
background-color: @color-gold-main;
}
}
.channelscroll {
width: 718rpx;
overflow-x: scroll;
margin-top: 32rpx;
// margin-left: -32rpx;
.box {
display: flex;
.infobox {
margin-left: 0rpx;
margin-right: 30rpx;
width: 503rpx;
height: 638rpx;
.infoimg {
width: 500rpx;
height: 400rpx;
}
.imgRaduis {
border-radius: 24rpx 24rpx 0 0;
}
.infotitle {
color: @color-gold-main;
font-size: 32rpx;
text-align: left;
font-weight: bold;
margin-top: 10rpx;
margin-left: 20rpx;
}
.infodesc {
font-size: 24rpx;
color: black;
margin-top: 10rpx;
padding-right: 40rpx;
margin-left: 20rpx;
}
}
}
}
}
}
.popup-content {
width: 750rpx;
height: 812rpx;
border-top-left-radius: 48rpx;
border-top-right-radius: 48rpx;
position: relative;
.btnclose {
width: 70rpx;
height: 70rpx;
position: absolute;
top: 36rpx;
right: 32rpx;
}
.xingmahui {
width: 750rpx;
height: 100%;
position: absolute;
bottom: 0;
}
.title {
position: absolute;
top: 47rpx;
left: 32rpx;
font-size: 36rpx;
color: @color-black-deep;
font-weight: bold;
}
.desc {
position: absolute;
top: 108rpx;
left: 32rpx;
font-size: 28rpx;
color: @color-black-medium;
font-weight: bold;
}
.qrcode {
width: 340rpx;
height: 340rpx;
position: absolute;
top: 220rpx;
left: 205rpx;
}
.btndownload {
width: 286rpx;
height: 89rpx;
position: absolute;
top: 630rpx;
left: 232rpx;
}
}
.video-popup {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 9999;
}
.close-btn-bottom {
margin: 32rpx auto 0 auto;
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: rgba(0, 0, 0, 0.5);
color: #fff;
font-size: 44rpx;
line-height: 64rpx;
text-align: center;
z-index: 10001;
display: flex;
align-items: center;
justify-content: center;
}
}
</
style
>
\ No newline at end of file
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment