|
|
@@ -207,7 +207,15 @@
|
|
|
import LiveViewerBar from '@/pages_course/living/components/LiveViewerBar.vue';
|
|
|
import LiveSideActions from '@/pages_course/living/components/LiveSideActions.vue';
|
|
|
import { fetchLiveOrderUser } from '@/pages_course/living/services/liveShopService.js';
|
|
|
- import { fetchLiveViewData } from '@/pages_course/living/services/liveRoomService.js';
|
|
|
+ import { fetchLiveUserInfo } from '@/pages_course/living/services/liveUserService.js';
|
|
|
+ import {
|
|
|
+ fetchLiveRoom,
|
|
|
+ fetchLiveViewData,
|
|
|
+ fetchCurrentActivities,
|
|
|
+ fetchRemainingTime,
|
|
|
+ fetchCompletionRecords,
|
|
|
+ clearLiveRoomRequestCache
|
|
|
+ } from '@/pages_course/living/services/liveRoomService.js';
|
|
|
import { createLiveSocket } from '@/pages_course/living/services/liveSocket.js';
|
|
|
import { parseWsEnvelope, parseJsonField, parseNumericField, isSuccessEnvelope } from '@/pages_course/living/services/liveSocketProtocol.js';
|
|
|
import {
|
|
|
@@ -218,20 +226,15 @@
|
|
|
liveRed,
|
|
|
liveDataLike,
|
|
|
collectGoods,
|
|
|
- currentActivities,
|
|
|
- getlive,
|
|
|
subNotifyLive,
|
|
|
internetTraffic,
|
|
|
liveInternetTraffic,
|
|
|
loginByMp,
|
|
|
- getUserInfo,
|
|
|
getIsAddKf,
|
|
|
liveWatchUser,
|
|
|
submitLiveQuiz,
|
|
|
- completionRecords,
|
|
|
completionReceive,
|
|
|
completionUnreceived,
|
|
|
- remainingTime,
|
|
|
updateWatchDuration,
|
|
|
receivePoints,
|
|
|
integrallogs
|
|
|
@@ -347,6 +350,13 @@
|
|
|
isLoadingLiveInfo: false, // 是否正在加载课程间信息
|
|
|
isLoadingVideo: false, // 是否正在加载视频资源
|
|
|
hasCheckedLogin: false, // 是否已检查登录状态
|
|
|
+ initPromise: null, // 登录后初始化 Promise,防止重复
|
|
|
+ p1DataLoaded: false,
|
|
|
+ secondaryDataLoaded: false,
|
|
|
+ chatHistoryLoaded: false,
|
|
|
+ isFirstShow: true,
|
|
|
+ isFetchingUserInfo: false,
|
|
|
+ lastTrafficSubmitAt: 0,
|
|
|
|
|
|
liveViewersData: [],
|
|
|
liveUserCalled: false,
|
|
|
@@ -512,11 +522,16 @@
|
|
|
this.initNetworkStatusListener();
|
|
|
},
|
|
|
async onPullDownRefresh() {
|
|
|
- // 下拉刷新时,重新加载数据
|
|
|
if (this.liveId) {
|
|
|
+ clearLiveRoomRequestCache(this.liveId);
|
|
|
this.isLoadingLiveInfo = false;
|
|
|
- await this.getliving(this.liveId);
|
|
|
- await this.loadChatHistory();
|
|
|
+ this.chatHistoryLoaded = false;
|
|
|
+ this.secondaryDataLoaded = false;
|
|
|
+ this.p1DataLoaded = false;
|
|
|
+ await this.getliving(this.liveId, { refresh: true });
|
|
|
+ await this.loadChatHistory(true);
|
|
|
+ this.modules.p1 = true;
|
|
|
+ this.loadP1Data(true);
|
|
|
}
|
|
|
setTimeout(() => {
|
|
|
uni.stopPullDownRefresh();
|
|
|
@@ -583,8 +598,11 @@
|
|
|
uni.removeStorageSync('scene');
|
|
|
}
|
|
|
|
|
|
- // 恢复播放和连接
|
|
|
- await this.resumePageActivity();
|
|
|
+ // 恢复播放和连接(首次 onShow 跳过,避免与 onLoad 重复拉取)
|
|
|
+ if (!this.isFirstShow) {
|
|
|
+ await this.resumePageActivity();
|
|
|
+ }
|
|
|
+ this.isFirstShow = false;
|
|
|
|
|
|
// 恢复观看时长统计(如果之前已经开始统计)
|
|
|
if (this.watchStartTime > 0 || this.accumulatedWatchDuration > 0) {
|
|
|
@@ -607,23 +625,10 @@
|
|
|
|
|
|
// 启动内存监控,定期清理
|
|
|
this.startMemoryMonitor();
|
|
|
- if (this.trafficTimer) {
|
|
|
- clearInterval(this.trafficTimer);
|
|
|
- this.trafficTimer = null;
|
|
|
- this.startTime = 0;
|
|
|
- this.totalTraffic = 0;
|
|
|
- }
|
|
|
- // 重置视频加载状态和流量计算开始时间
|
|
|
- this.videoLoaded = false;
|
|
|
- this.trafficStartTime = 0;
|
|
|
- // 清除等待定时器
|
|
|
- if (this.waitingTimer) {
|
|
|
- clearTimeout(this.waitingTimer);
|
|
|
- this.waitingTimer = null;
|
|
|
+ // 不在 onShow 重置流量统计,避免重复上报 getLiveInternetTraffic
|
|
|
+ if (!this.lookTimer) {
|
|
|
+ this.startTimer();
|
|
|
}
|
|
|
- this.waitingStartTime = 0;
|
|
|
- this.lastVideoUpdateTime = 0;
|
|
|
- this.startTimer();
|
|
|
this.$nextTick(() => {
|
|
|
console.log(444, this.userInfo);
|
|
|
if (!this.userInfo || !this.userInfo.nickname) {
|
|
|
@@ -964,24 +969,43 @@
|
|
|
},
|
|
|
methods: {
|
|
|
// 查询当前用户当前课程间领取积分的剩余时长
|
|
|
- getRemainingTime() {
|
|
|
+ getRemainingTime(refresh = false) {
|
|
|
if (!this.liveId) return;
|
|
|
- const data = {
|
|
|
- liveId: this.liveId
|
|
|
- }
|
|
|
- remainingTime(data).then((res) => {
|
|
|
+ fetchRemainingTime(this.liveId, refresh).then((res) => {
|
|
|
if (res.code == 200) {
|
|
|
- //this.pointsRemainingTime = res.data.remainingTime;
|
|
|
this.hasReceived = res.data.hasReceived;
|
|
|
this.videoDuration = res.data.videoDuration;
|
|
|
- this.watchDuration = res.data.watchDuration; //停留时长
|
|
|
- //this.completionRate= res.data.completionRate*0.01;//完课比例
|
|
|
+ this.watchDuration = res.data.watchDuration;
|
|
|
console.log("查询当前用户当前课程间领取积分的剩余时长", res)
|
|
|
}
|
|
|
- }).catch((error) => {
|
|
|
-
|
|
|
- });
|
|
|
-
|
|
|
+ }).catch(() => {});
|
|
|
+ },
|
|
|
+ loadSecondaryLiveData(refresh = false) {
|
|
|
+ if (!refresh && this.secondaryDataLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!this.liveId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.secondaryDataLoaded = true;
|
|
|
+ this.loadCompletionRecords(refresh);
|
|
|
+ if (this.liveItem.completionPointsEnabled) {
|
|
|
+ this.getRemainingTime(refresh);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ loadCompletionRecords(refresh = false) {
|
|
|
+ if (!this.liveId) return;
|
|
|
+ fetchCompletionRecords(this.liveId, refresh).then((res) => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ const targetData = res.data.find(item => item.liveId == this.liveId);
|
|
|
+ if (targetData) {
|
|
|
+ this.receiveStatus = true;
|
|
|
+ } else {
|
|
|
+ this.receiveStatus = false;
|
|
|
+ }
|
|
|
+ console.log("查询用户积分领取记录", res)
|
|
|
+ }
|
|
|
+ }).catch(() => {});
|
|
|
},
|
|
|
|
|
|
// 更新用户的看课时长 (传入课程间id和看课时长)
|
|
|
@@ -1790,17 +1814,26 @@
|
|
|
this.user.nickname = e.detail.value
|
|
|
},
|
|
|
async haveLogin() {
|
|
|
+ if (this.initPromise) {
|
|
|
+ return this.initPromise;
|
|
|
+ }
|
|
|
+ this.initPromise = this._doHaveLogin();
|
|
|
+ try {
|
|
|
+ return await this.initPromise;
|
|
|
+ } catch (err) {
|
|
|
+ this.initPromise = null;
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async _doHaveLogin() {
|
|
|
if (this.isOnload) {
|
|
|
return;
|
|
|
}
|
|
|
- this.userInfo = uni.getStorageSync('userInfo');
|
|
|
- if (this.userInfo) {
|
|
|
- await this.getUserInfo();
|
|
|
- }
|
|
|
+ this.isOnload = true;
|
|
|
+ await this.getUserInfo();
|
|
|
if (!this.liveId) {
|
|
|
return;
|
|
|
}
|
|
|
- this.isOnload = true;
|
|
|
await this.getliving(this.liveId);
|
|
|
await this.$nextTick();
|
|
|
await Promise.all([
|
|
|
@@ -1813,20 +1846,33 @@
|
|
|
this.scheduleDeferredModules();
|
|
|
},
|
|
|
scheduleDeferredModules() {
|
|
|
+ if (this.p1DataLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
setTimeout(() => {
|
|
|
+ if (this.p1DataLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
this.modules.p1 = true;
|
|
|
this.loadP1Data();
|
|
|
}, 1500);
|
|
|
},
|
|
|
- loadP1Data() {
|
|
|
- this.getliveViewData();
|
|
|
- this.loadLiveOrderUser();
|
|
|
+ loadP1Data(refresh = false) {
|
|
|
+ if (!refresh && this.p1DataLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!this.liveId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.p1DataLoaded = true;
|
|
|
+ this.getliveViewData(refresh);
|
|
|
+ this.loadLiveOrderUser(refresh);
|
|
|
this.modules.p2Activity = true;
|
|
|
- this.getCurrentActivities();
|
|
|
+ this.applyCurrentActivities(refresh);
|
|
|
},
|
|
|
- loadLiveOrderUser() {
|
|
|
+ loadLiveOrderUser(refresh = false) {
|
|
|
if (!this.liveId) return;
|
|
|
- fetchLiveOrderUser(this.liveId).then(res => {
|
|
|
+ fetchLiveOrderUser(this.liveId, refresh).then(res => {
|
|
|
if (res.code === 200) {
|
|
|
this.orderUser = res;
|
|
|
}
|
|
|
@@ -1940,9 +1986,13 @@
|
|
|
this.isKeyboardShow = false;
|
|
|
this.restoreGoodsCardAfterKeyboard();
|
|
|
},
|
|
|
- async loadChatHistory() {
|
|
|
+ async loadChatHistory(refresh = false) {
|
|
|
+ if (!refresh && this.chatHistoryLoaded) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (this.$refs.chat && this.$refs.chat.loadHistory) {
|
|
|
- await this.$refs.chat.loadHistory(this.liveItem);
|
|
|
+ await this.$refs.chat.loadHistory(this.liveItem, refresh);
|
|
|
+ this.chatHistoryLoaded = true;
|
|
|
}
|
|
|
},
|
|
|
onShopBuy({ productId, goodsId }) {
|
|
|
@@ -2551,6 +2601,11 @@
|
|
|
if (!this.liveId || !this.userInfo || !this.userInfo.userId) {
|
|
|
return;
|
|
|
}
|
|
|
+ const now = Date.now();
|
|
|
+ if (now - this.lastTrafficSubmitAt < 8000) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.lastTrafficSubmitAt = now;
|
|
|
|
|
|
// 计算当前观看时长对应的流量
|
|
|
const totalDuration = this.liveItem.videoDuration || this.liveItem.duration || 0;
|
|
|
@@ -2660,29 +2715,33 @@
|
|
|
},
|
|
|
// 恢复页面活动
|
|
|
async resumePageActivity() {
|
|
|
- if (this.liveItem) {
|
|
|
- await this.getliving(this.liveId);
|
|
|
- this.startTimeTimer(this.liveItem);
|
|
|
+ if (!this.liveId || !this.isOnload) {
|
|
|
+ if (!this.isSocketAvailable()) {
|
|
|
+ this.initSocket();
|
|
|
+ }
|
|
|
+ return;
|
|
|
}
|
|
|
+ await this.getliving(this.liveId, { skipSecondary: true });
|
|
|
+ this.startTimeTimer(this.liveItem);
|
|
|
if (!this.isSocketAvailable()) {
|
|
|
this.initSocket();
|
|
|
}
|
|
|
},
|
|
|
- async getUserInfo() {
|
|
|
- await getUserInfo().then(
|
|
|
- (res) => {
|
|
|
- if (res.code == 200) {
|
|
|
- this.userInfo = res.user;
|
|
|
- this.isNow = dayjs(this.userInfo.updateTime).isSame(dayjs(), 'day')
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- icon: 'none',
|
|
|
- title: '请求失败'
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
- (rej) => {}
|
|
|
- );
|
|
|
+ async getUserInfo(refresh = false) {
|
|
|
+ try {
|
|
|
+ const res = await fetchLiveUserInfo(refresh);
|
|
|
+ if (res.code == 200) {
|
|
|
+ this.userInfo = res.user;
|
|
|
+ this.isNow = dayjs(this.userInfo.updateTime).isSame(dayjs(), 'day');
|
|
|
+ } else {
|
|
|
+ uni.showToast({
|
|
|
+ icon: 'none',
|
|
|
+ title: '请求失败'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('getUserInfo failed', e);
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
//订阅消息
|
|
|
@@ -3217,9 +3276,9 @@
|
|
|
console.log('错误');
|
|
|
},
|
|
|
// 红包 卡片 抽奖
|
|
|
- getCurrentActivities() {
|
|
|
+ applyCurrentActivities(refresh = false) {
|
|
|
if (!this.liveId) return;
|
|
|
- currentActivities(this.liveId).then(
|
|
|
+ fetchCurrentActivities(this.liveId, refresh).then(
|
|
|
(res) => {
|
|
|
if (res.code === 200) {
|
|
|
// 提取数据(默认空数组/对象避免报错)
|
|
|
@@ -3487,45 +3546,22 @@
|
|
|
url: url
|
|
|
});
|
|
|
},
|
|
|
- // 查询用户积分领取记录
|
|
|
+ // 查询用户积分领取记录(供外部刷新时调用)
|
|
|
completionRecords() {
|
|
|
- if (!this.liveId) return;
|
|
|
- const data = {
|
|
|
- liveId: this.liveId
|
|
|
- }
|
|
|
- completionRecords(data).then((res) => {
|
|
|
- if (res.code == 200) {
|
|
|
- const targetData = res.data.find(item => item.liveId == this.liveId);
|
|
|
- if (targetData) {
|
|
|
- // 找到匹配的数据
|
|
|
- const receiveStatus = targetData.receiveStatus;
|
|
|
- this.receiveStatus = true;
|
|
|
- } else {
|
|
|
- console.log('未找到liveId为', this.liveId, '的数据');
|
|
|
- this.receiveStatus = false; // 或其他默认值
|
|
|
- }
|
|
|
- console.log("查询用户积分领取记录", res)
|
|
|
- }
|
|
|
- }).catch((error) => {
|
|
|
-
|
|
|
- });
|
|
|
+ this.loadCompletionRecords();
|
|
|
},
|
|
|
|
|
|
// 修改获取课程信息方法
|
|
|
- async getliving(liveId) {
|
|
|
+ async getliving(liveId, options = {}) {
|
|
|
+ const { skipSecondary = false, refresh = false } = options;
|
|
|
if (!liveId) return;
|
|
|
- // 防止重复请求
|
|
|
if (this.isLoadingLiveInfo) {
|
|
|
console.log('正在加载课程间信息,跳过重复请求');
|
|
|
return;
|
|
|
}
|
|
|
this.isLoadingLiveInfo = true;
|
|
|
- const param = {
|
|
|
- id: liveId
|
|
|
- };
|
|
|
try {
|
|
|
- const res = await getlive(param);
|
|
|
- this.isLoadingLiveInfo = false;
|
|
|
+ const res = await fetchLiveRoom(liveId, refresh);
|
|
|
if (res.code !== 200) {
|
|
|
uni.showToast({
|
|
|
title: res.msg,
|
|
|
@@ -3605,8 +3641,8 @@
|
|
|
this.completionRate = JSON.parse(this.liveItem.configJson).completionRate * 0.01
|
|
|
}
|
|
|
console.log("查询当前用户当前课程间领取积分的剩余时长", this.liveId)
|
|
|
- if (this.liveItem.completionPointsEnabled) {
|
|
|
- this.getRemainingTime(); //查询当前用户当前课程间领取积分的剩余时长
|
|
|
+ if (!skipSecondary) {
|
|
|
+ this.loadSecondaryLiveData(refresh);
|
|
|
}
|
|
|
this.$set(this.liveItem, 'autoplay', res.data.liveType !== 0);
|
|
|
this.$set(this.liveItem, 'showType', res.data.showType);
|
|
|
@@ -3626,8 +3662,6 @@
|
|
|
this.liveBeginWatchTime = this.getServerTimeNow();
|
|
|
}
|
|
|
}
|
|
|
- this.getliveViewData();
|
|
|
- this.completionRecords();
|
|
|
// 初始化观看时间统计
|
|
|
this.initWatchTime();
|
|
|
const diff = this.calculateLiveTimeDiff(this.liveItem.serviceStartTime, true)
|
|
|
@@ -3649,12 +3683,13 @@
|
|
|
}
|
|
|
});
|
|
|
} catch (err) {
|
|
|
- this.isLoadingLiveInfo = false;
|
|
|
console.error('获取课程信息失败:', err);
|
|
|
uni.showToast({
|
|
|
title: '获取课程信息失败',
|
|
|
icon: 'none'
|
|
|
});
|
|
|
+ } finally {
|
|
|
+ this.isLoadingLiveInfo = false;
|
|
|
}
|
|
|
},
|
|
|
getPureDecimal(num, precision = 6) {
|
|
|
@@ -3763,11 +3798,10 @@
|
|
|
},
|
|
|
|
|
|
//课程间点赞、关注、在线人数数据
|
|
|
- getliveViewData() {
|
|
|
+ getliveViewData(refresh = false) {
|
|
|
if (!this.liveId) return;
|
|
|
|
|
|
- // 使用 Promise 包装,支持 await
|
|
|
- return fetchLiveViewData(this.liveId).then((res) => {
|
|
|
+ return fetchLiveViewData(this.liveId, refresh).then((res) => {
|
|
|
if (res.code == 200) {
|
|
|
// 强制响应式更新,确保数据实时显示
|
|
|
this.liveViewData = res;
|