@@ -1,5 +1,5 @@
< template >
< view : style = "[componentStyle, { '--row-count': value.rowCount }]" >
< view class = "channel-list-container" : style = "[componentStyle, { '--row-count': value.rowCount }]" >
<!-- 轮播模式 -- >
< swiper v-if = "value.showStyle == 'carousel' && carouselConfig.type != 'hide'" :indicator-dots="isIndicatorDots"
: autoplay = "carouselConfig.autoplay || false" : interval = "carouselConfig.interval || 3000"
@@ -11,8 +11,8 @@
< ! - - 视频号视频卡片 , 轮播模式 - - >
< diy-channel-video :value = "item" @ video -play = " playVideo " :list-mode = "true"
:title-line-clamp = "value.titleLineClamp" :show-play-btn = "value.showPlayBtn"
:cover-style = "computedCoverStyle" :play-btn-style = "value.playBtn Style"
:aspect-ratio = "value.aspectRatio" / >
:show-view-count = "value.showViewCount" : cover-style = "computedCoverStyle"
:play-btn-style = "value.playBtnStyle" : aspect-ratio = "value.aspectRatio" / >
< / view >
< / view >
< / swiper-item >
@@ -24,22 +24,26 @@
< ! - - 视频号视频卡片 , 列表模式 - - >
< diy-channel-video :value = "item" @ video -play = " playVideo " :list-mode = "true"
:title-line-clamp = "value.titleLineClamp" :show-play-btn = "value.showPlayBtn"
:cover-style = "computedCoverStyle" :play-btn-style = "value.playBtn Style"
:aspect-ratio = "value.aspectRatio" / >
:show-view-count = "value.showViewCount" : cover-style = "computedCoverStyle"
:play-btn-style = "value.playBtnStyle" : aspect-ratio = "value.aspectRatio" / >
< / view >
< / view >
<!-- 其他布局模式 ( 如滚动布局 ) -- >
< scroll-view v-else
: class = "['channel-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle , 'row1-of' + value.rowCount]"
: scroll -x =" value.showStyle = = ' singleSlide ' " >
: class = "['channel-nav', value.showStyle == 'fixed' ? 'fixed-layout' : 'singleSlide' , 'row1-of' + value.rowCount]"
: scroll-x ="true"
:scroll-y = "false"
:enhanced = "true"
:bounces = "false" >
< view class = "uni-scroll-view-content" >
< view v-for = "(item, index) in value.list" :key="index" :class="['channel-nav-item', value.mode]" >
< view v-for = "(item, index) in value.list" :key="index"
: class = "['channel-nav-item', value.mode, 'row1-of' + value.rowCount]" >
<!-- 视频号视频卡片 , 滚动模式 -- >
< diy-channel-video :value = "item" @ video -play = " playVideo " :list-mode = "true"
:title-line-clamp = "value.titleLineClamp" :show-play-btn = "value.showPlayBtn"
:cover-style = "computedCoverStyle" :play-btn-style = "value.playBtn Style"
:aspect-ratio = "value.aspectRatio" / >
:show-view-count = "value.showViewCount" : cover-style = "computedCoverStyle"
:play-btn-style = "value.playBtnStyle" : aspect-ratio = "value.aspectRatio" / >
< / view >
< / view >
< / scroll-view >
@@ -71,6 +75,7 @@ export default {
* @property {number} topAroundRadius - 顶部圆角半径
* @property {number} bottomAroundRadius - 底部圆角半径
* @property {Object} ornament - 装饰效果配置
* @property {boolean} showViewCount - 是否显示播放量, 可选值: true, false
* @property {number} titleLineClamp - 标题显示行数
* @property {string} aspectRatio - 视频比例, 可选值: 16:9, 3:4
* @property {boolean} showPlayBtn - 是否显示播放按钮
@@ -103,6 +108,14 @@ export default {
// 组件创建时的逻辑
// 可以在这里进行初始化操作,如获取页面宽度等
} ,
mounted ( ) {
// 组件挂载后添加鼠标拖拽滚动功能
if ( ! [ 'fixed' , 'carousel' ] . includes ( this . value ? . showStyle ) ) {
this . $nextTick ( ( ) => {
this . addMouseDragScroll ( ) ;
} ) ;
}
} ,
watch : {
/**
* 组件刷新监听
@@ -130,24 +143,24 @@ export default {
* @returns {string} 样式字符串
*/
componentStyle ( ) {
le t style = '' ;
cons t style = { } ;
// 背景色
if ( this . value ? . componentBgColor ) {
style += ' background-c olor:' + this . value ? . componentBgColor + ';' ;
style . backgroundC olor = this . value ? . componentBgColor ;
}
// 圆角样式
if ( this . value ? . componentAngle == 'round' ) {
style += 'border-top-l eft-r adius:' + ( 2 * this . value ? . topAroundRadius ) + 'rpx; ' ;
style += 'border-top-r ight-r adius:' + ( 2 * this . value ? . topAroundRadius ) + 'rpx; ' ;
style += ' border-b ottom-l eft-r adius:' + ( 2 * this . value ? . bottomAroundRadius ) + 'rpx; ' ;
style += ' border-b ottom-r ight-r adius:' + ( 2 * this . value ? . bottomAroundRadius ) + 'rpx; ' ;
style . borderTopL eftR adius = ( 2 * this . value ? . topAroundRadius ) + 'rpx' ;
style . borderTopR ightR adius = ( 2 * this . value ? . topAroundRadius ) + 'rpx' ;
style . borderB ottomL eftR adius = ( 2 * this . value ? . bottomAroundRadius ) + 'rpx' ;
style . borderB ottomR ightR adius = ( 2 * this . value ? . bottomAroundRadius ) + 'rpx' ;
}
// 装饰效果:阴影
style += ' box-s hadow:' + ( this . value ? . ornament ? . type == 'shadow' ? '0 0 10rpx ' + this . value ? . ornament ? . color : '' ) + ';' ;
style . boxS hadow = this . value ? . ornament ? . type == 'shadow' ? '0 0 10rpx ' + this . value ? . ornament ? . color : '' ;
// 装饰效果:边框
style += ' border:' + ( this . value ? . ornament ? . type == 'stroke' ? '2rpx solid ' + this . value ? . ornament ? . color : '' ) + ';' ;
style . border = this . value ? . ornament ? . type == 'stroke' ? '2rpx solid ' + this . value ? . ornament ? . color : '' ;
return style ;
} ,
@@ -176,7 +189,7 @@ export default {
height = [ 510 , 280 , 220 , 180 ] [ this . value . rowCount - 1 ] ;
}
}
return 'height:' + ( 2 * height ) + 'rpx' ;
} ,
@@ -285,6 +298,105 @@ export default {
item . coverUrl = wechatChannelConfig . video . defaultCoverUrl ;
// #endif
}
} ,
/**
* 添加鼠标拖拽滚动功能
* 在Web环境中实现与微信小程序相同的拖拽滚动效果
*/
addMouseDragScroll ( ) {
// 只在Web环境中添加
// #ifndef MP
console . log ( 'addMouseDragScroll called' ) ;
let isDragging = false ;
let startX = 0 ;
let startScrollLeft = 0 ;
let currentScrollElement = null ;
// 查找最近的可滚动祖先元素
const findScrollableParent = ( element ) => {
while ( element && element !== document ) {
const style = window . getComputedStyle ( element ) ;
if ( style . overflowX === 'auto' || style . overflowX === 'scroll' ) {
return element ;
}
element = element . parentElement ;
}
return null ;
} ;
// 鼠标按下事件
const handleMouseDown = ( e ) => {
// 检查是否点击在组件内
if ( this . $el . contains ( e . target ) ) {
console . log ( 'mousedown event in component:' , e ) ;
// 查找可滚动元素
currentScrollElement = findScrollableParent ( e . target ) ;
if ( currentScrollElement ) {
console . log ( 'Found scrollable element:' , currentScrollElement ) ;
isDragging = true ;
startX = e . pageX ;
startScrollLeft = currentScrollElement . scrollLeft ;
currentScrollElement . style . cursor = 'grabbing' ;
}
}
} ;
// 鼠标移动事件
const handleMouseMove = ( e ) => {
if ( ! isDragging || ! currentScrollElement ) return ;
console . log ( 'mousemove event:' , e ) ;
e . preventDefault ( ) ;
const dx = e . pageX - startX ;
currentScrollElement . scrollLeft = startScrollLeft - dx ;
console . log ( 'scrollLeft:' , currentScrollElement . scrollLeft ) ;
} ;
// 鼠标释放事件
const handleMouseUp = ( ) => {
if ( isDragging && currentScrollElement ) {
console . log ( 'mouseup event' ) ;
currentScrollElement . style . cursor = 'grab' ;
}
isDragging = false ;
currentScrollElement = null ;
} ;
// 添加全局事件监听器
document . addEventListener ( 'mousedown' , handleMouseDown ) ;
document . addEventListener ( 'mousemove' , handleMouseMove ) ;
document . addEventListener ( 'mouseup' , handleMouseUp ) ;
document . addEventListener ( 'mouseleave' , handleMouseUp ) ;
console . log ( 'Global mouse event listeners added' ) ;
// 组件销毁时移除事件监听器
this . $once ( 'hook:beforeDestroy' , ( ) => {
document . removeEventListener ( 'mousedown' , handleMouseDown ) ;
document . removeEventListener ( 'mousemove' , handleMouseMove ) ;
document . removeEventListener ( 'mouseup' , handleMouseUp ) ;
document . removeEventListener ( 'mouseleave' , handleMouseUp ) ;
console . log ( 'Global mouse event listeners removed' ) ;
} ) ;
// 为所有.channel-nav元素添加必要的样式
setTimeout ( ( ) => {
const channelNavs = document . querySelectorAll ( '.channel-nav' ) ;
console . log ( 'Found channel-nav elements:' , channelNavs . length ) ;
channelNavs . forEach ( element => {
element . style . overflowX = 'auto' ;
element . style . overflowY = 'hidden' ;
element . style . whiteSpace = 'nowrap' ;
element . style . width = '100%' ;
element . style . maxWidth = '100%' ;
element . style . cursor = 'grab' ;
element . style . userSelect = 'none' ; // 防止文本选择
console . log ( 'Added styles to channel-nav:' , element ) ;
} ) ;
} , 100 ) ; // 延迟执行, 确保DOM已完全渲染
console . log ( 'Mouse drag scroll setup completed' ) ;
// #endif
}
}
}
@@ -293,6 +405,10 @@ export default {
< style lang = "scss" scoped >
@ import './css/common-channel.scss' ;
. channel - list - container {
padding : 16 px 16 px 0 px ;
}
/**
* 列表布局样式
*/
@@ -300,7 +416,6 @@ export default {
display : grid ;
grid - template - columns : repeat ( var ( -- row - count , 2 ) , 1 fr ) ;
gap : 8 px ;
padding : 16 px 16 px 0 px ;
}
/**
@@ -308,13 +423,36 @@ export default {
* 支持固定布局和滚动布局
*/
. channel - nav {
padding : 16 rpx ;
box - sizing : border - box ;
padding : 16 rpx ;
// 确保在H5环境中可以水平滚动
overflow - x : auto ;
white - space : nowrap ;
// 隐藏滚动条但保留滚动功能
: : - webkit - scrollbar {
display : none ;
}
scrollbar - width : none ;
- ms - overflow - style : none ;
// 启用触摸滚动和鼠标拖拽滚动
- webkit - overflow - scrolling : touch ;
scroll - behavior : smooth ;
. uni - scroll - view - content {
/* #ifdef MP-WEIXIN */
display : flex ;
flex - wrap : nowrap ;
gap : 16 rpx ;
/* #endif */
/* #ifndef MP-WEIXIN */
display : grid ;
grid - template - columns : repeat ( var ( -- row - count , 2 ) , 1 fr ) ;
gap : 16 rpx ;
/* #endif */
}
// 单滑动模式
@@ -323,6 +461,7 @@ export default {
display : flex ;
flex - wrap : nowrap ;
gap : 16 rpx ;
white - space : nowrap ;
}
. channel - nav - item {
@@ -335,33 +474,59 @@ export default {
display : flex ;
flex - direction : column ;
box - sizing : border - box ;
/* #ifdef MP-WEIXIN */
& . row1 - of1 {
width : 100 % ;
}
& . row1 - of2 {
width : calc ( 50 % - 8 rpx ) ;
}
& . row1 - of3 {
width : calc ( 33.333 % - 10.67 rpx ) ;
}
& . row1 - of4 {
width : calc ( 25 % - 12 rpx ) ;
}
/* #endif */
}
// 1 列布局
& . row1 - of1 {
. uni - scroll - view - content {
// #ifndef MP-WEIXIN
grid - template - columns : 1 fr ;
// #endif
}
}
// 2 列布局
& . row1 - of2 {
. uni - scroll - view - content {
// #ifndef MP-WEIXIN
grid - template - columns : repeat ( 2 , 1 fr ) ;
// #endif
}
}
// 3 列布局
& . row1 - of3 {
. uni - scroll - view - content {
// #ifndef MP-WEIXIN
grid - template - columns : repeat ( 3 , 1 fr ) ;
// #endif
}
}
// 4 列布局
& . row1 - of4 {
. uni - scroll - view - content {
// #ifndef MP-WEIXIN
grid - template - columns : repeat ( 4 , 1 fr ) ;
// #endif
}
}
}
@@ -387,7 +552,6 @@ export default {
display : grid ;
grid - template - columns : repeat ( var ( -- row - count , 2 ) , 1 fr ) ;
gap : 16 rpx ;
padding : 16 rpx ;
box - sizing : border - box ;
. channel - item {