memberList.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <div class="layer member-list" v-if="show" @click.self="closeMember">
  3. <div class="memberContent animated" :class="animateActive ? 'fadeInUpBig' : 'fadeOutDownBig'">
  4. <div class="blurBox"></div>
  5. <div class="content">
  6. <div class="memberHeader">
  7. <span> {{ t('base.memberManager') }} ({{ data?.length }})</span>
  8. <i class="iconfont"></i>
  9. </div>
  10. <div class="memberList">
  11. <div
  12. class="memberItem"
  13. v-for="(i, idx) in data"
  14. :key="idx"
  15. :class="i.IsOnline ? 'online' : 'offline'"
  16. >
  17. <div class="userMsg">
  18. <div class="avatar" :class="`${role}`">
  19. <!-- 头像会存在一次到两次encodeURIComponent -->
  20. <img
  21. :src="
  22. i?.Avatar?.length
  23. ? decodeURIComponent(decodeURIComponent(i?.Avatar))
  24. : defaultAvatar
  25. "
  26. alt=""
  27. />
  28. <div class="avatar-crown" v-show="i.Role === 'leader'"></div>
  29. <div
  30. class="avatar-crown-assistant"
  31. v-show="i.Role !== 'leader' && i.IsAssistant"
  32. ></div>
  33. </div>
  34. <div class="name">{{ i.Nickname }}</div>
  35. </div>
  36. <div class="button">
  37. <!-- T人 -->
  38. <!-- <div class="micBtn remove" @click="isNativeLeader && userCanKick(i)"></div> -->
  39. <div
  40. class="micBtn"
  41. v-if="i?.Role !== 'leader'"
  42. :class="i.IsWords ? 'ban_speak_on' : 'ban_speak_off'"
  43. :wo="i.IsWords"
  44. @click="isLeaderOrAssistant && userCanInput(i)"
  45. ></div>
  46. <ImageIcon
  47. class="assistant_icon"
  48. v-if="isNativeLeader && i.Role !== 'leader'"
  49. type="assistants"
  50. @click="(isNativeLeader || i.IsAssistant) && userCanBeAssistant(i)"
  51. />
  52. <ImageIcon
  53. class="kick_icon"
  54. v-if="isLeaderOrAssistant && i?.Role !== 'leader'"
  55. type="kick_user"
  56. @click="isLeaderOrAssistant && userCanKick(i)"
  57. />
  58. <!-- mic -->
  59. <div
  60. class="micBtn"
  61. :class="i.IsMuted ? 'mute_one_mic_off' : 'mute_one_mic_on'"
  62. @click="isLeaderOrAssistant && userCanSpeak(i)"
  63. ></div>
  64. <!-- mic -->
  65. <!-- <div
  66. class="micBtn"
  67. :class="i.IsMuted ? 'mute_one_mic_off' : 'mute_one_mic_on'"
  68. @click="onMemberMuted(i)"
  69. ></div> -->
  70. </div>
  71. </div>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </template>
  77. <script lang="ts" setup>
  78. import { propTypes } from '/@/utils/propTypes';
  79. import { UserInfoType, useRtcStore } from '/@/store/modules/rtc';
  80. import defaultAvatar from '/@/assets/images/rtcLive/avatar_small@2x.png';
  81. import { computed, watchEffect } from 'vue';
  82. import { useSocket } from '/@/hooks/userSocket';
  83. import { useI18n } from '/@/hooks/useI18n';
  84. import ImageIcon from '/@/components/basic/icon/index.vue';
  85. import { useMiniApp } from '/@/hooks/useMiniApp';
  86. import { useRtcSdk } from '/@/hooks/useTRTC';
  87. // import Dialog from '../basic/dialog';
  88. const rtcStore = useRtcStore();
  89. const { t } = useI18n();
  90. const role = computed(() => rtcStore.role);
  91. const currentUserId = computed(() => rtcStore.userId);
  92. const isLeaderOrAssistant = computed(() => rtcStore.isLeader || rtcStore.isAssistant);
  93. const isNativeLeader = computed(() => rtcStore.isLeader);
  94. // const isAssistant = computed(() => rtcStore.isAssistant);
  95. // const animateActive = ref(false);
  96. // const props =
  97. defineProps({
  98. show: propTypes.bool.def(false),
  99. animateActive: propTypes.bool.def(false),
  100. data: {
  101. type: Array as PropType<UserInfoType[]>,
  102. default: () => [],
  103. },
  104. currentListUser: {
  105. type: Object as PropType<UserInfoType>,
  106. default: () => {},
  107. },
  108. });
  109. watchEffect(() => {
  110. // console.log('memberList', props.data);
  111. });
  112. // watch(
  113. // () => props.data,
  114. // (val) => {
  115. // if (val.length > 3 && unref(role) == 'customer') {
  116. // Dialog.toast({ content: `房间已满员` });
  117. // const { closeSocket } = useSocket();
  118. // closeSocket();
  119. // }
  120. // },
  121. // { deep: true },
  122. // );
  123. const emit = defineEmits(['openMember', 'closeMember']);
  124. function closeMember(): void {
  125. emit('closeMember');
  126. }
  127. function userCanInput(member: UserInfoType) {
  128. const { socket } = useSocket();
  129. member.IsWords = !member.IsWords;
  130. socket.emit('action', {
  131. type: 'users-words',
  132. words: member.IsWords,
  133. userId: member.UserId,
  134. });
  135. }
  136. function userCanKick(member: UserInfoType) {
  137. const { socket } = useSocket();
  138. // member.IsWords = !member.IsWords;
  139. socket.emit('action', {
  140. type: 'users-kicked',
  141. userId: member.UserId,
  142. });
  143. }
  144. function userCanBeAssistant(member: UserInfoType) {
  145. const { socket } = useSocket();
  146. member.IsAssistant = !member.IsAssistant;
  147. socket.emit('action', {
  148. type: 'set-assistant',
  149. userId: member.UserId,
  150. status: member.IsAssistant,
  151. });
  152. }
  153. function userCanSpeak(member: UserInfoType) {
  154. const { socket } = useSocket();
  155. const { isUsingMiniApp } = useMiniApp();
  156. const { unMutedAudio, mutedAudio } = useRtcSdk();
  157. member.IsMuted = !member.IsMuted;
  158. socket.emit('action', {
  159. type: 'users-muted',
  160. muted: member.IsMuted,
  161. userId: member.UserId,
  162. });
  163. if (member.UserId === currentUserId.value) {
  164. if (!isUsingMiniApp.value) {
  165. console.warn('H5-主持人-操作MIC');
  166. if (member.IsMuted) {
  167. mutedAudio();
  168. } else {
  169. unMutedAudio();
  170. }
  171. }
  172. }
  173. }
  174. </script>
  175. <style lang="scss">
  176. @import './chatroom.scss';
  177. @media screen and (min-width: 768px) {
  178. .member-list {
  179. max-width: 11rem;
  180. width: 11rem;
  181. margin: 0 auto;
  182. transform: translate(-50%, 0);
  183. background: none !important;
  184. left: 50% !important;
  185. }
  186. }
  187. </style>