<template> <view class="container"> <trtc-room ref="trtc-component" :config="rtcConfig"> </trtc-room> <view class="tip-toast" v-if="showTipToast"> <view>当前房间为1v1双人通话房间</view> <view>不希望其他人打扰</view> </view> <view class="popup-open" @click="showGoods()"> <view class="iconfont iconzhibo-shangpin"></view> </view> <uni-popup ref="popup" type="bottom"> <view class="popup-box"> <view class="popup-close" @click="closeGoods()">收起</view> <scroll-view scroll-y="true" class="good-box"> <view class="goods-row" v-for="(item, index) in goodsList" :key="index"> <image class="goods-img" :src="item.imgPath" mode="aspectFill"></image> <view class="goods-info"> <view class="goods-name">{{item.productName}}</view> <!-- <view class="goods-sales">{{item.sellCount}}人付款</view> --> <view class="goods-number"> <text class="goods-icon">¥</text> <text class="goods-spec">{{item.bizPrice}}</text> <text class="price">原价:{{item.originalPrice}}</text> </view> </view> <!-- <view class="more-button"> <view class="iconfont icongengduo"></view> </view> --> </view> </scroll-view> </view> </uni-popup> <u-top-tips ref="uTips"></u-top-tips> <view class="top_box" :style="{ top: btn_top, left: btn_left}"> <image class="top_box_img" :src="head_img"></image> <view class="top_box_text"> <text class="text_box_top">{{title}}</text><text class="text_box_bottom" style="display:none">{{user_name}}</text> </view> </view> </view> </template> <script> const NET = require('@/utils/request') const API = require('@/config/api') import { genTestUserSig, setData } from "@/pagesGood/debug/GenerateTestUserSig"; import trtcRoom from "@/pagesGood/trtc-room/trtc-room"; export default { components: { trtcRoom }, data() { return { liveId: '', roomId: '', rtcConfig: { sdkAppID: '', // 必要参数 开通实时音视频服务创建应用后分配的 sdkAppID userID: '', // 必要参数 用户 ID 可以由您的帐号系统指定 userSig: '', // 必要参数 身份签名,相当于登录密码的作用 template: '' // 必要参数 组件模版,支持的值 1v1 grid custom ,注意:不支持动态修改, iOS 不支持 pusher 动态渲染 }, showTipToast: false, btn_left:0, btn_top:0, title:"", user_name:'1', head_img:"../static/images/loginLogo.png", goodsList: [] } }, onLoad(options) { let menuButtonObject = wx.getMenuButtonBoundingClientRect(); wx.getSystemInfo({ success: res => { this.setData({ btn_left: res.windowWidth - menuButtonObject.right+'rpx', btn_top:menuButtonObject.top+menuButtonObject.height+14+'rpx' }) }, }) NET.request(API.linkPickVideo, { tenantCode : options.tenantCode, orderId: options.orderId }, 'GET').then(res => { this.liveId = res.data.liveId this.roomId = res.data.roomId this.goodsList = res.data.liveProducResVO wx.setKeepScreenOn({ keepScreenOn: true }); // 获取 rtcroom 实例 this.trtcComponent = this.$refs['trtc-component']; // 监听TRTC Room 关键事件 this.bindTRTCRoomEvent(); // 将String 类型的 true false 转换成 boolean options.template = '1v1'; this.options = options; // querystring 只支持传递 String 类型, 注意类型转换 this.enterRoom({ roomID: this.roomId, userID: uni.getStorageSync("userData").userId, //设置为用户id template: '1v1', debugMode: false, cloudenv: 'PRO', }); }).catch(error => { this.$refs.uTips.show({ title: error.data.msg, type: 'warning', }) }) }, methods: { // 打开弹窗 showGoods() { this.$refs.popup.open() }, // 关闭弹窗 closeGoods() { this.$refs.popup.close() }, // goToGoodDetails(item) { // uni.navigateTo({ // url: '/pagesGood/goodDetails?goodId=' + item.productId // }); // }, setData, enterRoom: function(params) { params.template = params.template || '1v1'; params.roomID = params.roomID || 2333; params.userID = params.userID || new Date().getTime().toString(16); console.log('* room enterRoom', params); const Signature = genTestUserSig(params.userID); params.sdkAppID = Signature.sdkAppID; params.userSig = Signature.userSig; this.template = params.template; this.rtcConfig = { sdkAppID: params.sdkAppID, // 您的实时音视频服务创建应用后分配的 sdkAppID userID: params.userID, userSig: params.userSig, template: params.template, // 1v1 grid custom debugMode: params.debugMode, // 非必要参数,打开组件的调试模式,开发调试时建议设置为 true beautyLevel: 9 // 默认开启美颜 // cloudenv: params.cloudenv, // 非必要参数 }; this.setData({ rtcConfig: this.rtcConfig }, () => { // roomID 取值范围 1 ~ 4294967295 this.trtcComponent.enterRoom({ roomID: params.roomID }).then(() => { }).catch(res => { console.error('* room joinRoom 进房失败:', res); }); }); }, bindTRTCRoomEvent: function() { const TRTC_EVENT = this.trtcComponent.EVENT; this.timestamp = []; // 初始化事件订阅 this.trtcComponent.on(TRTC_EVENT.LOCAL_JOIN, event => { if(this.trtcComponent.getRemoteUserList().length>0){ var userId=this.trtcComponent.getRemoteUserList()[0].userID; NET.request(API.getMerchantsMainInfo + userId, {}, 'GET').then(res => { this.setData({ head_img:res.data.merchantImg, title:res.data.merchantNickname }) }).catch(error => { this.$refs.uTips.show({ title: '获取个人信息失败', type: 'warning', }) }) } console.log('* room LOCAL_JOIN', event); // 进房成功,触发该事件后可以对本地视频和音频进行设置 if (this.options.localVideo === true || this.options.template === '1v1') { //this.trtcComponent.publishLocalVideo(); } if (this.options.localAudio === true || this.options.template === '1v1') { this.trtcComponent.publishLocalAudio(); } }); this.trtcComponent.on(TRTC_EVENT.LOCAL_LEAVE, event => { console.log('* room LOCAL_LEAVE', event); }); this.trtcComponent.on(TRTC_EVENT.ERROR, event => { console.log('* room ERROR', event); }); // 远端用户进房 this.trtcComponent.on(TRTC_EVENT.REMOTE_USER_JOIN, event => { var userId=this.trtcComponent.getRemoteUserList()[0].userID; NET.request(API.getMerchantsMainInfo + userId, {}, 'GET').then(res => { this.setData({ head_img:res.data.merchantImg, title:res.data.merchantNickname }) }).catch(error => { this.$refs.uTips.show({ title: '获取个人信息失败', type: 'warning', }) }) console.log('* room REMOTE_USER_JOIN --- room.vue', event, this.trtcComponent.getRemoteUserList(), this.template); this.timestamp.push(new Date()); // 1v1视频通话时限制人数为两人的简易逻辑,建议通过后端实现房间人数管理 // 2人以上同时进行通话请选择网格布局 if (this.template === '1v1' && this.timestamp.length > 1) { const interval = this.timestamp[1] - this.timestamp[0]; if (interval < 1000) { // 房间里已经有两个人 this.setData({ showTipToast: true }, () => { setTimeout(() => { this.setData({ showTipToast: false }); wx.navigateBack({ delta: 1 }); }, 4000); }); } } }); // 远端用户退出 this.trtcComponent.on(TRTC_EVENT.REMOTE_USER_LEAVE, event => { this.setData({ head_img:"../static/images/loginLogo.png", title:'' }) console.log('* room REMOTE_USER_LEAVE', event, this.trtcComponent.getRemoteUserList()); if (this.template === '1v1') { this.timestamp = []; } if (this.template === '1v1' && this.remoteUser === event.data.userID) { this.remoteUser = null; } }); // 远端用户推送视频 this.trtcComponent.on(TRTC_EVENT.REMOTE_VIDEO_ADD, event => { console.log('* room REMOTE_VIDEO_ADD', event, this.trtcComponent.getRemoteUserList()); // 订阅视频 const userList = this.trtcComponent.getRemoteUserList(); const data = event.data; if (this.template === '1v1' && (!this.remoteUser || this.remoteUser === data.userID)) { // 1v1 只订阅第一个远端流 this.remoteUser = data.userID; this.trtcComponent.subscribeRemoteVideo({ userID: data.userID, streamType: data.streamType }); } else if (this.template === 'grid') { this.trtcComponent.subscribeRemoteVideo({ userID: data.userID, streamType: data.streamType }); } if (this.template === 'custom' && data.userID && data.streamType) { let index = userList.findIndex(item => { return item.userID === data.userID; }); index++; const y = 320 * index + 160; // 设置远端视图坐标和尺寸 this.trtcComponent.setViewRect({ userID: data.userID, streamType: data.streamType, xAxis: '480rpx', yAxis: y + 'rpx', width: '240rpx', height: '320rpx' }); } }); // 远端用户取消推送视频 this.trtcComponent.on(TRTC_EVENT.REMOTE_VIDEO_REMOVE, event => { console.log('* room REMOTE_VIDEO_REMOVE', event, this.trtcComponent.getRemoteUserList()); }); // 远端用户推送音频 this.trtcComponent.on(TRTC_EVENT.REMOTE_AUDIO_ADD, event => { console.log('* room REMOTE_AUDIO_ADD', event, this.trtcComponent.getRemoteUserList()); // 订阅音频 const data = event.data; if (this.template === '1v1' && (!this.remoteUser || this.remoteUser === data.userID)) { this.remoteUser = data.userID; this.trtcComponent.subscribeRemoteAudio({ userID: data.userID }); } else if (this.template === 'grid' || this.template === 'custom') { this.trtcComponent.subscribeRemoteAudio({ userID: data.userID }); } // 如果不订阅就不会自动播放音频 // this.trtcComponent.subscribeRemoteAudio({ userID: data.userID }) }); // 远端用户取消推送音频 this.trtcComponent.on(TRTC_EVENT.REMOTE_AUDIO_REMOVE, event => { console.log('* room REMOTE_AUDIO_REMOVE', event, this.trtcComponent.getRemoteUserList()); }); } } } </script> <style lang="less" scoped> page { width: 100%; height: 100%; } .container { width: 100%; height: 100%; float: left; position: relative; .tip-toast { position: absolute; top: 40vh; width: 70vw; left: 15vw; border-radius: 12rpx; height: 20vh; background: rgba(0, 0, 0, 0.8); color: white; display: flex; flex-direction: column; align-items: center; justify-content: center; } .tip-toast view { padding: 20rpx 0; font-size: 32rpx; } .top_box{ width: 304rpx; height: 86rpx; position: absolute; z-index: 100; background:rgba(0, 0, 0, 0.4); border-radius: 100px; top: 182rpx; left: 30rpx; } .top_box_img{ width: 86rpx; height: 86rpx; border-radius: 100rpx; float: left; } .top_box_text{ float: left; color: #fff; margin-left: 30rpx; width: 180rpx; padding-top: 2rpx; } .text_box_top{ font-size: 34rpx; width: 100%; display: block; height: 30rpx; float: left; margin-top: 19rpx; } .text_box_bottom{ font-size: 22rpx; float: left; margin-top: 10rpx; } .popup-open { width: 50px; height: 50px; position: fixed; bottom: 15px; right: 15px; background: #52A63A; border-radius: 50%; text-align: center; line-height: 50px; z-index: 20000; .iconzhibo-shangpin { color: #FFFFFF; font-size: 34px; } } .popup-box { width: 100%; height: 265px; float: left; background-color: #FFFFFF; border-radius: 15px 15px 0px 0px; box-sizing: border-box; padding: 16px 0 0 0; position: relative; .popup-close { width: 100%; height: 26px; float: left; box-sizing: border-box; padding: 10px 15px 0 15px; font-size: 15px; font-family: PingFang SC; color: #52A63A; line-height: 16px; } .good-box { width: 100%; height: calc(100% - 26px); box-sizing: border-box; padding: 0 0 10px 0; overflow: auto; position: relative; .goods-row:first-child { margin-top: 12px; } .goods-row { width: calc(100% - 30px); height: 104px; float: left; background: #FFFFFF; box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1); border-radius: 5px; margin: 0 15px 10px 15px; position: relative; .goods-img { width: 104px; height: 104px; object-fit: cover; float: left; margin-right: 15px; } .goods-info { width: calc(100% - 120px); float: left; padding-top: 10px; .goods-name { width: 100%; height: 30px; float: left; font-size: 15px; font-family: PingFang SC; color: #333333; line-height: 15px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; word-wrap: break-word; } .goods-sales { width: 100%; float: left; font-size: 12px; font-family: PingFang SC; color: #666666; line-height: 15px; margin: 4px 0 8px 0; } .goods-number { width: 100%; height: 24px; float: left; white-space: nowrap; font-family: PingFang SC; color: #52A63A; line-height: 24px; .goods-icon { font-size: 14px; } .goods-spec { font-size: 24px; } .price { font-size: 12px; text-decoration: line-through; color: #A67954; margin-left: 6px; } } } .more-button { width: 24px; height: 24px; position: absolute; right: 16px; bottom: 16px; .iconfont { font-size: 36px; color: #999999; } } } } } } </style>