// pages/video/video.ts import UrlParamsHandler from "../../../utils/store"; import { htmlToWxNodes } from "../../../utils/html-to-wx-nodes"; import { request } from "../../../utils/request"; import { version, appversion, appId } from "../../../env"; import { receiveRedPacket } from "../../../utils/util"; const app = getApp() const isMobileEnvironment = (): boolean => { const platform = wx.getSystemInfoSync().platform?.toLowerCase() || ''; return platform !== 'windows' && platform !== 'mac'; }; Page({ /** * 页面的初始数据 */ data: { dataList: {}, nodes: [] as any[], eveId: null, store: {}, active: 0, canSubmit: false, safeBottom: 0, initialLoading: false, }, /** * 生命周期函数--监听页面加载 */ async onLoad(options: any) { const openId = wx.getStorageSync("openId"); if (!openId) { // 未登录:保持 loading 遮罩,跳转 web-view 授权 const code = options.code || ""; const url = `/pages/webview-auth/index?back=video&code=${code}` wx.navigateTo({ url }); return; } // 已登录(含授权返回):隐藏 loading 遮罩,直接进入页面 this.setData({ initialLoading: true }); wx.hideShareMenu({ menus: ["shareAppMessage"], // 单独禁用好友分享 }); new UrlParamsHandler(options); // 合并 URL 参数与 globalData.store 中已有的登录信息(来自 webview-auth) app.globalData.store = { ...app.globalData.store, ...options, }; let safeBottom = 0; //@ts-ignore if (wx.getWindowInfo) { //@ts-ignore const systemInfo = wx.getWindowInfo(); safeBottom = Math.abs(systemInfo.windowHeight - systemInfo.safeArea.bottom) + 10; if (safeBottom === 0) safeBottom = 24; } else { const systemInfo = wx.getSystemInfoSync(); safeBottom = systemInfo.safeArea ? Math.abs(systemInfo.windowHeight - systemInfo.safeArea.bottom) + 10 : 24; } this.setData({ safeBottom: safeBottom, store: app.globalData.store, }); if (!isMobileEnvironment()) { this.handleEnterError( "当前环境不支持观看,请使用手机观看。", "环境不支持", ); return; } const bool = await app.login("video"); if (!bool) return; // 开启防截屏(仅限当前页面生命周期内) //@ts-ignore wx.setVisualEffectOnCapture({ visualEffect: 'hidden', }); }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, handleEnterError(message: string, title = "无法进入") { wx.showModal({ title: title, content: message, showCancel: false, confirmText: "确定", }); }, handleBack() { wx.switchTab({ url: "/pages/tab-bar/education/index", }); }, /** * 生命周期函数--监听页面显示 */ onShow() { const openId = wx.getStorageSync("openId"); if (!openId) return; this.setData({ initialLoading: true }); this.search(); }, /** * 生命周期函数--监听页面隐藏 */ onHide() { // 离开视频页时恢复截屏能力,避免影响其他页面 //@ts-ignore wx.setVisualEffectOnCapture({ visualEffect: 'none', }); }, /** * 生命周期函数--监听页面卸载 */ onUnload() { // 卸载时恢复截屏能力 //@ts-ignore wx.setVisualEffectOnCapture({ visualEffect: 'none', }); }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { }, /** * 用户点击右上角分享 */ onShareAppMessage() { }, onChange(event: any) { this.setData({ active: event.detail.index, }); }, // 监听答题变化 onAnswerChange() { this.updateProgress(); }, async search() { const app = getApp(); const bool = await app.checkLoginState(); if (!bool) return; const code = wx.getStorageSync("code"); const params = { openId: wx.getStorageSync("openId"), ...app.globalData.store, }; if (code) { const data = await request({ options: { url: `/app/video-watch/details?version=${version.details}&appVer=${appversion}`, method: "GET", data: params, }, }); if (!data.watch.url) { wx.reLaunch({ url: `/pages/live/registration/registration?content=${data.watch.content}&state=${-1}`, }); } const nodes = htmlToWxNodes(data.watch.content); this.setData({ dataList: data.watch, eveId: data.watch.eveId, nodes, }); } else { const data = await request({ options: { url: `/app/watch/details?version=${version.details}&appVer=${appversion}`, data: params, }, }); if (!data.data.url) { wx.reLaunch({ url: `/pages/live/registration/registration?content=${data.data.content }&state=${5}`, }); } const nodes = htmlToWxNodes(data.data.content); this.setData({ dataList: data.data, eveId: data.data.eveId, nodes, }); } this.selectComponent("#tabs").resize(); }, // 更新答题进度 updateProgress() { const quizComponent = this.selectComponent("#quizComponent"); if (quizComponent) { const canSubmit = quizComponent.isAllAnswered(); this.setData({ canSubmit: canSubmit, }); } }, handleSubmit(this) { const ended = wx.getStorageSync("ended") || false; if (!ended) { wx.showModal({ title: "请先观看视频,再答题", showCancel: false, confirmText: "确定", confirmColor: "#FF0000", }); return; } //@ts-ignore if (this.data.dataList?.userAnsNum >= this.data.dataList?.answerMax) { wx.showToast({ title: "答题次数已用完", icon: "none", duration: 6000, }); return; } const quizComponent = this.selectComponent("#quizComponent"); if (!quizComponent) { wx.showToast({ title: "组件加载失败", icon: "none", }); return; } const isAllAnswered = quizComponent.isAllAnswered(); if (!isAllAnswered) { const progress = quizComponent.getProgress(); wx.showModal({ title: "答题未完成", content: `您已完成 ${progress.answered}/${progress.total} 题,请完成所有题目后再提交。`, showCancel: false, confirmText: "继续答题", }); return; } const answers = quizComponent.getAllAnswers(); if (!answers || answers.length === 0) { wx.showToast({ title: "请先完成答题", icon: "none", }); return; } wx.showModal({ title: "确认提交", content: `您已完成 ${answers.length} 道题目,确定要提交答案吗?`, success: (res) => { if (res.confirm) { this.submitAnswers(answers); } }, }); }, async submitAnswers(answers: any[]) { const code = wx.getStorageSync("code"); const params = { answers, openId: wx.getStorageSync("openId"), eveId: this.data.eveId, ...this.data.store, }; wx.showLoading({ title: "提交中...", }); let res = null; if (code) { res = await request({ options: { url: "/app/video-watch/interactive", data: params, }, }); } else { res = await request({ options: { url: "/app/watch/interactive", data: params, }, }); } if (res.code !== 200) { wx.showToast({ title: res.msg || "提交失败", icon: "none", duration: 2000, }); return; } const { pass, redPackage } = res.data || {}; if (pass) { wx.showModal({ content: "🎉 领取红包!", showCancel: false, confirmText: "立即领取", confirmColor: "#FF0000", success: async (res) => { if (res.confirm) { if (redPackage?.packageInfo) { try { wx.showLoading({ title: "领取中", mask: true }); if (wx.canIUse?.("requestMerchantTransfer")) { await new Promise((resolve, reject) => { // @ts-ignore wx.requestMerchantTransfer({ mchId: redPackage.mchId, appId, package: redPackage.packageInfo, success: () => { wx.showToast({ title: "领取成功", icon: "success" }); resolve(); }, fail: (err: any) => { console.error("拉起转账失败:", err); wx.showToast({ title: "领取失败", icon: "none" }); reject(new Error(err?.errMsg || "领取失败")); }, }); }); } else { wx.showModal({ content: "你的微信版本过低,请更新至最新版本。", showCancel: false, }); throw new Error("微信版本过低"); } } catch (err: any) { wx.hideLoading(); const msg = err?.data?.msg || err?.errMsg || err?.message || "领取失败"; wx.showToast({ title: msg, icon: "none" }); } } else { await this.handleReceive(redPackage.redId); } } }, }); } else { wx.showToast({ title: "回答错误,您与红包擦肩而过", icon: "none", duration: 6000, }); } }, async handleReceive(id: any) { const { code } = this.data.store as Record; const params = { appId, code, openId: wx.getStorageSync("openId"), redId: id, } try { await receiveRedPacket( params, '/app/general/receive-red', appId ); } catch (err) { console.error('领取红包失败:', err); } }, // 跳转前暂停视频播放 pauseVideoBeforeNavigate() { const video = this.selectComponent("#myVideo") as any; if (video && video.pauseVideo) { video.pauseVideo(); } }, handleCustomReport() { this.pauseVideoBeforeNavigate(); const { code, state, seeId } = this.data.store as Record; const params: Record = {}; if (code) params.code = code; if (state) params.state = state; if (seeId) params.seeId = seeId; wx.navigateTo({ url: `/pages/live/report/report`, }); }, handleViewHitory() { this.pauseVideoBeforeNavigate(); const { code, state, seeId } = this.data.store as Record; const params: Record = {}; if (code) params.code = code; if (state) params.state = state; if (seeId) params.seeId = seeId; wx.navigateTo({ url: `/pages/live/red-history/red-history`, }); } });