fix(视频号组件): padding 影响布局

This commit is contained in:
2026-01-15 17:26:02 +08:00
parent 28359f2f16
commit 36fd0621fd
2 changed files with 186 additions and 26 deletions

View File

@@ -1,5 +1,5 @@
<template> <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" <swiper v-if="value.showStyle == 'carousel' && carouselConfig.type != 'hide'" :indicator-dots="isIndicatorDots"
:autoplay="carouselConfig.autoplay || false" :interval="carouselConfig.interval || 3000" :autoplay="carouselConfig.autoplay || false" :interval="carouselConfig.interval || 3000"
@@ -11,9 +11,8 @@
<!-- 视频号视频卡片轮播模式 --> <!-- 视频号视频卡片轮播模式 -->
<diy-channel-video :value="item" @video-play="playVideo" :list-mode="true" <diy-channel-video :value="item" @video-play="playVideo" :list-mode="true"
:title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn" :title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn"
:show-view-count="value.showViewCount" :show-view-count="value.showViewCount" :cover-style="computedCoverStyle"
:cover-style="computedCoverStyle" :play-btn-style="value.playBtnStyle" :play-btn-style="value.playBtnStyle" :aspect-ratio="value.aspectRatio" />
:aspect-ratio="value.aspectRatio" />
</view> </view>
</view> </view>
</swiper-item> </swiper-item>
@@ -25,24 +24,26 @@
<!-- 视频号视频卡片列表模式 --> <!-- 视频号视频卡片列表模式 -->
<diy-channel-video :value="item" @video-play="playVideo" :list-mode="true" <diy-channel-video :value="item" @video-play="playVideo" :list-mode="true"
:title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn" :title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn"
:show-view-count="value.showViewCount" :show-view-count="value.showViewCount" :cover-style="computedCoverStyle"
:cover-style="computedCoverStyle" :play-btn-style="value.playBtnStyle" :play-btn-style="value.playBtnStyle" :aspect-ratio="value.aspectRatio" />
:aspect-ratio="value.aspectRatio" />
</view> </view>
</view> </view>
<!-- 其他布局模式如滚动布局 --> <!-- 其他布局模式如滚动布局 -->
<scroll-view v-else <scroll-view v-else
:class="['channel-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle, 'row1-of' + value.rowCount]" :class="['channel-nav', value.showStyle == 'fixed' ? 'fixed-layout' : 'singleSlide', 'row1-of' + value.rowCount]"
:scroll-x="value.showStyle == 'singleSlide'"> :scroll-x="true"
:scroll-y="false"
:enhanced="true"
:bounces="false">
<view class="uni-scroll-view-content"> <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" <diy-channel-video :value="item" @video-play="playVideo" :list-mode="true"
:title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn" :title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn"
:show-view-count="value.showViewCount" :show-view-count="value.showViewCount" :cover-style="computedCoverStyle"
:cover-style="computedCoverStyle" :play-btn-style="value.playBtnStyle" :play-btn-style="value.playBtnStyle" :aspect-ratio="value.aspectRatio" />
:aspect-ratio="value.aspectRatio" />
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
@@ -107,6 +108,14 @@ export default {
// 组件创建时的逻辑 // 组件创建时的逻辑
// 可以在这里进行初始化操作,如获取页面宽度等 // 可以在这里进行初始化操作,如获取页面宽度等
}, },
mounted() {
// 组件挂载后添加鼠标拖拽滚动功能
if (!['fixed', 'carousel'].includes(this.value?.showStyle)) {
this.$nextTick(() => {
this.addMouseDragScroll();
});
}
},
watch: { watch: {
/** /**
* 组件刷新监听 * 组件刷新监听
@@ -134,24 +143,24 @@ export default {
* @returns {string} 样式字符串 * @returns {string} 样式字符串
*/ */
componentStyle() { componentStyle() {
let style = ''; const style = {};
// 背景色 // 背景色
if (this.value?.componentBgColor) { if (this.value?.componentBgColor) {
style += 'background-color:' + this.value?.componentBgColor + ';'; style.backgroundColor = this.value?.componentBgColor;
} }
// 圆角样式 // 圆角样式
if (this.value?.componentAngle == 'round') { if (this.value?.componentAngle == 'round') {
style += 'border-top-left-radius:' + (2 * this.value?.topAroundRadius) + 'rpx;'; style.borderTopLeftRadius = (2 * this.value?.topAroundRadius) + 'rpx';
style += 'border-top-right-radius:' + (2 * this.value?.topAroundRadius) + 'rpx;'; style.borderTopRightRadius = (2 * this.value?.topAroundRadius) + 'rpx';
style += 'border-bottom-left-radius:' + (2 * this.value?.bottomAroundRadius) + 'rpx;'; style.borderBottomLeftRadius = (2 * this.value?.bottomAroundRadius) + 'rpx';
style += 'border-bottom-right-radius:' + (2 * this.value?.bottomAroundRadius) + 'rpx;'; style.borderBottomRightRadius = (2 * this.value?.bottomAroundRadius) + 'rpx';
} }
// 装饰效果:阴影 // 装饰效果:阴影
style += 'box-shadow:' + (this.value?.ornament?.type == 'shadow' ? '0 0 10rpx ' + this.value?.ornament?.color : '') + ';'; style.boxShadow = 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; return style;
}, },
@@ -180,7 +189,7 @@ export default {
height = [510, 280, 220, 180][this.value.rowCount - 1]; height = [510, 280, 220, 180][this.value.rowCount - 1];
} }
} }
return 'height:' + (2 * height) + 'rpx'; return 'height:' + (2 * height) + 'rpx';
}, },
@@ -289,6 +298,105 @@ export default {
item.coverUrl = wechatChannelConfig.video.defaultCoverUrl; item.coverUrl = wechatChannelConfig.video.defaultCoverUrl;
// #endif // #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
} }
} }
} }
@@ -297,6 +405,10 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
@import './css/common-channel.scss'; @import './css/common-channel.scss';
.channel-list-container {
padding: 16px 16px 0px;
}
/** /**
* 列表布局样式 * 列表布局样式
*/ */
@@ -304,7 +416,6 @@ export default {
display: grid; display: grid;
grid-template-columns: repeat(var(--row-count, 2), 1fr); grid-template-columns: repeat(var(--row-count, 2), 1fr);
gap: 8px; gap: 8px;
padding: 16px 16px 0px;
} }
/** /**
@@ -312,13 +423,36 @@ export default {
* 支持固定布局和滚动布局 * 支持固定布局和滚动布局
*/ */
.channel-nav { .channel-nav {
padding: 16rpx;
box-sizing: border-box; box-sizing: border-box;
padding: 16rpx;
// 确保在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 { .uni-scroll-view-content {
/* #ifdef MP-WEIXIN */
display: flex;
flex-wrap: nowrap;
gap: 16rpx;
/* #endif */
/* #ifndef MP-WEIXIN */
display: grid; display: grid;
grid-template-columns: repeat(var(--row-count, 2), 1fr); grid-template-columns: repeat(var(--row-count, 2), 1fr);
gap: 16rpx; gap: 16rpx;
/* #endif */
} }
// 单滑动模式 // 单滑动模式
@@ -327,6 +461,7 @@ export default {
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
gap: 16rpx; gap: 16rpx;
white-space: nowrap;
} }
.channel-nav-item { .channel-nav-item {
@@ -339,33 +474,59 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
/* #ifdef MP-WEIXIN */
&.row1-of1 {
width: 100%;
}
&.row1-of2 {
width: calc(50% - 8rpx);
}
&.row1-of3 {
width: calc(33.333% - 10.67rpx);
}
&.row1-of4 {
width: calc(25% - 12rpx);
}
/* #endif */
} }
// 1 列布局 // 1 列布局
&.row1-of1 { &.row1-of1 {
.uni-scroll-view-content { .uni-scroll-view-content {
// #ifndef MP-WEIXIN
grid-template-columns: 1fr; grid-template-columns: 1fr;
// #endif
} }
} }
// 2 列布局 // 2 列布局
&.row1-of2 { &.row1-of2 {
.uni-scroll-view-content { .uni-scroll-view-content {
// #ifndef MP-WEIXIN
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
// #endif
} }
} }
// 3 列布局 // 3 列布局
&.row1-of3 { &.row1-of3 {
.uni-scroll-view-content { .uni-scroll-view-content {
// #ifndef MP-WEIXIN
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
// #endif
} }
} }
// 4 列布局 // 4 列布局
&.row1-of4 { &.row1-of4 {
.uni-scroll-view-content { .uni-scroll-view-content {
// #ifndef MP-WEIXIN
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
// #endif
} }
} }
} }
@@ -391,7 +552,6 @@ export default {
display: grid; display: grid;
grid-template-columns: repeat(var(--row-count, 2), 1fr); grid-template-columns: repeat(var(--row-count, 2), 1fr);
gap: 16rpx; gap: 16rpx;
padding: 16rpx;
box-sizing: border-box; box-sizing: border-box;
.channel-item { .channel-item {

View File

@@ -883,7 +883,7 @@ image {
} }
} }
/deep/ .channel-list { /deep/ .channel-list-container {
padding: 0rpx !important; padding: 0rpx !important;
} }