|
|
@@ -14,7 +14,7 @@
|
|
|
@waiting="onVideoWaiting" preload="auto" type="application/x-mpegURL" :controls="false"></video>
|
|
|
</view>
|
|
|
<image v-if="liveItem.status == 1 && !liveItem.previewUrl" class="trailer-placeholder"
|
|
|
- src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/readyStart.png">
|
|
|
+ src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/readyStartOne.png">
|
|
|
</image>
|
|
|
<view class="countdown-container" v-if="liveItem.status == 1 && liveCountdown">
|
|
|
<view class="live-name" v-if="liveItem.previewUrl">{{ liveItem.liveName }}</view>
|
|
|
@@ -232,7 +232,7 @@
|
|
|
@scroll="onScroll" ref="scrollView">
|
|
|
|
|
|
<view class="message-list" v-for="(item, talkIndex) in (talklist || [])"
|
|
|
- :key="item.uniqueId " :id="`list_${item.uniqueId }`" v-show="item.cmd != 'red' ">
|
|
|
+ :key="item.uniqueId" :id="`list_${item.uniqueId}`" v-show="item.cmd != 'red' ">
|
|
|
<view class="message-item">
|
|
|
<view class="message-content">
|
|
|
<text class="user-nickname">{{ item.nickName || '未命名' }}
|
|
|
@@ -609,7 +609,7 @@
|
|
|
<input placeholder="请搜索商品" v-model="inputInfo" @input="handleSearchInput" />
|
|
|
</view>
|
|
|
<view class="x-f">
|
|
|
- <view class="shopping-action-button mr30" @click="navgetTo('/pages_shopping/live/order')">
|
|
|
+ <view class="shopping-action-button mr30" @click="navgetTo('/pages_user/user/storeOrder?status=')">
|
|
|
<image class="action-button-icon"
|
|
|
src="https://bjzmky-1323137866.cos.ap-chongqing.myqcloud.com/userapp/images/carts.png" />
|
|
|
<view class="action-button-label">订单</view>
|
|
|
@@ -630,7 +630,7 @@
|
|
|
</view>
|
|
|
<view class="product-info">
|
|
|
<view class="product-name">{{ item.productName }}</view>
|
|
|
- <view class="product-sales">{{ item.sales }} 人已购</view>
|
|
|
+ <!-- <view class="product-sales">{{ item.sales }} 人已购</view> -->
|
|
|
<view class="product-action-section">
|
|
|
<text class="product-price">
|
|
|
<text class="price-symbol">¥</text>
|
|
|
@@ -1135,14 +1135,14 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
});
|
|
|
}
|
|
|
}, 1000);
|
|
|
-
|
|
|
- const systemInfo = uni.getSystemInfoSync();
|
|
|
- this.isIOS = systemInfo.platform === 'ios';
|
|
|
},
|
|
|
async onShow() {
|
|
|
setTimeout(()=>{
|
|
|
this.startCountdown();
|
|
|
},500);
|
|
|
+ const systemInfo = uni.getSystemInfoSync();
|
|
|
+ this.isIOS = systemInfo.platform === 'ios';
|
|
|
+ console.log(systemInfo,'当前系统型号')
|
|
|
if (!this.hasCheckedLogin) {
|
|
|
try {
|
|
|
const isLogin = await this.utils.checkLiveToken();
|
|
|
@@ -2727,37 +2727,51 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
forceScrollToBottom() {
|
|
|
// console.log('执行强制滚动到底部');
|
|
|
|
|
|
- // 方案1:直接设置一个很大的scrollTop值
|
|
|
- this.scrollTop = 999999;
|
|
|
-
|
|
|
- // 方案2:使用scroll-into-view滚动到最后一个元素
|
|
|
- this.$nextTick(() => {
|
|
|
- if (this.talklist && this.talklist.length > 0) {
|
|
|
- const lastMessage = this.talklist[this.talklist.length - 1];
|
|
|
- const targetId = `list_${lastMessage.uniqueId || (this.talklist.length - 1)}`;
|
|
|
- console.log(
|
|
|
- `尝试滚动到元素: ${targetId}, 当前消息数量: ${this.talklist.length}, 最后消息ID: ${lastMessage.uniqueId}`
|
|
|
- );
|
|
|
-
|
|
|
- this.scrollIntoView = targetId;
|
|
|
-
|
|
|
- // 清除scroll-into-view,避免影响后续滚动
|
|
|
+ // iOS 特殊处理:主要使用 scrollTop
|
|
|
+ if (this.isIOS) {
|
|
|
+ // iOS 方案:使用 scrollTop 滚动到底部
|
|
|
+ this.scrollIntoView = '';
|
|
|
+ this.scrollTop = 999999;
|
|
|
+ this.$nextTick(() => {
|
|
|
setTimeout(() => {
|
|
|
- this.scrollIntoView = '';
|
|
|
- }, 200);
|
|
|
- }
|
|
|
+ this.scrollTop = 9999999;
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ }, 100);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 非 iOS 平台:使用原有逻辑
|
|
|
+ // 方案1:直接设置一个很大的scrollTop值
|
|
|
+ this.scrollTop = 999999;
|
|
|
+
|
|
|
+ // 方案2:使用scroll-into-view滚动到最后一个元素
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.talklist && this.talklist.length > 0) {
|
|
|
+ const lastMessage = this.talklist[this.talklist.length - 1];
|
|
|
+ const targetId = `list_${lastMessage.uniqueId || (this.talklist.length - 1)}`;
|
|
|
+ console.log(
|
|
|
+ `尝试滚动到元素: ${targetId}, 当前消息数量: ${this.talklist.length}, 最后消息ID: ${lastMessage.uniqueId}`
|
|
|
+ );
|
|
|
+
|
|
|
+ this.scrollIntoView = targetId;
|
|
|
+
|
|
|
+ // 清除scroll-into-view,避免影响后续滚动
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollIntoView = '';
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
|
|
|
- // 方案3:使用更大的延迟再次设置scrollTop
|
|
|
- setTimeout(() => {
|
|
|
- this.scrollTop = 999999;
|
|
|
- console.log('延迟设置scrollTop为999999');
|
|
|
- }, 100);
|
|
|
+ // 方案3:使用更大的延迟再次设置scrollTop
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = 999999;
|
|
|
+ console.log('延迟设置scrollTop为999999');
|
|
|
+ }, 100);
|
|
|
|
|
|
- // 方案4:300ms后使用原生API作为最终备用方案
|
|
|
- setTimeout(() => {
|
|
|
- this.nativeScrollToBottom();
|
|
|
- }, 300);
|
|
|
- });
|
|
|
+ // 方案4:300ms后使用原生API作为最终备用方案
|
|
|
+ setTimeout(() => {
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ }, 300);
|
|
|
+ });
|
|
|
+ }
|
|
|
},
|
|
|
// 强制滚动到底部(用于发送消息,绕过防抖限制)
|
|
|
forceScrollToBottomOnSend() {
|
|
|
@@ -2771,76 +2785,141 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
this.lastScrollTime = Date.now();
|
|
|
// 清除scroll-into-view,避免冲突
|
|
|
this.scrollIntoView = '';
|
|
|
- // 方案1:立即使用scroll-into-view滚动到最后一条消息
|
|
|
- if (this.talklist.length > 0) {
|
|
|
- const lastMessage = this.talklist[this.talklist.length - 1];
|
|
|
- if (lastMessage && lastMessage.uniqueId) {
|
|
|
- this.scrollIntoView = `list_${lastMessage.uniqueId}`;
|
|
|
- //console.log(`强制滚动方案1: 设置scrollIntoView为list_${lastMessage.uniqueId}`);
|
|
|
- }
|
|
|
- }
|
|
|
- // 方案2:同时设置scrollTop为一个非常大的值
|
|
|
- const targetScrollTop = Date.now(); // 使用时间戳确保每次都不同
|
|
|
- this.scrollTop = targetScrollTop;
|
|
|
- //console.log('强制滚动方案2: 设置scrollTop为', targetScrollTop);
|
|
|
- // 方案3:立即尝试原生滚动
|
|
|
- this.nativeScrollToBottom();
|
|
|
- // 方案4:使用nextTick确保DOM更新后再次滚动
|
|
|
- this.$nextTick(() => {
|
|
|
- // 清除scroll-into-view后重新设置scrollTop
|
|
|
+
|
|
|
+ // iOS 特殊处理:主要使用 scrollTop,因为 scroll-into-view 在 iOS 上可能不稳定
|
|
|
+ if (this.isIOS) {
|
|
|
+ // iOS 方案:使用 scrollTop 滚动到底部
|
|
|
+ // 先清除 scroll-into-view,避免冲突
|
|
|
this.scrollIntoView = '';
|
|
|
- this.scrollTop = targetScrollTop + 1;
|
|
|
- //console.log('强制滚动方案3: nextTick后重新设置scrollTop');
|
|
|
- // 再次尝试原生滚动
|
|
|
- setTimeout(() => {
|
|
|
- this.nativeScrollToBottom();
|
|
|
- }, 50);
|
|
|
- });
|
|
|
- // 方案5:延迟检查和强制滚动(最终保障)
|
|
|
- this.scrollTimer = setTimeout(() => {
|
|
|
- this.checkAndForceScroll(targetScrollTop);
|
|
|
- this.scrollTimer = null;
|
|
|
- }, 200);
|
|
|
+ // 使用一个很大的 scrollTop 值
|
|
|
+ this.scrollTop = 999999;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 延迟再次设置,确保滚动生效
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = 9999999;
|
|
|
+ // 使用原生 API 作为备用
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ }, 100);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 非 iOS 平台:使用原有逻辑
|
|
|
+ // 方案1:立即使用scroll-into-view滚动到最后一条消息
|
|
|
+ if (this.talklist.length > 0) {
|
|
|
+ const lastMessage = this.talklist[this.talklist.length - 1];
|
|
|
+ if (lastMessage && lastMessage.uniqueId) {
|
|
|
+ this.scrollIntoView = `list_${lastMessage.uniqueId}`;
|
|
|
+ //console.log(`强制滚动方案1: 设置scrollIntoView为list_${lastMessage.uniqueId}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 方案2:同时设置scrollTop为一个非常大的值
|
|
|
+ const targetScrollTop = Date.now(); // 使用时间戳确保每次都不同
|
|
|
+ this.scrollTop = targetScrollTop;
|
|
|
+ //console.log('强制滚动方案2: 设置scrollTop为', targetScrollTop);
|
|
|
+ // 方案3:立即尝试原生滚动
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ // 方案4:使用nextTick确保DOM更新后再次滚动
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 清除scroll-into-view后重新设置scrollTop
|
|
|
+ this.scrollIntoView = '';
|
|
|
+ this.scrollTop = targetScrollTop + 1;
|
|
|
+ //console.log('强制滚动方案3: nextTick后重新设置scrollTop');
|
|
|
+ // 再次尝试原生滚动
|
|
|
+ setTimeout(() => {
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ }, 50);
|
|
|
+ });
|
|
|
+ // 方案5:延迟检查和强制滚动(最终保障)
|
|
|
+ this.scrollTimer = setTimeout(() => {
|
|
|
+ this.checkAndForceScroll(targetScrollTop);
|
|
|
+ this.scrollTimer = null;
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
// 检查并强制滚动
|
|
|
checkAndForceScroll(targetScrollTop) {
|
|
|
//console.log(`检查滚动状态: 当前位置=${this.currentScrollTop}, 目标位置=${targetScrollTop}`);
|
|
|
// 无论当前位置如何,都尝试强制滚动到底部
|
|
|
- // 使用scroll-into-view滚动到最后一条消息
|
|
|
- if (this.talklist.length > 0) {
|
|
|
- const lastMessage = this.talklist[this.talklist.length - 1];
|
|
|
- if (lastMessage && lastMessage.uniqueId) {
|
|
|
- this.scrollIntoView = `list_${lastMessage.uniqueId}`;
|
|
|
- //console.log(`最终检查: 设置scrollIntoView为list_${lastMessage.uniqueId}`);
|
|
|
- }
|
|
|
- }
|
|
|
- // 设置一个新的scrollTop值
|
|
|
- this.scrollTop = Date.now() + Math.random() * 1000;
|
|
|
- //console.log('最终检查: 设置新的scrollTop值');
|
|
|
- // 多次尝试原生滚动
|
|
|
- this.nativeScrollToBottom();
|
|
|
- setTimeout(() => {
|
|
|
+
|
|
|
+ // iOS 特殊处理:主要使用 scrollTop
|
|
|
+ if (this.isIOS) {
|
|
|
+ // iOS 方案:使用 scrollTop 滚动到底部
|
|
|
+ this.scrollIntoView = '';
|
|
|
+ this.scrollTop = 999999;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = 9999999;
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ }, 100);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 非 iOS 平台:使用原有逻辑
|
|
|
+ // 使用scroll-into-view滚动到最后一条消息
|
|
|
+ if (this.talklist.length > 0) {
|
|
|
+ const lastMessage = this.talklist[this.talklist.length - 1];
|
|
|
+ if (lastMessage && lastMessage.uniqueId) {
|
|
|
+ this.scrollIntoView = `list_${lastMessage.uniqueId}`;
|
|
|
+ //console.log(`最终检查: 设置scrollIntoView为list_${lastMessage.uniqueId}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 设置一个新的scrollTop值
|
|
|
+ this.scrollTop = Date.now() + Math.random() * 1000;
|
|
|
+ //console.log('最终检查: 设置新的scrollTop值');
|
|
|
+ // 多次尝试原生滚动
|
|
|
this.nativeScrollToBottom();
|
|
|
- }, 100);
|
|
|
+ setTimeout(() => {
|
|
|
+ this.nativeScrollToBottom();
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
// 使用原生API强制滚动(最终备用方案)
|
|
|
nativeScrollToBottom() {
|
|
|
try {
|
|
|
- // 方案1:使用uni.createSelectorQuery直接操作DOM
|
|
|
const query = uni.createSelectorQuery().in(this);
|
|
|
- query.select('#msgScroll').node((res) => {
|
|
|
- if (res && res.node) {
|
|
|
- // console.log('找到msgScroll节点,执行原生滚动');
|
|
|
- const scrollHeight = res.node.scrollHeight;
|
|
|
- res.node.scrollTop = scrollHeight;
|
|
|
- // 确保滚动生效,延迟再次设置
|
|
|
- setTimeout(() => {
|
|
|
- res.node.scrollTop = scrollHeight + 100;
|
|
|
- }, 50);
|
|
|
- }
|
|
|
- }).exec();
|
|
|
+
|
|
|
+ // iOS 特殊处理:主要使用 scrollTop,因为 scroll-into-view 在 iOS 上可能不稳定
|
|
|
+ if (this.isIOS) {
|
|
|
+ // iOS 方案:使用 fields 获取滚动信息并设置 scrollTop
|
|
|
+ query.select('#msgScroll').fields({
|
|
|
+ scrollOffset: true,
|
|
|
+ size: true
|
|
|
+ }, (res) => {
|
|
|
+ if (res && res.scrollHeight && res.height) {
|
|
|
+ const maxScrollTop = res.scrollHeight - res.height;
|
|
|
+ if (maxScrollTop > 0) {
|
|
|
+ // 直接设置一个足够大的 scrollTop 值,确保滚动到底部
|
|
|
+ this.scrollTop = maxScrollTop + 1000;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = maxScrollTop + 2000;
|
|
|
+ }, 100);
|
|
|
+ } else {
|
|
|
+ // 如果计算失败,使用一个很大的值
|
|
|
+ this.scrollTop = 999999;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = 9999999;
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果获取失败,使用一个很大的值
|
|
|
+ this.scrollTop = 999999;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = 9999999;
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ }).exec();
|
|
|
+ } else {
|
|
|
+ // 非 iOS 平台:使用原有逻辑
|
|
|
+ query.select('#msgScroll').node((res) => {
|
|
|
+ if (res && res.node) {
|
|
|
+ const scrollHeight = res.node.scrollHeight;
|
|
|
+ res.node.scrollTop = scrollHeight;
|
|
|
+ setTimeout(() => {
|
|
|
+ res.node.scrollTop = scrollHeight + 100;
|
|
|
+ }, 50);
|
|
|
+ }
|
|
|
+ }).exec();
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
console.error('原生滚动失败:', error);
|
|
|
}
|
|
|
@@ -3196,9 +3275,21 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
clearTimeout(this.scrollTimer);
|
|
|
this.scrollTimer = null;
|
|
|
}
|
|
|
- // 直接设置滚动位置
|
|
|
- this.scrollTop = 999999999;
|
|
|
-
|
|
|
+
|
|
|
+ // iOS 特殊处理:主要使用 scrollTop
|
|
|
+ if (this.isIOS) {
|
|
|
+ // iOS 方案:使用 scrollTop 滚动到底部
|
|
|
+ this.scrollIntoView = '';
|
|
|
+ this.scrollTop = 999999999;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollTop = 9999999999;
|
|
|
+ }, 100);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 非 iOS 平台:直接设置滚动位置
|
|
|
+ this.scrollTop = 999999999;
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
// 启动内存监控
|
|
|
@@ -5103,9 +5194,19 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
this.$forceUpdate();
|
|
|
|
|
|
// 使用单次nextTick确保DOM更新后再滚动
|
|
|
- this.$nextTick(() => {
|
|
|
- this.forceScrollToBottomOnSend();
|
|
|
- });
|
|
|
+ // iOS 需要更长的延迟来确保 DOM 完全渲染
|
|
|
+ if (this.isIOS) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // iOS 上需要额外延迟,确保消息元素完全渲染
|
|
|
+ setTimeout(() => {
|
|
|
+ this.forceScrollToBottomOnSend();
|
|
|
+ }, 100);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.forceScrollToBottomOnSend();
|
|
|
+ });
|
|
|
+ }
|
|
|
},
|
|
|
// 处理Socket消息
|
|
|
async handleSocketMessage(message) {
|
|
|
@@ -5856,7 +5957,8 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
|
|
|
.countdown-label {
|
|
|
font-size: 32rpx;
|
|
|
- color: rgba(250, 214, 176, 1);
|
|
|
+ //color: rgba(250, 214, 176, 1);
|
|
|
+ color:#fff
|
|
|
}
|
|
|
|
|
|
.countdown-separator {
|
|
|
@@ -5874,7 +5976,8 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
margin: 0 8rpx;
|
|
|
font-weight: 500;
|
|
|
font-size: 36rpx;
|
|
|
- color: rgba(0, 75, 59, 1);
|
|
|
+ color: #a30c0b;
|
|
|
+ //color: rgba(0, 75, 59, 1);
|
|
|
line-height: 60rpx;
|
|
|
}
|
|
|
}
|
|
|
@@ -5893,19 +5996,23 @@ import {CustomToast} from '@/components/custom-toast.vue';
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
text-align: center;
|
|
|
- border: 1px solid rgba(151, 151, 151, 1);
|
|
|
+ //border: 1px solid rgba(151, 151, 151, 1);
|
|
|
+ border: 1px solid rgba(255, 246, 214, 1);
|
|
|
font-size: 36rpx;
|
|
|
font-weight: bold;
|
|
|
|
|
|
&.reserve-button {
|
|
|
- color: rgba(0, 110, 80, 1);
|
|
|
+ //color: rgba(0, 110, 80, 1);
|
|
|
+ color: #a30c0b;
|
|
|
background: linear-gradient(231.51deg, rgba(249, 215, 178, 1) 0%, rgba(255, 255, 191, 1) 47.83%, rgba(255, 250, 229, 1) 65.77%, rgba(248, 214, 178, 1) 100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
&:not(.reserve-button) {
|
|
|
- color: rgba(255, 246, 214, 1);
|
|
|
- background: rgba(0, 110, 80, 1);
|
|
|
+ //color: rgba(255, 246, 214, 1);
|
|
|
+ //background: rgba(0, 110, 80, 1);
|
|
|
+ color: #fff;
|
|
|
+ background: #a30c0b;
|
|
|
}
|
|
|
|
|
|
.button-icon {
|