import request from './request.js' import { clickCopyText, pasteText } from './common.js' import logReport from './logReport.js' // 禁止双击缩放 document.addEventListener('dblclick', function (e) { e.preventDefault(); }); const { Dialog, Toast } = vant Toast.setDefaultOptions({ duration: 2000 }); // 从 CLOUD_GAME_SDK 结构中解构必要的函数和常量 const RtcEngineSDK = window.rtc_sdk.CloudGameSdk // 业务通道定时标识 let doConnectDirectivesIntervalerPing = null // 获取云机数据定时标识 let getUserCardInfoTimerInterval = null let getUserCardInfoRequestNum = 1 let doConnectDirectivesRequestNum = 1 let doConnectDirectivesTimerInterval = null // 触碰间隔定时标识 let noOperationSetTimeoutTimeInterval = null let noOperationSetIntervalTimeInterval = null // 倒计时定时标识 let countdownTimeInterval = null // 日志上报实例 let logReportObj = null; const app = new Vue({ el: '#app', data: { // 底部按钮 footerBtn: [{ key: 'task', img: '../static/img/wx/gengduo_icon.png' }, { key: 'home', img: '../static/img/wx/home_icon.png' }, { key: 'onBack', img: '../static/img/wx/fanhui_icon.png' }], // 宽高 width: 0, height: 0, // webRtc实例 engine: {}, // 横竖屏幕 false是竖 isLandscape: false, // 悬浮球位置 levitatedSpherePositionData: {}, // 右侧弹窗 levitatedSphereVisible: false, // 清晰度数据 definitionList: [{ name: '高清', value: 2800 }, { name: '标清', value: 2200, }, { name: '极速', value: 1800, }], // 选中的清晰度 definitionValue: '', // 分辨率 resolutionRatioVisible: false, resolutionRatioList: [], // 需要用到的参数 parametersData: {}, // 屏幕分辨率 phoneSize: {}, // 业务指令通道实例 doConnectDirectivesWs: null, // 粘贴版 pasteVersionVisible: false, pasteVersionList: [], // 复制内容 copyTextValue: '', copyTextVisible: false, // 卡数据 userCardInfoData: {}, // 是否显示计时 timingVisible: false, // 计费规则 billingRulesVisible: false, applyRecommendVisible: false, // 是否是启动不操作自动退出云机功能 isFiringNoOperationSetTimeout: false, // 超过指定触碰时间的弹窗 noOperationSetTimeoutTimeVisible: false, // 超过指定触碰时间的弹窗文案 confirmButtonText: '', // 云机剩余时长 countdownTime: 0, // 是否支持webRTC isSupportRtc: !!( typeof RTCPeerConnection !== 'undefined' && typeof RTCIceCandidate !== 'undefined' && typeof RTCSessionDescription !== 'undefined' ), // 推荐列表 recommendList: [], layoutViewWidth: null, layoutViewHeight: null, // 是否显示video isShowVideo: false, plugFlowStartTime: null, obtainCardInfoStartTime: null }, created() { this.initConfig() }, mounted() { // 初始化日志上报 this.initLogReport(); this.getUserCardInfo(); }, computed: { // 右侧弹框退出相关按钮 exitList() { let arr = [{ name: '剪贴版', key: "shearplate", img: '../static/img/wx/jianqieban_icon.png' }, { name: '退出', key: 'signout', img: '../static/img/wx/tuichu_icon.png' }] if ([1, 2, 3].includes(+this.parametersData.userCardType)) { arr.push({ name: '退出并下机', key: 'dormant', img: '../static/img/wx/tuichu_icon.png' }) } return arr }, rtcMediaPlayerStyle() { let obj = { objectFit: "fill" } if (this.isLandscape) { obj = { width: `${this.layoutViewHeight}px`, height: `${this.layoutViewWidth}px`, left: '50%', top: '50%', transform: 'translate(-50%, -50%) rotate(90deg)' } } return obj } }, methods: { // 初始化 initConfig() { // 获取窗口尺寸 this.getInitSize() let levitatedSpherePositionData = localStorage.getItem('levitatedSpherePositionData') let definitionValue = localStorage.getItem('definitionValue') // 悬浮球位置 this.levitatedSpherePositionData = levitatedSpherePositionData ? JSON.parse(levitatedSpherePositionData) : { right: '15px', top: '15px' } // 清晰度 this.definitionValue = definitionValue ? +definitionValue : 2200 // 获取参数 this.parametersData = getParameters() let { token, validTime, merchantSign } = this.parametersData // 给api增加需要的参数 request.defaults.headers.Authorization = token request.defaults.headers.versionname = '5.9.1' // 获取商户标识, 打开云机时必传, 用于日志上报 request.defaults.headers.merchantSign = merchantSign; window.onresize = () => { this.getInitSize() } }, // 连接webRTC connectWebRtc() { // console.time('获取推流响应消耗时间:') this.plugFlowStartTime = +new Date() const { sn: topic, cardToken: authToken, internetHttps, internetHttp, webrtcNetwork, webrtcTransferCmnet, webrtcTransferTelecom, webrtcTransferUnicom } = this.userCardInfoData; const isWss = location.protocol === 'https:' const url = `${isWss ? 'wss://' : 'ws://'}${isWss ? internetHttps : internetHttp}/nats`; const ICEServerUrl = [ // { "CMNET": webrtcTransferCmnet || '' }, // 移动 // { 'CHINANET-GD': webrtcTransferTelecom || '' }, // 电信 // { 'UNICOM-GD': webrtcTransferUnicom || '' }, // 联通 // webrtc三网地址遗弃, 统一使用三网解析地址 { "CMNET": webrtcNetwork }, // 移动 { 'CHINANET-GD': webrtcNetwork }, // 电信 { 'UNICOM-GD': webrtcNetwork }, // 联通 ]; const connection = { name: "猪猪令是猪", topic, // SN号 必填 url, //信令服务地址 必填 ICEServerUrl, width: 720, // 推流视频宽度 必填 height: 1280, // 推流视频高度 必填 // cardWidth: this.phoneSize.width || 1080, // 云机系统分辨率 宽 必填 // cardHeight: this.phoneSize.height || 1920, // 云机系统分辨率 高 必填 // cardDensity: this.phoneSize.dpi || 480, // 云机系统显示 密度 必填 cardWidth: 0, // 云机系统分辨率 宽 必填 cardHeight: 0, // 云机系统分辨率 高 必填 cardDensity: 0, // 云机系统显示 密度 必填 authToken, //拉流鉴权 token 必填 bitrate: 6000, //码率 必填 fps: 30, //必填 isAllowedOpenCamera: true, // 是否允许打开摄像头 callback: this.statusCallBack,//回调函数 必填 }; // 设置日志参数 推流质量 logReportObj.setParams({imageQuality: 6000}); // 初始化 SDK this.engine = new RtcEngineSDK(connection); this.engine.RtcEngine() }, // webRTC状态回调 statusCallBack(event) { if (event.type !== 'StreamStates') { // console.log("链接的状态", event, event.val); } switch (event.type) { case "screenChange": // 0:横屏 1:竖屏 // console.log("屏幕方向变化事件:" + event.val); this.isLandscape = event.val === 0; break; case "wsState": // “TIMEOUT”:nats链接超时 // success 链接成功 const status = ["TIMEOUT", "failed"] if (status.includes(event.val)) { // 设置日志 推流状态为失败 logReportObj.setParams({plugFowStatus: 2, linkWay: 0}); // 日志上报 logReportObj.collectLog( `信令服务地址nats失败: url: ${this.engine.options.url} 消息: ${JSON.stringify(event)}` ); Dialog.alert({ title: '提示', message: '链接超时', confirmButtonText: '确定', confirmButtonColor: '#3cc51f', beforeClose: (action, done) => { this.exit() done() } }) } break; case "rtcState": // “connected”:rtc链接成功 “failed”:rtc链接失败 “closed”:rtc链接关闭 “disconnected”:rtc链接超时 // console.log(event.val, 'rtc链接成功状态') if (event.val === "connected") { // Toast.clear(); // this.doConnectDirectives() // this.isShowVideo = true // this.$refs.rtcMediaPlayer.play() // let ms = +new Date - this.plugFlowStartTime // console.timeEnd('获取推流响应消耗时间:') // console.log(`获取推流响应消耗时间:${ms / 1000}秒`) // this.definitionFun(this.definitionValue) // this.pushflowPopup() // this.getResidueTime() // 设置日志 推流状态为失败 logReportObj.setParams({plugFowStatus: 1, linkWay: 1}); // 日志上报 logReportObj.collectLog(`推流成功`); playOnBtn.bind(this)() return } if (event.val === "connecting") return if (event.val === 'failed') { // 设置日志 推流状态为失败 logReportObj.setParams({plugFowStatus: 2, linkWay: 1}); // 日志上报 logReportObj.collectLog( `rtc链接失败: 消息: ${JSON.stringify(event)}` ); } if(event.val === 'disconnected') { // 设置日志 推流状态为失败 logReportObj.setParams({plugFowStatus: 2, linkWay: 1}); // 日志上报 logReportObj.collectLog( `rtc链接超时: 消息: ${JSON.stringify(event)}` ); } this.exit() break; case "AuthenticationStatus": // console.log(`鉴权${event.val === "success" ? '成功' : '失败'}`); if (event.val !== "success") { // 日志上报 logReportObj.collectLog( `rtc鉴权失败: 消息: ${JSON.stringify(event)}` ); } break; case "StreamStates": // “currentRoundTripTime”:延迟 “lostRate”:丢包率 “seconds_KBytes”:带宽 “framesPerSecond”:帧率 // ballPosition.value = event.val // console.log(event.val) break; case 'videoResolution': // 云机视频分辨率 // console.log(event.val, '分辨率') break case 'networkService': // 获取三网信息 // console.log("三网信息:", event.val); break case 'networkServiceURL': // 获取三网信息 // console.log("三网IP地址:", event.val); break } }, // 悬浮球移动 touchmoveLevitatedSphere(e) { let { pageX, pageY } = e.targetTouches[0] let min = 20 let MaxPageX = this.width - 20 let MaxPageY = this.height - 20 pageX = pageX <= min ? min : (pageX >= MaxPageX ? MaxPageX : pageX) pageY = pageY <= min ? min : (pageY >= MaxPageY ? MaxPageY : pageY) this.levitatedSpherePositionData = { left: `${pageX}px`, top: `${pageY}px`, transform: 'translate(-50%, -50%)' } }, touchendLevitatedSphere(e) { localStorage.setItem('levitatedSpherePositionData', JSON.stringify(this.levitatedSpherePositionData)) }, // 清晰度 definitionFun(value) { this.definitionValue = value this.engine.makeBitrate && this.engine.makeBitrate(value) // 设置日志参数 推流质量 logReportObj.setParams({imageQuality: value}); localStorage.setItem('definitionValue', value) this.levitatedSphereVisible = false }, // 修改分辨率 resolutionRatio() { request.get('/api/resources/v5/machine/resolution/getResolvingPower', { params: { userCardId: this.parametersData.userCardId } }).then(res => { if (res.success) { this.resolutionRatioList = res.data.map(item => { item.height = item.high return item }) this.levitatedSphereVisible = false this.resolutionRatioVisible = true } }) }, // 确定修改分辨率 confirmResolution() { let { width, height, dpi: density } = this.phoneSize this.engine.makeResolution && this.engine.makeResolution({ width, height, density }) this.resolutionRatioVisible = false }, // 退出相关按钮操作 exitFun(key) { switch (key) { case 'dormant': Dialog.alert({ title: '提示', message: '确定退出云手机并下机', confirmButtonText: '确定', confirmButtonColor: '#3cc51f', showCancelButton: true, beforeClose: (action, done) => { if (action === 'cancel') done() if (action === 'confirm') { this.downline(done) } } }) break; case 'shearplate': this.copyTextValue = '' pasteText().then(content => { typeof content !== 'boolean' ? this.openPasteboard(content) : this.copyTextVisible = true }, err => { this.copyTextVisible = true }) break; case 'signout': this.exit() break; } }, // 业务指令 doConnectDirectives() { let { internetHttps, internetHttp, localIp, cardToken } = this.userCardInfoData const isWss = location.protocol === 'https:' let cUrl = `${isWss ? 'wss' : 'ws'}://${isWss ? internetHttps : internetHttp}/businessChannel?cardIp=${localIp}&token=${cardToken}&type=directives` this.doConnectDirectivesWs = new WebSocket(cUrl); this.doConnectDirectivesWs.binaryType = 'arraybuffer' clearInterval(doConnectDirectivesIntervalerPing) // 链接成功 this.doConnectDirectivesWs.onopen = (e) => { doConnectDirectivesIntervalerPing = setInterval(() => { if (this.doConnectDirectivesWs.readyState === 1) { this.doConnectDirectivesWs.send(JSON.stringify({ type: 'ping' })); } else { clearInterval(doConnectDirectivesIntervalerPing); } }, 3000) this.doConnectDirectivesWs.send(JSON.stringify({ type: 'getVsStatus' })) this.doConnectDirectivesWs.send(JSON.stringify({ type: 'bitRate', data: { bitRate: 1243000 } })) // 设置日志参数 推流质量 logReportObj.setParams({imageQuality: 1243000}); this.doConnectDirectivesWs.send(JSON.stringify({ type: 'InputMethod', data: { type: 2 } })) this.doConnectDirectivesWs.send(JSON.stringify({ type: 'getPhoneSize' })) } // 接受到的消息 this.doConnectDirectivesWs.onmessage = res => { const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data; switch (result.type) { // 分辨率 case 'getPhoneSize': case 'setPhoneSize': let data = JSON.parse(JSON.stringify(result.data)) let { width, height } = data if (width > height) { data.width = height data.height = width } this.phoneSize = data break // 云机复制过来的文本 case 'reProduceText': if (navigator.clipboard) { navigator.clipboard.writeText(result.data.text); } break case 'downAdnInstallRep': Toast(result.data.msg) break // 接受到这个消息就自动退出云机 case 'exitPhone': this.exit() break } } // 链接报错的回调 this.doConnectDirectivesWs.onerror = res => { // 设置日志 推流状态为失败 logReportObj.setParams({plugFowStatus: 1, linkWay: 0}); // 日志上报 logReportObj.collectLog( `业务指令通道报错: url: ${res.target.url} type: ${res.type} 消息: ${JSON.stringify(res)}` ); clearInterval(doConnectDirectivesTimerInterval) if (doConnectDirectivesRequestNum > 6) { this.exit() return } doConnectDirectivesRequestNum++ this.doConnectDirectives() } }, // 粘贴版相关接口 shearContent({ type, params, queryStr }) { let url = '/api/public/v5/shear/content' if (queryStr) url += queryStr return request[type](url, params) }, // 清空全部、清除某条 deletePasteVersion(ids) { if (!ids) { Dialog.alert({ title: '提示', message: '确定清空剪贴板?', confirmButtonText: '确定', confirmButtonColor: '#3cc51f', showCancelButton: true, beforeClose: (action, done) => { if (action === 'cancel') done() if (action === 'confirm') { fun.bind(this)(done) } } }) return } fun.bind(this)() function fun(callBack = () => { }) { this.shearContent({ type: 'delete', queryStr: Qs.stringify( { ids: ids ? [ids] : this.pasteVersionList.map((v) => v.id), }, { arrayFormat: 'repeat', addQueryPrefix: true }, ) }).then(res => { if (res.status === 0) { this.getPasteVersion() callBack(true) } else { callBack(false) Toast(res.msg) } }).catch(() => { callBack(false) }) } }, // 获取粘贴版数据 getPasteVersion(callBack = () => { }) { this.shearContent({ type: 'get' }).then(res => { this.pasteVersionList = res.data callBack(true) }).catch(() => { callBack(false) }).finally(() => { }) }, // 复制弹窗是否关闭 beforeCloseCopy(action, done) { if (action !== 'confirm') { // 获取剪切板 this.getPasteVersion(() => { this.pasteVersionVisible = true this.levitatedSphereVisible = false done() }) return } if (!this.copyTextValue) { Toast('请输入复制到剪切板的内容') done(false) return } this.openPasteboard(this.copyTextValue, done) }, // 打开粘贴板 async openPasteboard(content, callBack = () => { }) { this.shearContent({ type: 'post', params: { content } }).then().finally(() => { callBack() // 获取剪切板 this.getPasteVersion(() => { this.pasteVersionVisible = true this.levitatedSphereVisible = false }) }) }, // 复制粘贴某条数据 copyPasteVersiontext(e) { clickCopyText(e, (event) => { this.doConnectDirectivesWs.send(JSON.stringify({ type: 'cutting', data: { str: event.text, }, })) Toast('复制成功') }, () => { Toast('复制失败') }) }, // 获取卡信息 getUserCardInfo() { Toast.loading({ duration: 0, // 持续展示 toast message: '数据加载中...', }); this.obtainCardInfoStartTime = + new Date() let { userCardId } = this.parametersData userCardId = +userCardId const statusTips = { // 5200:RBD资源挂载中 5200: '网络异常,请稍后重试', // 入使用排队9.9,年卡 5220: '云手机正在一键修复中', 5203: '正在排队中,请稍等', // 9.9年卡连接异常,重新进入排队 5204: '云机异常,正在为你重新分配云机', 5228: '卡的网络状态为差', 5229: '接口返回链接信息缺失', } let { isWeixin } = this.parametersData; let clientType = +isWeixin ? 'wx' : undefined; // 设置上报参数 logReportObj.setParams({userCardId}); clientType && logReportObj.setParams({clientType}); request.post('/api/resources/user/cloud/connect', { userCardId }).then(async res => { try { if (!res.success) { // 设置日志 推流状态为失败,和链接状态 logReportObj.setParams({plugFowStatus: 2, linkWay: logReportObj.RESPONSE_CODE[res.status] || 0}); // 日志上报 logReportObj.collectLog( `接口获取数据失败: url: /api/resources/user/cloud/connect method: post 参数: ${JSON.stringify({ userCardId })} 响应: ${JSON.stringify(res)}` ); return; } const data = res.data; // 设置上报参数 logReportObj.setParams({videoType: data.videoCode.toLowerCase(), resourceId: data.resourceId}); switch (res.status) { case 0: getUserCardInfoRequestNum = 1 // 不支持webRTC跳转到指定的页面 if (!res.data.isWebrtc) { // 关闭日志上报 logReportObj.destroy(); // 跳转指定页面 location.replace(`${location.origin}/h5/webRtcYJ/WXtrialInterface.html${location.search}`) return } if (!this.isSupportRtc) { // 设置日志 推流状态为失败 logReportObj.setParams({plugFowStatus: 2}); // 日志上报 logReportObj.collectLog(`${+isWeixin ? '微信小程序' : ''}当前版本暂不支持使用`); Dialog.alert({ title: '提示', message: `${+isWeixin ? '微信小程序' : ''}当前版本暂不支持使用,可下载谷歌浏览器或客户端进行使用`, confirmButtonText: '确定', confirmButtonColor: '#3cc51f', beforeClose: (action, done) => { this.exit() done() } }) return } // webRtc连接,需获取连接中转地址 if (res.data.webrtcNetworkAnalysis) { // 如果有网络分析的请求地址, 则请求,否则失败 const webrtcNetworkAnalysisReq = await request.get(res.data.webrtcNetworkAnalysis); if (webrtcNetworkAnalysisReq !== null && webrtcNetworkAnalysisReq.success) { if (webrtcNetworkAnalysisReq.data) { // 保存获取的连接地址到上个请求的响应中, 方便后面使用 res.data.webrtcNetwork = webrtcNetworkAnalysisReq.data; // 设置上报参数 logReportObj.setParams({transferServerIp: webrtcNetworkAnalysisReq.data}); }else{ // 设置上报参数 logReportObj.setParams({linkWay: 4, plugFowStatus: 2}); // 日志上报 logReportObj.collectLog( `webRtc连接,获取中转地址成功,但返回数据为空: url: ${res.data.webrtcNetworkAnalysis} method: get 参数: 无 响应: ${JSON.stringify(webrtcNetworkAnalysisReq)}` ); } }else{ // 设置上报参数 logReportObj.setParams({linkWay: 4, plugFowStatus: 2}); // 日志上报 logReportObj.collectLog( `webRtc连接,获取中转地址失败: url: ${res.data.webrtcNetworkAnalysis} method: get 参数: 无 响应: ${JSON.stringify(webrtcNetworkAnalysisReq)}` ); } }else{ // 设置上报参数 logReportObj.setParams({linkWay: 4, plugFowStatus: 2}); // 日志上报 logReportObj.collectLog( `webRtc连接,获取请求中转地址为空: url: /api/resources/user/cloud/connect method: post 参数: ${JSON.stringify({ userCardId })} 响应: ${JSON.stringify(res)}` ); } // 如果没有获取到连接地址, 则失败 if(!res.data.webrtcNetwork) { Dialog.alert({ title: '提示', message: '访问失败,请稍后重试', confirmButtonText: '确定', confirmButtonColor: '#3cc51f', beforeClose: (action, done) => { this.exit() done() } }) return; } this.userCardInfoData = res.data // let ms = + new Date() - this.obtainCardInfoStartTime this.connectWebRtc() return case 5200: case 5220: case 5203: case 5204: if (res.status === 5200) { reconnect.bind(this)() return } Toast(statusTips[res.status]) break default: // 设置上报参数 logReportObj.setParams({linkWay: logReportObj.RESPONSE_CODE[res.status] || 0}); // 日志上报 logReportObj.collectLog(statusTips[res.status] || `webRtc连接,获取请求中转地址返回异常: url: /api/resources/user/cloud/connect method: post 参数: ${JSON.stringify({ userCardId })} 响应: ${JSON.stringify(res)}` ); Toast('画面异常,请重新进入') break } setTimeout(() => { this.exit() }, 3000) } catch (error) { } }).catch((error) => { // 设置上报参数 logReportObj.setParams({linkWay: 4, plugFowStatus: 2}); // 日志上报 logReportObj.collectLog( `接口获取数据失败: url: /api/resources/user/cloud/connect method: post 参数: ${JSON.stringify({ userCardId })} 响应: ${JSON.stringify(error)}` ); }) // 重连 function reconnect() { // 重连6次结束 if (getUserCardInfoRequestNum > 6) { Toast('网络异常,请稍后重试') clearTimeout(getUserCardInfoTimerInterval) setTimeout(() => { this.exit() }, 3000) return } // 重连 getUserCardInfoTimerInterval = setTimeout(() => { this.getUserCardInfo() getUserCardInfoRequestNum++ }, 3000) } }, // 超过指定触碰时间是否提示关闭链接 pushflowPopup() { request.get('/api/public/v5/pushflow/popup').then(res => { if (res.success) { this.isFiringNoOperationSetTimeout = res.data this.noOperationSetTimeout() } }) }, // 退出功能 exit() { // 关闭日志上报 logReportObj.destroy(); this.engine.disconnect && this.engine.disconnect(); this.doConnectDirectivesWs && this.doConnectDirectivesWs.close() uni.reLaunch({ url: '/pages/index/index' }); }, // 不触碰屏幕显示退出链接弹窗 noOperationSetTimeout(key) { if (!this.isFiringNoOperationSetTimeout) return clearTimeout(noOperationSetTimeoutTimeInterval) if (key === 'cancel') { clearInterval(noOperationSetIntervalTimeInterval) this.noOperationSetTimeoutTimeVisible = false this.noOperationSetTimeout() return } noOperationSetTimeoutTimeInterval = setTimeout(() => { let index = 9 this.confirmButtonText = '退出(10秒)' this.noOperationSetTimeoutTimeVisible = true noOperationSetIntervalTimeInterval = setInterval(() => { this.confirmButtonText = `退出${index ? `(${index}秒)` : ''}` index-- if (index < 0) { this.noOperationSetTimeout('cancel') this.exit() } }, 1000) }, 300000) }, // 获取云机剩余时长 async getResidueTime() { clearInterval(countdownTimeInterval) const { userCardType, isShowCountdown, isShowRule } = this.parametersData const { userCardId } = this.userCardInfoData if (![1, 2, 3].includes(+userCardType)) return const res = await request.get(`/api/resources/yearMember/getResidueTime?userCardId=${userCardId}`) let time = res.data; if (!res.status) { this.countdownTime = residueTimeStamp(time) await request.get(`/api/resources/yearMember/startTime?userCardId=${userCardId}`) if (+isShowCountdown) this.timingVisible = true if (+isShowRule) this.billingRulesVisible = true countdownTimeInterval = setInterval(() => { if (time <= 0) { clearInterval(countdownTimeInterval) this.downline() return } time-- this.countdownTime = residueTimeStamp(time) }, 1000) } }, // 关闭倒计时弹窗 handlecountdownTimeClose() { const { userCardId } = this.userCardInfoData request.get(`/api/resources/yearMember/closeRemind?userCardId=${userCardId}`).then(res => { if (!res.status) { clearInterval(countdownTimeInterval) this.timingVisible = false return } Toast(res.msg); }) }, // 退出并下机 downline(fun = () => { }) { const { userCardId } = this.userCardInfoData request.get(`/api/resources/yearMember/downline?userCardId=${userCardId}`).then(res => { if (!res.status) { fun(true) // 通信给h5项目告知是退出并下机 parent.postMessage( { type: 'exit', }, '*', ); uni.postMessage({ data: { type: 'exit' } }); this.exit() return } fun(false) Toast(res.msg); }) }, // 获取推荐列表 getRecommend() { const { userCardId } = this.userCardInfoData request.get(`/api/public/v1/market/get/recommend?userCardId=${userCardId}`).then(res => { if (!res.status) { this.billingRulesVisible = false this.recommendList = res.data this.recommendList.length && (this.applyRecommendVisible = true) } }) }, // 下载apk downAndInstallApk({ downloadUrl: apkUrl, id: taskUid }) { this.doConnectDirectivesWs.send(JSON.stringify({ type: 'downAndInstallApk', data: { apkUrl, taskUid }, })) }, // 移开手指时会发生的回调 touchendRtcMediaPlayer(event) { this.engine.touchClick && this.engine.touchClick(event, 1, true) this.noOperationSetTimeout() }, // 返回、主页、任务器 footerBtnFun(key) { this.engine[key] && this.engine[key]() this.noOperationSetTimeout() }, // 获取初始化尺寸 getInitSize() { // 高度、悬浮球相关配置 this.height = window.innerHeight this.width = window.innerWidth this.$nextTick(() => { // 云机画面宽高 let layoutView = document.querySelector('.layout-view') this.layoutViewWidth = layoutView.offsetWidth this.layoutViewHeight = layoutView.offsetHeight }) }, // 音量 volumeControl(value) { this.engine.ExexuteKeyBoard && this.engine.ExexuteKeyBoard(value) this.$refs.rtcMediaPlayer && (this.$refs.rtcMediaPlayer.muted = false) }, // 初始化日志上报实例 initLogReport() { // 初始化日志上报实例 logReportObj = new logReport({ request }); uni.getEnv((res) => { // 设置上报参数 logReportObj.setParams({clientType: Object.keys(res)[0]}); }) } } }) function playOnBtn() { const { isTips } = this.parametersData; Dialog.alert({ title: '提示', message: `${+isTips ? '开始' : '继续'}使用云手机`, confirmButtonText: '确定', confirmButtonColor: '#3cc51f', beforeClose: (action, done) => { if (action === 'confirm') { this.isShowVideo = true Toast.clear(); this.$refs.rtcMediaPlayer.play() setTimeout(() => { this.doConnectDirectives() this.definitionFun(this.definitionValue) this.pushflowPopup() this.getResidueTime() done() }) } } }); } // 获取URL参数 function getParameters() { let arr = location.search.split('?') let obj = {} if (arr[1]) { arr = arr[1].split('&') arr.forEach(item => { let [key, value = ''] = item.split('=') obj[key] = value }) } return obj } // 倒计时处理的时间 function residueTimeStamp(value) { let theTime = value;//秒 let middle = 0;//分 let hour = 0;//小时 if (theTime > 59) { middle = parseInt(theTime / 60); theTime = parseInt(theTime % 60); } if (middle > 59) { hour = parseInt(middle / 60); middle = parseInt(middle % 60); } theTime < 10 ? theTime = '0' + theTime : theTime = theTime middle < 10 ? middle = '0' + middle : middle = middle hour < 10 ? hour = '0' + hour : hour = hour return hour + ':' + middle + ':' + theTime }