Compare commits

...

36 Commits

Author SHA1 Message Date
yj fbdc118292 优化 2025-11-10 13:43:26 +08:00
yj 819c899c57 优化 2025-11-10 12:47:34 +08:00
yj 300194a8e4 优化 2025-03-04 15:10:09 +08:00
yj 348b5d2ddc 网络状态 2025-03-04 15:01:25 +08:00
yj b978744362 优化 2025-03-03 17:46:13 +08:00
yj d6bdecc359 添加报错提示 2025-03-03 10:41:40 +08:00
yj 26f567ffd4 优化 2025-02-28 17:21:42 +08:00
yj d86738463f 优化 2025-02-28 15:33:59 +08:00
yj b030e2e26b bug修复 2025-02-28 14:41:16 +08:00
yj 043fbf1846 修改bug 2025-02-28 14:07:10 +08:00
yj fc73b4dd29 优化 2025-02-27 16:41:15 +08:00
yj 9994bbce4e 优化 2025-02-27 16:06:30 +08:00
yj 877754ac06 优化 2025-02-27 15:51:47 +08:00
yj d6718ae65b 暂时屏蔽5分钟下麦 2025-02-26 15:32:24 +08:00
yj d4c26577da 静音设置 2025-02-26 13:54:31 +08:00
yj f4c8ee36b0 优化 2025-02-25 17:16:45 +08:00
yj e4f57d216f 优化 2025-02-25 09:42:16 +08:00
yj 3b61578baa 全员观看-活跃用户 2025-02-24 16:38:47 +08:00
yj 9c4e9cb918 优化 2025-02-24 14:34:14 +08:00
yj a95e977ca1 聊天显示bug 2025-02-24 10:08:36 +08:00
yj 61c37c4b59 优化 2025-02-21 11:52:48 +08:00
yj dddd1e16f5 优化 2025-02-20 17:56:56 +08:00
yj b786ed9923 优化 2025-02-20 17:07:30 +08:00
yj 04f7b0bb4c 优化 2025-02-20 16:08:10 +08:00
yj 5ae26babb1 优化 2025-02-20 15:55:11 +08:00
yj 54187034df 优化 2025-02-20 14:19:00 +08:00
yj 21901de43a 优化 2025-02-20 09:37:38 +08:00
yj 2576d53a14 优化 2025-02-19 18:02:14 +08:00
yj fdceae0c76 优化 2025-02-19 16:12:37 +08:00
yj 3fedd96ce3 优化 2025-02-18 17:49:13 +08:00
yj 1d67b27a1a 入会时,记录用户当前使用版本 2025-02-18 11:07:27 +08:00
yj ecf913ce88 优化 2025-02-18 09:49:09 +08:00
yj e0ba230ce5 优化 2025-02-17 17:55:23 +08:00
yj 0c90133ca4 修复bug 2025-02-17 17:52:50 +08:00
yj f647c1b972 修改重连时间 2025-02-17 15:59:04 +08:00
yj b42a5ae6ab 发言人5分钟未推音视频流自动下麦 2025-02-17 11:21:00 +08:00
15 changed files with 716 additions and 208 deletions

View File

@ -21,3 +21,9 @@ export const GetOpenId = (code: string) => Request({
url: `/pub/mini-openid?js_code=${code}`, url: `/pub/mini-openid?js_code=${code}`,
method: 'get', method: 'get',
}) })
export const PostHomeVerLog = (data: any) =>
Request({
url: `/home/ver-log`,
method: 'post',
data
})

View File

@ -14,7 +14,8 @@
"t-message": "tdesign-miniprogram/message/message", "t-message": "tdesign-miniprogram/message/message",
"t-dialog": "tdesign-miniprogram/dialog/dialog", "t-dialog": "tdesign-miniprogram/dialog/dialog",
"t-popup": "tdesign-miniprogram/popup/popup", "t-popup": "tdesign-miniprogram/popup/popup",
"t-cell": "tdesign-miniprogram/cell/cell" "t-cell": "tdesign-miniprogram/cell/cell",
"t-toast": "tdesign-miniprogram/toast/toast"
}, },
"entryPagePath": "pages/form/index", "entryPagePath": "pages/form/index",
"window": { "window": {

BIN
assets/icon11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

BIN
assets/icon12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

BIN
assets/icon13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

BIN
assets/icon14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

View File

@ -1,4 +1,4 @@
import { GetCheckoutRoomNum, PostAnonLogin, GetAgoraConf, GetRoomRtcToken, GetOpenId } from '../../api/form/index' import { GetCheckoutRoomNum, PostAnonLogin, GetAgoraConf, GetRoomRtcToken, GetOpenId, PostHomeVerLog } from '../../api/form/index'
import { Message } from 'tdesign-miniprogram'; import { Message } from 'tdesign-miniprogram';
import { startSignalr, onStop } from '../../utils/singlr'; import { startSignalr, onStop } from '../../utils/singlr';
import { agora } from '../../utils/agora' import { agora } from '../../utils/agora'
@ -16,6 +16,20 @@ Page({
code: '' code: ''
}, },
onShow() { onShow() {
const deviceInfo = wx.getDeviceInfo()
if (deviceInfo && (deviceInfo.platform === 'windows' || deviceInfo.platform === 'mac')) {
wx.showModal({
title: '提示',
content: '当前仅支持移动端使用PC端无法使用。',
showCancel: false,
confirmText: '我知道了',
success: function () {
wx.exitMiniProgram && wx.exitMiniProgram();
}
});
return
}
wx.hideLoading()
const that = this; const that = this;
onStop() onStop()
this.setData({ this.setData({
@ -25,9 +39,50 @@ Page({
key: 'isConnected', key: 'isConnected',
success(res: any) { success(res: any) {
if (res.data) { if (res.data) {
that.setData({
isJoin: false
})
that.setData({ that.setData({
netWorkErrorDialog: true, netWorkErrorDialog: true,
}) })
wx.setStorage({
key: "isConnected",
data: false
})
}
},
})
wx.getStorage({
key: 'isAllLeave',
success(res: any) {
if (res.data) {
Message.success({
context: that,
offset: ['50px', 32],
duration: 2000,
content: '管理员已结束会议!',
});
wx.setStorage({
key: "isAllLeave",
data: false
})
}
},
})
wx.getStorage({
key: 'isForceExitRoom',
success(res: any) {
if (res.data) {
Message.success({
context: that,
offset: ['50px', 32],
duration: 2000,
content: '管理员已将你移出会议!',
});
wx.setStorage({
key: "isForceExitRoom",
data: false
})
} }
}, },
}) })
@ -104,7 +159,15 @@ Page({
token: res[0].data, token: res[0].data,
appid: res[1].data appid: res[1].data
}) })
} else {
this.setData({
isJoin: false
})
} }
}).catch(() => {
this.setData({
isJoin: false
})
}) })
}, },
getCode(callBack?) { getCode(callBack?) {
@ -130,6 +193,14 @@ Page({
key: "isConnected", key: "isConnected",
data: false data: false
}) })
wx.setStorage({
key: "isAllLeave",
data: false
})
wx.setStorage({
key: "isForceExitRoom",
data: false
})
this.setData({ this.setData({
netWorkErrorDialog: false netWorkErrorDialog: false
}) })
@ -174,6 +245,12 @@ Page({
uid: res.data.uid, uid: res.data.uid,
screenShareId: res.data.screenShareId, screenShareId: res.data.screenShareId,
}) })
const accountInfo = wx.getAccountInfoSync()
PostHomeVerLog({
version: accountInfo?.miniProgram?.envVersion + '-' + accountInfo?.miniProgram?.version,
platformType: 2,
roomNum: this.data.meetingForm.roomNum,
})
wx.navigateTo({ wx.navigateTo({
url: `/pages/meeting/index?roomNum=${this.data.meetingForm.roomNum}&nickName=${this.data.meetingForm.roomName}` url: `/pages/meeting/index?roomNum=${this.data.meetingForm.roomNum}&nickName=${this.data.meetingForm.roomName}`
}) })
@ -216,6 +293,18 @@ Page({
}) })
return return
} }
if (this.data.meetingForm.roomName.length > 10) {
Message.error({
context: this,
offset: [90, 32],
duration: 3000,
content: '入会名称最多10个字',
});
this.setData({
isJoin: false
})
return
}
GetCheckoutRoomNum(this.data.meetingForm.roomNum).then(async res => { GetCheckoutRoomNum(this.data.meetingForm.roomNum).then(async res => {
if (res.code === 200) { if (res.code === 200) {
if (res.data) { if (res.data) {

View File

@ -1,5 +1,6 @@
{ {
"usingComponents": {}, "usingComponents": {},
"navigationBarTextStyle": "white", "navigationBarTextStyle": "white",
"pageOrientation": "landscape" "pageOrientation": "landscape",
"disableScroll": true
} }

View File

@ -10,6 +10,8 @@
border-radius: 4rpx; border-radius: 4rpx;
padding: 2rpx; padding: 2rpx;
bottom: 4rpx; bottom: 4rpx;
max-width: calc(100% - 12rpx);
box-sizing: border-box;
&-view { &-view {
width: 16rpx; width: 16rpx;
@ -64,7 +66,9 @@
&-text { &-text {
color: white; color: white;
font-size: 12rpx; font-size: 12rpx;
margin-left: 2rpx; white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
} }
} }
@ -149,7 +153,7 @@
&-up { &-up {
position: fixed; position: fixed;
z-index: 5; z-index: 5;
right: 7.4%; right: 65px;
top: 14%; top: 14%;
color: white; color: white;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
@ -165,7 +169,7 @@
&-down { &-down {
position: fixed; position: fixed;
z-index: 5; z-index: 5;
right: 7.4%; right: 65px;
bottom: 14%; bottom: 14%;
color: white; color: white;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
@ -179,7 +183,7 @@
} }
&-box { &-box {
height: calc(100% / 3); height: 96px;
position: relative; position: relative;
padding: 2rpx 4rpx; padding: 2rpx 4rpx;
box-sizing: border-box; box-sizing: border-box;
@ -306,7 +310,7 @@
.user-popup { .user-popup {
width: 30vw; width: 30vw;
height: 100vh; height: 88vh;
background-color: #16191E; background-color: #16191E;
padding: 10rpx 0; padding: 10rpx 0;
box-sizing: border-box; box-sizing: border-box;
@ -314,12 +318,18 @@
flex-direction: column; flex-direction: column;
&-title { &-title {
color: white; color: gray;
text-align: center;
font-size: 16rpx; font-size: 16rpx;
flex-shrink: 0; flex-shrink: 0;
border-bottom: 1px rgb(59, 59, 59) solid; border-bottom: 1px rgb(59, 59, 59) solid;
padding-bottom: 10rpx; padding-bottom: 10rpx;
display: flex;
align-items: center;
justify-content: space-around;
&-active {
color: white;
}
} }
&-view { &-view {
@ -329,6 +339,7 @@
flex-grow: 1; flex-grow: 1;
&-view { &-view {
color: white;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@ -340,14 +351,17 @@
flex-grow: 1; flex-grow: 1;
&-text { &-text {
flex-grow: 1;
color: white;
font-size: 14rpx; font-size: 14rpx;
margin: 0 2rpx; margin: 0 2rpx;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
width: 0; max-width: 100rpx;
}
&-me {
color: white;
font-size: 14rpx;
} }
} }

View File

@ -1,15 +1,18 @@
import { GetRoomInfo, GetRoomUser, GetShowUser, GetApplySpeak, PostMuteAll, PostOpenMicr, PostOpenCamera, DeleteRoomManager } from '../../api/meeting/index' import { GetRoomInfo, GetRoomUser, GetShowUser, GetApplySpeak, PostMuteAll, PostOpenMicr, PostOpenCamera, DeleteRoomManager } from '../../api/meeting/index'
import { GetRoomRtcToken } from '../../api/form/index' import { GetRoomRtcToken } from '../../api/form/index'
import { agora } from '../../utils/agora' import { agora } from '../../utils/agora'
import { onInvoke, onSignalr, getSignIr, offSignalr } from '../../utils/singlr' import { onInvoke, onSignalr, getSignIr, offSignalr, onStop } from '../../utils/singlr'
import { role, getStorage } from '../../utils/utils' import { role, getStorage } from '../../utils/utils'
import { Message } from 'tdesign-miniprogram'; import { Message, Toast } from 'tdesign-miniprogram';
import * as signalR from "signalr-for-wx"; import * as signalR from "signalr-for-wx";
import dayjs from 'dayjs'; import dayjs from 'dayjs';
const computedBehavior = require('miniprogram-computed').behavior; const computedBehavior = require('miniprogram-computed').behavior;
let reconnectTime = "" as any; let reconnectTime = "" as any;
let refreshTime = "" as any; let refreshTime = "" as any;
let isReconnecTimeSetTimeout = "" as any; let isAutoApplySpeakTime = "" as any;
let isSpeakTime = "" as any;
let netWorkTime = "" as any;
let isReconnecTime = "" as any;
Page({ Page({
behaviors: [computedBehavior], behaviors: [computedBehavior],
data: { data: {
@ -72,6 +75,7 @@ Page({
}, },
], ],
channelId: '', channelId: '',
tabBarIndex: 1,
roomInfo: '', roomInfo: '',
roomUserList: [], roomUserList: [],
audioList: [], audioList: [],
@ -87,11 +91,13 @@ Page({
leaveDialog: false, leaveDialog: false,
userPopupVisible: false, userPopupVisible: false,
chatPopupVisible: false, chatPopupVisible: false,
inputPopupVisible: false,
isFullscreen: false, isFullscreen: false,
muted: false, muted: false,
currentRequestSpeakType: '', currentRequestSpeakType: '',
user: '', user: '',
messageStr: '', messageStr: '',
inputStr: '',
commonlyChatList: [ commonlyChatList: [
'能听到我说话吗?', '能听到我说话吗?',
'听得到', '听得到',
@ -101,7 +107,13 @@ Page({
isFirstShow: true, isFirstShow: true,
isCurrePage: true, isCurrePage: true,
isReconnec: false, isReconnec: false,
isReconnecTime: false, isAutoApplySpeakDialog: false,
showScroll: false,
reconnecNumber: 0,
setting: {
voiceStimulation: true, //语音激励
},
network: 0
}, },
watch: { watch: {
'roomUserList.**': function (roomUserList) { 'roomUserList.**': function (roomUserList) {
@ -110,7 +122,8 @@ Page({
userNumer: roomUserList.filter((item: any) => item.isRoom).length, userNumer: roomUserList.filter((item: any) => item.isRoom).length,
audioList: roomUserList.map(item => { audioList: roomUserList.map(item => {
return { return {
volume: 0, volume: item.volume || '0%',
volumeNumber: item.volumeNumber || 0,
uid: item.uid, uid: item.uid,
} }
}) })
@ -128,6 +141,32 @@ Page({
'footerList.**': function (footerList) { 'footerList.**': function (footerList) {
const footerListTemplate = [...footerList]; const footerListTemplate = [...footerList];
footerListTemplate[3].show = footerListTemplate[2].active footerListTemplate[3].show = footerListTemplate[2].active
// if (!footerListTemplate[1].active && !footerListTemplate[2].active) {
// if (isAutoApplySpeakTime) {
// clearTimeout(isAutoApplySpeakTime)
// isAutoApplySpeakTime = ''
// }
// isAutoApplySpeakTime = setTimeout(() => {
// let userItem = this.data.roomUserList.find((item: any) => item.uid === this.data.user.uid)
// if (!role.ID.includes(this.data.user.roleId) && userItem && userItem.isRoomManager) {
// DeleteRoomManager({
// roomId: this.data.roomInfo.id,
// roomNum: this.data.channelId,
// userId: userItem.uid
// })
// this.setData({
// isAutoApplySpeakDialog: true
// })
// }
// clearTimeout(isAutoApplySpeakTime)
// isAutoApplySpeakTime = ''
// }, 1000 * 60 * 5);
// } else {
// if (isAutoApplySpeakTime) {
// clearTimeout(isAutoApplySpeakTime)
// isAutoApplySpeakTime = ''
// }
// }
this.setData({ this.setData({
footerList: footerListTemplate footerList: footerListTemplate
}) })
@ -142,31 +181,9 @@ Page({
}, 10000); }, 10000);
} }
}, },
'isReconnecTime': function (isReconnecTime) {
if (isReconnecTime) {
isReconnecTimeSetTimeout = setTimeout(() => {
clearTimeout(isReconnecTimeSetTimeout)
this.setData({
isReconnec: true,
isReconnecTime: false,
})
isReconnecTimeSetTimeout = ''
wx.hideLoading()
}, 8000)
} else {
if (isReconnecTimeSetTimeout) {
clearTimeout(isReconnecTimeSetTimeout)
isReconnecTimeSetTimeout = ''
wx.hideLoading()
}
}
},
'isCurrePage': function (isCurrePage) { 'isCurrePage': function (isCurrePage) {
if (isCurrePage) { if (isCurrePage) {
if (refreshTime) { this.clearTimer()
clearInterval(refreshTime)
refreshTime = ''
}
} else { } else {
refreshTime = setInterval(() => { refreshTime = setInterval(() => {
GetRoomUser(this.data.channelId).then(res => { GetRoomUser(this.data.channelId).then(res => {
@ -203,6 +220,15 @@ Page({
}) })
} }
}, },
'isAdmin': function (isAdmin) {
const query = wx.createSelectorQuery()
query.select('#meeting-content-smallvideo').fields({ size: true, scrollOffset: true }, (res) => {
this.setData({
showScroll: Math.ceil(isAdmin * 94) > Math.ceil(res.height)
})
})
query.exec()
}
}, },
async onLoad(option) { async onLoad(option) {
wx.enableAlertBeforeUnload({ wx.enableAlertBeforeUnload({
@ -250,8 +276,14 @@ Page({
}, },
onReady() { onReady() {
wx.onNetworkStatusChange(this.listener) wx.onNetworkStatusChange(this.listener)
this.setStorageData()
}, },
onShow() { async onShow() {
if (netWorkTime) {
clearTimeout(netWorkTime)
netWorkTime = ''
}
this.getNetWorkSpeed()
wx.setKeepScreenOn({ wx.setKeepScreenOn({
keepScreenOn: true, keepScreenOn: true,
}); });
@ -263,62 +295,151 @@ Page({
isFirstShow: false, isFirstShow: false,
}) })
} else { } else {
const item = this.data.roomUserList.find(row => row.uid === this.data.user.uid) this.reconnecFun()
if (item && !item.isRoomManager) { }
isSpeakTime = setInterval(() => {
if (this.data.setting.voiceStimulation) {
function getMaxObject(arr) {
let maxObject = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i].volumeNumber > maxObject.volumeNumber) {
maxObject = arr[i];
}
}
return maxObject;
}
const isShare = this.data.roomUserList.find(item => item.shareSrc)
const item = getMaxObject(this.data.audioList)
const user = this.data.roomUserList.find(row => item.uid === row.uid)
if (item && (this.data.currentUid !== item.uid && !isShare && (user && user.isRoom) && item.volumeNumber > 0 && item.uid !== this.data.user.uid)) {
this.setData({
currentUid: item.uid
})
}
}
}, 3000)
},
// 隐藏
onHide() {
this.setData({
isCurrePage: true,
})
this.clearTimer()
},
// 卸载
onUnload() {
wx.offNetworkStatusChange(this.listener)
this.clearTimer()
},
// 获取网络质量
getNetWorkSpeed() {
this.getNetworkStatus().then(networkStatus => {
this.setData({
network: networkStatus,
})
netWorkTime = setTimeout(() => {
this.getNetWorkSpeed()
}, 3000);
})
},
getNetworkStatus() {
const DOWNLOAD_TIME = [500, 1500];
return new Promise((resolve) => {
try {
let networkStatus = 0
this.getNetworkType().then(({ networkType }) => {
if (['unknown', 'none'].includes(networkType)) {
return resolve(-1);
}
if (['2g', '3g'].includes(networkType)) {
return resolve(2);
}
const startTime = +new Date();
this.requestImage().then(() => {
const requestTime = +new Date() - startTime;
if (requestTime < DOWNLOAD_TIME[0]) {
networkStatus = 0;
} else if (requestTime > DOWNLOAD_TIME[1]) {
networkStatus = 1
} else {
networkStatus = 2;
}
return resolve(networkStatus);
})
});
} catch (error) {
resolve(0);
}
})
},
requestImage() {
return new Promise((resolve) => {
wx.request({
url: `https://meeting-api.23544.com/meeting/update/ddq.png?t=${+new Date()}`,
success() {
resolve('');
},
fail() {
resolve('')
}
})
})
},
getNetworkType() {
return new Promise((resolve) => {
wx.getNetworkType({
success(res) {
resolve(res);
},
fail(err) {
resolve(err);
}
})
})
},
// 设置缓存
async setStorageData() {
const setting: any = await getStorage('setting')
if (setting) {
this.setData({
setting
})
} else {
wx.setStorage({
key: "setting",
data: this.data.setting
})
}
},
// 重连
async reconnecFun() {
if (isReconnecTime) {
clearTimeout(isReconnecTime)
isReconnecTime = ''
}
isReconnecTime = setTimeout(() => {
wx.hideLoading()
this.setData({
isReconnec: true
})
}, 1000 * 30);
wx.hideLoading()
wx.showLoading({ wx.showLoading({
title: '重连中', title: '重连中',
mask: true mask: true
}) })
this.setData({ if (reconnectTime) {
isReconnecTime: true, clearTimeout(reconnectTime)
}) reconnectTime = ''
}
agora.destroy(() => { agora.destroy(() => {
reconnectTime = setInterval(() => { this.startReconnec()
})
},
async startReconnec() {
if (getSignIr() === signalR.HubConnectionState.Connected) { if (getSignIr() === signalR.HubConnectionState.Connected) {
this.reconnecFun() clearTimeout(reconnectTime)
clearInterval(reconnectTime)
reconnectTime = '' reconnectTime = ''
}
}, 2000)
})
}
}
},
onHide() {
this.setData({
isCurrePage: true,
isReconnecTime: false
})
if (reconnectTime) {
clearInterval(reconnectTime)
reconnectTime = ''
}
if (isReconnecTimeSetTimeout) {
clearInterval(isReconnecTimeSetTimeout)
isReconnecTimeSetTimeout = ''
}
if (refreshTime) {
clearInterval(refreshTime)
refreshTime = ''
}
},
onUnload() {
wx.offNetworkStatusChange(this.listener)
if (reconnectTime) {
clearInterval(reconnectTime)
reconnectTime = ''
}
if (isReconnecTimeSetTimeout) {
clearInterval(isReconnecTimeSetTimeout)
isReconnecTimeSetTimeout = ''
}
if (refreshTime) {
clearInterval(refreshTime)
refreshTime = ''
}
},
async reconnecFun() {
offSignalr()
await GetRoomRtcToken(this.data.channelId).then(res => { await GetRoomRtcToken(this.data.channelId).then(res => {
if (res.code === 200) { if (res.code === 200) {
agora.reconnecSetOption(res.data, async (bool) => { agora.reconnecSetOption(res.data, async (bool) => {
@ -335,9 +456,12 @@ Page({
content: '重连成功', content: '重连成功',
}); });
this.setData({ this.setData({
isReconnecTime: false,
isReconnec: false isReconnec: false
}) })
if (isReconnecTime) {
clearTimeout(isReconnecTime)
isReconnecTime = ''
}
} else { } else {
this.setData({ this.setData({
isReconnec: true isReconnec: true
@ -357,12 +481,100 @@ Page({
isReconnec: true isReconnec: true
}) })
}) })
} else {
if (this.data.reconnecNumber > 10) {
this.setIsConnectedBack()
} else {
this.setData({
reconnecNumber: this.data.reconnecNumber + 1
})
reconnectTime = setTimeout(() => {
this.startReconnec()
}, 3000)
}
}
}, },
// 清除定时器
clearTimer() {
if (refreshTime) {
clearInterval(refreshTime)
refreshTime = ''
}
if (reconnectTime) {
clearTimeout(reconnectTime)
reconnectTime = ''
}
if (isAutoApplySpeakTime) {
clearTimeout(isAutoApplySpeakTime)
isAutoApplySpeakTime = ''
}
if (isSpeakTime) {
clearInterval(isSpeakTime)
isSpeakTime = ''
}
if (netWorkTime) {
clearTimeout(netWorkTime)
netWorkTime = ''
}
if (isReconnecTime) {
clearTimeout(isReconnecTime)
isReconnecTime = ''
}
},
// 显示聊天输入框
showInputPopup() {
this.setData({
inputPopupVisible: true,
inputStr: this.data.messageStr,
chatPopupVisible: false
})
},
// 隐藏聊天输入框
hideInputPopup() {
this.setData({
inputPopupVisible: false,
messageStr: this.data.inputStr,
chatPopupVisible: true
})
},
// 申请发言提示框
confirmIsAutoApplySpeakDialog() {
if (!this.data.isClicked) {
GetApplySpeak(this.data.channelId).then(res => {
if (res.code === 200) {
this.setData({
isClicked: true,
})
this.message('申请发言成功').success()
}
this.setData({
isAutoApplySpeakDialog: false
})
}).catch(() => {
this.setData({
isAutoApplySpeakDialog: false
})
})
} else {
this.message('申请太频繁了,请稍后重试!').error();
}
},
// 关闭发言断开弹窗
cancelIsAutoApplySpeakDialog() {
this.setData({
isAutoApplySpeakDialog: false
})
},
// socket监听
startSignalr() { startSignalr() {
offSignalr()
onSignalr(async (item) => { onSignalr(async (item) => {
if (this.data.isCurrePage) { if (this.data.isCurrePage) {
const item = this.data.roomUserList.find(row => row.uid === this.data.user.uid)
if (item && !item.isRoomManager) {
return return
} }
}
const userInfo: any = await getStorage('user') const userInfo: any = await getStorage('user')
switch (item.key) { switch (item.key) {
// 聊天 // 聊天
@ -384,21 +596,19 @@ Page({
break; break;
// 全员离开房间 // 全员离开房间
case 'AllLeave': case 'AllLeave':
this.message('管理员已结束会议!').success() wx.setStorage({
wx.disableAlertBeforeUnload({ key: "isAllLeave",
complete: () => { data: true
wx.navigateBack()
}
}) })
this.closeRoom()
break; break;
// 移出会议 // 移出会议
case 'ForceExitRoom': case 'ForceExitRoom':
this.message('管理员已将你移出会议!').success() wx.setStorage({
wx.disableAlertBeforeUnload({ key: "isForceExitRoom",
complete: () => { data: true
wx.navigateBack()
}
}) })
this.closeRoom()
break; break;
// 更新视图模式 // 更新视图模式
case 'RefreshView': case 'RefreshView':
@ -527,13 +737,43 @@ Page({
// 显示设备列表 // 显示设备列表
case 'ShowDriverList': case 'ShowDriverList':
break;
// 修改用户名称
case 'ModifyNickName':
this.setAllUserListData('ModifyNickName', item)
break; break;
case 'SetSpeaker': case 'SetSpeaker':
await onInvoke('SetSpeakerCallback', item.RoomManagerInputDTO) await onInvoke('SetSpeakerCallback', item.RoomManagerInputDTO)
break; break;
// 扩展参数
case 'ReceivedOperation':
try {
const temp = JSON.parse(item.contentString)
if (temp.type === 'audio') {
await PostOpenMicr({
roomNum: temp.roomNum,
uid: temp.uid,
enableMicr: temp.enableMicr
})
} else {
await PostOpenCamera({
roomNum: temp.roomNum,
uid: temp.uid,
enableCamera: temp.enableCamera
})
}
} catch (error) {
}
break;
// 共享人取消共享屏幕
case 'StopedSharedScreen':
this.getShowUser()
break;
} }
}) })
}, },
// 声网监听
startClientEvent() { startClientEvent() {
agora.clientEvent({ agora.clientEvent({
streamAdded: async (url: string, uid: number | string) => { streamAdded: async (url: string, uid: number | string) => {
@ -568,9 +808,24 @@ Page({
agora.renewToken(res.data) agora.renewToken(res.data)
} }
}) })
},
updateUrl: (e) => {
const roomUserListTemp = [...this.data.roomUserList]
const item = roomUserListTemp.find(row => row.uid == e.uid || row.screenShareId == e.uid)
if (item) {
if (String(e.uid).length === 9) {
item.shareSrc = e.url;
} else {
item.src = e.url;
} }
}
},
error: (e) => {
this.reconnecFun()
},
}) })
}, },
// 获取房间用户
async getRoomUser(): Promise<void> { async getRoomUser(): Promise<void> {
await GetRoomUser(this.data.channelId).then(res => { await GetRoomUser(this.data.channelId).then(res => {
if (res.code === 200) { if (res.code === 200) {
@ -585,6 +840,30 @@ Page({
} }
}) })
}, },
// 切换tab
setTabBarIndex(e) {
this.setData({
tabBarIndex: Number(e.currentTarget.dataset.tabbarindex)
})
this.setStorageData()
},
// 修改缓存设置
changeSetting(e) {
this.data.setting[e.currentTarget.dataset.str] = e.detail.value
wx.setStorage({
key: "setting",
data: this.data.setting
})
},
// 成员显示用户名称
showMultiText(e) {
Toast({
context: this,
selector: '#t-toast',
message: e.currentTarget.dataset.item.userName,
});
},
// 查看全员观看
async getShowUser(): Promise<void> { async getShowUser(): Promise<void> {
await GetShowUser(this.data.channelId).then(async (res) => { await GetShowUser(this.data.channelId).then(async (res) => {
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
@ -594,6 +873,7 @@ Page({
} }
}) })
}, },
// 首次获取用户信息
async getRoomInfo(): Promise<void> { async getRoomInfo(): Promise<void> {
await GetRoomInfo(this.data.channelId).then(async (res) => { await GetRoomInfo(this.data.channelId).then(async (res) => {
if (res.code === 200) { if (res.code === 200) {
@ -603,14 +883,26 @@ Page({
} }
}) })
}, },
// 加入房间
async joinChannel(): Promise<void> { async joinChannel(): Promise<void> {
const item = this.data.roomUserList.find(row => row.uid === this.data.user.uid)
await onInvoke('joinChannel', { await onInvoke('joinChannel', {
roomNum: this.data.channelId, roomNum: this.data.channelId,
enableMicr: this.data.footerList[1].active, enableMicr: this.data.footerList[1].active,
enableCamera: this.data.footerList[2].active, enableCamera: this.data.footerList[2].active,
isRoomManager: item ? item.isRoomManager : false,
}) })
await agora.joinChannel() agora.joinChannel(item ? item.isRoomManager : false, (url: string) => {
const roomUserListTemp = [...this.data.roomUserList]
const itemUser = roomUserListTemp.find(row => row.uid == this.data.user.uid)
itemUser.src = url
this.setData({
roomUserList: roomUserListTemp,
})
})
this.changeAgoraDevice()
}, },
// 用户数据组装
async setAllUserListData(key: string, item: any, callBack?: Function): Promise<void> { async setAllUserListData(key: string, item: any, callBack?: Function): Promise<void> {
const { roomUserList } = this.data; const { roomUserList } = this.data;
const userInfo: any = await getStorage('user') const userInfo: any = await getStorage('user')
@ -683,9 +975,20 @@ Page({
roomUserList roomUserList
}) })
break; break;
case 'ModifyNickName':
let row = roomUserList.find((row: any) => row.uid == item.uid)
if (row) {
row.userName = item.nickName
row.avatarName = item.nickName?.slice(-2)
}
this.setData({
roomUserList
})
break;
} }
this.changeAgoraDevice() this.changeAgoraDevice()
}, },
// 点击底部按钮
async changeFooterList(e): Promise<void> { async changeFooterList(e): Promise<void> {
const userInfo: any = await getStorage('user') const userInfo: any = await getStorage('user')
const { index } = e.currentTarget.dataset; const { index } = e.currentTarget.dataset;
@ -788,6 +1091,7 @@ Page({
break; break;
} }
}, },
// 开关摄像头
async postOpenMicrApi(enableMicr: boolean, uid: string, isAll: boolean, isMessage: boolean = false): Promise<void> { async postOpenMicrApi(enableMicr: boolean, uid: string, isAll: boolean, isMessage: boolean = false): Promise<void> {
if (isAll) { if (isAll) {
await PostMuteAll({ await PostMuteAll({
@ -795,31 +1099,51 @@ Page({
enableMicr enableMicr
}) })
} else { } else {
await PostOpenMicr({ await onInvoke('sendOper2User', {
uid,
contentString: JSON.stringify({
roomNum: this.data.channelId, roomNum: this.data.channelId,
uid, uid,
enableMicr enableMicr,
type: 'audio'
}) })
})
// await PostOpenMicr({
// roomNum: this.data.channelId,
// uid,
// enableMicr
// })
} }
if (isMessage) { if (isMessage) {
this.message('操作成功').success() this.message('操作成功').success()
} }
}, },
// 开关摄像头
async postOpenCameraApi(enableCamera: boolean, uid: string, isMessage: boolean = false): Promise<void> { async postOpenCameraApi(enableCamera: boolean, uid: string, isMessage: boolean = false): Promise<void> {
if (enableCamera) { if (enableCamera) {
// await agora.startCameraCapture() // await agora.startCameraCapture()
} else { } else {
// await agora.stopCameraCapture(); // await agora.stopCameraCapture();
} }
await PostOpenCamera({ await onInvoke('sendOper2User', {
uid,
contentString: JSON.stringify({
roomNum: this.data.channelId, roomNum: this.data.channelId,
uid, uid,
enableCamera enableCamera,
type: 'video'
}) })
})
// await PostOpenCamera({
// roomNum: this.data.channelId,
// uid,
// enableCamera
// })
if (isMessage) { if (isMessage) {
this.message('操作成功').success() this.message('操作成功').success()
} }
}, },
// 关闭弹窗
async closeDialog(e) { async closeDialog(e) {
const { type } = e.currentTarget.dataset; const { type } = e.currentTarget.dataset;
switch (e.type) { switch (e.type) {
@ -852,12 +1176,7 @@ Page({
break; break;
} }
}, },
playerStateChange(e) { // 音量提示
},
recorderStateChange(e) {
},
playerAudioVolumenotify(e) { playerAudioVolumenotify(e) {
const { uid } = e.currentTarget.dataset; const { uid } = e.currentTarget.dataset;
const { volume } = e.detail; const { volume } = e.detail;
@ -866,18 +1185,26 @@ Page({
const item = audioListTemp.find(row => row.uid == uid) const item = audioListTemp.find(row => row.uid == uid)
if (item) { if (item) {
item.volume = Math.floor(percentage) + '%' item.volume = Math.floor(percentage) + '%'
item.volumeNumber = Math.floor(percentage)
} }
this.setData({ this.setData({
audioList: audioListTemp, audioList: audioListTemp,
userVolume: audioListTemp.find(row => row.uid == this.data.user.uid).volume userVolume: audioListTemp.find(row => row.uid == this.data.user.uid).volume
}) })
}, },
// 切换视频
clickChangeVideo(e) { clickChangeVideo(e) {
const { item } = e.currentTarget.dataset; const { item } = e.currentTarget.dataset;
const isShare = this.data.roomUserList.find(item => item.shareSrc)
if (isShare) {
this.message(`正在进行屏幕共享,不允许切换画面。`).error()
} else {
this.setData({ this.setData({
currentUid: item.uid currentUid: item.uid
}) })
}
}, },
// 悬浮提示
message(content: string) { message(content: string) {
return { return {
success: () => { success: () => {
@ -898,6 +1225,7 @@ Page({
} }
} }
}, },
// 获取当前用户在房间信息
async getUserRoomInfo(): Promise<any> { async getUserRoomInfo(): Promise<any> {
const userInfo: any = await getStorage('user') const userInfo: any = await getStorage('user')
return new Promise((resolve, _reject) => { return new Promise((resolve, _reject) => {
@ -909,6 +1237,7 @@ Page({
} }
}) })
}, },
// 更改数据
async changeAgoraDevice(): Promise<any> { async changeAgoraDevice(): Promise<any> {
const userInfo: any = await getStorage('user') const userInfo: any = await getStorage('user')
this.data.roomUserList.forEach(async (item: any) => { this.data.roomUserList.forEach(async (item: any) => {
@ -927,47 +1256,64 @@ Page({
} }
}); });
}, },
// 退出提示
async back() { async back() {
this.setData({ this.setData({
leaveDialog: true leaveDialog: true
}) })
}, },
// 关闭聊天和成员
onVisibleChange() { onVisibleChange() {
this.setData({ this.setData({
userPopupVisible: false, userPopupVisible: false,
chatPopupVisible: false, chatPopupVisible: false,
}) })
}, },
// 聊天内容输入框赋值
changeMessageStr(e) { changeMessageStr(e) {
this.setData({ this.setData({
messageStr: e.detail.value messageStr: e.detail.value
}) })
}, },
// 聊天内容输入框赋值
changeInputStr(e) {
this.setData({
inputStr: e.detail.value
})
},
// 聊天发送
async sendMeg(e) { async sendMeg(e) {
if (this.data.messageStr || e.target.dataset.item) { if (this.data.messageStr || e.target.dataset.item) {
await onInvoke('sendChannelMsg', { await onInvoke('sendChannelMsg', {
roomNum: this.data.channelId, roomNum: this.data.channelId,
msg: e.target.dataset.item || this.data.messageStr msg: e.target.dataset.item || this.data.messageStr
}) })
const item = this.data.roomUserList.find(row => row.uid === this.data.user.uid)
this.setData({ this.setData({
chatList: [...this.data.chatList, { chatList: [...this.data.chatList, {
userName: this.data.user.userName, userName: item.userName,
message: e.target.dataset.item || this.data.messageStr, message: e.target.dataset.item || this.data.messageStr,
timestamp: dayjs(+new Date()).format('HH:mm:ss'), timestamp: dayjs(+new Date()).format('HH:mm:ss'),
me: true me: true
}], }],
})
if (!e.target.dataset.item) {
this.setData({
messageStr: '' messageStr: ''
}) })
}
this.scrollToBottom() this.scrollToBottom()
} else { } else {
this.message('请输入文字!').error() this.message('请输入文字!').error()
} }
}, },
// 全屏切换
changeFullscreen() { changeFullscreen() {
this.setData({ this.setData({
isFullscreen: !this.data.isFullscreen isFullscreen: !this.data.isFullscreen
}) })
}, },
// 聊天框位置滚动
scrollToBottom() { scrollToBottom() {
wx.createSelectorQuery() wx.createSelectorQuery()
.select('#chatView') .select('#chatView')
@ -979,10 +1325,8 @@ Page({
}) })
}) })
}, },
async listener(res) { // 断网退出房间
if (res.isConnected && (res.networkType !== 'none' || res.networkType !== 'unknown')) { setIsConnectedBack() {
} else {
wx.setStorage({ wx.setStorage({
key: "isConnected", key: "isConnected",
data: true data: true
@ -992,8 +1336,16 @@ Page({
wx.navigateBack() wx.navigateBack()
} }
}) })
},
// 监听网络变化
async listener(res) {
if (res.isConnected && (res.networkType !== 'none' || res.networkType !== 'unknown')) {
} else {
} }
}, },
// 重连失败退出房间
closeRoom() { closeRoom() {
wx.disableAlertBeforeUnload({ wx.disableAlertBeforeUnload({
complete: () => { complete: () => {
@ -1004,9 +1356,7 @@ Page({
} }
}) })
}, },
scroll() { // 上箭头滚动
},
scrollUp() { scrollUp() {
const query = wx.createSelectorQuery() const query = wx.createSelectorQuery()
query.select('#meeting-content-smallvideo').scrollOffset((res => { query.select('#meeting-content-smallvideo').scrollOffset((res => {
@ -1016,6 +1366,7 @@ Page({
})) }))
query.exec() query.exec()
}, },
// 下箭头滚动
scrollDown() { scrollDown() {
const query = wx.createSelectorQuery() const query = wx.createSelectorQuery()
query.select('#meeting-content-smallvideo').scrollOffset((res => { query.select('#meeting-content-smallvideo').scrollOffset((res => {

View File

@ -1,7 +1,11 @@
<!--pages/meeting/index.wxml--> <!--pages/meeting/index.wxml-->
<view class="meeting"> <view class="meeting">
<view wx:if="{{!isFullscreen}}"> <view wx:if="{{!isFullscreen}}" style="position: relative;">
<header-tab title='会议号:{{roomInfo.roomNum}} 会议名称:{{roomInfo.roomName}}' backGround='rgb(35,36,38)' iconSize='24' color="white" titleStyle='padding:12rpx 0;font-size:16rpx' isStatusBarHeight="{{false}}" isBack='{{false}}'></header-tab> <header-tab title='会议号:{{roomInfo.roomNum}} 会议名称:{{roomInfo.roomName}}' backGround='rgb(35,36,38)' iconSize='24' color="white" titleStyle='padding:12rpx 0;font-size:16rpx' isStatusBarHeight="{{false}}" isBack='{{false}}'></header-tab>
<image src="/assets/icon11.png" style="width: 20rpx;height: 20rpx;position: absolute;left: 20rpx;top: 50%;transform: translate(0,-50%);" wx:if="{{network === 0}}" />
<image src="/assets/icon12.png" style="width: 20rpx;height: 20rpx;position: absolute;left: 20rpx;top: 50%;transform: translate(0,-50%);" wx:elif="{{network === 2}}" />
<image src="/assets/icon14.png" style="width: 20rpx;height: 20rpx;position: absolute;left: 20rpx;top: 50%;transform: translate(0,-50%);" wx:elif="{{network === -1}}" />
<image src="/assets/icon13.png" style="width: 20rpx;height: 20rpx;position: absolute;left: 20rpx;top: 50%;transform: translate(0,-50%);" wx:else />
</view> </view>
<view class="meeting-content"> <view class="meeting-content">
<view class="meeting-content-noAdmin" wx:if="{{isAdmin === 0}}"> <view class="meeting-content-noAdmin" wx:if="{{isAdmin === 0}}">
@ -16,20 +20,20 @@
<t-icon name="fullscreen-2" size="24rpx" data-name="fullscreen-2" wx:else /> <t-icon name="fullscreen-2" size="24rpx" data-name="fullscreen-2" wx:else />
</view> </view>
<view class="meeting-content-video-canvas" wx:if="{{currentUser.shareSrc}}"> <view class="meeting-content-video-canvas" wx:if="{{currentUser.shareSrc}}">
<live-player id="player" src="{{currentUser.shareSrc}}" mode="RTC" autoplay="true" bindstatechange="playerStateChange" object-fit="contain"/> <live-player id="player" src="{{currentUser.shareSrc}}" mode="RTC" autoplay="true" object-fit="contain" muted="{{true}}" />
</view> </view>
<view class="meeting-content-video-canvas" wx:elif="{{currentUser.src && currentUser.enableCamera}}"> <view class="meeting-content-video-canvas" wx:elif='{{currentUser.enableCamera}}'>
<live-player id="player" src="{{currentUser.src}}" mode="RTC" autoplay="true" bindstatechange="playerStateChange" object-fit="contain" muted="{{currentUser.uid === user.uid}}" /> <live-player id="player" src="{{currentUser.src}}" mode="RTC" autoplay="true" object-fit="contain" muted="{{true}}" />
</view> </view>
<view class="meeting-content-video-user"> <view class="meeting-content-video-user">
<view class="meeting-content-video-user-view" style=" background:{{currentUser.roleId === '1' || currentUser.roleId === '3'? '#FDC229' : '#3F51B5' }}"> <view class="meeting-content-video-user-view" wx:if="{{currentUser.roleId === '1' || currentUser.roleId === '3'}}" style=" background:#FDC229">
<image src="/assets/icon9.png" class="meeting-content-video-user-view-image" /> <image src="/assets/icon9.png" class="meeting-content-video-user-view-image" />
</view> </view>
<image wx:if="{{!currentUser.enableMicr}}" src="/assets/{{currentUser.enableMicr ? 'icon2' : 'icon2-active'}}.png" class="meeting-content-video-user-image" /> <image wx:if="{{!currentUser.enableMicr}}" src="/assets/{{currentUser.enableMicr ? 'icon2' : 'icon2-active'}}.png" class="meeting-content-video-user-image" />
<text class="meeting-content-video-user-text">{{currentUser.userName}}</text> <text class="meeting-content-video-user-text">{{currentUser.userName}}</text>
</view> </view>
</view> </view>
<scroll-view scroll-y class="meeting-content-smallvideo" id="meeting-content-smallvideo" style="width: {{isFullscreen ? '0' :'20%'}}" bindscroll='scroll' scroll-top="{{scrollTop}}"> <scroll-view scroll-y class="meeting-content-smallvideo" id="meeting-content-smallvideo" style="width: {{isFullscreen ? '0' :'170px'}}" scroll-top="{{scrollTop}}">
<view class="meeting-content-smallvideo-box" id="video-{{item.uid}}" wx:for="{{roomUserList}}" data-item="{{item}}" wx:key="index" bind:tap="clickChangeVideo" wx:if="{{item.isRoom && item.isAdmin}}"> <view class="meeting-content-smallvideo-box" id="video-{{item.uid}}" wx:for="{{roomUserList}}" data-item="{{item}}" wx:key="index" bind:tap="clickChangeVideo" wx:if="{{item.isRoom && item.isAdmin}}">
<view class="meeting-content-smallvideo-box-view {{item.uid == currentUid ? 'active' : ''}}"> <view class="meeting-content-smallvideo-box-view {{item.uid == currentUid ? 'active' : ''}}">
<view class="meeting-content-smallvideo-box-view-avatar {{item.uid == currentUid ? 'active' : ''}}" wx:if="{{!item.enableCamera}}"> <view class="meeting-content-smallvideo-box-view-avatar {{item.uid == currentUid ? 'active' : ''}}" wx:if="{{!item.enableCamera}}">
@ -38,11 +42,11 @@
</view> </view>
</view> </view>
<view class="meeting-content-smallvideo-box-view-canvas" wx:if="{{item.src}}"> <view class="meeting-content-smallvideo-box-view-canvas" wx:if="{{item.src}}">
<live-pusher wx:if="{{user.uid === item.uid}}" url="{{item.src}}" mode="RTC" object-fit="contain" bindstatechange="recorderStateChange" background-mute enable-mic="{{footerList[1].active}}" enable-camera max-bitrate="500" min-bitrate="200" autopush enable-agc enable-ans device-position="front" class="meeting-content-smallvideo-box-view-canvas-play" data-uid="{{item.uid}}" bindaudiovolumenotify="playerAudioVolumenotify" beauty='{{9}}' whiteness='{{9}}' /> <live-pusher wx:if="{{user.uid === item.uid}}" url="{{item.src}}" mode="RTC" object-fit="contain" background-mute enable-mic="{{footerList[1].active}}" enable-camera max-bitrate="500" min-bitrate="200" autopush enable-agc enable-ans device-position="front" class="meeting-content-smallvideo-box-view-canvas-play" data-uid="{{item.uid}}" bindaudiovolumenotify="playerAudioVolumenotify" beauty='{{9}}' whiteness='{{9}}' />
<live-player src="{{item.src}}" class="meeting-content-smallvideo-box-view-canvas-play" mode="RTC" autoplay="true" bindstatechange="playerStateChange" object-fit="contain" data-uid="{{item.uid}}" bindaudiovolumenotify="playerAudioVolumenotify" wx:else /> <live-player src="{{item.src}}" class="meeting-content-smallvideo-box-view-canvas-play" mode="RTC" autoplay="true" muted="{{item.uid === user.uid ? true : !item.enableMicr}}" object-fit="contain" data-uid="{{item.uid}}" bindaudiovolumenotify="playerAudioVolumenotify" wx:else />
</view> </view>
<view class="meeting-content-smallvideo-box-view-user"> <view class="meeting-content-smallvideo-box-view-user">
<view class="meeting-content-smallvideo-box-view-user-view" style=" background:{{ item.roleId === '1' || item.roleId === '3' ? '#FDC229' : '#3F51B5' }}"> <view class="meeting-content-smallvideo-box-view-user-view" wx:if="{{item.roleId === '1' || item.roleId === '3'}}" style=" background:#FDC229">
<image src="/assets/icon9.png" class="meeting-content-smallvideo-box-view-user-view-image" /> <image src="/assets/icon9.png" class="meeting-content-smallvideo-box-view-user-view-image" />
</view> </view>
<image wx:if="{{!item.enableMicr}}" src="/assets/{{item.enableMicr ? 'icon2' : 'icon2-active'}}.png" class="meeting-content-smallvideo-box-view-user-image" /> <image wx:if="{{!item.enableMicr}}" src="/assets/{{item.enableMicr ? 'icon2' : 'icon2-active'}}.png" class="meeting-content-smallvideo-box-view-user-image" />
@ -59,10 +63,10 @@
</view> </view>
</view> </view>
</view> </view>
<view class="meeting-content-smallvideo-up" bind:tap="scrollUp" wx:if="{{!isFullscreen && isAdmin>3}}"> <view class="meeting-content-smallvideo-up" bind:touchstart="scrollUp" wx:if="{{!isFullscreen && showScroll && isAdmin >0}}">
<t-icon name="chevron-up" size="24rpx" data-name="chevron-up" /> <t-icon name="chevron-up" size="24rpx" data-name="chevron-up" />
</view> </view>
<view class="meeting-content-smallvideo-down" bind:tap="scrollDown" wx:if="{{!isFullscreen && isAdmin>3}}"> <view class="meeting-content-smallvideo-down" bind:touchstart="scrollDown" wx:if="{{!isFullscreen && showScroll && isAdmin >0}}">
<t-icon name="chevron-down" size="24rpx" data-name="chevron-down" /> <t-icon name="chevron-down" size="24rpx" data-name="chevron-down" />
</view> </view>
</scroll-view> </scroll-view>
@ -91,16 +95,18 @@
<t-message id="t-message" /> <t-message id="t-message" />
<t-dialog visible="{{applySpeakDialog}}" content="该操作需向管理员申请发言权限" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" cancel-btn="取消" data-type="applySpeakDialog" bind:confirm="closeDialog" bind:cancel="closeDialog" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" /> <t-dialog visible="{{applySpeakDialog}}" content="该操作需向管理员申请发言权限" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" cancel-btn="取消" data-type="applySpeakDialog" bind:confirm="closeDialog" bind:cancel="closeDialog" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" />
<t-dialog visible="{{leaveDialog}}" content="确定离开房间吗?" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" cancel-btn="取消" data-type="leaveDialog" bind:confirm="closeDialog" bind:cancel="closeDialog" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" /> <t-dialog visible="{{leaveDialog}}" content="确定离开房间吗?" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" cancel-btn="取消" data-type="leaveDialog" bind:confirm="closeDialog" bind:cancel="closeDialog" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" />
<t-popup visible="{{userPopupVisible}}" bind:visible-change="onVisibleChange" placement="right"> <t-popup visible="{{userPopupVisible}}" bind:visible-change="onVisibleChange" placement="right" style="bottom: 0;top:unset;height: 88vh;">
<view class="user-popup"> <view class="user-popup">
<view class="user-popup-title"> <view class="user-popup-title">
成员 <view class="{{ tabBarIndex === 1 ? ' user-popup-title-active' : '' }}" bind:tap="setTabBarIndex" data-tabBarIndex='1'>成员</view>
<view class="{{ tabBarIndex === 2 ? ' user-popup-title-active' : '' }}" bind:tap="setTabBarIndex" data-tabBarIndex='2'>设置</view>
</view> </view>
<scroll-view scroll-y class="user-popup-view" enhanced> <scroll-view scroll-y class="user-popup-view" enhanced wx:if="{{tabBarIndex === 1}}">
<view class="user-popup-view-view" wx:for="{{roomUserList}}" data-item="{{item}}" wx:key="index" wx:if="{{item.isRoom}}"> <view class="user-popup-view-view" wx:for="{{roomUserList}}" data-item="{{item}}" wx:key="index" wx:if="{{item.isRoom}}">
<view class="user-popup-view-view-avatar"> <view class="user-popup-view-view-avatar" bind:tap="showMultiText" data-item="{{item}}">
<t-avatar size="36rpx">{{item.avatarName}}</t-avatar> <t-avatar size="36rpx">{{item.avatarName}}</t-avatar>
<text class="user-popup-view-view-avatar-text">{{item.userName}}</text> <text class="user-popup-view-view-avatar-text">{{item.userName}}</text>
<text class="user-popup-view-view-avatar-me" wx:if="{{user.uid=== item.uid}}">(我)</text>
</view> </view>
<view class="user-popup-view-view-image"> <view class="user-popup-view-view-image">
<image src="/assets/{{item.enableMicr ? 'icon2' : 'icon2-active'}}.png" class="user-popup-view-view-image-icon" /> <image src="/assets/{{item.enableMicr ? 'icon2' : 'icon2-active'}}.png" class="user-popup-view-view-image-icon" />
@ -108,6 +114,12 @@
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
<scroll-view scroll-y class="user-popup-view" enhanced wx:else>
<view class="user-popup-view-view">
<text>语音激励</text>
<switch checked="{{setting.voiceStimulation}}" bindchange="changeSetting" data-str='voiceStimulation' />
</view>
</scroll-view>
</view> </view>
</t-popup> </t-popup>
<t-popup visible="{{chatPopupVisible}}" bind:visible-change="onVisibleChange" placement="right"> <t-popup visible="{{chatPopupVisible}}" bind:visible-change="onVisibleChange" placement="right">
@ -130,9 +142,19 @@
</view> </view>
</view> </view>
<view class="chat-popup-input"> <view class="chat-popup-input">
<input type="text" placeholder="请输入文字" class="chat-popup-input-text" value="{{messageStr}}" bind:input="changeMessageStr" /> <input type="text" placeholder="请输入文字" class="chat-popup-input-text" value="{{messageStr}}" bind:input="changeMessageStr" disabled bind:tap="showInputPopup" />
<view class="chat-popup-input-submit" bind:tap="sendMeg">发送</view> <view class="chat-popup-input-submit" bind:tap="sendMeg">发送</view>
</view> </view>
</view> </view>
</t-popup> </t-popup>
<t-popup visible="{{inputPopupVisible}}" bind:visible-change="hideInputPopup" placement="top" close-on-overlay-click='{{false}}'>
<view style="padding: 10rpx;display: flex;align-items: center;">
<view class="chat-popup-input-submit" bind:tap="hideInputPopup">确认</view>
<text style="color: gray;font-size: 16rpx;margin: 0 0 0 6rpx">{{inputStr.length}}/30</text>
<view style="height: 30rpx;width: 1px;background-color: gray;margin: 0 6rpx"></view>
<input type="text" placeholder="请输入文字" value="{{inputStr}}" maxlength='{{30}}' bind:input="changeInputStr" style="flex-grow: 1;" />
</view>
</t-popup>
<t-dialog visible="{{isReconnec}}" content="重连失败,请退出重试!" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" data-type="isReconnec" cancel-btn="{{null}}" bind:confirm="closeRoom" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" /> <t-dialog visible="{{isReconnec}}" content="重连失败,请退出重试!" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" data-type="isReconnec" cancel-btn="{{null}}" bind:confirm="closeRoom" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" />
<t-dialog visible="{{isAutoApplySpeakDialog}}" content="由于您长时间未发言,已自动取消发言权限,是否重新申请发言?" cancel-btn="取消" confirm-btn="{{ { content: '确定', variant: 'base', theme: 'primary' } }}" data-type="isAutoApplySpeakDialog" bind:cancel="cancelIsAutoApplySpeakDialog" bind:confirm="confirmIsAutoApplySpeakDialog" style="transform: scale(0.5) translate3d(-50%, -50%, 0);" close-btn="{{false}}" />
<t-toast id="t-toast" style="transform: scale(0.5) translate3d(-50%, -50%, 0);transform-origin: 0% 0%;" />

View File

@ -5,5 +5,5 @@
"compileHotReLoad": true, "compileHotReLoad": true,
"urlCheck": true "urlCheck": true
}, },
"libVersion": "3.6.5" "libVersion": "3.8.8"
} }

View File

@ -22,13 +22,10 @@ export const agora = {
destroy: async (callback?) => { destroy: async (callback?) => {
if (client) { if (client) {
await client.leave() await client.leave()
await client.destroy(() => { await client.destroy()
callback?.()
client = ''; client = '';
})
} else {
callback?.()
} }
callback?.()
}, },
// 设置角色 // 设置角色
setRole: async (isRoomManager: boolean, callBack?: Function) => { setRole: async (isRoomManager: boolean, callBack?: Function) => {
@ -54,9 +51,11 @@ export const agora = {
await agora.init(callback) await agora.init(callback)
}, },
// 加入频道 // 加入频道
joinChannel: () => { joinChannel: async (roleStatus: boolean, callBack: Function) => {
client.join(option.token, option.channelId, option.uid, () => { await client.join(option.token, option.channelId, option.uid, () => {
agora.setRole(false) agora.setRole(roleStatus, (url) => {
callBack(url)
})
}) })
}, },
// 刷新token // 刷新token
@ -64,7 +63,7 @@ export const agora = {
client.renewToken(token) client.renewToken(token)
}, },
// 监听 // 监听
clientEvent: ({ streamAdded, streamRemoved, tokenRef }) => { clientEvent: ({ streamAdded, streamRemoved, tokenRef, updateUrl, error }: any) => {
client.on("stream-added", async e => { client.on("stream-added", async e => {
await agora.subscribe(e.uid, (url: string, uid: number | string) => { await agora.subscribe(e.uid, (url: string, uid: number | string) => {
streamAdded(url, uid) streamAdded(url, uid)
@ -76,6 +75,12 @@ export const agora = {
client.on("token-privilege-will-expire", async e => { client.on("token-privilege-will-expire", async e => {
tokenRef() tokenRef()
}); });
client.on("error", async e => {
error()
});
client.on("update-url", async e => {
updateUrl(e)
});
}, },
// 订阅远端音视频流 // 订阅远端音视频流
subscribe: async (uid: number | string, callBack: Function) => { subscribe: async (uid: number | string, callBack: Function) => {

View File

@ -1,7 +1,6 @@
// const apiBase = "http://192.168.2.9:5192" // const apiBase = "http://192.168.2.9:5192"
const apiBase = "https://meeting-api.23544.com/pc" const apiBase = "https://meeting-api.23544.com/pc"
// const apiBase = "https://meeting-api.23544.com/test29" // const apiBase = "https://meeting-api.23544.com/test29"
import { Message } from 'tdesign-miniprogram';
export const Request = (params) => { export const Request = (params) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
wx.getStorage({ wx.getStorage({
@ -47,21 +46,12 @@ function requestMethods(obj, callback) {
callback('success', res) callback('success', res)
}, },
fail: res => { fail: res => {
if (res.errMsg === 'request:fail timeout') { if (res.errno === 5) {
Message.error({ wx.showToast({
context: this, icon: 'error',
offset: [20, 32], title: '网络连接超时,请检查网络状态',
duration: 2000, mask: true
content: '网络连接超时,请检查网络状态', })
});
}
if (res.errMsg === 'request:fail ') {
Message.error({
context: this,
offset: [20, 32],
duration: 2000,
content: '网络已断开,请检查网络状态',
});
} }
callback('fail', res) callback('fail', res)
}, },

View File

@ -68,6 +68,10 @@ export const onInvoke = async (str: string, data: any) => {
// 发言人设置成功 // 发言人设置成功
await connection.invoke(str, data) await connection.invoke(str, data)
break; break;
case 'sendOper2User':
// 扩展参数
await connection.invoke(str, data.uid, data.contentString)
break;
} }
} }
export const onSignalr = (callBack: Function) => { export const onSignalr = (callBack: Function) => {
@ -197,6 +201,14 @@ export const onSignalr = (callBack: Function) => {
driversJsonString driversJsonString
}) })
}); });
// 修改用户名称
connection.on("ModifyNickName", (uid, nickName) => {
callBack({
key: 'ModifyNickName',
uid,
nickName
})
});
// 设置发言人 // 设置发言人
connection.on("SetSpeaker", (RoomManagerInputDTO) => { connection.on("SetSpeaker", (RoomManagerInputDTO) => {
callBack({ callBack({
@ -204,10 +216,24 @@ export const onSignalr = (callBack: Function) => {
RoomManagerInputDTO RoomManagerInputDTO
}) })
}); });
// 扩展参数
connection.on("ReceivedOperation", (contentString) => {
callBack({
key: 'ReceivedOperation',
contentString
})
});
// 共享人取消共享屏幕
connection.on("StopedSharedScreen", (ScreenShareId) => {
callBack({
key: 'StopedSharedScreen',
ScreenShareId
})
});
} }
} }
export const onStop = async () => { export const onStop = async () => {
agora.destroy(); await agora.destroy();
if (connection) { if (connection) {
connection.stop() connection.stop()
connection = ''; connection = '';
@ -260,7 +286,10 @@ export const offSignalr = () => {
connection.off('DriverList'); connection.off('DriverList');
connection.off('SetDriver'); connection.off('SetDriver');
connection.off('ShowDriverList'); connection.off('ShowDriverList');
connection.off('ModifyNickName');
connection.off('SetSpeaker'); connection.off('SetSpeaker');
connection.off('ReceivedOperation');
connection.off('StopedSharedScreen');
} }
} }