mdm-client 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/App.vue +1 -1
- package/src/components/LiveMultipleMeeting/LiveMultipleMeeting.vue +104 -5
- package/src/components/LivePoint/LivePoint.vue +25 -0
- package/src/components/LivePointMeeting/LivePointMeeting.vue +63 -2
- package/src/components/MiniumVideoDialog/MiniumVideoDialog.vue +185 -50
- package/src/components/other/appointDialog.vue +1 -1
- package/src/components/other/layoutSwitch.vue +1 -1
- package/src/components/other/leaveOptionDialog.vue +1 -1
- package/src/components/other/moreOptionDialog.vue +1 -1
- package/src/components/other/screenShareBoard.vue +2 -2
- package/src/utils/livekit/live-client-esm.js +1 -1
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -66,7 +66,7 @@ export default {
|
|
|
66
66
|
baseUrl: "https://10.2.12.103:8443",
|
|
67
67
|
roomServerUrl: "wss://10.2.12.103:8443",
|
|
68
68
|
token:
|
|
69
|
-
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
|
|
69
|
+
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJMb2dpbkluZm8iOnsibG9naW5Db2RlIjoibGl1amluYm8iLCJ1c2VyTmFtZSI6IuWImOmUpuazoiIsInRlbmFudElEIjo3OTA2MDE5OTgyNTAxMDAwLCJkZXB0VHJlZSI6Ijc5MDYwNzA4NTA5MDEwMDAvNzkwNzk1MzkyNjcwMTAwMCIsInVzZXJJRCI6NzkwNjI1NzUyOTgwMTAwMCwicm9sZUlEIjo3OTA2MDc0MzkyMDAxMDAwLCJ2ZXJzaW9uSUQiOjc5MDc5NDk3NjQyMDEwMDB9LCJwbGF0Zm9ybUlEIjowLCJwaG9uZSI6IiIsImV4cCI6MTc2NDA5MzM3MCwiaWF0IjoxNzYzMzczMzcwfQ.sWfU8eZPDc05YIgstuI40C-lDvXZq3G30b-j9qAxWGg",
|
|
70
70
|
liveClient: null,
|
|
71
71
|
showMessage: null,
|
|
72
72
|
};
|
|
@@ -792,6 +792,33 @@ export default {
|
|
|
792
792
|
});
|
|
793
793
|
},
|
|
794
794
|
},
|
|
795
|
+
meetingNum: {
|
|
796
|
+
handler(newVal) {
|
|
797
|
+
if (!newVal) return
|
|
798
|
+
try {
|
|
799
|
+
const key = `lk:ss_prefs:${newVal}`
|
|
800
|
+
const raw = sessionStorage.getItem(key)
|
|
801
|
+
if (!raw) return
|
|
802
|
+
const saved = JSON.parse(raw)
|
|
803
|
+
if (saved && typeof saved === 'object') {
|
|
804
|
+
if (saved.systemAudio === 'include' || saved.systemAudio === 'exclude') {
|
|
805
|
+
this.screenShareCaptureOption.systemAudio = saved.systemAudio
|
|
806
|
+
}
|
|
807
|
+
if (saved.resolution && typeof saved.resolution === 'object') {
|
|
808
|
+
const { width, height, frameRate } = saved.resolution
|
|
809
|
+
this.screenShareCaptureOption.resolution = {
|
|
810
|
+
width: width ?? 1920,
|
|
811
|
+
height: height ?? 1080,
|
|
812
|
+
frameRate: typeof frameRate === 'number' ? frameRate : 60,
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
} catch (err) {
|
|
817
|
+
// 忽略解析异常
|
|
818
|
+
}
|
|
819
|
+
},
|
|
820
|
+
immediate: true,
|
|
821
|
+
}
|
|
795
822
|
},
|
|
796
823
|
created() {
|
|
797
824
|
this.showMessage = new ShowMessage();
|
|
@@ -2921,7 +2948,7 @@ export default {
|
|
|
2921
2948
|
videoDiv.appendChild(signalElm);
|
|
2922
2949
|
|
|
2923
2950
|
// 构建码率显示元素
|
|
2924
|
-
let bitrateElm = document.getElementById(`bitrate-${identity}`)
|
|
2951
|
+
let bitrateElm = document.getElementById(`bitrate-${videoItem.identity}`)
|
|
2925
2952
|
if (!bitrateElm) {
|
|
2926
2953
|
bitrateElm = document.createElement('div')
|
|
2927
2954
|
bitrateElm.id = `bitrate-${videoItem.identity}`
|
|
@@ -3074,6 +3101,11 @@ export default {
|
|
|
3074
3101
|
if (videoItem?.audioTrack) {
|
|
3075
3102
|
videoItem.audioTrack.detach();
|
|
3076
3103
|
}
|
|
3104
|
+
if (videoItem?.screenShareAudioTrack) {
|
|
3105
|
+
try {
|
|
3106
|
+
videoItem.screenShareAudioTrack.detach()
|
|
3107
|
+
} catch (e) {}
|
|
3108
|
+
}
|
|
3077
3109
|
return;
|
|
3078
3110
|
}
|
|
3079
3111
|
// 与会者屏幕共享布局切换
|
|
@@ -3136,6 +3168,32 @@ export default {
|
|
|
3136
3168
|
if (videoItem?.audioTrack) {
|
|
3137
3169
|
videoItem.audioTrack.attach(videoElm);
|
|
3138
3170
|
}
|
|
3171
|
+
// 屏幕共享系统音频:使用独立的隐藏 audio 元素,避免某些浏览器在多音轨时替换 video 的音频源
|
|
3172
|
+
if (videoItem?.isScreenShareEnabled && videoItem?.screenShareAudioTrack) {
|
|
3173
|
+
const audioHolderId = `screenshare-audio-${videoItem.identity}`
|
|
3174
|
+
let audioHolder = document.getElementById(audioHolderId)
|
|
3175
|
+
if (!audioHolder) {
|
|
3176
|
+
audioHolder = document.createElement('audio')
|
|
3177
|
+
audioHolder.id = audioHolderId
|
|
3178
|
+
audioHolder.style.display = 'none'
|
|
3179
|
+
audioHolder.setAttribute('playsinline', '')
|
|
3180
|
+
audioHolder.autoplay = true
|
|
3181
|
+
// 将隐藏audio元素插入到与会者容器,便于随与会者一起清理
|
|
3182
|
+
videoDiv && videoDiv.appendChild(audioHolder)
|
|
3183
|
+
}
|
|
3184
|
+
try {
|
|
3185
|
+
videoItem.screenShareAudioTrack.attach(audioHolder)
|
|
3186
|
+
} catch (e) {
|
|
3187
|
+
console.warn('屏幕共享系统音频附加失败', videoItem.identity, e)
|
|
3188
|
+
}
|
|
3189
|
+
} else {
|
|
3190
|
+
// 如果当前不再共享屏幕,清理残留的隐藏 audio 元素
|
|
3191
|
+
const orphanAudio = document.getElementById(`screenshare-audio-${videoItem.identity}`)
|
|
3192
|
+
if (orphanAudio) {
|
|
3193
|
+
try { videoItem.screenShareAudioTrack?.detach(orphanAudio) } catch (_) {}
|
|
3194
|
+
orphanAudio.remove()
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3139
3197
|
}
|
|
3140
3198
|
// 更新与会者名称
|
|
3141
3199
|
let nameDom = document.getElementById(videoItem.identity);
|
|
@@ -4132,8 +4190,6 @@ export default {
|
|
|
4132
4190
|
}
|
|
4133
4191
|
},
|
|
4134
4192
|
async chooseVideoDevice(e) {
|
|
4135
|
-
this.dispatchLocalTrack('video')
|
|
4136
|
-
await this.sleep(100)
|
|
4137
4193
|
await this.changeActiveDevice("videoinput", e);
|
|
4138
4194
|
this.videoSelectShow = false;
|
|
4139
4195
|
},
|
|
@@ -4157,7 +4213,50 @@ export default {
|
|
|
4157
4213
|
await this.liveClient.changeScreenShareStatus(this.screenShareCaptureOption);
|
|
4158
4214
|
},
|
|
4159
4215
|
screenShareOptionChange(e) {
|
|
4160
|
-
|
|
4216
|
+
if (!e) return
|
|
4217
|
+
const { isFluencyPriority, systemAudioInclude } = e
|
|
4218
|
+
|
|
4219
|
+
// 1) 生效到当前响应式配置(将于下一次开始共享时使用;不对正在共享做自动重启)
|
|
4220
|
+
this.screenShareCaptureOption.systemAudio = systemAudioInclude ? 'include' : 'exclude'
|
|
4221
|
+
const targetFrameRate = isFluencyPriority ? 60 : 30
|
|
4222
|
+
if (
|
|
4223
|
+
!this.screenShareCaptureOption.resolution ||
|
|
4224
|
+
typeof this.screenShareCaptureOption.resolution !== 'object'
|
|
4225
|
+
) {
|
|
4226
|
+
this.screenShareCaptureOption.resolution = { width: 1920, height: 1080, frameRate: targetFrameRate }
|
|
4227
|
+
} else {
|
|
4228
|
+
this.screenShareCaptureOption.resolution.frameRate = targetFrameRate
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4231
|
+
// 2) 正在共享时尽量实时生效:
|
|
4232
|
+
// - 帧率:对现有轨道调用 applyConstraints(frameRate)
|
|
4233
|
+
// - 系统音频:单独发布/取消发布 ScreenShareAudio 轨道,避免影响视频轨道
|
|
4234
|
+
// if (isScreenShareEnabled?.value) {
|
|
4235
|
+
// try {
|
|
4236
|
+
// const fr = screenShareCaptureOption?.resolution?.frameRate
|
|
4237
|
+
// if (typeof fr === 'number') {
|
|
4238
|
+
// await liveClient.updateScreenShareFrameRate(fr)
|
|
4239
|
+
// }
|
|
4240
|
+
// } catch (_) {}
|
|
4241
|
+
// try {
|
|
4242
|
+
// await liveClient.setScreenShareSystemAudio(systemAudioInclude)
|
|
4243
|
+
// } catch (_) {}
|
|
4244
|
+
// }
|
|
4245
|
+
|
|
4246
|
+
// 3) 按会议号持久化(当前会话内保留,退出会议后不跨会保留)
|
|
4247
|
+
const roomId = this.meetingNum
|
|
4248
|
+
if (roomId) {
|
|
4249
|
+
try {
|
|
4250
|
+
const key = `lk:ss_prefs:${roomId}`
|
|
4251
|
+
const toSave = {
|
|
4252
|
+
systemAudio: this.screenShareCaptureOption.systemAudio,
|
|
4253
|
+
resolution: { ...this.screenShareCaptureOption.resolution },
|
|
4254
|
+
}
|
|
4255
|
+
sessionStorage.setItem(key, JSON.stringify(toSave))
|
|
4256
|
+
} catch (err) {
|
|
4257
|
+
// 忽略持久化异常
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4161
4260
|
},
|
|
4162
4261
|
stopScreenShare() {
|
|
4163
4262
|
this.changeScreenShareStatus(this.screenShareCaptureOption);
|
|
@@ -5515,7 +5614,7 @@ export default {
|
|
|
5515
5614
|
align-items: center;
|
|
5516
5615
|
justify-content: space-between;
|
|
5517
5616
|
position: absolute;
|
|
5518
|
-
z-index:
|
|
5617
|
+
z-index: 4100;
|
|
5519
5618
|
bottom: -66px;
|
|
5520
5619
|
left: 0;
|
|
5521
5620
|
transition: all 0.2s ease;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
<teleport to="body">
|
|
24
24
|
<LivePointMeeting
|
|
25
25
|
v-if="isMeetingDialogShow"
|
|
26
|
+
ref="livePointMeetingRef"
|
|
26
27
|
:joinType="pointMeetingData.joinType"
|
|
27
28
|
:meetingNum="pointMeetingData.meetingNum"
|
|
28
29
|
:meetingType="pointMeetingData.meetingType"
|
|
@@ -36,9 +37,18 @@
|
|
|
36
37
|
@miniLinkSend="miniLinkSend"
|
|
37
38
|
@meetingStarted="isInMeeting = true"
|
|
38
39
|
@meetingEnded="isInMeeting = false"
|
|
40
|
+
@pointMeetingMinum="openMiniVideoDialog"
|
|
39
41
|
>
|
|
40
42
|
</LivePointMeeting>
|
|
41
43
|
</teleport>
|
|
44
|
+
<teleport to="body">
|
|
45
|
+
<minium-video-dialog
|
|
46
|
+
v-if="isMiniVideoDialogShow"
|
|
47
|
+
:trackData="trackData"
|
|
48
|
+
@resetMultiDialog="resetPointDialog"
|
|
49
|
+
@miniVideoDialogClose="closeMiniVideoDialog"
|
|
50
|
+
></minium-video-dialog>
|
|
51
|
+
</teleport>
|
|
42
52
|
</div>
|
|
43
53
|
</template>
|
|
44
54
|
|
|
@@ -48,6 +58,7 @@ import { mittBus, ShowMessage } from "../../utils/index.js";
|
|
|
48
58
|
import LiveCallBoard from "../LiveCallBoard/LiveCallBoard.vue";
|
|
49
59
|
import LivePointMeeting from "../LivePointMeeting/LivePointMeeting.vue";
|
|
50
60
|
import LiveInviteReceive from "../LiveInviteReceive/LiveInviteReceive.vue";
|
|
61
|
+
import MiniumVideoDialog from "../MiniumVideoDialog/MiniumVideoDialog.vue";
|
|
51
62
|
import Teleport from 'vue2-teleport'
|
|
52
63
|
|
|
53
64
|
export default {
|
|
@@ -56,6 +67,7 @@ export default {
|
|
|
56
67
|
LiveCallBoard,
|
|
57
68
|
LivePointMeeting,
|
|
58
69
|
LiveInviteReceive,
|
|
70
|
+
MiniumVideoDialog,
|
|
59
71
|
Teleport
|
|
60
72
|
},
|
|
61
73
|
props: {
|
|
@@ -92,6 +104,8 @@ export default {
|
|
|
92
104
|
isInMeeting: false,
|
|
93
105
|
liveClient: null,
|
|
94
106
|
showMessage: null,
|
|
107
|
+
isMiniVideoDialogShow: false,
|
|
108
|
+
trackData: {}
|
|
95
109
|
};
|
|
96
110
|
},
|
|
97
111
|
computed: {
|
|
@@ -198,6 +212,17 @@ export default {
|
|
|
198
212
|
meetingDialogClose() {
|
|
199
213
|
this.isMeetingDialogShow = false;
|
|
200
214
|
},
|
|
215
|
+
openMiniVideoDialog(e) {
|
|
216
|
+
this.trackData = e ?? {}
|
|
217
|
+
this.isMiniVideoDialogShow = true
|
|
218
|
+
},
|
|
219
|
+
resetPointDialog() {
|
|
220
|
+
this.isMiniVideoDialogShow = false
|
|
221
|
+
this.$refs.livePointMeetingRef && this.$refs.livePointMeetingRef.resetDialog()
|
|
222
|
+
},
|
|
223
|
+
closeMiniVideoDialog() {
|
|
224
|
+
this.isMiniVideoDialogShow = false
|
|
225
|
+
},
|
|
201
226
|
handleLiveClientInitSuccess() {
|
|
202
227
|
this.liveClient = window["liveClient"];
|
|
203
228
|
}
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
<span>{{ meetingDuration }}</span>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="top-group">
|
|
9
|
+
<div class="minimize-btn" @click="minumDialog"></div>
|
|
9
10
|
<div class="full-screen-btn" @click="switchComponentFullScreen"></div>
|
|
11
|
+
<div class="close-btn" @click="confirmClose"></div>
|
|
10
12
|
</div>
|
|
11
13
|
</div>
|
|
12
14
|
<div class="point-meeting-wrapper">
|
|
@@ -78,6 +80,7 @@
|
|
|
78
80
|
|
|
79
81
|
<script>
|
|
80
82
|
import { calculateTime, ShowMessage } from "../../utils/index.js";
|
|
83
|
+
import { MessageBox } from "element-ui";
|
|
81
84
|
|
|
82
85
|
export default {
|
|
83
86
|
name: "LivePointMeeting",
|
|
@@ -591,13 +594,63 @@ export default {
|
|
|
591
594
|
closeMeetingDialog() {
|
|
592
595
|
this.$emit("meetingDialogClose");
|
|
593
596
|
},
|
|
597
|
+
// 最小化窗口: 复用 multi 会议的最小化逻辑,向父组件抛出 pointMeetingMinum 事件
|
|
598
|
+
minumDialog() {
|
|
599
|
+
if (!this.isInMeeting) {
|
|
600
|
+
this.showMessage.message('error', '请先进入会议')
|
|
601
|
+
return
|
|
602
|
+
}
|
|
603
|
+
if (!this.localIdentity) {
|
|
604
|
+
this.showMessage.message('error', '获取本地与会者信息失败')
|
|
605
|
+
return
|
|
606
|
+
}
|
|
607
|
+
// 查找本地与会者渲染数据(视频或音频)
|
|
608
|
+
let localVideoTrack = null
|
|
609
|
+
if (this.liveClient?.roomMode === 'auto') {
|
|
610
|
+
const idx = this.participants.findIndex(item => item.identity === this.localIdentity)
|
|
611
|
+
if (idx > -1) {
|
|
612
|
+
localVideoTrack = this.participants[idx]?.videoTrack || null
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// 通知父组件打开最小化窗口
|
|
616
|
+
this.$emit('pointMeetingMinum', {
|
|
617
|
+
identity: this.localIdentity,
|
|
618
|
+
name: this.localName,
|
|
619
|
+
videoTrack: this.liveClient?.roomMode === 'auto' ? localVideoTrack : null,
|
|
620
|
+
})
|
|
621
|
+
// 隐藏当前窗口(保持状态以便恢复)
|
|
622
|
+
this.$refs.rootElm && (this.$refs.rootElm.style.visibility = 'hidden')
|
|
623
|
+
},
|
|
624
|
+
// 还原窗口(供父组件调用)
|
|
625
|
+
resetDialog() {
|
|
626
|
+
this.$refs.rootElm && (this.$refs.rootElm.style.visibility = 'visible')
|
|
627
|
+
},
|
|
594
628
|
async leaveRoom() {
|
|
629
|
+
if (!this.isInMeeting) {
|
|
630
|
+
this.closeMeetingDialog();
|
|
631
|
+
return
|
|
632
|
+
}
|
|
595
633
|
if (this.liveClient) {
|
|
596
634
|
await this.liveClient.leaveRoom();
|
|
597
635
|
}
|
|
598
636
|
// 重置房间连接处理标志
|
|
599
637
|
this.isRoomConnectedHandled = false;
|
|
600
638
|
},
|
|
639
|
+
confirmClose() {
|
|
640
|
+
if(!this.isInMeeting) {
|
|
641
|
+
this.closeMeetingDialog();
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
MessageBox.confirm('点击确定后会议将被解散,您确定要这么做么?', '警告', {
|
|
645
|
+
confirmButtonText: '确定',
|
|
646
|
+
cancelButtonText: '取消',
|
|
647
|
+
type: 'warning',
|
|
648
|
+
}).then(() => {
|
|
649
|
+
this.leaveRoom();
|
|
650
|
+
}).catch(() => {
|
|
651
|
+
// 取消操作
|
|
652
|
+
});
|
|
653
|
+
},
|
|
601
654
|
// 切换组件全屏状态
|
|
602
655
|
async switchComponentFullScreen(e) {
|
|
603
656
|
if (
|
|
@@ -1151,6 +1204,13 @@ export default {
|
|
|
1151
1204
|
display: flex;
|
|
1152
1205
|
align-items: center;
|
|
1153
1206
|
|
|
1207
|
+
.minimize-btn {
|
|
1208
|
+
cursor: pointer;
|
|
1209
|
+
width: 16px;
|
|
1210
|
+
height: 16px;
|
|
1211
|
+
margin-right: 12px;
|
|
1212
|
+
background: url('../../assets/image/screenBlue/meeting_slide_small_icon.png') no-repeat center / 100% 100%;
|
|
1213
|
+
}
|
|
1154
1214
|
.duration-icon {
|
|
1155
1215
|
width: 15px;
|
|
1156
1216
|
height: 15px;
|
|
@@ -1171,8 +1231,9 @@ export default {
|
|
|
1171
1231
|
|
|
1172
1232
|
.close-btn {
|
|
1173
1233
|
cursor: pointer;
|
|
1174
|
-
width:
|
|
1175
|
-
height:
|
|
1234
|
+
width: 16px;
|
|
1235
|
+
height: 16px;
|
|
1236
|
+
margin-left: 12px;
|
|
1176
1237
|
background: var(--close-icon) no-repeat center / 100% 100%;
|
|
1177
1238
|
}
|
|
1178
1239
|
}
|