mdm-client 1.0.0

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.
Files changed (262) hide show
  1. package/README.md +92 -0
  2. package/index.js +35 -0
  3. package/package.json +41 -0
  4. package/src/App.vue +246 -0
  5. package/src/assets/audio/moon_light.ogg +0 -0
  6. package/src/assets/font/DINPro-Medium.otf +0 -0
  7. package/src/assets/font/FZZhengHeiS-B-GB.ttf +0 -0
  8. package/src/assets/font/PingFang Regular.otf +0 -0
  9. package/src/assets/font/SourceHanSansCN-Regular.otf +0 -0
  10. package/src/assets/image/common/add_other_icon.png +0 -0
  11. package/src/assets/image/common/bottomFrame.png +0 -0
  12. package/src/assets/image/common/broadcastOn.png +0 -0
  13. package/src/assets/image/common/broadcastTask.png +0 -0
  14. package/src/assets/image/common/call.png +0 -0
  15. package/src/assets/image/common/call_user_mic_off_icon.png +0 -0
  16. package/src/assets/image/common/call_user_mic_on_icon.png +0 -0
  17. package/src/assets/image/common/cam-off.png +0 -0
  18. package/src/assets/image/common/cam-on.png +0 -0
  19. package/src/assets/image/common/cam_off_small.png +0 -0
  20. package/src/assets/image/common/camera.png +0 -0
  21. package/src/assets/image/common/cameraBtn1.png +0 -0
  22. package/src/assets/image/common/cameraBtn2.png +0 -0
  23. package/src/assets/image/common/cameraBtn3.png +0 -0
  24. package/src/assets/image/common/cameraBtn4.png +0 -0
  25. package/src/assets/image/common/cameraBtn5.png +0 -0
  26. package/src/assets/image/common/cameraBtn6.png +0 -0
  27. package/src/assets/image/common/cameraBtn7.png +0 -0
  28. package/src/assets/image/common/cameraClose.png +0 -0
  29. package/src/assets/image/common/cameraFull.png +0 -0
  30. package/src/assets/image/common/cameraOff.png +0 -0
  31. package/src/assets/image/common/cancel_icon.png +0 -0
  32. package/src/assets/image/common/card_blue.png +0 -0
  33. package/src/assets/image/common/card_grey.png +0 -0
  34. package/src/assets/image/common/chosen_icon.png +0 -0
  35. package/src/assets/image/common/chosen_icon_slided.png +0 -0
  36. package/src/assets/image/common/custom_layout_equipment_avatar.png +0 -0
  37. package/src/assets/image/common/custom_layout_user_avatar.png +0 -0
  38. package/src/assets/image/common/default_avatar.png +0 -0
  39. package/src/assets/image/common/default_avatar_mini.png +0 -0
  40. package/src/assets/image/common/delete-number.svg +3 -0
  41. package/src/assets/image/common/deviceIcon.png +0 -0
  42. package/src/assets/image/common/fourOff.png +0 -0
  43. package/src/assets/image/common/fourOn.png +0 -0
  44. package/src/assets/image/common/group.png +0 -0
  45. package/src/assets/image/common/groupManage.png +0 -0
  46. package/src/assets/image/common/histroy_meeting_icon.png +0 -0
  47. package/src/assets/image/common/icon-device.svg +12 -0
  48. package/src/assets/image/common/icon-monitor.svg +12 -0
  49. package/src/assets/image/common/icon-/345/260/217/347/250/213/345/272/217.svg +5 -0
  50. package/src/assets/image/common/icon-/345/272/224/347/255/224.svg +5 -0
  51. package/src/assets/image/common/icon-/350/247/206/351/242/221.svg +7 -0
  52. package/src/assets/image/common/input_search_icon.png +0 -0
  53. package/src/assets/image/common/launch_icon.png +0 -0
  54. package/src/assets/image/common/layout-active1.png +0 -0
  55. package/src/assets/image/common/layout-active2.png +0 -0
  56. package/src/assets/image/common/layout1.png +0 -0
  57. package/src/assets/image/common/layout2.png +0 -0
  58. package/src/assets/image/common/loading.png +0 -0
  59. package/src/assets/image/common/login/checked_icon.png +0 -0
  60. package/src/assets/image/common/login/login_bg.png +0 -0
  61. package/src/assets/image/common/login/login_form_left_icon.png +0 -0
  62. package/src/assets/image/common/login/pwd_icon.png +0 -0
  63. package/src/assets/image/common/login/user_icon.png +0 -0
  64. package/src/assets/image/common/login/verify_icon.png +0 -0
  65. package/src/assets/image/common/logo.png +0 -0
  66. package/src/assets/image/common/ltypeOff.png +0 -0
  67. package/src/assets/image/common/ltypeOn.png +0 -0
  68. package/src/assets/image/common/manager_cam_off_icon.png +0 -0
  69. package/src/assets/image/common/manager_mic_off_icon.png +0 -0
  70. package/src/assets/image/common/map-cicle-icon.svg +6 -0
  71. package/src/assets/image/common/map-icon-search-info.svg +11 -0
  72. package/src/assets/image/common/map-location.svg +37 -0
  73. package/src/assets/image/common/map.png +0 -0
  74. package/src/assets/image/common/mic-off.png +0 -0
  75. package/src/assets/image/common/mic-on.png +0 -0
  76. package/src/assets/image/common/mic_off_small.png +0 -0
  77. package/src/assets/image/common/minum_cam_off_icon.png +0 -0
  78. package/src/assets/image/common/minum_cam_on_icon.png +0 -0
  79. package/src/assets/image/common/minum_expand_icon.png +0 -0
  80. package/src/assets/image/common/minum_mic_off_icon.png +0 -0
  81. package/src/assets/image/common/minum_mic_on_icon.png +0 -0
  82. package/src/assets/image/common/minum_reset_icon.png +0 -0
  83. package/src/assets/image/common/minum_slide_icon.png +0 -0
  84. package/src/assets/image/common/more_icon.png +0 -0
  85. package/src/assets/image/common/mute.png +0 -0
  86. package/src/assets/image/common/newFolder.png +0 -0
  87. package/src/assets/image/common/newTask.png +0 -0
  88. package/src/assets/image/common/nineOff.png +0 -0
  89. package/src/assets/image/common/nineOn.png +0 -0
  90. package/src/assets/image/common/none.png +0 -0
  91. package/src/assets/image/common/offline.png +0 -0
  92. package/src/assets/image/common/oneOff.png +0 -0
  93. package/src/assets/image/common/oneOn.png +0 -0
  94. package/src/assets/image/common/online.png +0 -0
  95. package/src/assets/image/common/output_off_small.png +0 -0
  96. package/src/assets/image/common/playOff.png +0 -0
  97. package/src/assets/image/common/playOn.png +0 -0
  98. package/src/assets/image/common/playStop.png +0 -0
  99. package/src/assets/image/common/preview_icon.png +0 -0
  100. package/src/assets/image/common/preview_meet_icon.png +0 -0
  101. package/src/assets/image/common/scan-map.png +0 -0
  102. package/src/assets/image/common/screen_blue.png +0 -0
  103. package/src/assets/image/common/screen_gray.png +0 -0
  104. package/src/assets/image/common/screen_white.png +0 -0
  105. package/src/assets/image/common/select_item_check.png +0 -0
  106. package/src/assets/image/common/select_item_checked.png +0 -0
  107. package/src/assets/image/common/selector.png +0 -0
  108. package/src/assets/image/common/selectorOn.png +0 -0
  109. package/src/assets/image/common/share_icon.png +0 -0
  110. package/src/assets/image/common/signal_good.png +0 -0
  111. package/src/assets/image/common/signal_poor.png +0 -0
  112. package/src/assets/image/common/sixteenOff.png +0 -0
  113. package/src/assets/image/common/sixteenOn.png +0 -0
  114. package/src/assets/image/common/slide-bth-expand.png +0 -0
  115. package/src/assets/image/common/slide_btn.png +0 -0
  116. package/src/assets/image/common/speak.png +0 -0
  117. package/src/assets/image/common/speakOn.png +0 -0
  118. package/src/assets/image/common/speaker-off.png +0 -0
  119. package/src/assets/image/common/speaker-on.png +0 -0
  120. package/src/assets/image/common/speaking.png +0 -0
  121. package/src/assets/image/common/speed-left.svg +5 -0
  122. package/src/assets/image/common/speed-right.svg +5 -0
  123. package/src/assets/image/common/tree_checked_icon.png +0 -0
  124. package/src/assets/image/common/tree_expand_icon.png +0 -0
  125. package/src/assets/image/common/tree_slide_icon.png +0 -0
  126. package/src/assets/image/common/tree_uncheck_icon.png +0 -0
  127. package/src/assets/image/common/unchosen_icon.png +0 -0
  128. package/src/assets/image/common/up.png +0 -0
  129. package/src/assets/image/common/volume.png +0 -0
  130. package/src/assets/image/common/warning.png +0 -0
  131. package/src/assets/image/screenBlue/a1.png +0 -0
  132. package/src/assets/image/screenBlue/a2.png +0 -0
  133. package/src/assets/image/screenBlue/a3.png +0 -0
  134. package/src/assets/image/screenBlue/a4.png +0 -0
  135. package/src/assets/image/screenBlue/a5.png +0 -0
  136. package/src/assets/image/screenBlue/a6.png +0 -0
  137. package/src/assets/image/screenBlue/add.png +0 -0
  138. package/src/assets/image/screenBlue/add_group_icon.png +0 -0
  139. package/src/assets/image/screenBlue/add_to_group_icon.png +0 -0
  140. package/src/assets/image/screenBlue/arrow_icon.png +0 -0
  141. package/src/assets/image/screenBlue/audio_level_icon.png +0 -0
  142. package/src/assets/image/screenBlue/b1.png +0 -0
  143. package/src/assets/image/screenBlue/b2.png +0 -0
  144. package/src/assets/image/screenBlue/b3.png +0 -0
  145. package/src/assets/image/screenBlue/b4.png +0 -0
  146. package/src/assets/image/screenBlue/b5.png +0 -0
  147. package/src/assets/image/screenBlue/b6.png +0 -0
  148. package/src/assets/image/screenBlue/bottom_footer_bg.png +0 -0
  149. package/src/assets/image/screenBlue/call_clear_icon.png +0 -0
  150. package/src/assets/image/screenBlue/call_duration_icon.png +0 -0
  151. package/src/assets/image/screenBlue/call_fullscreen_icon.png +0 -0
  152. package/src/assets/image/screenBlue/call_mini_icon.png +0 -0
  153. package/src/assets/image/screenBlue/call_video_icon.png +0 -0
  154. package/src/assets/image/screenBlue/call_voice_icon.png +0 -0
  155. package/src/assets/image/screenBlue/cam_on_small.png +0 -0
  156. package/src/assets/image/screenBlue/close_icon.png +0 -0
  157. package/src/assets/image/screenBlue/copy-icon.png +0 -0
  158. package/src/assets/image/screenBlue/custom_layout_drag_icon.png +0 -0
  159. package/src/assets/image/screenBlue/custom_layout_grid16_active_icon.png +0 -0
  160. package/src/assets/image/screenBlue/custom_layout_grid16_icon.png +0 -0
  161. package/src/assets/image/screenBlue/custom_layout_grid4_active_icon.png +0 -0
  162. package/src/assets/image/screenBlue/custom_layout_grid4_icon.png +0 -0
  163. package/src/assets/image/screenBlue/custom_layout_grid9_active_icon.png +0 -0
  164. package/src/assets/image/screenBlue/custom_layout_grid9_icon.png +0 -0
  165. package/src/assets/image/screenBlue/custom_layout_header_icon.png +0 -0
  166. package/src/assets/image/screenBlue/custom_layout_placeholder_bg.png +0 -0
  167. package/src/assets/image/screenBlue/custom_layout_refresh_icon.png +0 -0
  168. package/src/assets/image/screenBlue/custom_layout_rightside_active_icon.png +0 -0
  169. package/src/assets/image/screenBlue/custom_layout_rightside_icon.png +0 -0
  170. package/src/assets/image/screenBlue/custom_layout_ring_active_icon.png +0 -0
  171. package/src/assets/image/screenBlue/custom_layout_ring_icon.png +0 -0
  172. package/src/assets/image/screenBlue/custom_layout_topside_active_icon.png +0 -0
  173. package/src/assets/image/screenBlue/custom_layout_topside_icon.png +0 -0
  174. package/src/assets/image/screenBlue/date_picker_icon.png +0 -0
  175. package/src/assets/image/screenBlue/dialog_check_icon.png +0 -0
  176. package/src/assets/image/screenBlue/emoji-logo.png +0 -0
  177. package/src/assets/image/screenBlue/header_alert_icon.png +0 -0
  178. package/src/assets/image/screenBlue/manager_cam_on_icon.png +0 -0
  179. package/src/assets/image/screenBlue/manager_mic_on_icon.png +0 -0
  180. package/src/assets/image/screenBlue/manager_more_icon.png +0 -0
  181. package/src/assets/image/screenBlue/meeting_board_bg.png +0 -0
  182. package/src/assets/image/screenBlue/meeting_chat_emoji_icon.png +0 -0
  183. package/src/assets/image/screenBlue/meeting_chat_icon.png +0 -0
  184. package/src/assets/image/screenBlue/meeting_chat_image_icon.png +0 -0
  185. package/src/assets/image/screenBlue/meeting_chat_logo.png +0 -0
  186. package/src/assets/image/screenBlue/meeting_copy_icon.png +0 -0
  187. package/src/assets/image/screenBlue/meeting_invite_icon.png +0 -0
  188. package/src/assets/image/screenBlue/meeting_layout_icon.png +0 -0
  189. package/src/assets/image/screenBlue/meeting_member_icon.png +0 -0
  190. package/src/assets/image/screenBlue/meeting_mode_icon.png +0 -0
  191. package/src/assets/image/screenBlue/meeting_record_icon.png +0 -0
  192. package/src/assets/image/screenBlue/meeting_setting_icon.png +0 -0
  193. package/src/assets/image/screenBlue/meeting_share_icon.png +0 -0
  194. package/src/assets/image/screenBlue/meeting_slide_small_icon.png +0 -0
  195. package/src/assets/image/screenBlue/mic_on_small.png +0 -0
  196. package/src/assets/image/screenBlue/module_bg1.png +0 -0
  197. package/src/assets/image/screenBlue/module_bg2.png +0 -0
  198. package/src/assets/image/screenBlue/monitor/circle data.png +0 -0
  199. package/src/assets/image/screenBlue/monitor/circle.png +0 -0
  200. package/src/assets/image/screenBlue/output_on_small.png +0 -0
  201. package/src/assets/image/screenBlue/page_bg.png +0 -0
  202. package/src/assets/image/screenBlue/pic-logo.png +0 -0
  203. package/src/assets/image/screenBlue/preview_date_icon.png +0 -0
  204. package/src/assets/image/screenBlue/preview_empty_icon.png +0 -0
  205. package/src/assets/image/screenBlue/preview_more_icon.png +0 -0
  206. package/src/assets/image/screenBlue/receive_hang_off_icon.png +0 -0
  207. package/src/assets/image/screenBlue/receive_hang_on_icon.png +0 -0
  208. package/src/assets/image/screenBlue/receive_video_icon.png +0 -0
  209. package/src/assets/image/screenBlue/receive_voice_icon.png +0 -0
  210. package/src/assets/image/screenBlue/send-logo.png +0 -0
  211. package/src/assets/image/screenBlue/slide_menu_bg.png +0 -0
  212. package/src/assets/image/screenBlue/top_header_bg.png +0 -0
  213. package/src/assets/image/screenBlue/yq.png +0 -0
  214. package/src/assets/json/emoji.json +222 -0
  215. package/src/assets/style/base.scss +217 -0
  216. package/src/assets/style/elForm.scss +80 -0
  217. package/src/assets/style/font.scss +16 -0
  218. package/src/assets/style/index.scss +5 -0
  219. package/src/assets/style/math.scss +11 -0
  220. package/src/assets/style/mixin.scss +69 -0
  221. package/src/components/LiveCallBoard/LiveCallBoard.vue +237 -0
  222. package/src/components/LiveInviteReceive/LiveInviteReceive.vue +150 -0
  223. package/src/components/LiveMulti/LiveMulti.vue +303 -0
  224. package/src/components/LiveMultipleMeeting/LiveMultipleMeeting.vue +4469 -0
  225. package/src/components/LiveMultipleMeeting/style/index.scss +337 -0
  226. package/src/components/LivePoint/LivePoint.vue +372 -0
  227. package/src/components/LivePointMeeting/LivePointMeeting.vue +1134 -0
  228. package/src/components/LivePointMeeting/style/index.scss +202 -0
  229. package/src/components/MeetingReadyDialog/MeetingReadyDialog.vue +583 -0
  230. package/src/components/MiniumVideoDialog/MiniumVideoDialog.vue +449 -0
  231. package/src/components/other/LayoutPlaceholder.vue +184 -0
  232. package/src/components/other/addressBook.vue +1121 -0
  233. package/src/components/other/appointDialog.vue +208 -0
  234. package/src/components/other/callBoard.vue +191 -0
  235. package/src/components/other/chatArea.vue +727 -0
  236. package/src/components/other/customGroupDialog.vue +180 -0
  237. package/src/components/other/customLayout.vue +1112 -0
  238. package/src/components/other/editGroupDialog.vue +290 -0
  239. package/src/components/other/inviteNonContactDialog.vue +160 -0
  240. package/src/components/other/layoutSwitch.vue +183 -0
  241. package/src/components/other/leaveOptionDialog.vue +90 -0
  242. package/src/components/other/memberManage.vue +502 -0
  243. package/src/components/other/moreOptionDialog.vue +291 -0
  244. package/src/components/other/screenShareBoard.vue +121 -0
  245. package/src/components/other/selectDialog.vue +279 -0
  246. package/src/components/other/selectSpecialDialog.vue +234 -0
  247. package/src/components/other/settingDialog.vue +756 -0
  248. package/src/components/other/themeDialog.vue +180 -0
  249. package/src/components/other/updateNameDialog.vue +162 -0
  250. package/src/directive/clickOutside.js +58 -0
  251. package/src/directive/drag.js +165 -0
  252. package/src/directive/scale.js +22 -0
  253. package/src/directive/throttle.js +77 -0
  254. package/src/main.js +21 -0
  255. package/src/request/index.js +27 -0
  256. package/src/utils/api.js +82 -0
  257. package/src/utils/index.js +4 -0
  258. package/src/utils/livekit/live-client-esm-old.js +1 -0
  259. package/src/utils/livekit/live-client-esm.js +1 -0
  260. package/src/utils/message.js +24 -0
  261. package/src/utils/mitt.js +4 -0
  262. package/src/utils/tool.js +154 -0
@@ -0,0 +1,1134 @@
1
+ <template>
2
+ <div ref="rootElm" class="point-meeting" id="point-meeting" :style="{ resize: 'both' }">
3
+ <div class="point-meeting-top" v-drag="'point-meeting'">
4
+ <div class="top-group">
5
+ <div class="duration-icon"></div>
6
+ <span>{{ meetingDuration }}</span>
7
+ </div>
8
+ <div class="top-group">
9
+ <div class="full-screen-btn" @click="switchComponentFullScreen"></div>
10
+ </div>
11
+ </div>
12
+ <div class="point-meeting-wrapper">
13
+ <div
14
+ id="point-meeting-contain"
15
+ :class="[
16
+ 'meeting-contain',
17
+ meetingType === 'video' || meetingType === 'miniLink'
18
+ ? 'meeting-contain-video'
19
+ : 'meeting-contain-audio',
20
+ ]"
21
+ @mousemove="setPageFooterVisible(4)"
22
+ >
23
+ <div v-if="isWaiting" class="waiting-mask-video">呼叫中...</div>
24
+ </div>
25
+ </div>
26
+ <div :class="['point-meeting-foot', { 'point-meeting-foot-show': isFootShow }]">
27
+ <div
28
+ class="point-meeting-foot-btn mic-on"
29
+ v-if="isMicroEnabled"
30
+ @click="changeLocalMicrophoneStatus"
31
+ >
32
+ <div class="icon"></div>
33
+ <div class="title">麦克风</div>
34
+ </div>
35
+ <div class="point-meeting-foot-btn mic-off" v-else @click="changeLocalMicrophoneStatus">
36
+ <div class="icon"></div>
37
+ <div class="title">麦克风</div>
38
+ </div>
39
+ <template v-if="meetingType !== 'voice'">
40
+ <div
41
+ class="point-meeting-foot-btn cam-on"
42
+ v-if="isCameraEnabled"
43
+ @click="changeLocalCameraStatus"
44
+ >
45
+ <div class="icon"></div>
46
+ <div class="title">摄像头</div>
47
+ </div>
48
+ <div class="point-meeting-foot-btn cam-off" v-else @click="changeLocalCameraStatus">
49
+ <div class="icon"></div>
50
+ <div class="title">摄像头</div>
51
+ </div>
52
+ </template>
53
+ <div class="point-meeting-foot-btn speaker-on" v-if="isSpeakerEnabled" @click="setToDeafness">
54
+ <div class="icon"></div>
55
+ <div class="title">扬声器</div>
56
+ </div>
57
+ <div class="point-meeting-foot-btn speaker-off" v-else @click="cancelDeafness">
58
+ <div class="icon"></div>
59
+ <div class="title">扬声器</div>
60
+ </div>
61
+ <template v-if="meetingType !== 'voice'">
62
+ <div class="point-meeting-foot-btn screen-share" @click="changeScreenShareStatus">
63
+ <div class="icon"></div>
64
+ <div class="title">{{ isScreenShareEnabled ? "结束共享" : "共享屏幕" }}</div>
65
+ </div>
66
+ <div class="point-meeting-foot-btn preview" @click="changePreviewStatus">
67
+ <div class="icon"></div>
68
+ <div class="title">{{ isPreviewOpen ? "关闭预览" : "开启预览" }}</div>
69
+ </div>
70
+ </template>
71
+ <div class="point-meeting-foot-btn cancel" @click="leaveRoom">
72
+ <div class="icon"></div>
73
+ <div class="title">结束通话</div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </template>
78
+
79
+ <script>
80
+ import { calculateTime, ShowMessage } from "../../utils/index.js";
81
+
82
+ export default {
83
+ name: "LivePointMeeting",
84
+ props: {
85
+ joinType: {
86
+ type: String,
87
+ default: "join", // "join" | "launch"
88
+ },
89
+ meetingNum: {
90
+ type: String,
91
+ default: "",
92
+ },
93
+ meetingType: {
94
+ type: String,
95
+ default: "video", // "video" | "voice" | "miniLink"
96
+ },
97
+ invitePhone: {
98
+ type: String,
99
+ default: "",
100
+ },
101
+ inviteName: {
102
+ type: String,
103
+ default: "",
104
+ },
105
+ inviteType: {
106
+ type: [Number, String],
107
+ default: 0,
108
+ },
109
+ inviteWays: {
110
+ type: String,
111
+ default: "phoneCall",
112
+ },
113
+ inviteUserData: {
114
+ type: Object,
115
+ default: () => ({}),
116
+ },
117
+ isInMeeting: {
118
+ type: Boolean,
119
+ default: false
120
+ }
121
+ },
122
+ data() {
123
+ return {
124
+ durationInterval: null,
125
+ footVisibleInterval: null,
126
+ liveClient: null,
127
+ showMessage: null,
128
+ localIdentity: "",
129
+ localName: "",
130
+ tempMeetingNum: "",
131
+ roomMetadata: null,
132
+ componentEventList: [],
133
+ trackList: [],
134
+ participants: [],
135
+ isMicroEnabled: false,
136
+ isCameraEnabled: false,
137
+ isSpeakerEnabled: false,
138
+ isScreenShareEnabled: false,
139
+ isPreviewOpen: true,
140
+ isWaiting: false,
141
+ duration: 0,
142
+ isDurationCalc: true,
143
+ isFootShow: false,
144
+ footVisibleDuration: 3,
145
+ isRoomConnectedHandled: false
146
+ }
147
+ },
148
+ computed: {
149
+ participantNum() {
150
+ return this.participants.length;
151
+ },
152
+ meetingDuration() {
153
+ return calculateTime(this.duration);
154
+ }
155
+ },
156
+ watch: {
157
+ footVisibleDuration(newVal) {
158
+ if (newVal <= 0) {
159
+ this.isFootShow = false;
160
+ if (this.footVisibleInterval) {
161
+ clearInterval(this.footVisibleInterval);
162
+ }
163
+ }
164
+ }
165
+ },
166
+ methods: {
167
+ async createRoom() {
168
+ if (!this.liveClient) {
169
+ return;
170
+ }
171
+ await this.liveClient.createRoom(this.meetingType === "voice" ? 2 : 1);
172
+ },
173
+ async joinRoom() {
174
+ if (!this.liveClient) {
175
+ return;
176
+ }
177
+ const param = {
178
+ echoCancellation: true,
179
+ noiseSuppression: true,
180
+ roomNum: this.joinType === "launch" ? this.tempMeetingNum : this.meetingNum,
181
+ };
182
+ try {
183
+ await this.liveClient.joinRoom(param);
184
+ } catch (e) {
185
+ this.showMessage.message("error", "加入会议失败");
186
+ }
187
+ },
188
+ // 添加事件到事件监听数组
189
+ addEventToList(eventName) {
190
+ if (this.componentEventList.indexOf(eventName) < 0) {
191
+ this.componentEventList.push(eventName);
192
+ }
193
+ },
194
+ // 解除已绑定的事件
195
+ dispatchLiveClientEvent() {
196
+ if (this.liveClient) {
197
+ if (this.componentEventList.length > 0) {
198
+ this.componentEventList.forEach((eventName) => {
199
+ this.liveClient.off(eventName);
200
+ });
201
+ }
202
+ }
203
+ },
204
+ // 清除所有音视频轨道
205
+ clearAllTrack() {
206
+ if (this.trackList.length > 0) {
207
+ this.trackList.forEach((track) => {
208
+ track?.detach();
209
+ track?.stop();
210
+ });
211
+ }
212
+ this.trackList = [];
213
+ },
214
+ // 清除组件定时器
215
+ clearAllInterval() {
216
+ if (this.durationInterval) {
217
+ clearInterval(this.durationInterval);
218
+ this.durationInterval = null;
219
+ }
220
+ },
221
+ // 切换本地用户摄像头
222
+ async changeLocalCameraStatus() {
223
+ await this.liveClient.changeCameraStatus();
224
+ },
225
+ // 切换本地用户麦克风
226
+ async changeLocalMicrophoneStatus() {
227
+ await this.liveClient.changeMicrophoneStatus();
228
+ },
229
+ // 开启/关闭屏幕共享
230
+ async changeScreenShareStatus() {
231
+ await this.liveClient.changeScreenShareStatus();
232
+ },
233
+ // 本地与会者置聋
234
+ async setToDeafness() {
235
+ await this.liveClient.setParticipantDeafness(this.localIdentity);
236
+ },
237
+ // 本地与会者取消置聋
238
+ async cancelDeafness() {
239
+ await this.liveClient.cancelParticipantDeafness(this.localIdentity);
240
+ },
241
+ // 设置底部工具条显示
242
+ setPageFooterVisible(time) {
243
+ this.footVisibleDuration = time;
244
+ this.isFootShow = true;
245
+ if (this.footVisibleInterval) {
246
+ clearInterval(this.footVisibleInterval);
247
+ }
248
+ this.footVisibleInterval = setInterval(() => {
249
+ if (this.footVisibleDuration > 0) {
250
+ this.footVisibleDuration--;
251
+ }
252
+ }, 1000);
253
+ },
254
+ // 切换是否预览
255
+ changePreviewStatus() {
256
+ if (!this.isInMeeting) {
257
+ return;
258
+ }
259
+ const layoutBlurElm = document.querySelector("#point-meeting-contain .layout-blur");
260
+ const layoutNormalElm = document.querySelector("#point-meeting-contain .layout-normal");
261
+ if (this.isPreviewOpen) {
262
+ if (layoutBlurElm.hasChildNodes) {
263
+ const child = layoutBlurElm.firstElementChild;
264
+ if (child.id === `participant-${this.localIdentity}`) {
265
+ // 小画面是自己,直接关闭
266
+ layoutBlurElm.style.visibility = "hidden";
267
+ this.isPreviewOpen = false;
268
+ } else {
269
+ if (layoutNormalElm.hasChildNodes) {
270
+ const normalChild = layoutNormalElm.firstElementChild;
271
+ layoutBlurElm.appendChild(normalChild);
272
+ layoutNormalElm.appendChild(child);
273
+ layoutBlurElm.style.visibility = "hidden";
274
+ this.isPreviewOpen = false;
275
+ } else {
276
+ layoutNormalElm.appendChild(child);
277
+ layoutBlurElm.style.visibility = "hidden";
278
+ this.isPreviewOpen = false;
279
+ }
280
+ }
281
+ }
282
+ } else {
283
+ if (this.isScreenShareEnabled) {
284
+ this.showMessage.message("error", "当前正在共享屏幕,无法开启预览");
285
+ return;
286
+ } else {
287
+ layoutBlurElm.style.visibility = "visible";
288
+ this.isPreviewOpen = true;
289
+ }
290
+ }
291
+ },
292
+ // 初始化点对点会议事件
293
+ initClientEvent() {
294
+ if (!this.liveClient) {
295
+ this.showMessage.message("error", "liveClient未能成功初始化");
296
+ return;
297
+ }
298
+ // 监听sdk错误抛出
299
+ this.liveClient.on("errorAlert", (e) => {
300
+ this.addEventToList("errorAlert");
301
+ if(e.severity == 'high' || e.severity == 'critical') {
302
+ if(e?.context?.originalMessage == "could not establish pc connection") {
303
+ this.showMessage.message("error", "无法建立连接,请检查udp端口是否启用");
304
+ } else {
305
+ this.showMessage.message("error", e.message);
306
+ }
307
+ }
308
+ });
309
+ // 会议房间成功创建
310
+ this.liveClient.on("roomCreatedSuccess", async (e) => {
311
+ this.addEventToList("roomCreatedSuccess");
312
+ this.showMessage.message("success", "会议房间创建成功");
313
+ this.tempMeetingNum = e;
314
+ await this.joinRoom();
315
+ });
316
+ // 加入会议失败
317
+ this.liveClient.on("joinRoomError", (e) => {
318
+ this.addEventToList("joinRoomError");
319
+ this.handleJoinRoomError(e);
320
+ });
321
+ this.liveClient.on("roomMetadataChanged", (e) => {
322
+ const metadata = JSON.parse(e);
323
+ this.roomMetadataChange(metadata);
324
+ });
325
+ // 会议链接成功
326
+ this.liveClient.on("roomConnected", (e) => {
327
+ this.addEventToList("roomConnected");
328
+ if (this.liveClient?.room) {
329
+ const metadata = JSON.parse(this.liveClient.room.metadata);
330
+ // 初始化部分会议信息
331
+ this.initRoomMetadata(metadata);
332
+ this.$emit("meetingStarted");
333
+ this.handleRoomConnected(e);
334
+ this.handleDeviceInvite(e);
335
+ if(this.joinType === "launch") {
336
+ this.isWaiting = true;
337
+ }
338
+ this.initRoomDuration(metadata);
339
+ }
340
+ });
341
+ // 本地轨道发布
342
+ this.liveClient.on("localTrackPublished", (e) => {
343
+ this.addEventToList("localTrackPublished");
344
+ console.log("本地轨道发布", e);
345
+ });
346
+ // 远程轨道订阅
347
+ this.liveClient.on("trackSubscribed", (e) => {
348
+ this.addEventToList("trackSubscribed");
349
+ console.log("远程轨道订阅", e);
350
+ });
351
+ // 摄像头状态切换
352
+ this.liveClient.on("localCameraChange", (e) => {
353
+ this.addEventToList("localCameraChange");
354
+ this.isCameraEnabled = e;
355
+ if (this.isCameraEnabled) {
356
+ this.showMessage.message("success", "摄像头已开启");
357
+ } else {
358
+ this.showMessage.message("success", "摄像头已关闭");
359
+ }
360
+ });
361
+ // 麦克风状态切换
362
+ this.liveClient.on("localMicrophoneChange", (e) => {
363
+ this.addEventToList("localMicrophoneChange");
364
+ this.isMicroEnabled = e;
365
+ if (this.isMicroEnabled) {
366
+ this.showMessage.message("success", "麦克风已开启");
367
+ } else {
368
+ this.showMessage.message("success", "麦克风已关闭");
369
+ }
370
+ });
371
+ // 屏幕共享状态切换
372
+ this.liveClient.on("localScreenShareChange", (e) => {
373
+ this.addEventToList("localScreenShareChange");
374
+ this.isScreenShareEnabled = e;
375
+ if (this.isScreenShareEnabled) {
376
+ this.showMessage.message("success", "屏幕共享已开启");
377
+ } else {
378
+ this.showMessage.message("success", "屏幕共享已关闭");
379
+ }
380
+ });
381
+ // 监听videoCallRender事件 视频通话
382
+ this.liveClient.on("videoCallRender", (e) => {
383
+ this.addEventToList("videoCallRender");
384
+ this.renderVideoItem(e);
385
+ });
386
+ // 监听audioCallRender事件 语音通话
387
+ this.liveClient.on("audioCallRender", (e) => {
388
+ this.addEventToList("audioCallRender");
389
+ this.renderAudioItem(e);
390
+ });
391
+ // 监听发出的邀请被拒绝
392
+ this.liveClient.on("receiveInviteRefuse", (e) => {
393
+ this.addEventToList("receiveInviteRefuse");
394
+ this.showMessage.message("warning", "您的会议邀请被对方拒绝");
395
+ if(this.joinType === "launch") {
396
+ this.isWaiting = false;
397
+ }
398
+ });
399
+ // 监听用户与房间断开链接事件
400
+ this.liveClient.on("roomDisconnected", async () => {
401
+ this.addEventToList("roomDisconnected");
402
+ this.showMessage.message("info", "房间链接已断开");
403
+ this.clearMeetingStatus();
404
+ // 调用删除房间接口
405
+ if (this.joinType === "launch") {
406
+ try {
407
+ await this.liveClient.deleteRoom(this.tempMeetingNum)
408
+ } catch (e) {
409
+ console.error(e);
410
+ } finally {
411
+ this.clearAllInterval();
412
+ this.closeMeetingDialog();
413
+ }
414
+ } else {
415
+ this.clearAllInterval();
416
+ this.closeMeetingDialog();
417
+ }
418
+ });
419
+ },
420
+ // 处理加入会议报错
421
+ handleJoinRoomError(e) {
422
+ console.error("加入会议失败", e);
423
+ this.showMessage.message("error", "加入会议失败");
424
+ this.clearMeetingStatus();
425
+ },
426
+ // 初始化会议信息
427
+ initRoomMetadata(metadata) {
428
+ this.roomMetadataChange(metadata);
429
+ },
430
+ // 会议信息变更
431
+ roomMetadataChange(metadata) {
432
+ console.log("roomMetadataChange", metadata);
433
+ this.roomMetadata = metadata;
434
+ this.initRoomDuration(metadata);
435
+ },
436
+ // 初始化会议时长
437
+ initRoomDuration(metadata) {
438
+ if (this.isDurationCalc) {
439
+ if (this.durationInterval) {
440
+ clearInterval(this.durationInterval);
441
+ this.durationInterval = null;
442
+ }
443
+ this.durationInterval = setInterval(() => {
444
+ if (new Date(metadata.roomStartTime).getTime() > 0) {
445
+ this.duration = Math.floor(
446
+ (Date.now() - new Date(metadata.roomStartTime).getTime()) / 1000
447
+ );
448
+ this.isDurationCalc = false;
449
+ } else {
450
+ this.duration++;
451
+ }
452
+ }, 1000);
453
+ }
454
+ },
455
+ // 房间连接成功处理函数
456
+ handleRoomConnected(e) {
457
+ if (this.joinType === "launch") {
458
+ if (this.inviteWays === "phoneCall") {
459
+ if (this.meetingType === "miniLink") {
460
+ this.liveClient
461
+ .inviteParticipant(
462
+ this.tempMeetingNum,
463
+ [
464
+ {
465
+ identity: this.invitePhone,
466
+ userName: this.inviteName || this.invitePhone,
467
+ phone: this.invitePhone,
468
+ },
469
+ ],
470
+ this.meetingType === "voice",
471
+ 3
472
+ )
473
+ .then((res) => {
474
+ if (res.code === 200) {
475
+ this.showMessage.message("success", "成功发送邀请");
476
+ } else {
477
+ this.showMessage.message("error", res?.msg || "邀请发送失败");
478
+ this.isWaiting = false;
479
+ }
480
+ })
481
+ .catch((err) => {
482
+ console.error("邀请发送失败:", err);
483
+ this.showMessage.message("error", err?.message || "邀请发送失败");
484
+ this.isWaiting = false;
485
+ });
486
+ }
487
+ } else if (this.inviteWays === "identity") {
488
+ this.sendInviteMessage();
489
+ }
490
+ }
491
+ },
492
+ // volte邀请特殊处理
493
+ handleDeviceInvite(e) {
494
+ if (this.joinType === "launch") {
495
+ if (this.inviteWays === "phoneCall") {
496
+ if (this.meetingType === "video" || this.meetingType === "voice") {
497
+ this.liveClient
498
+ .makeCall(this.inviteName || this.invitePhone, this.invitePhone, Number(this.inviteType))
499
+ .then(() => {
500
+ this.showMessage.message("success", "外呼邀请发送成功");
501
+ })
502
+ .catch((err) => {
503
+ this.isWaiting = false;
504
+ this.showMessage.message("error", "外呼邀请发送失败");
505
+ });
506
+ }
507
+ }
508
+ }
509
+ },
510
+ // 发送邀请信息
511
+ sendInviteMessage() {
512
+ console.log("sendInviteMessage", this.inviteUserData);
513
+
514
+ if (!this.inviteUserData?.identity) {
515
+ this.showMessage.message("error", "缺少被邀请人identity");
516
+ return;
517
+ }
518
+ if (this.inviteUserData?.identity === this.localIdentity) {
519
+ this.showMessage.message("error", "不能邀请自己");
520
+ return;
521
+ }
522
+ this.liveClient
523
+ .inviteParticipant(
524
+ this.tempMeetingNum,
525
+ [
526
+ {
527
+ identity: this.inviteUserData?.identity,
528
+ userName: this.inviteUserData?.userName || this.inviteUserData?.phone,
529
+ phone: this.inviteUserData?.phone,
530
+ },
531
+ ],
532
+ this.meetingType === "voice",
533
+ this.meetingType === "miniLink" ? 3 : 0
534
+ )
535
+ .then((res) => {
536
+ if (res.code === 200) {
537
+ this.showMessage.message("success", "成功发送邀请");
538
+ } else {
539
+ this.showMessage.message("error", res?.msg || "邀请发送失败");
540
+ this.isWaiting = false;
541
+ }
542
+ })
543
+ .catch((err) => {
544
+ console.error("邀请发送失败:", err);
545
+ this.showMessage.message("error", err?.message || "邀请发送失败");
546
+ this.isWaiting = false;
547
+ });
548
+ },
549
+ closeMeetingDialog() {
550
+ this.$emit("meetingDialogClose");
551
+ },
552
+ async leaveRoom() {
553
+ if (this.liveClient) {
554
+ await this.liveClient.leaveRoom();
555
+ }
556
+ // 重置房间连接处理标志
557
+ this.isRoomConnectedHandled = false;
558
+ },
559
+ // 切换组件全屏状态
560
+ async switchComponentFullScreen(e) {
561
+ if (
562
+ document.fullscreenElement ||
563
+ document.msFullscreenElement ||
564
+ document.mozFullScreenElement ||
565
+ document.webkitFullscreenElement
566
+ ? true
567
+ : false
568
+ ) {
569
+ if (document.exitFullscreen) {
570
+ document.exitFullscreen();
571
+ } else if (document.mozCancelFullScreen) {
572
+ document.mozCancelFullScreen();
573
+ } else if (document.webkitCancelFullScreen) {
574
+ document.webkitCancelFullScreen();
575
+ } else if (document.msExitFullscreen) {
576
+ document.msExitFullscreen();
577
+ }
578
+ } else {
579
+ await this.$nextTick();
580
+ if (this.$refs.rootElm.requestFullscreen) {
581
+ this.$refs.rootElm.requestFullscreen();
582
+ }
583
+ }
584
+ },
585
+ // 判断与会者是否被邀请
586
+ judgeParticipantIsInvited(identity) {
587
+ const reg = /^(sip_)+?/;
588
+ const reg1 = /^(sip_0)+?/;
589
+ if (reg1.test(identity)) {
590
+ return identity === "sip_0" + this.invitePhone;
591
+ } else if (reg.test(identity)) {
592
+ return identity === "sip_" + this.invitePhone;
593
+ } else {
594
+ return identity === this.invitePhone;
595
+ }
596
+ },
597
+ // 判断会议中是否有其他人正在共享
598
+ judgeParticipantScreenShare() {
599
+ if (this.participantNum <= 0) {
600
+ return false;
601
+ }
602
+ const index = this.participants.findIndex((item) => {
603
+ return item.identity !== this.localIdentity && item.isScreenShareEnabled;
604
+ });
605
+ if (index > -1) {
606
+ return true;
607
+ } else {
608
+ return false;
609
+ }
610
+ },
611
+ addToParticipantList(userItem) {
612
+ if (this.participantNum <= 0) {
613
+ this.participants.push(userItem);
614
+ } else {
615
+ const index = this.participants.findIndex((item) => {
616
+ return item.identity === userItem.identity;
617
+ });
618
+ if (index !== -1) {
619
+ // 更新数组中与会者
620
+ this.participants.splice(index, 1, userItem);
621
+ } else {
622
+ this.participants.push(userItem);
623
+ }
624
+ }
625
+ },
626
+ removeFromParticipantList(userItem) {
627
+ if (this.participantNum <= 0) {
628
+ return;
629
+ } else {
630
+ const index = this.participants.findIndex((item) => {
631
+ return item.identity === userItem.identity;
632
+ });
633
+ if (index !== -1) {
634
+ // 更新数组中与会者
635
+ this.participants.splice(index, 1);
636
+ }
637
+ }
638
+ },
639
+ renderVideoItem(videoItem) {
640
+ console.log("视频通话渲染" + videoItem.identity + ":", videoItem);
641
+ if (videoItem.isLocal) {
642
+ const metadata = videoItem.metadata;
643
+ this.isCameraEnabled = videoItem.isCameraEnabled;
644
+ this.isMicroEnabled = videoItem.isMicrophoneEnabled;
645
+ this.isScreenShareEnabled = videoItem.isScreenShareEnabled;
646
+ this.isSpeakerEnabled = !metadata.isDeafness;
647
+ this.localIdentity = videoItem.identity;
648
+ this.localName = videoItem.name;
649
+ }
650
+ const container = document.getElementById("point-meeting-contain");
651
+ let videoDiv = document.getElementById(`participant-${videoItem.identity}`);
652
+ let layoutBlurElm = document.querySelector("#point-meeting-contain .layout-blur");
653
+ let layoutNormalElm = document.querySelector("#point-meeting-contain .layout-normal");
654
+ if (!layoutBlurElm) {
655
+ layoutBlurElm = document.createElement("div");
656
+ layoutBlurElm.className = "layout-blur";
657
+ container.appendChild(layoutBlurElm);
658
+ }
659
+ if (!layoutNormalElm) {
660
+ layoutNormalElm = document.createElement("div");
661
+ layoutNormalElm.className = "layout-normal";
662
+ container.insertBefore(layoutNormalElm, container.firstElementChild ?? null);
663
+ }
664
+ if (!container) {
665
+ this.showMessage.message("error", "会议容器不存在");
666
+ return;
667
+ }
668
+ if (!videoDiv && !videoItem.remove) {
669
+ videoDiv = document.createElement("div");
670
+ videoDiv.id = `participant-${videoItem.identity}`;
671
+ videoDiv.className = videoItem.isLocal ? "participant local" : "participant";
672
+ videoDiv.innerHTML = `
673
+ <video id="video-${
674
+ videoItem.identity
675
+ }" class="p-video" autoplay webkit-playsinline playsinline x5-video-player-type="h5"></video>
676
+ <div id="describe-${videoItem.identity}" class="describe">
677
+ <div id="microphone-${videoItem.identity}" class="microphone"></div>
678
+ <div id="${videoItem.identity}" class="identity">${
679
+ videoItem.isLocal ? videoItem.name + "(我)" : videoItem.name
680
+ }</div>
681
+ </div>
682
+ `;
683
+ if (videoItem.isScreenShareEnabled || videoItem.isCameraEnabled) {
684
+ } else {
685
+ videoDiv.innerHTML = `
686
+ <video id="video-${videoItem.identity}" class="p-video" autoplay webkit-playsinline playsinline x5-video-player-type="h5"></video>
687
+ <div id="board-${videoItem.identity}" class="board">
688
+ <div class="board-icon"></div>
689
+ <div class="board-title">
690
+ <div id="microphone-${videoItem.identity}" class="microphone"></div>
691
+ <span class="board-title-text">${videoItem.name}</span>
692
+ </div>
693
+ </div>
694
+ `;
695
+ }
696
+ if (videoItem.isLocal) {
697
+ if (layoutBlurElm.hasChildNodes) {
698
+ let child = null;
699
+ while ((child = layoutBlurElm.firstElementChild)) {
700
+ layoutNormalElm.insertBefore(child, layoutNormalElm.firstElementChild ?? null);
701
+ }
702
+ }
703
+ layoutBlurElm.appendChild(videoDiv);
704
+ } else {
705
+ if (this.participantNum >= 2) {
706
+ return;
707
+ } else {
708
+ if (layoutNormalElm.hasChildNodes) {
709
+ let child = null;
710
+ while ((child = layoutNormalElm.firstElementChild)) {
711
+ layoutBlurElm.appendChild(child);
712
+ }
713
+ }
714
+ layoutNormalElm.appendChild(videoDiv);
715
+ }
716
+ }
717
+ this.addToParticipantList(videoItem);
718
+ }
719
+ // 与会者状态变更
720
+ // 视频元素
721
+ let videoElm = document.getElementById(`video-${videoItem.identity}`);
722
+ // 当与会者断开会议链接即remove为true
723
+ if (videoItem.remove) {
724
+ if (videoElm) {
725
+ videoElm.srcObject = null;
726
+ videoElm.src = "";
727
+ videoElm.remove();
728
+ }
729
+ if (videoDiv) {
730
+ videoDiv.remove();
731
+ }
732
+ this.removeFromParticipantList(videoItem);
733
+
734
+ // 音视频轨道与video元素解绑
735
+ if (videoItem.videoTrack) {
736
+ videoItem.videoTrack.detach();
737
+ }
738
+ if (videoItem.audioTrack) {
739
+ videoItem.audioTrack.detach();
740
+ }
741
+ return;
742
+ }
743
+ if (this.joinType === "launch" && !videoItem.isLocal) {
744
+ if (this.meetingType === "miniLink") {
745
+ if (!videoItem.isLocal) {
746
+ this.isWaiting = false;
747
+ }
748
+ } else {
749
+ // if (this.judgeParticipantIsInvited(videoItem.identity) && videoItem?.audioTrack) {
750
+ // this.isWaiting = false;
751
+ // }
752
+ if (!videoItem.isLocal && videoItem?.audioTrack) {
753
+ this.isWaiting = false;
754
+ }
755
+ }
756
+ }
757
+ // 底部描述元素
758
+ let describeElm = document.getElementById(`describe-${videoItem.identity}`);
759
+ // 摄像头关闭后展板元素
760
+ let boardElm = document.getElementById(`board-${videoItem.identity}`);
761
+ // 底部麦克风图标元素
762
+ let microElm = document.getElementById(`microphone-${videoItem.identity}`);
763
+ // 声明麦克风按钮点击事件回调
764
+ const unableMicrophone = () => {
765
+ this.liveClient.changeParticipantMicrophoneStatus(videoItem.identity, true);
766
+ };
767
+ const enableMicrophone = () => {
768
+ this.liveClient.changeParticipantMicrophoneStatus(videoItem.identity, false);
769
+ };
770
+ // 设置指定元素为焦点
771
+ const setBlurVideoLeft = () => {
772
+ if (!this.isPreviewOpen) {
773
+ return;
774
+ }
775
+ let layoutBlurElm = document.querySelector("#point-meeting-contain .layout-blur");
776
+ let layoutNormalElm = document.querySelector("#point-meeting-contain .layout-normal");
777
+ let localChild = layoutBlurElm.firstElementChild;
778
+ let currentEle = document.getElementById(`participant-${videoItem.identity}`);
779
+ if (localChild) {
780
+ if (localChild.id === `participant-${this.localIdentity}`) {
781
+ return;
782
+ } else {
783
+ layoutNormalElm.insertBefore(localChild, layoutNormalElm.firstChild ?? null);
784
+ if (currentEle) {
785
+ layoutBlurElm.appendChild(currentEle);
786
+ }
787
+ }
788
+ } else {
789
+ layoutBlurElm.appendChild(currentEle);
790
+ }
791
+ };
792
+ // 为与会者元素绑定事件
793
+ if (videoDiv) {
794
+ videoDiv.onclick = setBlurVideoLeft;
795
+ }
796
+ if (videoItem.isScreenShareEnabled || videoItem.isCameraEnabled) {
797
+ if (boardElm) {
798
+ videoDiv.removeChild(boardElm);
799
+ boardElm = null;
800
+ }
801
+ if (!describeElm) {
802
+ describeElm = document.createElement("div");
803
+ describeElm.className = "describe";
804
+ describeElm.id = `describe-${videoItem.identity}`;
805
+ describeElm.innerHTML = `
806
+ <div id="microphone-${videoItem.identity}" class="microphone"></div>
807
+ <div id="${videoItem.identity}" class="identity">${
808
+ videoItem.isLocal ? videoItem.name + "(我)" : videoItem.name
809
+ }</div>
810
+ `;
811
+ videoDiv.appendChild(describeElm);
812
+ }
813
+ } else {
814
+ if (describeElm) {
815
+ videoDiv.removeChild(describeElm);
816
+ describeElm = null;
817
+ }
818
+ if (!boardElm) {
819
+ boardElm = document.createElement("div");
820
+ boardElm.className = "board";
821
+ boardElm.id = `board-${videoItem.identity}`;
822
+ boardElm.innerHTML = `
823
+ <div class="board-icon"></div>
824
+ <div class="board-title">
825
+ <span class="board-title-text">${videoItem.name}</span>
826
+ <div id="microphone-${videoItem.identity}" class="microphone"></div>
827
+ </div>
828
+ `;
829
+ if (boardElm) {
830
+ videoDiv.appendChild(boardElm);
831
+ }
832
+ }
833
+ }
834
+ // 更新麦克风元素
835
+ microElm = document.getElementById(`microphone-${videoItem.identity}`);
836
+ // 为麦克风元素绑定事件
837
+ if (microElm && videoItem.isMicrophoneEnabled) {
838
+ microElm.className = "microphone microphone-active";
839
+ microElm.onclick = unableMicrophone;
840
+ } else if (microElm && !videoItem.isMicrophoneEnabled) {
841
+ microElm.className = "microphone microphone-inactive";
842
+ microElm.onclick = enableMicrophone;
843
+ }
844
+ // 音视频轨道绑定到video元素
845
+ if (videoItem.videoTrack) {
846
+ videoItem.videoTrack.attach(videoElm);
847
+ }
848
+ if (!videoItem.isLocal) {
849
+ if (videoItem.audioTrack) {
850
+ videoItem.audioTrack.attach(videoElm);
851
+ }
852
+ }
853
+ this.addToParticipantList(videoItem);
854
+ },
855
+ renderAudioItem(audioItem) {
856
+ console.log("语音通话渲染" + audioItem.identity + ":", audioItem);
857
+ if (audioItem.isLocal) {
858
+ const metadata = audioItem.metadata;
859
+ this.isMicroEnabled = audioItem.isMicrophoneEnabled;
860
+ this.isSpeakerEnabled = !metadata.isDeafness;
861
+ this.localIdentity = audioItem.identity;
862
+ this.localName = audioItem.name;
863
+ }
864
+ if (!audioItem.isLocal) {
865
+ const container = document.getElementById("point-meeting-contain");
866
+ let audioDiv = document.getElementById(`participant-${audioItem.identity}`);
867
+ if (!container) {
868
+ this.showMessage.message("error", "会议容器不存在");
869
+ return;
870
+ }
871
+ if (!audioDiv && !audioItem.remove) {
872
+ audioDiv = document.createElement("div");
873
+ audioDiv.id = `participant-${audioItem.identity}`;
874
+ audioDiv.className = audioItem.isLocal ? "participant local" : "participant";
875
+ audioDiv.innerHTML = `
876
+ <audio id="audio-${audioItem.identity}" class="p-audio" autoplay></audio>
877
+ <div class="participant-icon"></div>
878
+ <div class="participant-title">
879
+ <div id="microphone-${audioItem.identity}" class="microphone"></div>
880
+ <span class="participant-title-text">${audioItem.name}</span>
881
+ </div>
882
+ `;
883
+ if (audioItem.isLocal) {
884
+ container.insertBefore(audioDiv, container.firstChild ?? null);
885
+ } else {
886
+ container.appendChild(audioDiv);
887
+ }
888
+ this.addToParticipantList(audioItem);
889
+ }
890
+ let audioElm = document.getElementById(`audio=${audioItem.identity}`);
891
+ if (audioItem.remove) {
892
+ if (audioElm) {
893
+ audioElm.srcObject = null;
894
+ audioElm.src = "";
895
+ audioElm.remove();
896
+ }
897
+ if (audioDiv) {
898
+ audioDiv.remove();
899
+ }
900
+ this.removeFromParticipantList(audioItem);
901
+ if (audioItem.audioTrack) {
902
+ audioItem.audioTrack.detach();
903
+ }
904
+ }
905
+ if (this.joinType === "launch") {
906
+ if (audioItem?.audioTrack) {
907
+ this.isWaiting = false;
908
+ }
909
+ }
910
+ // 底部麦克风图标元素
911
+ let microElm = document.getElementById(`microphone-${audioItem.identity}`);
912
+ // 声明麦克风按钮点击事件回调
913
+ const unableMicrophone = () => {
914
+ this.liveClient.changeParticipantMicrophoneStatus(audioItem.identity, true);
915
+ };
916
+ const enableMicrophone = () => {
917
+ this.liveClient.changeParticipantMicrophoneStatus(audioItem.identity, false);
918
+ };
919
+ if (microElm && audioItem.isMicrophoneEnabled) {
920
+ microElm.className = "microphone microphone-active";
921
+ microElm.onclick = unableMicrophone;
922
+ } else if (microElm && !audioItem.isMicrophoneEnabled) {
923
+ microElm.className = "microphone microphone-inactive";
924
+ microElm.onclick = enableMicrophone;
925
+ }
926
+ if (audioItem.audioTrack) {
927
+ audioItem.audioTrack.attach(audioElm);
928
+ }
929
+ }
930
+ this.addToParticipantList(audioItem);
931
+ },
932
+ clearMeetingStatus() {
933
+ this.$emit("meetingEnded");
934
+ }
935
+ },
936
+ mounted() {
937
+ this.liveClient = window["liveClient"];
938
+ this.showMessage = new ShowMessage();
939
+ this.initClientEvent();
940
+ if (this.joinType === "launch") {
941
+ // 发起会议
942
+ if (this.meetingType === "video" || this.meetingType === "miniLink") {
943
+ this.liveClient.roomMode = "auto";
944
+ } else if (this.meetingType === "voice") {
945
+ this.liveClient.roomMode = "audio";
946
+ } else {
947
+ void 0;
948
+ }
949
+ this.createRoom();
950
+ } else {
951
+ // 加入会议
952
+ if (this.meetingType === "video" || this.meetingType === "miniLink") {
953
+ this.liveClient.roomMode = "auto";
954
+ } else if (this.meetingType === "voice") {
955
+ this.liveClient.roomMode = "audio";
956
+ } else {
957
+ void 0;
958
+ }
959
+ this.joinRoom();
960
+ }
961
+ this.setPageFooterVisible(4);
962
+ },
963
+ beforeDestroy() {
964
+ if (this.isInMeeting) {
965
+ this.leaveRoom();
966
+ }
967
+ this.dispatchLiveClientEvent();
968
+ // 重置房间连接处理标志
969
+ this.isRoomConnectedHandled = false;
970
+ this.clearMeetingStatus();
971
+ },
972
+ }
973
+ </script>
974
+
975
+ <style lang="scss" scoped>
976
+ .point-meeting {
977
+ width: 710px;
978
+ height: 440px;
979
+ position: fixed;
980
+ inset: 0;
981
+ margin: auto;
982
+ z-index: 2000;
983
+ background: var(--dialog-bg);
984
+ font-weight: 400;
985
+ font-size: 16px;
986
+ color: var(--theme-font-color);
987
+ overflow: hidden;
988
+ transform: translate(0, 0);
989
+ border: 1px solid var(--dialog-border-color);
990
+ border-radius: 10px;
991
+ box-shadow: 0px 0px 10px 0px var(--dialog-shadow-color);
992
+
993
+ &-top {
994
+ width: 100%;
995
+ display: flex;
996
+ align-items: center;
997
+ height: 40px;
998
+ justify-content: space-between;
999
+ padding: 0 20px;
1000
+ border-bottom: 1px solid var(--dialog-border-color);
1001
+ .top-group {
1002
+ display: flex;
1003
+ align-items: center;
1004
+
1005
+ .duration-icon {
1006
+ width: 15px;
1007
+ height: 15px;
1008
+ background: var(--call-duration-icon) no-repeat center / 100% 100%;
1009
+ margin-right: 4px;
1010
+ }
1011
+
1012
+ span {
1013
+ white-space: nowrap;
1014
+ }
1015
+
1016
+ .full-screen-btn {
1017
+ cursor: pointer;
1018
+ width: 16px;
1019
+ height: 16px;
1020
+ background: var(--call-fullscreen-icon) no-repeat center / 100% 100%;
1021
+ }
1022
+
1023
+ .close-btn {
1024
+ cursor: pointer;
1025
+ width: 20px;
1026
+ height: 20px;
1027
+ background: var(--close-icon) no-repeat center / 100% 100%;
1028
+ }
1029
+ }
1030
+ }
1031
+
1032
+ &-wrapper {
1033
+ width: 100%;
1034
+ height: calc(100% - 40px);
1035
+ }
1036
+
1037
+ &-foot {
1038
+ position: absolute;
1039
+ bottom: -52px;
1040
+ left: 0;
1041
+ width: 100%;
1042
+ height: 52px;
1043
+ display: flex;
1044
+ align-items: center;
1045
+ justify-content: space-around;
1046
+ background: var(--call-foot-bg);
1047
+ z-index: 200;
1048
+ transition: bottom 0.2s;
1049
+
1050
+ &-show {
1051
+ bottom: 0px;
1052
+ }
1053
+
1054
+ &-btn {
1055
+ display: flex;
1056
+ flex-direction: column;
1057
+ align-items: center;
1058
+ cursor: pointer;
1059
+
1060
+ .icon {
1061
+ width: 20px;
1062
+ height: 20px;
1063
+ margin-bottom: 4px;
1064
+ }
1065
+
1066
+ .title {
1067
+ font-weight: 400;
1068
+ font-size: 14px;
1069
+ line-height: 20px;
1070
+ white-space: nowrap;
1071
+ }
1072
+ }
1073
+
1074
+ .mic-on {
1075
+ .icon {
1076
+ background: var(--common-mic-on) no-repeat center / 100% 100%;
1077
+ }
1078
+ }
1079
+
1080
+ .mic-off {
1081
+ .icon {
1082
+ background: var(--common-mic-off) no-repeat center / 100% 100%;
1083
+ }
1084
+ }
1085
+
1086
+ .cam-on {
1087
+ .icon {
1088
+ background: var(--common-cam-on) no-repeat center / 100% 100%;
1089
+ }
1090
+ }
1091
+
1092
+ .cam-off {
1093
+ .icon {
1094
+ background: var(--common-cam-off) no-repeat center / 100% 100%;
1095
+ }
1096
+ }
1097
+
1098
+ .speaker-on {
1099
+ .icon {
1100
+ background: var(--common-speaker-on) no-repeat center / 100% 100%;
1101
+ }
1102
+ }
1103
+
1104
+ .speaker-off {
1105
+ .icon {
1106
+ background: var(--common-speaker-off) no-repeat center / 100% 100%;
1107
+ }
1108
+ }
1109
+
1110
+ .screen-share {
1111
+ .icon {
1112
+ background: var(--common-share-icon) no-repeat center / 100% 100%;
1113
+ }
1114
+ }
1115
+
1116
+ .preview {
1117
+ .icon {
1118
+ background: var(--common-preview-meet-icon) no-repeat center / 100% 100%;
1119
+ }
1120
+ }
1121
+
1122
+ .cancel {
1123
+ .icon {
1124
+ width: 22px;
1125
+ height: 22px;
1126
+ background: var(--common-cancel-icon) no-repeat center / 100% 100%;
1127
+ }
1128
+ }
1129
+ }
1130
+ }
1131
+ </style>
1132
+ <style lang="scss">
1133
+ @import "./style/index.scss";
1134
+ </style>