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,449 @@
1
+ <template>
2
+ <div
3
+ class="minium-video-dialog"
4
+ id="minium-video-dialog"
5
+ ref="dialogRef"
6
+ :style="{ resize: isResizeable ? 'both' : 'none' }"
7
+ @mouseenter="handleMouseEnter"
8
+ @mousemove="handleMouseMove"
9
+ >
10
+ <div class="minium-video-dialog-content" v-drag="'minium-video-dialog'">
11
+ <div class="video-content" v-show="isExpand">
12
+ <video class="cur-speaker-video" id="video-contain" muted></video>
13
+ <div class="describe" v-if="curSpeaker && curSpeaker.name">
14
+ <div
15
+ :class="[
16
+ 'microphone',
17
+ curSpeakerMicrophoneStatus ? 'microphone-active' : 'microphone-inactive',
18
+ ]"
19
+ ></div>
20
+ <div class="identity">{{ curSpeaker.name }}</div>
21
+ </div>
22
+ </div>
23
+ <div class="speaking-wrapper" v-show="!isExpand">
24
+ <div :class="['cur-speaking-mic', curSpeakerMicrophoneStatus ? 'mic-on' : 'mic-off']"></div>
25
+ <div class="cur-speaking">
26
+ <div class="cur-speaking-title">正在讲话:</div>
27
+ <div class="cur-speaking-list">{{ speakersName }}</div>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ <div
32
+ :class="['minium-video-dialog-footer', {'show-footer': showFooter}]"
33
+ v-drag="'minium-video-dialog'"
34
+ >
35
+ <div class="minium-video-dialog-footer-btn mic-on" v-if="localMicrophoneStatus" @click="changeLocalMicrophoneStatus"></div>
36
+ <div class="minium-video-dialog-footer-btn mic-off" v-else @click="changeLocalMicrophoneStatus"></div>
37
+ <div class="minium-video-dialog-footer-btn camera-on" v-if="localCameraStatus" @click="changeLocalCameraStatus"></div>
38
+ <div class="minium-video-dialog-footer-btn camera-off" v-else @click="changeLocalCameraStatus"></div>
39
+ <div class="minium-video-dialog-footer-btn reset" @click="reset"></div>
40
+ <div :class="['minium-video-dialog-footer-btn', isExpand ? 'slide' : 'expand']" @click="changeExpand"></div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script>
46
+ export default {
47
+ name: 'MiniumVideoDialog',
48
+ props: {
49
+ isResizeable: {
50
+ type: Boolean,
51
+ default: true,
52
+ },
53
+ trackData: {
54
+ type: Object,
55
+ },
56
+ },
57
+ data() {
58
+ return {
59
+ isExpand: true,
60
+ curSpeakers: [],
61
+ curSpeaker: null,
62
+ localCameraStatus: false,
63
+ localMicrophoneStatus: false,
64
+ curSpeakerMicrophoneStatus: false,
65
+ curSpeakerCameraStatus: false,
66
+ curSpeakerTrack: null,
67
+ showFooter: false,
68
+ footerTimer: null,
69
+ };
70
+ },
71
+ computed: {
72
+ speakersName() {
73
+ if (this.curSpeakers.length > 0) {
74
+ return this.curSpeakers.map((item) => item.name).join(",");
75
+ }
76
+ return "";
77
+ },
78
+ },
79
+ mounted() {
80
+ this.$nextTick(() => {
81
+ this.setInitialPosition();
82
+ });
83
+ this.initLiveClient();
84
+ },
85
+ beforeDestroy() {
86
+ this.clearFooterTimer();
87
+ this.dispatchLiveClientEvent();
88
+ },
89
+ methods: {
90
+ changeExpand() {
91
+ const dialog = document.getElementById('minium-video-dialog');
92
+ if (!dialog) {
93
+ this.isExpand = !this.isExpand;
94
+ return;
95
+ }
96
+
97
+ // 记录当前状态和高度
98
+ const wasExpanded = this.isExpand;
99
+ const currentHeight = dialog.offsetHeight;
100
+
101
+ // 切换状态
102
+ this.isExpand = !this.isExpand;
103
+
104
+ // 等待DOM更新后调整位置
105
+ this.$nextTick(() => {
106
+ const newHeight = dialog.offsetHeight;
107
+ const heightDifference = currentHeight - newHeight;
108
+
109
+ // 获取当前的transform值
110
+ const currentTransform = dialog.style.transform;
111
+
112
+ if (currentTransform) {
113
+ // 解析当前的translate值
114
+ const transformMatch = currentTransform.match(/translate\(([^,]+),\s*([^)]+)\)/);
115
+ if (transformMatch) {
116
+ const currentX = parseFloat(transformMatch[1]);
117
+ const currentY = parseFloat(transformMatch[2]);
118
+
119
+ // 调整Y位置以保持底部对齐
120
+ const newY = currentY + heightDifference;
121
+
122
+ // 确保不会超出屏幕顶部
123
+ const finalY = Math.max(20, newY);
124
+
125
+ // 设置新的transform值
126
+ dialog.style.transform = `translate(${currentX}px, ${finalY}px)`;
127
+ }
128
+ }
129
+ });
130
+ },
131
+
132
+ // 初始化liveClient
133
+ initLiveClient() {
134
+ const liveClient = window['liveClient'];
135
+ if(!liveClient) {
136
+ return;
137
+ }
138
+ this.curSpeaker = {
139
+ identity: liveClient.room.localParticipant.identity,
140
+ name: liveClient.room.localParticipant.name,
141
+ };
142
+ this.localCameraStatus = liveClient.room.localParticipant.isCameraEnabled;
143
+ this.localMicrophoneStatus = liveClient.room.localParticipant.isMicrophoneEnabled;
144
+ this.curSpeakerMicrophoneStatus = liveClient.room.localParticipant.isMicrophoneEnabled;
145
+ this.curSpeakerCameraStatus = liveClient.room.localParticipant.isCameraEnabled;
146
+ this.curSpeakerTrack = this.trackData.videoTrack;
147
+ // 初始化视频轨道绑定
148
+ this.initVideoAttach();
149
+ // 监听并处理liveclient事件
150
+ this.initLiveClientEvent();
151
+ },
152
+
153
+ // 设置初始位置
154
+ setInitialPosition() {
155
+ const dialog = document.getElementById('minium-video-dialog');
156
+ if (dialog) {
157
+ const windowWidth = window.innerWidth;
158
+ const windowHeight = window.innerHeight;
159
+ const dialogWidth = dialog.offsetWidth;
160
+ const dialogHeight = dialog.offsetHeight;
161
+
162
+ // 计算右上角位置,保留20px边距
163
+ const rightPosition = windowWidth - dialogWidth - 20;
164
+ const topPosition = 20;
165
+
166
+ // 设置transform属性
167
+ dialog.style.transform = `translate(${rightPosition}px, ${topPosition}px)`;
168
+ }
169
+ },
170
+
171
+ // 重置位置
172
+ resetPosition() {
173
+ this.setInitialPosition();
174
+ },
175
+
176
+ // 鼠标移入事件处理
177
+ handleMouseEnter() {
178
+ this.showFooter = true;
179
+ this.resetFooterTimer();
180
+ },
181
+
182
+ // 鼠标移动事件处理
183
+ handleMouseMove() {
184
+ this.showFooter = true;
185
+ this.resetFooterTimer();
186
+ },
187
+
188
+ // 重置footer定时器
189
+ resetFooterTimer() {
190
+ this.clearFooterTimer();
191
+ this.footerTimer = setTimeout(() => {
192
+ this.showFooter = false;
193
+ }, 2000);
194
+ },
195
+
196
+ initVideoAttach() {
197
+ if(this.curSpeakerTrack) {
198
+ const videoElm = document.getElementById('video-contain');
199
+ videoElm && this.curSpeakerTrack.attach(videoElm);
200
+ }
201
+ },
202
+
203
+ initLiveClientEvent() {
204
+ const liveClient = window['liveClient'];
205
+ if(!liveClient) {
206
+ return;
207
+ }
208
+ liveClient.on("localCameraChange", this.handleLocalCameraChange);
209
+ liveClient.on("localMicrophoneChange", this.handleLocalMicrophoneChange);
210
+ liveClient.on("activeSpeakerChange", this.handleActiveSpeakerChange);
211
+ liveClient.on("videoCallRender", this.handleVideoCallRender);
212
+ liveClient.on("roomDisconnected", this.handleRoomDisconnected);
213
+ },
214
+
215
+ handleLocalCameraChange(e) {
216
+ this.localCameraStatus = e;
217
+ },
218
+
219
+ handleLocalMicrophoneChange(e) {
220
+ this.localMicrophoneStatus = e;
221
+ },
222
+
223
+ handleActiveSpeakerChange(e) {
224
+ if (e.length > 0) {
225
+ let maxAudioLevel = 0;
226
+ let maxAudioLevelIndex = -1;
227
+ e.forEach((speaker, index) => {
228
+ if (speaker.audioLevel > maxAudioLevel) {
229
+ maxAudioLevel = speaker.audioLevel;
230
+ maxAudioLevelIndex = index;
231
+ }
232
+ });
233
+ if (maxAudioLevelIndex >= 0) {
234
+ this.curSpeaker = e[maxAudioLevelIndex];
235
+ }
236
+ this.curSpeakers = e;
237
+ }
238
+ },
239
+
240
+ handleVideoCallRender(e) {
241
+ if(e.local) {
242
+ this.localCameraStatus = e.isCameraEnabled;
243
+ this.localMicrophoneStatus = e.isMicrophoneEnabled;
244
+ }
245
+ if(e.identity === this.curSpeaker?.identity) {
246
+ this.curSpeakerCameraStatus = e.isCameraEnabled;
247
+ this.curSpeakerMicrophoneStatus = e.isMicrophoneEnabled;
248
+ if(e?.videoTrack) {
249
+ this.curSpeakerTrack = e.videoTrack;
250
+ }
251
+ }
252
+ },
253
+
254
+ handleRoomDisconnected() {
255
+ this.$emit('miniVideoDialogClose');
256
+ },
257
+
258
+ reset() {
259
+ this.$emit('resetMultiDialog');
260
+ },
261
+
262
+ dispatchLiveClientEvent() {
263
+ const liveClient = window['liveClient'];
264
+ if(liveClient) {
265
+ liveClient.off("localCameraChange", this.handleLocalCameraChange);
266
+ liveClient.off("localMicrophoneChange", this.handleLocalMicrophoneChange);
267
+ liveClient.off("activeSpeakerChange", this.handleActiveSpeakerChange);
268
+ liveClient.off("videoCallRender", this.handleVideoCallRender);
269
+ liveClient.off("roomDisconnected", this.handleRoomDisconnected);
270
+ }
271
+ },
272
+
273
+ async changeLocalMicrophoneStatus() {
274
+ const liveClient = window['liveClient'];
275
+ if(liveClient) {
276
+ await liveClient.changeMicrophoneStatus();
277
+ }
278
+ },
279
+
280
+ async changeLocalCameraStatus() {
281
+ const liveClient = window['liveClient'];
282
+ if(liveClient) {
283
+ await liveClient.changeCameraStatus();
284
+ }
285
+ },
286
+
287
+ clearFooterTimer() {
288
+ if (this.footerTimer) {
289
+ clearTimeout(this.footerTimer);
290
+ this.footerTimer = null;
291
+ }
292
+ },
293
+ },
294
+ }
295
+ </script>
296
+
297
+ <style lang="scss" scoped>
298
+ .minium-video-dialog {
299
+ width: 320px;
300
+ height: fit-content;
301
+ position: fixed;
302
+ top: 0;
303
+ left: 0;
304
+ z-index: 2001;
305
+ background: var(--dialog-bg);
306
+ border-radius: 4px;
307
+ overflow: hidden;
308
+ transform: translate(0, 0);
309
+ &-content {
310
+ min-height: 40px;
311
+ height: auto;
312
+ position: relative;
313
+ .video-content {
314
+ position: relative;
315
+ .cur-speaker-video {
316
+ width: 100%;
317
+ height: 190px;
318
+ border-radius: 4px;
319
+ object-fit: contain;
320
+ }
321
+ .describe {
322
+ position: absolute;
323
+ bottom: 6px;
324
+ left: 6px;
325
+ z-index: 50;
326
+ height: 24px;
327
+ display: flex;
328
+ align-items: center;
329
+ flex-wrap: nowrap;
330
+ padding: 0 10px;
331
+ background: var(--call-audio-text-bg);
332
+ border-radius: 4px;
333
+ .microphone {
334
+ width: 11px;
335
+ height: 16px;
336
+ cursor: pointer;
337
+ margin-right: 6px;
338
+ &-active {
339
+ background: url("@/assets/image/common/call_user_mic_on_icon.png") no-repeat center /
340
+ 100% 100%;
341
+ }
342
+ &-inactive {
343
+ background: url("@/assets/image/common/call_user_mic_off_icon.png") no-repeat center /
344
+ 100% 100%;
345
+ }
346
+ }
347
+ .identity {
348
+ white-space: nowrap;
349
+ font-weight: 400;
350
+ font-size: 14px;
351
+ color: var(--theme-font-color);
352
+ }
353
+ }
354
+ }
355
+ .speaking-wrapper {
356
+ height: 40px;
357
+ display: flex;
358
+ flex-wrap: nowrap;
359
+ align-items: center;
360
+ padding: 0 10px;
361
+ .cur-speaking-mic {
362
+ width: 11px;
363
+ height: 16px;
364
+ margin-right: 20px;
365
+ flex: 1 0;
366
+ &.mic-on {
367
+ background: url("@/assets/image/common/call_user_mic_on_icon.png") no-repeat center /
368
+ 100% 100%;
369
+ }
370
+ &.mic-off {
371
+ background: url("@/assets/image/common/call_user_mic_off_icon.png") no-repeat center /
372
+ 100% 100%;
373
+ }
374
+ }
375
+ .cur-speaking {
376
+ width: calc(100% - 11px - 20px);
377
+ color: var(--theme-font-color);
378
+ font-size: 14px;
379
+ font-weight: 400;
380
+ display: flex;
381
+ align-items: center;
382
+ flex-wrap: nowrap;
383
+ &-title {
384
+ width: fit-content;
385
+ white-space: nowrap;
386
+ flex: 0 0;
387
+ }
388
+ &-list {
389
+ flex: 1 0;
390
+ white-space: nowrap;
391
+ overflow: hidden;
392
+ text-overflow: ellipsis;
393
+ }
394
+ }
395
+ }
396
+ }
397
+ &-footer {
398
+ position: absolute;
399
+ z-index: 100;
400
+ bottom: -40px; /* 默认隐藏在底部外 */
401
+ left: 0;
402
+ width: 100%;
403
+ height: 40px;
404
+ display: flex;
405
+ align-items: center;
406
+ transition: bottom 0.3s ease-in-out;
407
+ justify-content: space-evenly;
408
+ background: rgba(0,0,0,0.4);
409
+
410
+ &.show-footer {
411
+ bottom: 0; /* 显示时滑入 */
412
+ }
413
+
414
+ &-btn {
415
+ width: 32px;
416
+ height: 32px;
417
+ cursor: pointer;
418
+ &.mic-on {
419
+ background: url("@/assets/image/common/minum_mic_on_icon.png") no-repeat center /
420
+ 100% 100%;
421
+ }
422
+ &.mic-off {
423
+ background: url("@/assets/image/common/minum_mic_off_icon.png") no-repeat center /
424
+ 100% 100%;
425
+ }
426
+ &.camera-on {
427
+ background: url("@/assets/image/common/minum_cam_on_icon.png") no-repeat center /
428
+ 100% 100%;
429
+ }
430
+ &.camera-off {
431
+ background: url("@/assets/image/common/minum_cam_off_icon.png") no-repeat center /
432
+ 100% 100%;
433
+ }
434
+ &.reset {
435
+ background: url("@/assets/image/common/minum_reset_icon.png") no-repeat center /
436
+ 100% 100%;
437
+ }
438
+ &.expand {
439
+ background: url("@/assets/image/common/minum_expand_icon.png") no-repeat center /
440
+ 100% 100%;
441
+ }
442
+ &.slide {
443
+ background: url("@/assets/image/common/minum_slide_icon.png") no-repeat center /
444
+ 100% 100%;
445
+ }
446
+ }
447
+ }
448
+ }
449
+ </style>
@@ -0,0 +1,184 @@
1
+ <template>
2
+ <div
3
+ class="layout-placeholder"
4
+ :class="{
5
+ 'has-member': !!member,
6
+ 'is-hover': isHover
7
+ }"
8
+ :style="gridAreaStyle"
9
+ >
10
+ <!-- 占位符状态 -->
11
+ <div v-if="!member" class="placeholder-empty"></div>
12
+
13
+ <!-- 成员状态 -->
14
+ <div v-else class="placeholder-member">
15
+ <!-- 关闭按钮 - 右上角 -->
16
+ <div class="close-btn" @click="handleClose">
17
+ <div class="close-icon"></div>
18
+ </div>
19
+
20
+ <!-- 成员头像 - 中间 -->
21
+ <div class="member-avatar">
22
+ </div>
23
+
24
+ <!-- 成员名称 - 左下角 -->
25
+ <div class="member-name">{{ member.name }}</div>
26
+ </div>
27
+ </div>
28
+ </template>
29
+
30
+ <script>
31
+ export default {
32
+ name: "LayoutPlaceholder",
33
+ props: {
34
+ index: {
35
+ type: Number,
36
+ required: true
37
+ },
38
+ member: {
39
+ type: Object,
40
+ default: null
41
+ },
42
+ layoutType: {
43
+ type: String,
44
+ default: 'grid4'
45
+ },
46
+ isHover: {
47
+ type: Boolean,
48
+ default: false
49
+ }
50
+ },
51
+ computed: {
52
+ gridAreaStyle() {
53
+ if (this.layoutType === 'ring') {
54
+ const areaMap = {
55
+ 1: 'main',
56
+ 2: 'slot1',
57
+ 3: 'slot2',
58
+ 4: 'slot3',
59
+ 5: 'slot4',
60
+ 6: 'slot5',
61
+ 7: 'slot6',
62
+ 8: 'slot7'
63
+ };
64
+ return {
65
+ gridArea: areaMap[this.index]
66
+ };
67
+ } else if (this.layoutType === 'topSide') {
68
+ const areaMap = {
69
+ 1: 'main', // 下方焦点位置
70
+ 2: 'slot2', // 上排左侧
71
+ 3: 'slot3', // 上排中间
72
+ 4: 'slot4' // 上排右侧
73
+ };
74
+ return {
75
+ gridArea: areaMap[this.index]
76
+ };
77
+ } else if (this.layoutType === 'rightSide') {
78
+ const areaMap = {
79
+ 1: 'main', // 左侧焦点位置
80
+ 2: 'slot2', // 右侧上方
81
+ 3: 'slot3', // 右侧中间
82
+ 4: 'slot4' // 右侧下方
83
+ };
84
+ return {
85
+ gridArea: areaMap[this.index]
86
+ };
87
+ }
88
+ return {};
89
+ }
90
+ },
91
+ methods: {
92
+ handleClose() {
93
+ this.$emit('clear');
94
+ }
95
+ }
96
+ };
97
+ </script>
98
+
99
+ <style lang="scss" scoped>
100
+ .layout-placeholder {
101
+ width: 100%;
102
+ height: 100%;
103
+ border-radius: 4px;
104
+ position: relative;
105
+ overflow: hidden;
106
+ transition: all 0.2s ease;
107
+
108
+ &.is-hover {
109
+ border: 2px dashed var(--theme-color);
110
+ background: rgba(1, 132, 255, 0.15);
111
+ transform: scale(1.02);
112
+ box-shadow: 0 2px 8px rgba(1, 132, 255, 0.3);
113
+ }
114
+
115
+ .placeholder-empty {
116
+ width: 100%;
117
+ height: 100%;
118
+ background: var(--custom-layout-placeholder-bg) no-repeat center / cover;
119
+ border-radius: 4px;
120
+ }
121
+
122
+ .placeholder-member {
123
+ width: 100%;
124
+ height: 100%;
125
+ background: var(--custom-layout-placeholder-bg) no-repeat center / cover;
126
+ border-radius: 4px;
127
+ position: relative;
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+
132
+ .close-btn {
133
+ position: absolute;
134
+ top: 8px;
135
+ right: 8px;
136
+ width: 20px;
137
+ height: 20px;
138
+ background: rgba(0, 0, 0, 0.5);
139
+ border-radius: 50%;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ cursor: pointer;
144
+ z-index: 10;
145
+ transition: background 0.2s ease;
146
+
147
+ &:hover {
148
+ background: rgba(0, 0, 0, 0.7);
149
+ }
150
+
151
+ .close-icon {
152
+ width: 10px;
153
+ height: 10px;
154
+ background: var(--close-icon) no-repeat center / contain;
155
+ }
156
+ }
157
+
158
+ .member-avatar {
159
+ width: auto;
160
+ height: 30%;
161
+ aspect-ratio: 1/1;
162
+ background: var(--custom-layout-user-avatar) no-repeat center / cover;
163
+ border-radius: 50%;
164
+ }
165
+
166
+ .member-name {
167
+ position: absolute;
168
+ bottom: 8px;
169
+ left: 8px;
170
+ color: var(--theme-font-color);
171
+ font-size: 12px;
172
+ font-weight: 400;
173
+ font-family: var(--main-font);
174
+ background: var(--custom-layout-des-bg);
175
+ padding: 2px 6px;
176
+ border-radius: 4px;
177
+ max-width: calc(100% - 16px);
178
+ white-space: nowrap;
179
+ overflow: hidden;
180
+ text-overflow: ellipsis;
181
+ }
182
+ }
183
+ }
184
+ </style>