chore(组件:微信视频号): 支持选择显示轮播图模式

This commit is contained in:
2026-01-15 11:36:34 +08:00
parent febf614e13
commit b195da84dd
3 changed files with 186 additions and 17 deletions

View File

@@ -156,6 +156,72 @@
font-size: 14px;
}
/* 轮播样式 */
.wechat_channel-box .video-carousel-wrap {
position: relative;
width: 100%;
overflow: hidden;
}
.wechat_channel-box .video-carousel {
position: relative;
width: 100%;
overflow: hidden;
}
.wechat_channel-box .carousel-item {
position: absolute;
top: 0;
left: 0;
width: 100%;
opacity: 0;
transition: opacity 0.5s ease-in-out;
z-index: 1;
}
.wechat_channel-box .carousel-item.active {
position: relative;
opacity: 1;
z-index: 2;
}
.wechat_channel-box .carousel-indicators {
position: relative;
margin-top: 8px;
margin-bottom: 8px;
margin-left: auto;
margin-right: auto;
width: fit-content;
display: flex;
gap: 8px;
z-index: 10;
}
.wechat_channel-box .carousel-indicators .indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.5);
cursor: pointer;
transition: background-color 0.3s ease;
}
.wechat_channel-box .carousel-indicators .indicator.active {
background-color: #000000;
transform: scale(1.2);
}
/* 轮播模式下的视频项样式 */
.wechat_channel-box .video-carousel-wrap .video-item {
width: 100%;
max-width: 100%;
}
/* 轮播模式下的通道预览样式 */
.wechat_channel-box .video-carousel-wrap .channel-preview {
width: 100%;
}
/* 16:9比例下的固定高度 */
/* 一行显示1个 */
.wechat_channel-box[data-ratio="16:9"] {

View File

@@ -2,7 +2,55 @@
<!-- 预览 -->
<template slot="preview" >
<div class="video-list-wrap" :style="{ '--row-count': nc.rowCount || 2 }">
<!-- 轮播模式 -->
<div v-if="nc.showStyle == 'carousel'" class="video-carousel-wrap" :style="{ '--row-count': nc.rowCount || 2 }">
<div class="video-carousel">
<div v-for="(itemGroup, groupIdx) in nc.groupedList" :key="groupIdx" class="carousel-item" :class="{ active: nc.currentSlide == groupIdx }">
<div class="video-list" :style="{ '--row-count': nc.rowCount || 2 }">
<div v-for="(item, idx) in itemGroup" :key="idx" class="video-item">
<div class="channel-preview" v-if="item.coverUrl" :style="{
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0) }">
<img :src="changeImgUrl(item.coverUrl)" style="width:100%;display:block;" mode="aspectFill"/>
<div v-if="nc.showPlayBtn" class="play-btn"></div>
<div class="channel-info" v-if="item.finderUserName || item.videoTitle">
<div class="channel-avatar" v-if="item.avatarUrl">
<img :src="changeImgUrl(item.avatarUrl)" mode="aspectFill"/>
</div>
<div class="channel-text">
<!-- <div class="channel-name" v-if="item.finderUserName">{{ item.finderUserName }}</div> -->
<div class="video-title" :class="'title-max-lines-' + (nc.titleLineClamp || 1)">{{ item.videoTitle || '视频标题' }}</div>
</div>
</div>
<div class="view-count" v-if="item.showViewCount">{{ item.viewCount }}次观看</div>
</div>
<div class="video-placeholder" v-else :style="{
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0) }">
<div class="placeholder-text">请配置视频号信息</div>
</div>
</div>
</div>
</div>
</div>
<div v-if="nc.groupedList && nc.groupedList.length > 0" class="carousel-indicators">
<span v-for="(itemGroup, groupIdx) in nc.groupedList" :key="groupIdx" class="indicator" :class="{ active: nc.currentSlide == groupIdx }" @click="nc.currentSlide = groupIdx"></span>
</div>
<div v-else class="video-placeholder" :style="{
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0) }">
<div class="placeholder-text">请添加视频号</div>
</div>
</div>
<!-- 非轮播模式 -->
<div v-else class="video-list-wrap" :style="{ '--row-count': nc.rowCount || 2 }">
<div v-if="nc.list && nc.list.length > 0" class="video-list">
<div v-for="(item, idx) in nc.list" :key="idx" class="video-item">
<div class="channel-preview" v-if="item.coverUrl" :style="{

View File

@@ -20,8 +20,11 @@ Vue.component("wechat_channel-edit", {
<div class="layui-form-item">
<label class="layui-form-label sm">显示风格</label>
<div class="layui-input-block">
<input type="radio" name="show_style" lay-filter="showStyle" value="fixed" title="固定高度" :checked="data.showStyle == 'fixed' || !data.showStyle">
<input type="radio" name="show_style" lay-filter="showStyle" value="auto" title="自适应高度" :checked="data.showStyle == 'auto'">
<select name="show_style" lay-filter="showStyle" v-model="data.showStyle">
<option value="carousel" :selected="data.showStyle == 'carousel'">轮播</option>
<option value="fixed" :selected="data.showStyle == 'fixed'">固定</option>
<option value="auto" :selected="data.showStyle == 'singleSlide'">单页</option>
</select>
</div>
</div>
@@ -189,6 +192,8 @@ Vue.component("wechat_channel-edit", {
data: this.$parent.data
};
},
created: function () {
if (!this.$parent.data.verify) this.$parent.data.verify = [];
this.$parent.data.verify.push(this.verify);//加载验证方法
@@ -224,6 +229,14 @@ Vue.component("wechat_channel-edit", {
this.data.showPlayBtn = true;
}
// 初始化轮播幻灯片索引
if (this.data.currentSlide === undefined) {
this.data.currentSlide = 0;
}
// 初始化分组列表
this.updateGroupedList();
// 初始化列表项
this.data.list.forEach((item, index) => {
if (!item.avatarImageType) {
@@ -302,13 +315,20 @@ Vue.component("wechat_channel-edit", {
form.on('select(rowCount)', (data) => {
const count = parseInt(data.value);
this.data.rowCount = count;
// 更新分组列表
this.updateGroupedList();
// 重新初始化轮播功能确保根据新的rowCount重新分组
this.initCarousel();
});
// 显示风格切换
form.on('radio(showStyle)', (data) => {
const elem = data.elem;
const style = elem.value;
form.on('select(showStyle)', (data) => {
const style = data.value;
this.data.showStyle = style;
// 更新分组列表
this.updateGroupedList();
// 重新初始化轮播功能
this.initCarousel();
});
// 显示播放按钮切换
@@ -336,6 +356,9 @@ Vue.component("wechat_channel-edit", {
// 初始化拖拽排序
this.initSortable();
// 初始化轮播自动切换
this.initCarousel();
},
methods: {
verify: function () {
@@ -503,6 +526,38 @@ Vue.component("wechat_channel-edit", {
};
document.head.appendChild(script);
}
},
// 更新分组列表
updateGroupedList: function () {
const list = this.data.list || [];
const rowCount = this.data.rowCount || 2;
const groups = [];
for (let i = 0; i < list.length; i += rowCount) {
groups.push(list.slice(i, i + rowCount));
}
this.data.groupedList = groups;
console.log("groupedList", this.data.groupedList);
},
// 初始化轮播自动切换
initCarousel: function () {
// 清除现有的轮播定时器
if (this.carouselTimer) {
clearInterval(this.carouselTimer);
}
// 更新分组列表
this.updateGroupedList();
// 只有当显示风格为carousel且有多个分组时才启动轮播
if (this.data.showStyle === 'carousel' && this.data.groupedList && this.data.groupedList.length > 1) {
this.carouselTimer = setInterval(() => {
this.data.currentSlide = (this.data.currentSlide + 1) % this.data.groupedList.length;
}, 3000); // 每3秒切换一次
}
}
},
});