Commit 5b69ec19 by liuquan

3.1.0

A:新增修改订单地址
A:新增订单详情
A:新增药方作废
A:药方支付添加作废提示
A:药方支付添加库存不足提示
U:修改赠送患者免费咨询次数规则
U:修改聊天页弹出报告样式
U:修复了连续点击事件
U:修改药品订单状态展示
D:删除了预备咨询服务
parents
const service = require('./utils/service.js');
const tim = require('./utils/tim.js');
const Util = require('./utils/util.js');
App({
globalData: {
userInfo: null,
isLogin: false,
sessionRecord: false,
headerHeight: 0,
statusBarHeight: 0,
isDebug: true,
},
onLaunch: function (options) {
console.log("onLaunch")
var that = this
wx.login({
success: function (msg) {
service.getOpenId(msg.code).then((res) => {
wx.setStorageSync('user', res); //存储openid
return service.getUserData(res.openid)
}).then((res) => {
wx.setStorageSync('data', res)
console.log('%c查询成功', "color:#04BE02", res);
that.globalData.userInfo = res;
if (Util.isEmpty(res.unionid)) return service.breakPromise();
else return service.getUserSig(res.unionid)
}).then((res) => {
return tim.login(res.data.userid, res.data.sign)
}).then(function (imResponse) {
console.log('%c登录成功', "color:#04BE02", imResponse);
if (imResponse.data.repeatLogin === true) {
// 标识账号已登录,本次登录操作为重复登录。v2.5.1 起支持
console.log('"%c本次登录操作为重复登录', "color:#ff0000", imResponse.data.errorInfo);
}
}).catch(function (imError) {
console.log('"%c登录失败', "color:#ff0000", imError); // 登录失败
console.warn('login error:', imError); // 登录失败的相关信息
});
}
})
const {
model,
system,
statusBarHeight
} = wx.getSystemInfoSync()
let headHeight
if (/iphone\s{0,}x/i.test(model)) {
headHeight = 88
} else if (system.indexOf('Android') !== -1) {
headHeight = 68
} else {
headHeight = 64
}
this.globalData.headerHeight = headHeight
this.globalData.statusBarHeight = statusBarHeight
},
onShow:function(){
console.log("onShow")
},
onHide:function(){
console.log("onHide")
},
///小程序强制更新
forcedUpdate: function () {
service.forcedUpdate().then((res) => {
if (res.code == 1) {
if (res.data.is_required == 1) {
if (wx.canIUse('getUpdateManager')) {
const updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
if (res.hasUpdate) {
updateManager.onUpdateReady(function () {})
updateManager.onUpdateFailed(function () {})
}
})
} else {
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
}
}
})
},
//个人信息
getUserData: function (data) {
var that = this;
service.getUserData(data).then((res) => {
console.log("res", res)
that.globalData.userInfo = res;
wx.setStorageSync('data', res)
})
},
//登录方法
getUserInfo: function (cb) {
var that = this;
//登录
wx.login({
success: function (msg) {
wx.getUserInfo({
success: function (res) {
if (msg.code) {
var data = {};
data.code = msg.code;
data.encryptedData = res.encryptedData;
data.iv = res.iv;
data.type = 1;
service.addUserInfo(data).then((res) => {
console.log('%c添加成功', "color:#04BE02", res);
that.globalData.unionid = res.unionId;
that.getUserData(res.openId)
if (Util.isEmpty(res.unionId)) return service.breakPromise();
else return service.getUserSig(res.unionId)
}).then((res) => {
return tim.login(res.data.userid, res.data.sign)
}).then(function (imResponse) {
that.globalData.isLogin = true;
typeof cb == "function" && cb(that.globalData.unionid)
console.log('%c登录成功', "color:#04BE02", imResponse.data.errorInfo);
if (imResponse.data.repeatLogin === true) {
// 标识账号已登录,本次登录操作为重复登录。v2.5.1 起支持
console.log('"%c本次登录操作为重复登录', "color:#ff0000", imResponse.data.errorInfo);
}
}).catch(function (imError) {
typeof cb == "function" && cb(that.globalData.unionid)
console.log('"%c登录失败', "color:#ff0000", imError); // 登录失败
console.warn('login error:', imError); // 登录失败的相关信息
});
}
},
fail: function (e) {
var data = {
code: msg.code,
type: 0
};
service.addUserInfo(data).then((res) => {
typeof cb == "function" && cb(res)
})
}
})
},
fail: function (err) {
typeof cb == "function" && cb(err)
console.log("login失败")
}
})
},
getaddFriend: function (add_unionid, type) {
var that = this;
// if (this.globalData.userInfo) {
// typeof cb == "function" && cb(this.globalData.userInfo)
// } else {
//调用登录接口
wx.login({
success: function (res1) {
wx.setStorageSync("code", res1)
wx.getUserInfo({
success: function (res) {
// that.globalData.userInfo = res.userInfo;
// that.globalData.refuse = 1;
// typeof cb == "function" && cb(that.globalData.userInfo)
wx.setStorageSync('userInfo', res.userInfo);
if (res1.code) {
var data = {};
data.add_unionid = add_unionid;
data.options_type = type;
data.code = res1.code;
data.encryptedData = res.encryptedData;
data.iv = res.iv;
service.appAddFriend(data).then(addres => {
if (addres.code == 1 || addres.code == 3) {
console.log('添加成功!')
if (type == 1) {}
} else {
wx.setStorageSync('addFriend', true);
console.log('添加失败!')
}
});
}
},
fail: function (e) {}
})
},
fail: function (err) {
console.log("添加失败err", err)
}
})
// }
},
})
\ No newline at end of file
{
"pages": [
"pages/index/index",
"pages/chatNews/chatNews",
"pages/addressBook/addressBook",
"pages/prescription/order/order",
"pages/my/my",
"pages/search/search",
"pages/docuterInfo/docuterInfo",
"pages/doctorIntro/doctorIntro",
"pages/dati/dati",
"pages/dati02/dati02",
"pages/dati03/dati03",
"pages/dati04/dati04",
"pages/info/info",
"pages/info1/info1"
],
"subpackages": [
{
"root": "packageA",
"name": "chat",
"pages": [
"chat/chat",
"room/room",
"myDoctor/myDoctor",
"myPrescription/myPrescription",
"drugOrder/drugOrder",
"drugOrderInfo/drugOrderInfo",
"drugOrderDetail/drugOrderDetail",
"site/site",
"addsite/addsite",
"serviceDetails/serviceDetails",
"recipeDetails/recipeDetails",
"buyService/buyService",
"selectUser/selectUser",
"editUser/editUser",
"editPatientInfo/editPatientInfo",
"consent/consent",
"logistics/logistics",
"patientList/patientList",
"chattingRecords/chattingRecords",
"beBeingService/beBeingService"
]
},
{
"root": "packageB",
"name": "pack2",
"pages": [
"invoice/invoice",
"invoiceInfo/invoiceInfo",
"invoiceDetail/invoiceDetail",
"myService/myService",
"myDetails/myDetails",
"myReport/myReport",
"followUp/followUp",
"enterEmial/enterEmial",
"invoiceprompt/invoiceprompt",
"webview/webview",
"agreement/agreement",
"promise/promise"
]
}
],
"window": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "小懂健康",
"navigationBarTextStyle": "black",
"backgroundColor": "#f2f2f2",
"enablePullDownRefresh": false
},
"tabBar": {
"color": "#dadbe3",
"selectedColor": "#2684ff",
"backgroundColor": "#fff",
"borderStyle": "black",
"list": [
{
"selectedIconPath": "images/sy.png",
"iconPath": "images/syw.png",
"pagePath": "pages/index/index",
"text": "首页"
},
{
"selectedIconPath": "images/xx.png",
"iconPath": "images/xxw.png",
"pagePath": "pages/chatNews/chatNews",
"text": "服务"
},
{
"selectedIconPath": "images/wd.png",
"iconPath": "images/wdw.png",
"pagePath": "pages/my/my",
"text": "我的"
}
]
},
"sitemapLocation": "sitemap.json"
}
\ No newline at end of file
/**app.wxss**/
/* @import '/miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss'; */
page{
--base: #111111;
--regular: #495060;
--secondary : #999999;
--border : #dddddd;
--border-base : #dbdbdb;
--border-light :#e9eaec;
--success : #0ac160;
--chat : #95ec69;
--primary : #006fff;
--primary-10 : rgba(0, 111, 255, 0.1) ;
--primary-30 : rgba(0, 111, 255, 0.3) ;
--dark-primary : #0063e5;
--light-primary : #98c6fd;
--warning : #ffab20;
--danger : #fb5250;
--light-button : #dbdbdb;
--dark-button : #c5c5c5;
--background : #ededed;
--light-background : #f1f1f1;
--dark-background : #c4c4c4;
--white : #ffffff;
--black : #000000;
}
page {
-webkit-tap-highlight-color: transparent;
-webkit-appearance: none;
background: #f5f8fb;
padding-bottom:1rpx;
}
[class*="cuIcon-"] {
font-family: "cuIcon";
font-size: inherit;
font-style: normal;
}
button {
background: transparent;
border: 0;
color: #fff;
height: 100rpx;
line-height: 100rpx;
padding: 0;
}
button::after {
border: 0;
}
.button-hover {
background: transparent;
color: #fff;
}
.clearfix:after {
content: " ";
display: block;
height: 0;
clear: both;
}
/*top 线 */
.line_top {
position: absolute;
width: 100%;
height: 1px;
top: 0;
left: 0;
background: #f0f2f5;
z-index: 999;
}
.show {
display: block;
}
.hid {
display: none;
}
.record404 {
background: #fff;
width: 100%;
height: 100%;
position: relative;
text-align: center;
z-index: 10;
}
.r404{
width: 100%;
height: 32rpx;
line-height: 32rpx;
text-align: center;
margin-top: 250rpx;
}
.r404 text{
color: #999;
font-size: 32rpx;
}
.re404-photo {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 900rpx;
text-align: center;
}
.re404-wujilu {
width: 640rpx;
height: 480rpx;
position: absolute;
top: 230rpx;
left: 110rpx;
margin-left: -61rpx;
}
.re404-txt {
position: absolute;
width: 260rpx;
left: 50%;
margin-left: -130rpx;
top: 664rpx;
display: block;
color: #999;
font-size: 30rpx;
font-weight: 300;
}
.t-round {
position: absolute;
top: 21rpx;
left: 120rpx;
width: 40rpx;
height: 40rpx;
text-align: center;
line-height: 40rpx;
border-radius: 50%;
color: #fff;
background: red;
z-index: 9999;
font-size: 22rpx;
font-weight: bold;
}
.iphonex {
background: #fff;
width: 100%;
height: 2rpx;
margin-top: 150rpx;
}
.loadingImg{
display: block;
width: 128rpx;
height: 128rpx;
position: fixed;
top: 50%;
margin-top: -64rpx;
left: 50%;
margin-left: -64rpx;
}
.all-btn{
width: 690rpx;
height: 90rpx;
text-align: center;
line-height: 90rpx;
background: #1384ff;
margin: 0 auto;
border-radius: 5rpx;
}
/* loading */
.loadingimg {
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
text-align: center;
position: fixed;
}
.loadingimg image {
width: 100rpx;
height: 100rpx;
position: absolute;
left: 50%;
margin-left: -50rpx;
top: 30%;
margin-top: -50rpx;
}
.authorization{
height: 100%;
width: 750rpx;
text-align:center;
}
.authorization-img{
width: 140rpx;
height: 140rpx;
margin-top: 200rpx;
display: block;
position: relative;
left: 305rpx;
}
.authorization-text-a{
margin-top: 40rpx;
font-size: 36rpx;
color: #212121;
}
.authorization-text-b{
margin-top: 30rpx;
font-size: 28rpx;
color: #666666;
}
.authorization-btn{
margin-top: 60rpx;
font-size: 36rpx;
color: #ffffff;
background: #1384ff;
height: 90rpx;
width: 650rpx;
border-radius: 10rpx;
line-height: 90rpx;
}
\ No newline at end of file
<!-- 404 -->
<template name='noRecord'>
<view class="record404" style="height:{{winH}}px">
<image src='../../images/wujilu@2x.png' class='re404-wujilu'></image>
<text class='re404-txt'>暂时没有相关记录</text>
</view>
</template>
<template name="loading">
<view class='loadingimg'>
<image src='/images/loadingx.gif'></image>
</view>
</template>
<template>
<view class="spinner">
<view class="bounce1"></view>
<view class="bounce2"></view>
<view class="bounce3"></view>
</view>
</template>
<template>
<view class='cu-load load-modal'>
<view class='cuIcon-emojifill text-orange'></view>
<!-- <image src='/images/logo.png' class='png' mode='aspectFit'></image> -->
<view class='gray-text'>加载中...</view>
</view>
</template>
<template name="modal">
<view class="cu-modal {{isShow?'show':''}}" bindtap='hideModal' catchtouchmove="true">
<view class='cu-dialog' catchtap>
<view class='modal-top' wx:if="{{modalTitle!=''}}">
<view class='header'>{{modalTitle}}</view>
</view>
<view class='modal-body'>
<text> {{modalMsg}}</text>
</view>
<view class='modal-footer' wx:if="{{showCancel}}">
<text class='cancle' catchtap='_cancelEvent'>取消</text>
<text class='sure' catchtap='_confirmEvent'>确定</text>
</view>
<view class='modal-footer' wx:else>
<text class='sure width-100' catchtap='_confirmEvent' data-type="{{type}}">确定</text>
</view>
</view>
</view>
</template>
\ No newline at end of file
@import '/components/main.wxss';
/* ==================
模态窗口
==================== */
.cu-modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1110;
opacity: 0;
outline: 0;
text-align: center;
-ms-transform: scale(1.185);
transform: scale(1.185);
backface-visibility: hidden;
perspective: 2000rpx;
background: rgba(0, 0, 0, 0.6);
transition: all 0.3s ease-in-out 0s;
pointer-events: none;
}
.cu-modal::before {
content: "\200B";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.cu-modal.show {
opacity: 1;
transition-duration: 0.3s;
-ms-transform: scale(1);
transform: scale(1);
overflow-x: hidden;
overflow-y: auto;
pointer-events: auto;
}
.cu-dialog {
position: relative;
display: inline-block;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
width: 680rpx;
max-width: 100%;
background-color: #f8f8f8;
border-radius: 10rpx;
overflow: hidden;
}
.cu-modal.bottom-modal::before {
vertical-align: bottom;
}
.cu-modal.bottom-modal .cu-dialog {
width: 100%;
border-radius: 0;
}
.cu-modal.bottom-modal {
margin-bottom: -1000rpx;
}
.cu-modal.bottom-modal.show {
margin-bottom: 0;
}
.cu-modal.drawer-modal {
transform: scale(1);
display: flex;
}
.cu-modal.drawer-modal .cu-dialog {
height: 100%;
min-width: 200rpx;
border-radius: 0;
margin: initial;
transition-duration: 0.3s;
}
.cu-modal.drawer-modal.justify-start .cu-dialog {
transform: translateX(-100%);
}
.cu-modal.drawer-modal.justify-end .cu-dialog {
transform: translateX(100%);
}
.cu-modal.drawer-modal.show .cu-dialog {
transform: translateX(0%);
}
.cu-modal .cu-dialog>.cu-bar:first-child .action{
min-width: 100rpx;
margin-right: 0;
min-height: 100rpx;
}
.modal-top {
font-size: 50rpx;
font-weight: 500;
color: #000000;
padding: 40rpx 0;
}
.modal-body {
width: 560rpx;
font-size: 32rpx;
margin: 0 auto;
font-weight: 400;
text-align: left;
color: #555;
line-height: 46rpx;
letter-spacing: 2rpx;
}
.modal-footer {
margin-top: 60rpx;
display: flex;
justify-content: space-between;
}
.cancle {
width: 260rpx;
height: 80rpx;
line-height: 80rpx;
border: 1px solid #2684ff;
text-align: center;
border-radius: 6rpx;
}
.sure {
width: 260rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 6rpx;
background: #2684ff;
color: #fff;
}
.width-100{
width: 100%!important;
}
.cu-dialog {
width: 620rpx;
padding: 30rpx;
}
/* ==================
纯css的loding
==================== */
.spinner {
margin:auto;
margin-top: 300rpx;
width: 750rpx;
text-align: center;
}
.spinner > view {
width: 30px;
height: 30px;
background-color: #2684ff;
border-radius: 100%;
display: inline-block;
-webkit-animation: bouncedelay 1.4s infinite ease-in-out;
animation: bouncedelay 1.4s infinite ease-in-out;
/* Prevent first frame from flickering when animation starts */
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.spinner .bounce1 {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.spinner .bounce2 {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
@-webkit-keyframes bouncedelay {
0%, 80%, 100% { -webkit-transform: scale(0.0) }
40% { -webkit-transform: scale(1.0) }
}
@keyframes bouncedelay {
0%, 80%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 40% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
/*
Animation 微动画
基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
*/
/* css 滤镜 控制黑白底色gif的 */
.gif-black{
mix-blend-mode: screen;
}
.gif-white{
mix-blend-mode: multiply;
}
/* Animation css */
[class*=animation-] {
animation-duration: .5s;
animation-timing-function: ease-out;
animation-fill-mode: both
}
.animation-fade {
animation-name: fade;
animation-duration: .8s;
animation-timing-function: linear
}
.animation-scale-up {
animation-name: scale-up
}
.animation-scale-down {
animation-name: scale-down
}
.animation-slide-top {
animation-name: slide-top
}
.animation-slide-bottom {
animation-name: slide-bottom
}
.animation-slide-left {
animation-name: slide-left
}
.animation-slide-right {
animation-name: slide-right
}
.animation-shake {
animation-name: shake
}
.animation-reverse {
animation-direction: reverse
}
@keyframes fade {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@keyframes scale-up {
0% {
opacity: 0;
transform: scale(.2)
}
100% {
opacity: 1;
transform: scale(1)
}
}
@keyframes scale-down {
0% {
opacity: 0;
transform: scale(1.8)
}
100% {
opacity: 1;
transform: scale(1)
}
}
@keyframes slide-top {
0% {
opacity: 0;
transform: translateY(-100%)
}
100% {
opacity: 1;
transform: translateY(0)
}
}
@keyframes slide-bottom {
0% {
opacity: 0;
transform: translateY(100%)
}
100% {
opacity: 1;
transform: translateY(0)
}
}
@keyframes shake {
0%,
100% {
transform: translateX(0)
}
10% {
transform: translateX(-9px)
}
20% {
transform: translateX(8px)
}
30% {
transform: translateX(-7px)
}
40% {
transform: translateX(6px)
}
50% {
transform: translateX(-5px)
}
60% {
transform: translateX(4px)
}
70% {
transform: translateX(-3px)
}
80% {
transform: translateX(2px)
}
90% {
transform: translateX(-1px)
}
}
@keyframes slide-left {
0% {
opacity: 0;
transform: translateX(-100%)
}
100% {
opacity: 1;
transform: translateX(0)
}
}
@keyframes slide-right {
0% {
opacity: 0;
transform: translateX(100%)
}
100% {
opacity: 1;
transform: translateX(0)
}
}
\ No newline at end of file
// components/answer/answer.js
const Util = require('../../utils/util.js');
var Tim = require('../../utils/tim.js');
import TIM from 'tim-wx-sdk';
const audioContext = wx.createInnerAudioContext();
Component({
/**
* 组件的属性列表
*/
properties: { //对外属性,即如果外部的wxml文件传入数据时,会把数据设置成properties的属性
//判断是否是TabBar页
'TabBar': {
type: String,
value: 'hide',
observer: function (newVal, oldVal) {
this.setData({
TabBar: newVal
});
}
},
},
/**
* 组件的初始数据
*/
data: {
roomID: '',
template: '1v1',
debugMode: false,
cloudenv: 'PRO',
answerText: ' · · ·',
text: [' ·', ' · ·', ' · · ·'],
index: 0,
videocall: false, //是否有存在的请求
roomFile: {}, //房间信息
TabBar: 'hide'//如果是show就隐藏TabBar栏
},
/**
* 组件的方法列表
*/
methods: {
//展示弹框
showAnswer: function () {
this.setData({
isShow: true,
})
if (this.data.TabBar == 'show') {
wx.hideTabBar({
animation: true
})
}
this.openAudio(1);
this.setData({
textTime: setInterval(() => {
var answerText = this.data.text[this.data.index];
this.setData({
answerText: answerText,
index: this.data.index == 2 ? 0 : this.data.index + 1
})
}, 500)
})
},
//隐藏弹框
hideAnswer: function () {
this.setData({
isShow: false
})
this.openAudio(0);
clearInterval(this.data.textTime);
//判断是否是TabBar页
if (this.data.TabBar == 'show') {
wx.showTabBar({
animation: true
});
}
},
//挂断
hangUp() {
let that = this;
that.setData({
videocall: false
})
Tim.sendRejectVideocall(that.data.roomFile.to);
wx.showToast({
title: '已拒接',
icon: 'none',
duration: 2000
})
that.hideAnswer();
},
//接听
connect() {
wx.showToast({
title: '正在连接中',
icon: 'loading'
})
this.enterRoom();
this.hideAnswer();
},
//准备进房视频
enterRoom: function () {
let that = this;
const roomID = that.data.roomID
const nowTime = new Date()
if (nowTime - that.tapTime < 1000) {
return
}
if (!roomID) {
wx.showToast({
title: '请输入房间号',
icon: 'none',
duration: 2000,
})
return
}
if (roomID > 4294967295 || roomID < 1) {
wx.showToast({
title: '房间号取值范围为 1~4294967295',
icon: 'none',
duration: 2000,
})
return
}
let userID = wx.getStorageSync('data').account_number;
let url = `/packageA/room/room?roomID=${roomID}&template=${that.data.template}&debugMode=${that.data.debugMode}&cloudenv=${that.data.cloudenv}&userID=${userID}&roomFile=${JSON.stringify(that.data.roomFile)}`
that.tapTime = nowTime
that.checkDeviceAuthorize().then((result) => {
console.log('授权成功', result)
that.setData({
videocall: false
})
wx.navigateTo({
url: url
})
}).catch((error) => {
console.log('没有授权', error)
})
},
//查看授权
checkDeviceAuthorize: function () {
this.hasOpenDeviceAuthorizeModal = false
return new Promise((resolve, reject) => {
if (!wx.getSetting || !wx.getSetting()) {
// 微信测试版 获取授权API异常,目前只能即使没授权也可以通过
resolve()
}
wx.getSetting().then((result) => {
console.log('getSetting', result)
this.authorizeMic = result.authSetting['scope.record']
this.authorizeCamera = result.authSetting['scope.camera']
if (result.authSetting['scope.camera'] && result.authSetting['scope.record']) {
// 授权成功
resolve()
} else {
// 没有授权,弹出授权窗口
// 注意: wx.authorize 只有首次调用会弹框,之后调用只返回结果,如果没有授权需要自行弹框提示处理
console.log('getSetting 没有授权,弹出授权窗口', result)
wx.authorize({
scope: 'scope.record',
}).then((res) => {
console.log('authorize mic', res)
this.authorizeMic = true
if (this.authorizeCamera) {
resolve()
}
}).catch((error) => {
console.log('authorize mic error', error)
this.authorizeMic = false
})
wx.authorize({
scope: 'scope.camera',
}).then((res) => {
console.log('authorize camera', res)
this.authorizeCamera = true
if (this.authorizeMic) {
resolve()
} else {
this.openConfirm()
reject(new Error('authorize fail'))
}
}).catch((error) => {
console.log('authorize camera error', error)
this.authorizeCamera = false
this.openConfirm()
reject(new Error('authorize fail'))
})
}
})
})
},
//打开授权设置
openConfirm: function () {
if (this.hasOpenDeviceAuthorizeModal) {
return
}
this.hasOpenDeviceAuthorizeModal = true
return wx.showModal({
content: '您没有打开麦克风和摄像头的权限,是否去设置打开?',
confirmText: '确认',
cancelText: '取消',
success: (res) => {
this.hasOpenDeviceAuthorizeModal = false
console.log(res)
// 点击“确认”时打开设置页面
if (res.confirm) {
console.log('用户点击确认')
wx.openSetting({
success: (res) => {},
})
} else {
console.log('用户点击取消')
}
},
})
},
/**
* 播放铃声
* @param {type} 1为播放 0为停止
*/
openAudio(type) {
wx.stopVoice();
console.log("openAudio");
audioContext.autoplay = true;
audioContext.loop = true;
audioContext.startTime = 0;
audioContext.src = "https://www.xiaodongai.com/xiaodongai/kongtian/Public/Wechat/inquiry/ring_tone.mp3";
if (type == 1) {
audioContext.play();
} else {
audioContext.stop();
}
},
},
pageLifetimes: {
// 组件所在页面的生命周期函数
/**组件调用时监听im视频通话消息 */
show: function () {
let that = this;
let onMessageReceived = function (event) {
// console.log("%c收到推送的单聊", "color:#04BE02", event, that.data.videocall)
let index = Number(event.data.length - 1);
let data = JSON.parse(event.data[index].payload.data);
//判断当前消息为视频通话并且无正在进行中的视频请求时弹出
let videocall = that.data.videocall;
if (data.type == "LaunchVideo" && !videocall) {
that.setData({
roomID: data.content,
roomFile: {
to: event.data[index].to,
doctorName: event.data[index].nick,
doctorheadimg: event.data[index].avatar
},
videocall: true
})
that.showAnswer();
}
//判断当前消息为挂断视频通话并且有正在进行中的视频请求时隐藏
if (data.type == "closeVideo" && event.data[index].to == that.data.roomFile.to && videocall) {
that.setData({
videocall: false,
roomID: '',
})
wx.showToast({
title: '对方已取消视频通话',
icon: 'none',
duration: 2000
})
that.hideAnswer();
}
// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面
// event.name - TIM.EVENT.MESSAGE_RECEIVED
// event.data - 存储 Message 对象的数组 - [Message]
};
this.setData({
onMessageReceived: onMessageReceived
})
Tim.tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.data.onMessageReceived);
},
// hide: function () {
// console.log('hide')
// },
hide: function () {
// console.log('hide');
// console.log('this.data.onMessageReceived',this.data.onMessageReceived)
wx.stopVoice();
Tim.tim.off(TIM.EVENT.MESSAGE_RECEIVED, this.data.onMessageReceived);
//有视频请求的时候退出当前页挂断
if(this.data.videocall){
this.hangUp();
}
},
resize: function () {},
},
})
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!--components/answer/answer.wxml-->
<view class="cu-modal bottom-modal {{isShow?'show':''}}" catchtouchmove="true">
<!-- <text class="cuIcon-close answer-close" catchtap="hideAnswer" ></text> -->
<image class="answer-img" src="{{roomFile.doctorheadimg}}"></image>
<view class="answer-name">{{roomFile.doctorName}}</view>
<view class="answer-text">邀请你进行视频通话{{answerText}}</view>
<view class="answer-content">
<view>
<image class="answer-icon" src="/images/f@2x.png" catchtap="hangUp"></image>
<view>挂断</view>
</view>
<view>
<image class="answer-icon" src="/images/u@2x.png" catchtap="connect"></image>
<view>接听</view>
</view>
</view>
</view>
\ No newline at end of file
/* components/answer/answer.wxss */
@import '../cu-modal.wxss';
@import '../icon.wxss';
.cu-modal{
backdrop-filter: blur(40rpx);
}
.answer-close {
position: absolute;
right: 15rpx;
top: 15rpx;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
padding: 10rpx;
font-size: 40rpx;
color: #fff;
font-weight: 800;
}
.answer-img{
position: absolute;
left: 285rpx;
top: 120rpx;
width: 160rpx;
height: 160rpx;
border-radius: 30rpx;
background: transparent;
}
.answer-name{
position: absolute;
left: 0rpx;
width: 100%;
text-align: center;
top: 340rpx;
border-radius: 10rpx;
color: #fff;
font-size: 38rpx;
}
.answer-text{
position: absolute;
left: 0rpx;
width: 100%;
text-align: center;
font-weight: 300;
top: 410rpx;
border-radius: 10rpx;
color: #efefef;
font-size: 28rpx;
}
.answer-content{
position: absolute;
left: 0rpx;
width: 590rpx;
text-align: center;
bottom: 160rpx;
border-radius: 10rpx;
color: #fff;
font-size: 32rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
padding:0 80rpx;
font-size: 28rpx;
}
.answer-icon{
height: 120rpx;
width: 120rpx;
margin-bottom: 20rpx;
}
\ No newline at end of file
/* ==================
模态窗口
==================== */
.cu-modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1110;
opacity: 0;
outline: 0;
text-align: center;
-ms-transform: scale(1.185);
transform: scale(1.185);
backface-visibility: hidden;
perspective: 2000rpx;
background: rgba(0, 0, 0, 0.6);
transition: all 0.3s ease-in-out 0s;
pointer-events: none;
}
.cu-modal::before {
content: "\200B";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.cu-modal.show {
opacity: 1;
transition-duration: 0.3s;
-ms-transform: scale(1);
transform: scale(1);
overflow-x: hidden;
overflow-y: auto;
pointer-events: auto;
}
.cu-dialog {
position: relative;
display: inline-block;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
width: 680rpx;
max-width: 100%;
background-color: #f8f8f8;
border-radius: 10rpx;
overflow: hidden;
}
.cu-modal.bottom-modal::before {
vertical-align: bottom;
}
.cu-modal.bottom-modal .cu-dialog {
width: 100%;
border-radius: 0;
}
.cu-modal.bottom-modal {
margin-bottom: -1000rpx;
}
.cu-modal.bottom-modal.show {
margin-bottom: 0;
}
.cu-modal.drawer-modal {
transform: scale(1);
display: flex;
}
.cu-modal.drawer-modal .cu-dialog {
height: 100%;
min-width: 200rpx;
border-radius: 0;
margin: initial;
transition-duration: 0.3s;
}
.cu-modal.drawer-modal.justify-start .cu-dialog {
transform: translateX(-100%);
}
.cu-modal.drawer-modal.justify-end .cu-dialog {
transform: translateX(100%);
}
.cu-modal.drawer-modal.show .cu-dialog {
transform: translateX(0%);
}
.cu-modal .cu-dialog>.cu-bar:first-child .action{
min-width: 100rpx;
margin-right: 0;
min-height: 100rpx;
}
\ No newline at end of file
// components/login/login.js
const Util = require('../../utils/util.js');
const app = getApp();
Component({
/**
* 组件的属性列表
*/
properties: {
loginTitle: {
type: String,
value: '请先授权登录',
},
loginMsg: {
type: String,
value: '为了更好的为您提供服务,请允许微信授权后再使用功能',
},
loginBtn:{
type: String,
value: '登 录',
},
showClose:{
type:Boolean,
value:false
},
},
/**
* 组件的初始数据
*/
data: {},
/**
* 组件的方法列表
*/
methods: {
//隐藏弹框
hideLogin() {
this.setData({
isShow: false
})
},
//展示弹框
showLogin() {
this.setData({
isShow: true
})
},
getInfo: function (e) {
let that = this;
if (e.detail.userInfo) {
wx.showLoading({
title: '正在登录',
})
app.getUserInfo(function (cb) {
if (!Util.isEmpty(cb)) {
wx.showToast({
title: '登录成功',
})
that.hideLogin();
that._refreshEvent();
}
});
}
},
//回调
_refreshEvent() {
this.triggerEvent('refreshEvent')
},
//默认Tap事件,阻止开发工具警告消息
true(){},
}
})
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!--components/login/login.wxml-->
<view class="cu-modal bottom-modal {{isShow?'show':''}}" bindtap="{{showClose?'hideLogin':''}}" catchtouchmove="true">
<view class='cu-dialog' catchtap>
<text class="cuIcon-close login-close" catchtap="hideLogin" wx:if="{{showClose}}" ></text>
<!-- <image class='login-close' catchtap="hideLogin" src="/images/icon@2x.png"></image> -->
<view class="login-title">{{loginTitle}}</view>
<view class="login-text">{{loginMsg}}</view>
<button class='login-btn' bindgetuserinfo="getInfo" open-type='getUserInfo'>{{loginBtn}}</button>
<view catchtap="_refreshEvent"></view>
</view>
</view>
\ No newline at end of file
/* components/login/login.wxss */
@import '../cu-modal.wxss';
@import '../icon.wxss';
.login-content{
width: 100%;
height: 480rpx;
background: #ffffff;
border-radius: 20rpx 20rpx 0 0;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
}
.login-close{
position: absolute;
right: 15rpx;
top: 15rpx;
width: 40rpx;
height: 40rpx;
padding: 10rpx;
font-size: 40rpx;
color: #000000;
font-weight: 800;
}
.login-title{
font-size: 50rpx;
font-weight: bold;
color: #000000;
letter-spacing: 2rpx;
margin-top: 84rpx;
margin-bottom: 50rpx;
}
.login-text{
width: 620rpx;
font-size: 32rpx;
margin:0 auto;
font-weight: 400;
text-align:left;
color: #555;
line-height: 46rpx;
letter-spacing: 2rpx;
}
.login-btn{
width: 620rpx;
height: 88rpx;
line-height: 88rpx;
background: #2684ff;
border-radius: 10rpx;
margin: 0 auto;
margin-top: 50rpx;
}
.cu-dialog {
height: 540rpx;
border-radius: 10rpx 10rpx 0 0!important;
}
\ No newline at end of file
// components/modal/modal.js
Component({
/**
* 组件的属性列表
*/
properties: {
showCancel: {
type: Boolean,
value: true
},
modalMsg: {
type: String,
value: ' ',
},
modalTitle: {
type: String,
value: ' ',
}
},
/**
* 组件的初始数据
*/
data: {},
/**
* 组件的方法列表
*/
methods: {
//隐藏弹框
hideModal() {
this.setData({
isShow: false
})
},
//展示弹框
showModal() {
this.setData({
isShow: true
})
},
showCancel(e) {
this.setData({
showCancel: e
})
},
_cancelEvent() {
//触发取消回调
this.triggerEvent("cancelEvent")
},
_confirmEvent() {
//触发成功回调
this.triggerEvent("confirmEvent");
},
//默认Tap事件,阻止开发工具警告消息
true() {},
}
})
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<!--components/modal/modal.wxml-->
<view class="cu-modal {{isShow?'show':''}}" bindtap='hideModal' catchtouchmove="true">
<view class='cu-dialog' catchtap>
<view class='modal-top' wx:if="{{modalTitle!=''}}">
<view class='header'>{{modalTitle}}</view>
</view>
<view class='modal-body'>
<text> {{modalMsg}}</text>
</view>
<view class='modal-footer' wx:if="{{showCancel}}">
<text class='cancle' catchtap='_cancelEvent'>取消</text>
<text class='sure' catchtap='_confirmEvent'>确定</text>
</view>
<view class='modal-footer' wx:else>
<text class='sure width-100' catchtap='_confirmEvent'>确定</text>
</view>
</view>
</view>
<!-- <view class="cu-modal bottom-modal {{isShow?'show':''}}" bindtap="hideModal">
<view class="cu-dialog" catchtap>
<view class="cu-bar bg-white">
<view class="action text-blue" bindtap="hideModal">取消</view>
<view class="action text-green" bindtap="hideModal">确定</view>
</view>
<view class="grid col-3 padding-sm">
</view>
</view>
</view> -->
\ No newline at end of file
/* components/modal/modal.wxss */
@import '../cu-modal.wxss';
.modal-top {
font-size: 50rpx;
font-weight: 500;
color: #000000;
padding: 40rpx 0;
}
.modal-body {
width: 560rpx;
font-size: 32rpx;
margin: 0 auto;
font-weight: 400;
text-align: left;
color: #555;
line-height: 46rpx;
letter-spacing: 2rpx;
}
.modal-footer {
margin-top: 60rpx;
margin-bottom: 30rpx;
display: flex;
justify-content: space-between;
}
.cancle {
width: 260rpx;
height: 80rpx;
line-height: 80rpx;
border: 1px solid #2684ff;
text-align: center;
border-radius: 6rpx;
}
.sure {
width: 260rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 6rpx;
background: #2684ff;
color: #fff;
}
.width-100{
width: 100%!important;
}
.cu-dialog {
width: 620rpx;
padding: 30rpx;
}
export const EVENT = {
LOCAL_JOIN: 'LOCAL_JOIN', // 本地进房成功
LOCAL_LEAVE: 'LOCAL_LEAVE', // 本地退房
REMOTE_USER_JOIN: 'REMOTE_USER_JOIN', // 远端用户进房
REMOTE_USER_LEAVE: 'REMOTE_USER_LEAVE', // 远端用户退房
REMOTE_VIDEO_ADD: 'REMOTE_VIDEO_ADD', // 远端视频流添加事件,当远端用户取消发布音频流后会收到该通知
REMOTE_VIDEO_REMOVE: 'REMOTE_VIDEO_REMOVE', // 远端视频流移出事件,当远端用户取消发布音频流后会收到该通知
REMOTE_AUDIO_ADD: 'REMOTE_AUDIO_ADD', // 远端音频流添加事件,当远端用户取消发布音频流后会收到该通知
REMOTE_AUDIO_REMOVE: 'REMOTE_AUDIO_REMOVE', // 远端音频流移除事件,当远端用户取消发布音频流后会收到该通知
REMOTE_STATE_UPDATE: 'REMOTE_STATE_UPDATE', // 远端用户播放状态变更
LOCAL_NET_STATE_UPDATE: 'LOCAL_NET_STATE_UPDATE', // 本地推流网络状态变更
REMOTE_NET_STATE_UPDATE: 'REMOTE_NET_STATE_UPDATE', // 远端用户网络状态变更
LOCAL_AUDIO_VOLUME_UPDATE: 'LOCAL_AUDIO_VOLUME_UPDATE', // 本地音量变更
REMOTE_AUDIO_VOLUME_UPDATE: 'REMOTE_AUDIO_VOLUME_UPDATE', // 远端用户音量变更
VIDEO_FULLSCREEN_UPDATE: 'VIDEO_FULLSCREEN_UPDATE', // 调用 player requestFullScreen 或者 exitFullScreen 后触发
BGM_PLAY_START: 'BGM_PLAY_START', // 调用 LivePusherContext.playBGM(Object object)
BGM_PLAY_FAIL: 'BGM_PLAY_FAIL', //
BGM_PLAY_PROGRESS: 'BGM_PLAY_PROGRESS', // bgm 播放时间戳变更
BGM_PLAY_COMPLETE: 'BGM_PLAY_COMPLETE', // bgm 播放结束 或者 调用 LivePusherContext.stopBGM() ?
ERROR: 'ERROR', // pusher 出现错误
IM_READY: 'IM_READY', // IM SDK 可用
IM_MESSAGE_RECEIVED: 'IM_MESSAGE_RECEIVED', // 收到IM 消息
IM_NOT_READY: 'IM_NOT_READY', // IM SDK 不可用
IM_KICKED_OUT: 'IM_KICKED_OUT', // IM SDK 下线
IM_ERROR: 'IM_ERROR', // IM SDK 下线
}
export const DEFAULT_COMPONENT_CONFIG = {
sdkAppID: '',
userID: '',
userSig: '',
template: '',
debugMode: false, // 是否开启调试模式
enableIM: false, // 是否开启 IM
}
export const DEFAULT_PUSHER_CONFIG = {
url: '',
mode: 'RTC', // RTC:实时通话(trtc sdk) live:直播模式(liteav sdk)
autopush: false, // 自动推送
enableCamera: false, // 是否开启摄像头
enableMic: false, // 是否开启麦克风
enableAgc: false, // 是否开启音频自动增益
enableAns: false, // 是否开启音频噪声抑制
enableEarMonitor: false, // 是否开启耳返(目前只在iOS平台有效)
enableAutoFocus: true, // 是否自动对焦
enableZoom: false, // 是否支持调整焦距
minBitrate: 600, // 最小码率
maxBitrate: 900, // 最大码率
videoWidth: 360, // 视频宽(若设置了视频宽高就会忽略aspect)
videoHeight: 640, // 视频高(若设置了视频宽高就会忽略aspect)
beautyLevel: 0, // 美颜,取值范围 0-9 ,0 表示关闭
whitenessLevel: 0, // 美白,取值范围 0-9 ,0 表示关闭
videoOrientation: 'vertical', // vertical horizontal
videoAspect: '9:16', // 宽高比,可选值有 3:4,9:16
frontCamera: 'front', // 前置或后置摄像头,可选值:front,back
enableRemoteMirror: false, // 设置推流画面是否镜像,产生的效果会表现在 live-player
localMirror: 'auto', // auto:前置摄像头镜像,后置摄像头不镜像(系统相机的表现)enable:前置摄像头和后置摄像头都镜像 disable: 前置摄像头和后置摄像头都不镜像
enableBackgroundMute: false, // 进入后台时是否静音
audioQuality: 'high', // 高音质(48KHz)或低音质(16KHz),可选值:high,low
audioVolumeType: 'voicecall', // 声音类型 可选值: media: 媒体音量,voicecall: 通话音量
audioReverbType: 0, // 音频混响类型 0: 关闭 1: KTV 2: 小房间 3:大会堂 4:低沉 5:洪亮 6:金属声 7:磁性
// waitingImage: 'https://web-player-1252463788.cos.ap-shanghai.myqcloud.com/demo/1px.png', // 当微信切到后台时的垫片图片 trtc暂不支持
waitingImage: 'https://mc.qcloudimg.com/static/img/daeed8616ac5df256c0591c22a65c4d3/pause_publish.jpg', // 当微信切到后台时的垫片图片 trtc暂不支持
waitingImageHash: '',
beautyStyle: 'smooth', // 美颜类型,取值有:smooth: 光滑 、nature: 自然
filter: '', // standard: 标准 pink: 粉嫩 nostalgia: 怀旧 blues: 蓝调 romantic: 浪漫 cool: 清凉 fresher: 清新 solor: 日系 aestheticism: 唯美 whitening:美白 cerisered: 樱红
}
export const DEFAULT_PLAYER_CONFIG = {
src: '',
mode: 'RTC',
autoplay: true, // 7.0.9 必须设置为true,否则 Android 有概率调用play()失败
muteAudio: true, // 默认不拉取音频,需要手动订阅,如果要快速播放,需要设置false
muteVideo: true, // 默认不拉取视频,需要手动订阅,如果要快速播放,需要设置false
orientation: 'vertical', // 画面方向 vertical horizontal
objectFit: 'fillCrop', // 填充模式,可选值有 contain,fillCrop
enableBackgroundMute: false, // 进入后台时是否静音(已废弃,默认退台静音)
minCache: 1, // 最小缓冲区,单位s(RTC 模式推荐 0.2s)
maxCache: 2, // 最大缓冲区,单位s(RTC 模式推荐 0.8s)
soundMode: 'speaker', // 声音输出方式 ear speaker
enableRecvMessage: 'false', // 是否接收SEI消息
autoPauseIfNavigate: true, // 当跳转到其它小程序页面时,是否自动暂停本页面的实时音视频播放
autoPauseIfOpenNative: true, // 当跳转到其它微信原生页面时,是否自动暂停本页面的实时音视频播放
}
var MTA_CONFIG={app_id:"",event_id:"",api_base:"https://pingtas.qq.com/pingd",prefix:"_mta_",version:"1.3.10",stat_share_app:!1,stat_pull_down_fresh:!1,stat_reach_bottom:!1,stat_param:!0};function getNetworkType(a){wx.getNetworkType({success:function(b){a(b.networkType)}})}
function getSystemInfo(){var a=wx.getSystemInfoSync();return{adt:encodeURIComponent(a.model),scl:a.pixelRatio,scr:a.windowWidth+"x"+a.windowHeight,lg:a.language,fl:a.version,jv:encodeURIComponent(a.system),tz:encodeURIComponent(a.platform)}}function getUID(){try{return wx.getStorageSync(MTA_CONFIG.prefix+"auid")}catch(a){}}function setUID(){try{var a=getRandom();wx.setStorageSync(MTA_CONFIG.prefix+"auid",a);return a}catch(b){}}
function getSID(){try{return wx.getStorageSync(MTA_CONFIG.prefix+"ssid")}catch(a){}}function setSID(){try{var a="s"+getRandom();wx.setStorageSync(MTA_CONFIG.prefix+"ssid",a);return a}catch(b){}}function getRandom(a){for(var b=[0,1,2,3,4,5,6,7,8,9],c=10;1<c;c--){var d=Math.floor(10*Math.random()),f=b[d];b[d]=b[c-1];b[c-1]=f}for(c=d=0;5>c;c++)d=10*d+b[c];return(a||"")+(d+""+ +new Date)}
function getPagePath(){try{var a=getCurrentPages(),b="/";0<a.length&&(b=a.pop().__route__);return b}catch(c){console.log("get current page path error:"+c)}}function getMainInfo(){var a={dm:"wechat.apps.xx",url:encodeURIComponent(getPagePath()+getQuery(MTA.Data.pageQuery)),pvi:"",si:"",ty:0};a.pvi=function(){var b=getUID();b||(b=setUID(),a.ty=1);return b}();a.si=function(){var a=getSID();a||(a=setSID());return a}();return a}
function getBasicInfo(){var a=getSystemInfo();getNetworkType(function(a){try{wx.setStorageSync(MTA_CONFIG.prefix+"ntdata",a)}catch(c){}});a.ct=wx.getStorageSync(MTA_CONFIG.prefix+"ntdata")||"4g";return a}function getExtentInfo(){var a=MTA.Data.userInfo;var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(c+"="+a[c]);a=b.join(";");return{r2:MTA_CONFIG.app_id,r4:"wx",ext:"v="+MTA_CONFIG.version+(null!==a&&""!==a?";ui="+encodeURIComponent(a):"")}}
function getQuery(a){if(!MTA_CONFIG.stat_param||!a)return"";a=ignoreParams(a);var b=[],c;for(c in a)b.push(c+"="+a[c]);return 0<b.length?"?"+b.join("&"):""}function ignoreParams(a){if(1>MTA_CONFIG.ignore_params.length)return a;var b={},c;for(c in a)0<=MTA_CONFIG.ignore_params.indexOf(c)||(b[c]=a[c]);return b}
function initOnload(){var a=Page;Page=function(b){var c=b.onLoad;b.onLoad=function(a){c&&c.call(this,a);MTA.Data.lastPageQuery=MTA.Data.pageQuery;MTA.Data.pageQuery=a;MTA.Data.lastPageUrl=MTA.Data.pageUrl;MTA.Data.pageUrl=getPagePath();MTA.Data.show=!1;MTA.Page.init()};a(b)}}
var MTA={App:{init:function(a){"appID"in a&&(MTA_CONFIG.app_id=a.appID);"eventID"in a&&(MTA_CONFIG.event_id=a.eventID);"statShareApp"in a&&(MTA_CONFIG.stat_share_app=a.statShareApp);"statPullDownFresh"in a&&(MTA_CONFIG.stat_pull_down_fresh=a.statPullDownFresh);"statReachBottom"in a&&(MTA_CONFIG.stat_reach_bottom=a.statReachBottom);"ignoreParams"in a&&(MTA_CONFIG.ignore_params=a.ignoreParams);"statParam"in a&&(MTA_CONFIG.stat_param=a.statParam);setSID();try{"lauchOpts"in a&&(MTA.Data.lanchInfo=a.lauchOpts,
MTA.Data.lanchInfo.landing=1)}catch(b){}"autoReport"in a&&a.autoReport&&initOnload()}},Page:{init:function(){var a=getCurrentPages()[getCurrentPages().length-1];a.onShow&&!function(){var b=a.onShow;a.onShow=function(){if(!0===MTA.Data.show){var a=MTA.Data.lastPageQuery;MTA.Data.lastPageQuery=MTA.Data.pageQuery;MTA.Data.pageQuery=a;MTA.Data.lastPageUrl=MTA.Data.pageUrl;MTA.Data.pageUrl=getPagePath()}MTA.Data.show=!0;MTA.Page.stat();b.apply(this,arguments)}}();MTA_CONFIG.stat_pull_down_fresh&&a.onPullDownRefresh&&
!function(){var b=a.onPullDownRefresh;a.onPullDownRefresh=function(){MTA.Event.stat(MTA_CONFIG.prefix+"pulldownfresh",{url:a.__route__});b.apply(this,arguments)}}();MTA_CONFIG.stat_reach_bottom&&a.onReachBottom&&!function(){var b=a.onReachBottom;a.onReachBottom=function(){MTA.Event.stat(MTA_CONFIG.prefix+"reachbottom",{url:a.__route__});b.apply(this,arguments)}}();MTA_CONFIG.stat_share_app&&a.onShareAppMessage&&!function(){var b=a.onShareAppMessage;a.onShareAppMessage=function(){MTA.Event.stat(MTA_CONFIG.prefix+
"shareapp",{url:a.__route__});return b.apply(this,arguments)}}()},multiStat:function(a,b){if(1==b)MTA.Page.stat(a),!0;else{var c=getCurrentPages()[getCurrentPages().length-1];c.onShow&&!function(){var b=c.onShow;c.onShow=function(){MTA.Page.stat(a);b.call(this,arguments)}}()}},stat:function(a){if(""!=MTA_CONFIG.app_id){var b=[],c=getExtentInfo();a&&(c.r2=a);a=[getMainInfo(),c,getBasicInfo()];if(MTA.Data.lanchInfo){a.push({ht:MTA.Data.lanchInfo.scene});MTA.Data.pageQuery&&MTA.Data.pageQuery._mta_ref_id&&
a.push({rarg:MTA.Data.pageQuery._mta_ref_id});try{1==MTA.Data.lanchInfo.landing&&(c.ext+=";lp=1",MTA.Data.lanchInfo.landing=0)}catch(e){}}a.push({rdm:"/",rurl:0>=MTA.Data.lastPageUrl.length?MTA.Data.pageUrl+getQuery(MTA.Data.lastPageQuery):encodeURIComponent(MTA.Data.lastPageUrl+getQuery(MTA.Data.lastPageQuery))});a.push({rand:+new Date});c=0;for(var d=a.length;c<d;c++)for(var f in a[c])a[c].hasOwnProperty(f)&&b.push(f+"="+("undefined"==typeof a[c][f]?"":a[c][f]));wx.request({url:MTA_CONFIG.api_base+
"?"+b.join("&").toLowerCase()})}}},Event:{stat:function(a,b){if(""!=MTA_CONFIG.event_id){var c=[],d=getMainInfo(),f=getExtentInfo();d.dm="wxapps.click";d.url=a;f.r2=MTA_CONFIG.event_id;var e="undefined"===typeof b?{}:b;var k=[],g;for(g in e)e.hasOwnProperty(g)&&k.push(encodeURIComponent(g)+"="+encodeURIComponent(e[g]));e=k.join(";");f.r5=e;e=0;d=[d,f,getBasicInfo(),{rand:+new Date}];for(f=d.length;e<f;e++)for(var h in d[e])d[e].hasOwnProperty(h)&&c.push(h+"="+("undefined"==typeof d[e][h]?"":d[e][h]));
wx.request({url:MTA_CONFIG.api_base+"?"+c.join("&").toLowerCase()})}}},Data:{userInfo:null,lanchInfo:null,pageQuery:null,lastPageQuery:null,pageUrl:"",lastPageUrl:"",show:!1}};module.exports=MTA;
\ No newline at end of file
import { DEFAULT_PUSHER_CONFIG } from '../common/constants.js'
class Pusher {
constructor(options) {
Object.assign(this, DEFAULT_PUSHER_CONFIG, {
isVisible: true, // 手Q初始化时不能隐藏 puser和player 否则黑屏
}, options)
}
/**
* 通过wx.createLivePusherContext 获取<live-pusher> context
* @param {Object} context 组件上下文
* @returns {Object} livepusher context
*/
getPusherContext(context) {
if (!this.pusherContext) {
this.pusherContext = wx.createLivePusherContext(context)
}
return this.pusherContext
}
reset() {
console.log('Pusher reset', this.pusherContext)
if (this.pusherContext) {
console.log('Pusher pusherContext.stop()')
this.pusherContext.stop()
this.pusherContext = null
}
Object.assign(this, DEFAULT_PUSHER_CONFIG, {
isVisible: true,
})
}
}
export default Pusher
// 一个stream 对应一个 player
import { DEFAULT_PLAYER_CONFIG } from '../common/constants.js'
class Stream {
constructor(options) {
Object.assign(this, DEFAULT_PLAYER_CONFIG, {
userID: '', // 该stream 关联的userID
streamType: '', // stream 类型 [main small] aux
streamID: '', // userID + '_' + streamType
isVisible: true, // 手Q初始化时不能隐藏 puser和player 否则黑屏。iOS 微信初始化时不能隐藏,否则同层渲染失败,player会置顶
hasVideo: false,
hasAudio: false,
volume: 0, // 音量大小 0~100
playerContext: undefined, // playerContext 依赖component context来获取,目前只能在渲染后获取
}, options)
}
setProperty(options) {
Object.assign(this, options)
}
reset() {
if (this.playerContext) {
this.playerContext.stop()
this.playerContext = undefined
}
Object.assign(this, DEFAULT_PLAYER_CONFIG, {
userID: '', // 该stream 关联的userID
streamType: '', // stream 类型 [main small] aux
streamID: '',
isVisible: true,
hasVideo: false,
hasAudio: false,
volume: 0, // 音量大小 0~100
playerContext: undefined,
})
}
}
export default Stream
class User {
constructor(options) {
Object.assign(this, {
userID: '',
// hasMainStream: false, // 触发 1034 且stream type 为 main 即为true
// hasAuxStream: false, // 触发 1034 且stream type 为 aux 即为true
// hasSmallStream: false, // 触发 1034 且stream type 为 small 即为true
streams: {
// main: mainStream
// aux: auxStream
}, // 有0~2个Stream, 进房没有推流,main aux, small 特殊处理,small 和 main 同时只播放一路
// stream 是用于渲染 live-player 的数据源
}, options)
}
}
export default User
<!-- template 1v1 -->
<template name='1v1'>
<view class="template-1v1">
<view wx:for="{{streamList}}" wx:key="streamID" wx:if="{{item.src && (item.hasVideo || item.hasAudio)}}" class="view-container player-container {{item.isVisible?'':'none'}}">
<live-player class="player" id="{{item.streamID}}" data-userid="{{item.userID}}" data-streamid="{{item.streamID}}" data-streamtype="{{item.streamType}}" src="{{item.src}}" mode="RTC" autoplay="{{item.autoplay}}" mute-audio="{{item.muteAudio}}" mute-video="{{item.muteVideo}}" orientation="{{item.orientation}}" object-fit="{{item.objectFit}}" background-mute="{{item.enableBackgroundMute}}" min-cache="{{item.minCache}}" max-cache="{{item.maxCache}}" sound-mode="{{item.soundMode}}" enable-recv-message="{{item.enableRecvMessage}}" auto-pause-if-navigate="{{item.autoPauseIfNavigate}}" auto-pause-if-open-native="{{item.autoPauseIfOpenNative}}" debug="{{debug}}" bindstatechange="_playerStateChange" bindfullscreenchange="_playerFullscreenChange" bindnetstatus="_playerNetStatus" bindaudiovolumenotify="_playerAudioVolumeNotify" />
</view>
<view class="view-container pusher-container {{pusher.isVisible?'':'none'}} {{streamList.length===0? 'fullscreen':''}}">
<live-pusher class="pusher" url="{{pusher.url}}" mode="{{pusher.mode}}" autopush="{{pusher.autopush}}" enable-camera="{{pusher.enableCamera}}" enable-mic="{{pusher.enableMic}}" muted="{{!pusher.enableMic}}" enable-agc="{{pusher.enableAgc}}" enable-ans="{{pusher.enableAns}}" enable-ear-monitor="{{pusher.enableEarMonitor}}" auto-focus="{{pusher.enableAutoFocus}}" zoom="{{pusher.enableZoom}}" min-bitrate="{{pusher.minBitrate}}" max-bitrate="{{pusher.maxBitrate}}" video-width="{{pusher.videoWidth}}" video-height="{{pusher.videoHeight}}" beauty="{{pusher.beautyLevel}}" whiteness="{{pusher.whitenessLevel}}" orientation="{{pusher.videoOrientation}}" aspect="{{pusher.videoAspect}}" device-position="{{pusher.frontCamera}}" remote-mirror="{{pusher.enableRemoteMirror}}" local-mirror="{{pusher.localMirror}}" background-mute="{{pusher.enableBackgroundMute}}" audio-quality="{{pusher.audioQuality}}" audio-volume-type="{{pusher.audioVolumeType}}" audio-reverb-type="{{pusher.audioReverbType}}" waiting-image="{{pusher.waitingImage}}" debug="{{debug}}" bindstatechange="_pusherStateChangeHandler" bindnetstatus="_pusherNetStatusHandler" binderror="_pusherErrorHandler" bindbgmstart="_pusherBGMStartHandler" bindbgmprogress="_pusherBGMProgressHandler" bindbgmcomplete="_pusherBGMCompleteHandler" bindaudiovolumenotify="_pusherAudioVolumeNotify" />
<view class="loading" wx:if="{{streamList.length === 0}}">
<view class="loading-img">
<image src="./static/loading.png" class="rotate-img"></image>
</view>
<view class="loading-text">等待接听中...</view>
</view>
</view>
<!-- <view class="doctor-info">
<image class="doctor-image" src="{{config.roomFile.doctorheadimg}}"></image>
<view class="doctor-text">
<view class="doctor-name">{{config.roomFile.doctorName}}</view>
<view class="callduration">{{config.roomFile.callduration}}</view>
</view>
</view> -->
<!-- <view class="handle-btns">
<view class="btn-normal" bindtap="_toggleSoundMode">
<image class="btn-image" src="{{streamList[0].soundMode === 'ear' ? './static/phone.png': './static/speaker-true.png'}} "></image>
</view>
</view> -->
<view class="handle-btns">
<view class="time">{{config.roomFile.callduration}}</view>
</view>
<view class="bottom-btns">
<view class="btn-normal" bindtap="_toggleAudio">
<image class="btn-image" src="{{pusher.enableMic? './static/audio-true.png': './static/audio-false.png'}} "></image>
</view>
<view class="btn-hangup" bindtap="_hangUp">
<image class="btn-image" src="./static/hangup.png"></image>
</view>
<view class="btn-normal" bindtap="switchCamera">
<image class="btn-image" src="./static/switch.png"></image>
</view>
</view>
</view>
</template>
\ No newline at end of file
/* 1v1 视频电话模式 */
.template-1v1 {
width: 100vw;
height: 100vh;
position: relative;
}
.template-1v1 .pusher-container {
width: 240rpx;
height: 320rpx;
position: absolute;
right: 20rpx;
top: 160rpx;
z-index: 2;
}
.template-1v1 .pusher-container.fullscreen {
width: 100vw;
height: 100vh;
top: 0;
right: 0;
}
.template-1v1 .loading {
position: absolute;
top: 40vh;
left: 50vw;
transform: translate(-50%, 0);
width: 300rpx;
height: 250rpx;
border-radius: 12rpx;
background: rgba(0, 0, 0, 0.6);
color: white;
padding: 40rpx;
display: flex;
flex-direction: column;
}
.template-1v1 .loading-img {
height: 200rpx;
display: flex;
justify-content: center;
align-items: center;
animation: rotate 2s linear infinite;
}
.template-1v1 .rotate-img {
width: 160rpx;
height: 160rpx;
}
.template-1v1 .loading-text {
width: 100%;
padding-top: 40rpx;
text-align: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}
.template-1v1 .player-container:nth-child(1) {
width: 100vw;
height: 100vh;
}
.template-1v1 .doctor-info {
position: absolute;
z-index: 3;
width: 450rpx;
height: 120rpx;
left: 20rpx;
top: 160rpx;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.template-1v1 .doctor-info .doctor-image {
width: 120rpx;
height: 120rpx;
border-radius: 30rpx;
}
.template-1v1 .doctor-info .doctor-text {
background: rgba(0, 0, 0, 0.3);
border-radius: 20px;
width: 260rpx;
height: auto;
margin-left: 30rpx;
padding: 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: flex;
flex-direction: column;
color: #fff;
}
.template-1v1 .doctor-info .doctor-name {
font-size: 40rpx;
font-weight: 500;
}
.template-1v1 .doctor-info .callduration {
font-size: 30rpx;
font-weight: 500;
}
.time {
padding: 12rpx 24rpx;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 6rpx;
color: #fff;
max-width: 350rpx;
line-height: 1.5;
box-sizing: border-box;
text-align: center;
}
.template-1v1 .handle-btns {
position: absolute;
z-index: 3;
bottom: 15vh;
width: 100vw;
display: flex;
flex-direction: row;
justify-content: space-around;
}
.template-1v1 .bottom-btns {
position: absolute;
z-index: 3;
bottom: 3vh;
width: 100vw;
display: flex;
flex-direction: row;
justify-content: space-around;
}
/* .template-1v1 image {
width: 4vh;
height: 4vh;
} */
.template-1v1 .btn-normal {
width: 8vh;
height: 8vh;
box-sizing: border-box;
display: flex;
background: white;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.template-1v1 .btn-hangup .btn-image,
.template-1v1 .btn-normal .btn-image {
width: 4vh;
height: 4vh;
}
.template-1v1 .btn-hangup {
width: 8vh;
height: 8vh;
background: #f75c45;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
\ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
<import src='./template/1v1/1v1.wxml'/>
<view class="trtc-room-container {{isFullscreenDevice?'fullscreen-device-fix':''}}">
<block wx:if="{{template === '1v1'}}">
<template is='1v1' data="{{pusher, streamList, debug, enableIM,config}}"></template>
</block>
<view class="im-panel" wx:if="{{enableIM && showIMPanel}}">
<view class="message-panel-body">
<scroll-view scroll-y="true" class="message-scroll-container" scroll-into-view="message{{messageList.length-1}}" scroll-with-animation="{{true}}">
<view class="message-list">
<view class="message-item" wx:for="{{messageList}}" wx:key="index" id="message{{index}}">
<span class="user-name {{item.name == config.userID?'mine':''}}">{{item.name}}</span>
<span class="message-content">{{item.message}}</span>
</view>
<view id="message-bottom"></view>
</view>
</scroll-view>
</view>
<view class="message-panel-bottom">
<view class="message-input-container">
<input class="message-input" type="text" value="{{messageContent}}" bindinput='_inputIMMessage' bindconfirm='_sendIMMessage' confirm-type="send" placeholder="请输入消息" maxlength="200" placeholder-style="color:#ffffff;opacity: 0.55;"/>
</view>
<view class="message-send-btn">
<button class="btn" bindtap="_sendIMMessage" hover-class="btn-hover">发送</button>
</view>
</view>
<view bindtap="_toggleIMPanel" class='close-btn'>X</view>
</view>
<view class="debug-info-btn {{debugMode && !debugPanel?'':'none'}}">
<button class="debug-btn" bindtap="_debugTogglePanel" hover-class="button-hover">Debug</button>
</view>
<view class="debug-info {{debugMode && debugPanel?'':'none'}}">
<view bindtap="_debugTogglePanel" class='close-btn'>X</view>
<view>appVersion: {{appVersion}}</view>
<view>libVersion: {{libVersion}}</view>
<view>template: {{template}}</view>
<view>debug: <button class="{{debug?'':'false'}} debug-btn" bindtap="_debugToggleVideoDebug" hover-class="button-hover">{{debug}}</button></view>
<view>userID: {{pusher.userID}}</view>
<view>roomID: {{pusher.roomID}}</view>
<view>camera: <button class="{{pusher.enableCamera?'':'false'}} debug-btn" bindtap="_toggleVideo" hover-class="button-hover">{{pusher.enableCamera}}</button></view>
<view>mic: <button class="{{pusher.enableMic?'':'false'}} debug-btn" bindtap="_toggleAudio" hover-class="button-hover">{{pusher.enableMic}}</button></view>
<view>switch camera: <button class="debug-btn" bindtap="switchCamera" hover-class="button-hover">{{cameraPosition||pusher.frontCamera}}</button></view>
<view>Room:
<button class="debug-btn" bindtap="_debugEnterRoom" hover-class="button-hover">Enter</button>
<button class="debug-btn" bindtap="_debugExitRoom" hover-class="button-hover">Exit</button>
<button class="debug-btn" bindtap="_debugGoBack" hover-class="button-hover">Go back</button>
</view>
<view>IM: <button class="debug-btn" bindtap="_debugSendRandomMessage" hover-class="button-hover">send</button></view>
<view>user count: {{userList.length}}</view>
<view wx:for="{{userList}}" wx:key="userID">{{item.userID}}|
mainV:<span class="text {{item.hasMainVideo? 'true' : 'false' }}">{{item.hasMainVideo||false}}</span>|
mainA:<span class="text {{item.hasMainAudio? 'true' : 'false' }}">{{item.hasMainAudio||false}}</span>|
auxV:<span class="text {{item.hasAuxVideo? 'true' : 'false' }}">{{item.hasAuxVideo||false}}</span></view>
<view>stream count: {{streamList.length}}</view>
<view wx:for="{{streamList}}" wx:key="streamID">{{item.userID}}|{{item.streamType}}|
SubV:<button class="{{!item.muteVideo?'':'false'}} debug-btn" bindtap="_debugToggleRemoteVideo" hover-class="button-hover" data-user-i-d="{{item.userID}}" data-stream-type="{{item.streamType}}">{{!item.muteVideo}}</button>|
SubA:<button class="{{!item.muteAudio?'':'false'}} debug-btn" bindtap="_debugToggleRemoteAudio" hover-class="button-hover" data-user-i-d="{{item.userID}}" data-stream-type="{{item.streamType}}">{{!item.muteAudio}}</button></view>
</view>
</view>
@import "./template/1v1/1v1.wxss";
.pusher {
width: 100%;
height: 100%;
}
.player {
width: 100%;
height: 100%;
}
.debug-info{
max-width: 100vw;
max-height: 90vh;
box-sizing: border-box;
overflow-y: scroll;
position: absolute;
z-index: 9999;
background-color: rgba(0, 0, 0, .5);
color: #fff;
bottom: 20rpx;
left: 0;
padding: 10rpx;
font-size: 12px;
}
.debug-info-btn .debug-btn,
.debug-info .debug-btn{
padding: 0 8px;
min-height: 18px;
width: auto;
font-size: 12px;
line-height: 18px;
display: inline-block;
color: #06ae56;
background-color: #f2f2f2;
}
.debug-info .debug-btn.false{
color: rgb(114, 114, 114);
}
.debug-info-btn .debug-btn,
.debug-info .button-hover {
background-color: rgb(219, 219, 219);
}
.debug-info .close-btn{
position: absolute;
top: 0;
right: 0;
padding: 5px 10px;
}
.debug-info .text.true{
color: #1fff8b;
}
.debug-info .text.false{
color: #ff2e2e;
}
.debug-info-btn{
position: absolute;
z-index: 9998;
bottom: 160rpx;
left: 0;
}
.trtc-room-container .btn {
display: inline-block;
width: auto;
height: 60rpx;
min-height: 60rpx;
line-height: 60rpx;
font-size: 12px;
font-weight: normal;
padding: 0 10rpx;
color: #006eff;
background-color: #f2f2f2;
margin: 0 16rpx;
}
.trtc-room-container .btn.active{
color: #f2f2f2;
background-color: #006eff;
}
.trtc-room-container .btn-hover{
background-color: #d1d1d1;
}
.im-panel{
position: absolute;
z-index: 9;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 90vw;
height: 320rpx;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
padding: 20rpx 0;
border-radius: 10rpx;
font-size: 12px;
/* bottom: 25vh; */
color: #fff;
background-color: rgba(0, 0, 0, 0.8);
}
.im-panel .close-btn {
position: absolute;
top: 0;
right: -3px;
padding: 5px 10px;
z-index: 99;
}
.message-panel-body{
width: 100%;
height: 80%;
overflow-x: hidden;
overflow-y: scroll;
}
.message-scroll-container{
height: 100%;
/* box-sizing: border-box;
padding: 0 20rpx; */
}
.message-list{
width: 100%;
box-sizing: border-box;
padding: 0 20rpx;
/* display: flex;
flex-direction: column; */
}
.message-item{
width: 100%;
/* height: 36rpx; */
/* padding: 0 20rpx; */
padding-bottom: 10rpx;
display: flex;
flex-direction: row;
}
.message-item .user-name{
width: 20%;
color: #2483ff;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.user-name.mine{
color: #ff7424;
}
.message-item .separate{
padding:0 5px;
color: #fff;
}
.message-item .message-content{
word-wrap:break-word;
word-break:break-all;
padding-left: 20rpx;
position: relative;
max-width: 80%;
box-sizing: border-box;
}
.message-content::after{
content: ':';
position: absolute;
left: 0;
top: 0;
}
.message-panel-bottom{
width: 100%;
height: 50rpx;
box-sizing: border-box;
padding: 0 20rpx 0;
margin-top: 20rpx;
display: flex;
flex-direction: row;
}
.message-input-container {
flex-grow: 1;
}
.message-input-container .message-input {
font-size: 12px;
padding-left: 20rpx;
border-radius: 10rpx;
height: 100%;
background-color: rgba(0,0,0,0.1);
}
.message-send-btn .btn{
margin-right: 0;
height: 50rpx;
min-height: 50rpx;
line-height: 50rpx;
}
.volume-animation{
position: absolute;
width: 80rpx;
height: 80rpx;
left: 0;
top: initial;
bottom: 20rpx;
z-index: 9;
/* transform: translate(-50%, 0); */
}
.volume-animation .image{
position: absolute;
width: 80rpx;
height: 80rpx;
}
.volume-animation .audio-active{
animation: viewlinear 1.5s linear infinite;
}
@keyframes viewlinear {
/** 第一种写法**/
0% {
height: 0;
}
100% {
height: 100%;
}
}
.none,
.view-container.none,
.template-1v1 .view-container.none{
display: none !important;
}
export default function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} if (num1 < num2) {
return -1
}
}
return 0
}
import compareVersion from './compare-version.js'
const TAG_NAME = 'TRTC-ROOM'
const env = wx ? wx : qq
if (!env) {
console.error(TAG_NAME, '不支持当前小程序环境')
}
const systemInfo = env.getSystemInfoSync()
const safeArea = systemInfo.safeArea
if (systemInfo.system === 'iOS 13.3' || (systemInfo.model === 'iPhoneX' && systemInfo.system === 'iOS 13.3.1') ) {
// audio-volume-type = media
console.log('use media audio volume type')
}
console.log(TAG_NAME, 'SystemInfo', systemInfo)
let isNewVersion
if (typeof qq !== 'undefined') {
isNewVersion = true
} else if (typeof wx !== 'undefined') {
if (compareVersion(systemInfo.version, '7.0.8') >= 0 || // mobile pc
(compareVersion(systemInfo.version, '2.4.0') >= 0 && compareVersion(systemInfo.version, '6.0.0') < 0) && // mac os
compareVersion(systemInfo.SDKVersion, '2.10.0') >= 0) {
isNewVersion = true
} else {
isNewVersion = false
}
}
export const IS_TRTC = isNewVersion
export const IS_QQ = typeof qq !== 'undefined'
export const IS_WX = typeof wx !== 'undefined'
export const IS_IOS = /iOS/i.test(systemInfo.system)
export const IS_ANDROID = /Android/i.test(systemInfo.system)
export const IS_MAC = /mac/i.test(systemInfo.system)
export const APP_VERSION = systemInfo.version
export const LIB_VERSION = (function() {
if (systemInfo.SDKBuild) {
return systemInfo.SDKVersion + '-' + systemInfo.SDKBuild
}
return systemInfo.SDKVersion
})()
let isFullscreenDevie = false
if (systemInfo.screenHeight > safeArea.bottom) {
// if (/iphone\s{0,}x/i.test(systemInfo.model)) {
isFullscreenDevie = true
}
export const IS_FULLSCREEN_DEVICE = isFullscreenDevie
console.log(TAG_NAME, 'APP_VERSION:', APP_VERSION, ' LIB_VERSION:', LIB_VERSION, ' is new version:', IS_TRTC)
class Event {
on(event, fn, ctx) {
if (typeof fn !== 'function') {
console.error('listener must be a function')
return
}
this._stores = this._stores || {};
(this._stores[event] = this._stores[event] || []).push({ cb: fn, ctx: ctx })
}
emit(event) {
this._stores = this._stores || {}
let store = this._stores[event]
let args
if (store) {
store = store.slice(0)
args = [].slice.call(arguments, 1),
args[0] = {
eventCode: event,
data: args[0],
}
for (let i = 0, len = store.length; i < len; i++) {
store[i].cb.apply(store[i].ctx, args)
}
}
}
off(event, fn) {
this._stores = this._stores || {}
// all
if (!arguments.length) {
this._stores = {}
return
}
// specific event
const store = this._stores[event]
if (!store) return
// remove all handlers
if (arguments.length === 1) {
delete this._stores[event]
return
}
// remove specific handler
let cb
for (let i = 0, len = store.length; i < len; i++) {
cb = store[i].cb
if (cb === fn) {
store.splice(i, 1)
break
}
}
return
}
}
module.exports = Event
images/a.png

590 Bytes

images/add.png

405 Bytes

images/g2x.png

509 Bytes

This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment