fix
This commit is contained in:
@@ -13,7 +13,7 @@ const isMobileEnvironment = (): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
|
// 页面私有变量,避免触发无效渲染
|
||||||
_wasPlayingBeforeInterrupt: false,
|
_wasPlayingBeforeInterrupt: false,
|
||||||
_pauseVideoHandler: null as any,
|
_pauseVideoHandler: null as any,
|
||||||
_resumeVideoHandler: null as any,
|
_resumeVideoHandler: null as any,
|
||||||
@@ -22,11 +22,8 @@ Page({
|
|||||||
_networkStatusChangeHandler: null as any,
|
_networkStatusChangeHandler: null as any,
|
||||||
_videoContext: null as any,
|
_videoContext: null as any,
|
||||||
|
|
||||||
/**
|
|
||||||
* 页面的初始数据
|
|
||||||
*/
|
|
||||||
data: {
|
data: {
|
||||||
dataList: {},
|
dataList: {} as any,
|
||||||
nodes: [] as any[],
|
nodes: [] as any[],
|
||||||
eveId: null,
|
eveId: null,
|
||||||
store: {},
|
store: {},
|
||||||
@@ -41,38 +38,28 @@ Page({
|
|||||||
isAppHidden: false,
|
isAppHidden: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 生命周期函数--监听页面加载
|
|
||||||
*/
|
|
||||||
async onLoad(options: any) {
|
async onLoad(options: any) {
|
||||||
const app = getApp<IAppOption>();
|
const app = getApp<IAppOption>();
|
||||||
wx.hideShareMenu({ menus: ["shareAppMessage"] });
|
wx.hideShareMenu({ menus: ["shareAppMessage"] });
|
||||||
new UrlParamsHandler(options);
|
new UrlParamsHandler(options);
|
||||||
app.globalData.store = options;
|
app.globalData.store = options;
|
||||||
|
|
||||||
|
// 适配底部安全区
|
||||||
let safeBottom = 24;
|
let safeBottom = 24;
|
||||||
try {
|
try {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const systemInfo = wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync();
|
const { windowHeight, safeArea } = wx.getWindowInfo ? wx.getWindowInfo() : wx.getSystemInfoSync();
|
||||||
safeBottom = Math.abs(systemInfo.windowHeight - systemInfo.safeArea.bottom) + 10;
|
safeBottom = safeArea ? Math.abs(windowHeight - safeArea.bottom) + 10 : 24;
|
||||||
if (safeBottom === 0) safeBottom = 24;
|
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
|
|
||||||
this.setData({
|
this.setData({ safeBottom, store: options });
|
||||||
safeBottom,
|
|
||||||
store: options,
|
|
||||||
resumeTime: this.getResumeTime(),
|
|
||||||
});
|
|
||||||
|
|
||||||
this.initSystemListeners();
|
this.initSystemListeners();
|
||||||
|
|
||||||
if (!isMobileEnvironment()) {
|
if (!isMobileEnvironment()) {
|
||||||
this.handleEnterError("当前环境不支持观看,请使用手机观看。", "环境不支持");
|
return this.handleEnterError("当前环境不支持观看,请使用手机观看。", "环境不支持");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool = await app.login("video");
|
if (!(await app.login("video"))) return;
|
||||||
if (!bool) return;
|
|
||||||
|
|
||||||
//@ts-ignore 开启防截屏
|
//@ts-ignore 开启防截屏
|
||||||
if (wx.setVisualEffectOnCapture) wx.setVisualEffectOnCapture({ visualEffect: 'hidden' });
|
if (wx.setVisualEffectOnCapture) wx.setVisualEffectOnCapture({ visualEffect: 'hidden' });
|
||||||
@@ -85,10 +72,7 @@ Page({
|
|||||||
onHide() {
|
onHide() {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
if (wx.setVisualEffectOnCapture) wx.setVisualEffectOnCapture({ visualEffect: 'none' });
|
if (wx.setVisualEffectOnCapture) wx.setVisualEffectOnCapture({ visualEffect: 'none' });
|
||||||
|
|
||||||
if (this.data.currentTime > 0) {
|
|
||||||
this.flushProgress();
|
this.flushProgress();
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnload() {
|
onUnload() {
|
||||||
@@ -96,11 +80,9 @@ Page({
|
|||||||
if (wx.setVisualEffectOnCapture) wx.setVisualEffectOnCapture({ visualEffect: 'none' });
|
if (wx.setVisualEffectOnCapture) wx.setVisualEffectOnCapture({ visualEffect: 'none' });
|
||||||
this.flushProgress();
|
this.flushProgress();
|
||||||
|
|
||||||
try {
|
try { this.pauseVideoBeforeNavigate(); } catch (err) { }
|
||||||
this.pauseVideoBeforeNavigate();
|
|
||||||
} catch (err) { }
|
|
||||||
|
|
||||||
// 卸载时清理所有系统级监听与定时器
|
// 卸载事件与定时器
|
||||||
if (this._pauseVideoHandler) wx.offAudioInterruptionBegin(this._pauseVideoHandler);
|
if (this._pauseVideoHandler) wx.offAudioInterruptionBegin(this._pauseVideoHandler);
|
||||||
if (this._resumeVideoHandler) wx.offAudioInterruptionEnd(this._resumeVideoHandler);
|
if (this._resumeVideoHandler) wx.offAudioInterruptionEnd(this._resumeVideoHandler);
|
||||||
if (this._appHideHandler) wx.offAppHide(this._appHideHandler);
|
if (this._appHideHandler) wx.offAppHide(this._appHideHandler);
|
||||||
@@ -126,18 +108,16 @@ Page({
|
|||||||
wx.onNetworkStatusChange(this._networkStatusChangeHandler);
|
wx.onNetworkStatusChange(this._networkStatusChangeHandler);
|
||||||
|
|
||||||
this._pauseVideoHandler = () => {
|
this._pauseVideoHandler = () => {
|
||||||
// 来电等系统中断:先落盘进度再暂停
|
|
||||||
this.flushProgress();
|
this.flushProgress();
|
||||||
this._wasPlayingBeforeInterrupt = this.data.playing;
|
this._wasPlayingBeforeInterrupt = this.data.playing;
|
||||||
this.pauseVideoBeforeNavigate();
|
this.pauseVideoBeforeNavigate();
|
||||||
};
|
};
|
||||||
|
|
||||||
this._resumeVideoHandler = () => {
|
this._resumeVideoHandler = () => {
|
||||||
const wasPlaying = this._wasPlayingBeforeInterrupt;
|
if (this._wasPlayingBeforeInterrupt && !this.data.isAppHidden) {
|
||||||
this._wasPlayingBeforeInterrupt = false;
|
|
||||||
if (wasPlaying && !this.data.isAppHidden) {
|
|
||||||
this.resumeVideoAfterInterrupt();
|
this.resumeVideoAfterInterrupt();
|
||||||
}
|
}
|
||||||
|
this._wasPlayingBeforeInterrupt = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
this._appHideHandler = () => {
|
this._appHideHandler = () => {
|
||||||
@@ -171,63 +151,12 @@ Page({
|
|||||||
this.getVideoContext().play();
|
this.getVideoContext().play();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 统一写进度:interruptedTime 与 currentTime 成对写,保证两者永远一致
|
// 统一进度落盘(极简版,直接信任内存里的 currentTime)
|
||||||
flushProgress(time?: number) {
|
flushProgress() {
|
||||||
const t = Math.max(time || this.data.currentTime || 0, Number(wx.getStorageSync("currentTime") || 0));
|
const t = this.data.currentTime;
|
||||||
if (t <= 0) return;
|
if (t > 0) {
|
||||||
wx.setStorageSync("interruptedTime", t);
|
wx.setStorageSync("interruptedTime", t);
|
||||||
wx.setStorageSync("currentTime", t);
|
wx.setStorageSync("currentTime", t);
|
||||||
},
|
|
||||||
|
|
||||||
// 视频元信息就绪后才 seek,否则 seek 会被静默忽略
|
|
||||||
onPlayerLoadedMetadata() {
|
|
||||||
this.seekToResumeTime();
|
|
||||||
},
|
|
||||||
|
|
||||||
seekToResumeTime() {
|
|
||||||
const t = this.getResumeTime();
|
|
||||||
if (t > 0) {
|
|
||||||
this.getVideoContext().seek(t);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onPlayerPlay() {
|
|
||||||
this.setData({ playing: true });
|
|
||||||
this.seekToResumeTime();
|
|
||||||
this.startSendProgress();
|
|
||||||
},
|
|
||||||
|
|
||||||
onPlayerPause() {
|
|
||||||
this.setData({ playing: false });
|
|
||||||
this.clearSendProgressTimer();
|
|
||||||
this.flushProgress();
|
|
||||||
},
|
|
||||||
|
|
||||||
onPlayerEnded() {
|
|
||||||
this.setData({ playing: false, resumeTime: 0 });
|
|
||||||
wx.setStorageSync("ended", true);
|
|
||||||
this.clearSendProgressTimer();
|
|
||||||
wx.removeStorageSync("interruptedTime");
|
|
||||||
wx.removeStorageSync("currentTime");
|
|
||||||
},
|
|
||||||
|
|
||||||
onPlayerError(e: any) {
|
|
||||||
const detail = (e && e.detail) || e || {};
|
|
||||||
wx.showModal({
|
|
||||||
title: "播放出错",
|
|
||||||
content: String(detail.errMsg || detail.message || JSON.stringify(detail) + '请联系坐席'),
|
|
||||||
showCancel: false,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// 接收原生组件的时间更新
|
|
||||||
onPlayerTimeUpdate(e: any) {
|
|
||||||
let time = e.detail?.currentTime ?? e.detail?.detail?.currentTime;
|
|
||||||
if (typeof time === 'number' && time > 0) {
|
|
||||||
const currentTime = Math.floor(time);
|
|
||||||
if (currentTime === this.data.currentTime) return;
|
|
||||||
this.data.currentTime = currentTime;
|
|
||||||
if (currentTime % 5 === 0) this.flushProgress(currentTime);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -238,12 +167,54 @@ Page({
|
|||||||
return Math.max(interrupted, current);
|
return Math.max(interrupted, current);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onPlayerPlay() {
|
||||||
|
this.setData({ playing: true });
|
||||||
|
// 异步拉取到 fileid 后,初次播放如果存在历史记录,则跳转
|
||||||
|
if (this.data.resumeTime > 0) {
|
||||||
|
this.getVideoContext().seek(this.data.resumeTime);
|
||||||
|
this.setData({ resumeTime: 0 }); // 跳转完立即清空,防止二次跳转
|
||||||
|
}
|
||||||
|
this.startSendProgress();
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayerPause() {
|
||||||
|
this.setData({ playing: false });
|
||||||
|
this.clearSendProgressTimer();
|
||||||
|
this.flushProgress();
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayerEnded() {
|
||||||
|
this.setData({ playing: false, resumeTime: 0, currentTime: 0 });
|
||||||
|
wx.setStorageSync("ended", true);
|
||||||
|
this.clearSendProgressTimer();
|
||||||
|
wx.removeStorageSync("interruptedTime");
|
||||||
|
wx.removeStorageSync("currentTime");
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayerError(e: any) {
|
||||||
|
const detail = e?.detail || e || {};
|
||||||
|
wx.showModal({
|
||||||
|
title: "播放出错",
|
||||||
|
content: String(detail.errMsg || detail.message || JSON.stringify(detail) + ',请联系客服'),
|
||||||
|
showCancel: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayerTimeUpdate(e: any) {
|
||||||
|
let time = e.detail?.currentTime ?? e.detail?.detail?.currentTime;
|
||||||
|
if (typeof time === 'number' && time > 0) {
|
||||||
|
const currentTime = Math.floor(time);
|
||||||
|
if (currentTime === this.data.currentTime) return; // 避免重复操作
|
||||||
|
this.data.currentTime = currentTime;
|
||||||
|
// 逢 5 秒落盘一次
|
||||||
|
if (currentTime % 5 === 0) this.flushProgress();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
startSendProgress() {
|
startSendProgress() {
|
||||||
this.clearSendProgressTimer();
|
this.clearSendProgressTimer();
|
||||||
this.sendProgress();
|
this.sendProgress(); // 启动时先发一次
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => this.sendProgress(), 15000) as unknown as number;
|
||||||
this.sendProgress();
|
|
||||||
}, 15000) as unknown as number;
|
|
||||||
this.setData({ sendDurationTimer: timer });
|
this.setData({ sendDurationTimer: timer });
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -256,21 +227,18 @@ Page({
|
|||||||
|
|
||||||
async sendProgress() {
|
async sendProgress() {
|
||||||
if (!this.data.playing) return;
|
if (!this.data.playing) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const openId = wx.getStorageSync("openId");
|
|
||||||
const code = wx.getStorageSync("code");
|
const code = wx.getStorageSync("code");
|
||||||
const state = wx.getStorageSync("state");
|
const openId = wx.getStorageSync("openId");
|
||||||
const seeId = wx.getStorageSync("seeId");
|
const duration = this.data.currentTime + 1; // 时长兜底补偿
|
||||||
// 视频时长兜底补偿
|
|
||||||
const duration = this.data.currentTime + 1;
|
|
||||||
|
|
||||||
const url = code ? `/app/video-watch/inspect` : `/app/watch/inspect`;
|
const params = code
|
||||||
const params = code ? { openId, code, duration } : { openId, state, seeId, duration };
|
? { openId, code, duration }
|
||||||
|
: { openId, state: wx.getStorageSync("state"), seeId: wx.getStorageSync("seeId"), duration };
|
||||||
|
|
||||||
await request({
|
await request({
|
||||||
options: {
|
options: {
|
||||||
url,
|
url: code ? `/app/video-watch/inspect` : `/app/watch/inspect`,
|
||||||
data: aesEncrypt(JSON.stringify(params), AES_KEY, AES_IV),
|
data: aesEncrypt(JSON.stringify(params), AES_KEY, AES_IV),
|
||||||
},
|
},
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
@@ -280,10 +248,6 @@ Page({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onAnswerChange() {
|
|
||||||
this.updateProgress();
|
|
||||||
},
|
|
||||||
|
|
||||||
async search() {
|
async search() {
|
||||||
const app = getApp<IAppOption>();
|
const app = getApp<IAppOption>();
|
||||||
if (!(await app.checkLoginState())) return;
|
if (!(await app.checkLoginState())) return;
|
||||||
@@ -291,19 +255,21 @@ Page({
|
|||||||
const code = wx.getStorageSync("code");
|
const code = wx.getStorageSync("code");
|
||||||
const params = { openId: wx.getStorageSync("openId"), ...app.globalData.store };
|
const params = { openId: wx.getStorageSync("openId"), ...app.globalData.store };
|
||||||
|
|
||||||
const url = code ? `/app/video-watch/details` : `/app/watch/details`;
|
|
||||||
const data = await request({
|
const data = await request({
|
||||||
options: { url, method: code ? "GET" : "POST", data: params },
|
options: {
|
||||||
|
url: code ? `/app/video-watch/details` : `/app/watch/details`,
|
||||||
|
method: code ? "GET" : "POST",
|
||||||
|
data: params
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const targetData = code ? data.watch : data.data;
|
const targetData = code ? data.watch : data.data;
|
||||||
|
|
||||||
if (!targetData.extend?.fileid) {
|
if (!targetData?.extend?.fileid) {
|
||||||
const stateParam = code ? -1 : 5;
|
const stateParam = code ? -1 : 5;
|
||||||
wx.reLaunch({
|
return wx.reLaunch({
|
||||||
url: `/pages/live/registration/registration?content=${targetData?.content || ''}&state=${stateParam}`,
|
url: `/pages/live/registration/registration?content=${targetData?.content || ''}&state=${stateParam}`,
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
@@ -311,13 +277,13 @@ Page({
|
|||||||
eveId: targetData.eveId,
|
eveId: targetData.eveId,
|
||||||
nodes: htmlToWxNodes(targetData.content),
|
nodes: htmlToWxNodes(targetData.content),
|
||||||
fileid: targetData.extend.fileid,
|
fileid: targetData.extend.fileid,
|
||||||
resumeTime: this.getResumeTime(),
|
resumeTime: this.getResumeTime(), // 获取到真实视频时,一次性读取恢复点
|
||||||
});
|
});
|
||||||
|
|
||||||
this.selectComponent("#tabs")?.resize();
|
this.selectComponent("#tabs")?.resize();
|
||||||
},
|
},
|
||||||
|
|
||||||
updateProgress() {
|
onAnswerChange() {
|
||||||
const quizComponent = this.selectComponent("#quizComponent");
|
const quizComponent = this.selectComponent("#quizComponent");
|
||||||
if (quizComponent) {
|
if (quizComponent) {
|
||||||
this.setData({ canSubmit: quizComponent.isAllAnswered() });
|
this.setData({ canSubmit: quizComponent.isAllAnswered() });
|
||||||
@@ -326,9 +292,9 @@ Page({
|
|||||||
|
|
||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
if (!wx.getStorageSync("ended")) {
|
if (!wx.getStorageSync("ended")) {
|
||||||
return wx.showModal({ title: "请先观看完整视频,再答题", showCancel: false, confirmColor: "#FF0000" });
|
return wx.showModal({ title: "提示", content: "请先观看完整视频,再参与答题", showCancel: false, confirmColor: "#FF0000" });
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
|
||||||
if (this.data.dataList?.userAnsNum >= this.data.dataList?.answerMax) {
|
if (this.data.dataList?.userAnsNum >= this.data.dataList?.answerMax) {
|
||||||
return wx.showToast({ title: "答题次数已用完", icon: "none", duration: 3000 });
|
return wx.showToast({ title: "答题次数已用完", icon: "none", duration: 3000 });
|
||||||
}
|
}
|
||||||
@@ -337,10 +303,10 @@ Page({
|
|||||||
if (!quizComponent) return wx.showToast({ title: "组件加载失败", icon: "none" });
|
if (!quizComponent) return wx.showToast({ title: "组件加载失败", icon: "none" });
|
||||||
|
|
||||||
if (!quizComponent.isAllAnswered()) {
|
if (!quizComponent.isAllAnswered()) {
|
||||||
const progress = quizComponent.getProgress();
|
const { answered, total } = quizComponent.getProgress();
|
||||||
return wx.showModal({
|
return wx.showModal({
|
||||||
title: "答题未完成",
|
title: "答题未完成",
|
||||||
content: `您已完成 ${progress.answered}/${progress.total} 题,请完成所有题目后再提交。`,
|
content: `您已完成 ${answered}/${total} 题,请完成所有题目后再提交。`,
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -381,13 +347,12 @@ Page({
|
|||||||
confirmText: "立即领取",
|
confirmText: "立即领取",
|
||||||
confirmColor: "#FF0000",
|
confirmColor: "#FF0000",
|
||||||
success: async (res) => {
|
success: async (res) => {
|
||||||
if (res.confirm) {
|
if (!res.confirm) return;
|
||||||
if (redPackage?.packageInfo) {
|
if (redPackage?.packageInfo) {
|
||||||
this.transferRedPacket(redPackage);
|
this.transferRedPacket(redPackage);
|
||||||
} else if (redPackage?.redId) {
|
} else if (redPackage?.redId) {
|
||||||
await this.handleReceive(redPackage.redId);
|
await this.handleReceive(redPackage.redId);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -401,21 +366,20 @@ Page({
|
|||||||
wx.hideLoading();
|
wx.hideLoading();
|
||||||
return wx.showModal({ content: "你的微信版本过低,请更新至最新版本。", showCancel: false });
|
return wx.showModal({ content: "你的微信版本过低,请更新至最新版本。", showCancel: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
// @ts-ignore
|
//@ts-ignore
|
||||||
wx.requestMerchantTransfer({
|
wx.requestMerchantTransfer({
|
||||||
mchId: redPackage.mchId,
|
mchId: redPackage.mchId,
|
||||||
appId,
|
appId,
|
||||||
package: redPackage.packageInfo,
|
package: redPackage.packageInfo,
|
||||||
success: () => {
|
success: () => resolve(),
|
||||||
wx.hideLoading();
|
|
||||||
wx.showToast({ title: "领取成功", icon: "success" });
|
|
||||||
resolve();
|
|
||||||
},
|
|
||||||
fail: (err: any) => reject(new Error(err?.errMsg || "领取失败")),
|
fail: (err: any) => reject(new Error(err?.errMsg || "领取失败")),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
wx.hideLoading();
|
||||||
|
wx.showToast({ title: "领取成功", icon: "success" });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
wx.hideLoading();
|
wx.hideLoading();
|
||||||
wx.showToast({ title: err?.message || "领取失败", icon: "none" });
|
wx.showToast({ title: err?.message || "领取失败", icon: "none" });
|
||||||
@@ -423,18 +387,16 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async handleReceive(id: any) {
|
async handleReceive(id: any) {
|
||||||
const { code } = this.data.store as Record<string, any>;
|
|
||||||
try {
|
try {
|
||||||
wx.showLoading({ title: "领取中" });
|
wx.showLoading({ title: "领取中" });
|
||||||
await receiveRedPacket(
|
await receiveRedPacket(
|
||||||
{ appId, code, openId: wx.getStorageSync("openId"), redId: id },
|
{ appId, code: wx.getStorageSync("code"), openId: wx.getStorageSync("openId"), redId: id },
|
||||||
'/app/general/receive-red',
|
'/app/general/receive-red',
|
||||||
appId
|
appId
|
||||||
);
|
);
|
||||||
wx.hideLoading();
|
wx.hideLoading();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
wx.hideLoading();
|
wx.hideLoading();
|
||||||
console.error('领取红包失败:', err);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user