shuisheng 1 år sedan
förälder
incheckning
9b3d7c7fd9

BIN
src/assets/img/default-avatar.png


BIN
src/assets/img/lazy_error.png


BIN
src/assets/img/lazy_error.webp


BIN
src/assets/img/lazy_loading.png


BIN
src/assets/img/lazy_loading.webp


+ 14 - 7
src/components/Avatar/index.vue

@@ -5,9 +5,13 @@
   >
     <div class="cycle-wrap">
       <div
+        v-if="url && url !== ''"
         class="avatar"
-        :class="{ border }"
-        v-lazy:background-image="avatar"
+        v-lazy:background-image="url"
+      ></div>
+      <div
+        class="avatar default"
+        v-else
       ></div>
       <template v-if="living && !disableLiving">
         <div class="cycle cycle-1"></div>
@@ -22,17 +26,17 @@
 <script lang="ts" setup>
 withDefaults(
   defineProps<{
-    avatar?: string;
+    url?: string;
+    name?: string;
     size: number;
     living?: boolean;
-    border?: boolean;
     disableLiving?: boolean;
   }>(),
   {
-    avatar: '',
+    url: '',
+    name: '',
     size: 100,
     living: false,
-    border: false,
     disableLiving: false,
   }
 );
@@ -65,8 +69,11 @@ withDefaults(
       cursor: pointer;
 
       @extend %coverBg;
-      &.border {
+      &.default {
+        background-color: white;
         border: 1px solid $theme-color-gold;
+        background-image: url('@/assets/img/default-avatar.png');
+        background-size: 70% !important;
       }
     }
     .cycle {

+ 3 - 3
src/hooks/use-pull.ts

@@ -285,7 +285,7 @@ export function usePull() {
 
   async function handleWebRtcMeetingOnePlay(data) {
     await handleMeeting();
-    console.log('handleWebRtcLivePlay');
+    console.log('handleWebRtcMeetingOnePlay');
     handleStopDrawing();
     videoLoading.value = true;
     appStore.liveLine = LiveLineEnum.rtc;
@@ -378,6 +378,7 @@ export function usePull() {
 
   function handleHlsPlay() {
     console.log('handleHlsPlay', hlsurl.value);
+    destroyFlv();
     handleStopDrawing();
     videoLoading.value = true;
     appStore.liveLine = LiveLineEnum.hls;
@@ -388,6 +389,7 @@ export function usePull() {
 
   function handleFlvPlay() {
     console.log('handleFlvPlay', flvurl.value);
+    destroyHls();
     handleStopDrawing();
     videoLoading.value = true;
     appStore.liveLine = LiveLineEnum.flv;
@@ -486,8 +488,6 @@ export function usePull() {
     (newVal) => {
       console.log('liveLine变了', newVal);
       handleStopDrawing();
-      destroyFlv();
-      destroyHls();
       remoteStream.value = [];
       if (!roomLiving.value) {
         return;

+ 2 - 0
src/hooks/use-push.ts

@@ -30,6 +30,7 @@ export function usePush() {
   const msgIsFile = ref<WsMessageIsFileEnum>(WsMessageIsFileEnum.no);
 
   const {
+    keepRtcLivingTimer,
     roomLiving,
     initWs,
     handleStartLive,
@@ -243,6 +244,7 @@ export function usePush() {
     roomLiving.value = false;
     localStream.value = undefined;
     closeRtc();
+    clearInterval(keepRtcLivingTimer.value);
   }
 
   function sendRoomNoLive() {

+ 51 - 23
src/hooks/use-websocket.ts

@@ -31,7 +31,6 @@ import { useUserStore } from '@/store/user';
 import { LiveRoomTypeEnum } from '@/types/ILiveRoom';
 import { IUser } from '@/types/IUser';
 import {
-  WSLivePkKeyType,
   WsAnswerType,
   WsBatchSendOffer,
   WsCandidateType,
@@ -39,13 +38,13 @@ import {
   WsDisableSpeakingType,
   WsJoinType,
   WsLeavedType,
+  WsLivePkKeyType,
   WsMessageType,
   WsMsgTypeEnum,
   WsOfferType,
   WsOtherJoinType,
   WsRoomLivingType,
   WsStartLiveType,
-  WsUpdateJoinInfoType,
 } from '@/types/websocket';
 import {
   createNullVideo,
@@ -100,32 +99,30 @@ export const useWebsocket = () => {
   const currentVideoContentHint = ref(videoContentHint.value[3].value);
   const currentAudioContentHint = ref(audioContentHint.value[0].value);
   const timerObj = ref({});
+  const keepRtcLivingTimer = ref();
   const damuList = ref<IWsMessage[]>([]);
   const joinedDelay = 5000;
-
-  onUnmounted(() => {
-    clearInterval(loopHeartbeatTimer.value);
-    clearInterval(loopGetLiveUserTimer.value);
-  });
+  const keepRtcLivingDelay = 5000;
 
   watch(
-    [() => userStore.userInfo?.id, () => connectStatus.value],
-    ([userInfo, status]) => {
-      if (userInfo && status === WsConnectStatusEnum.connect) {
-        const ws = networkStore.wsMap.get(roomId.value);
-        if (!ws) return;
-        ws.send<WsUpdateJoinInfoType['data']>({
-          requestId: getRandomString(8),
-          msgType: WsMsgTypeEnum.updateJoinInfo,
-          data: {
-            live_room_id: Number(roomId.value),
-          },
-        });
+    () => roomLiving.value,
+    (newval) => {
+      if (newval) {
+        appStore.playing = true;
+      } else {
+        appStore.playing = false;
       }
     },
-    { immediate: true }
+    {
+      immediate: true,
+    }
   );
 
+  onUnmounted(() => {
+    clearInterval(loopHeartbeatTimer.value);
+    clearInterval(loopGetLiveUserTimer.value);
+  });
+
   const mySocketId = computed(() => {
     return networkStore.wsMap.get(roomId.value)?.socketIo?.id || '-1';
   });
@@ -364,6 +361,31 @@ export const useWebsocket = () => {
         sender: mySocketId.value,
         receiver: 'tencentcloud_css',
       });
+    } else if (
+      [
+        LiveRoomTypeEnum.wertc_live,
+        LiveRoomTypeEnum.wertc_meeting_one,
+        LiveRoomTypeEnum.wertc_meeting_two,
+      ].includes(type)
+    ) {
+      const main = () => {
+        networkStore.wsMap.get(roomId.value)?.send<WsJoinType['data']>({
+          requestId: getRandomString(8),
+          msgType: WsMsgTypeEnum.keepRtcLiving,
+          data: {
+            live_room_id: Number(roomId.value),
+            duration: keepRtcLivingDelay / 1000,
+          },
+        });
+      };
+      main();
+      keepRtcLivingTimer.value = setInterval(() => {
+        if (!roomLiving.value) {
+          clearInterval(keepRtcLivingTimer.value);
+          return;
+        }
+        main();
+      }, keepRtcLivingDelay);
     }
   }
 
@@ -404,7 +426,7 @@ export const useWebsocket = () => {
     });
 
     // 收到livePkKey
-    ws.socketIo.on(WsMsgTypeEnum.livePkKey, (data: WSLivePkKeyType['data']) => {
+    ws.socketIo.on(WsMsgTypeEnum.livePkKey, (data: WsLivePkKeyType['data']) => {
       console.log('收到livePkKey', data);
       const url = router.resolve({
         name: routerName.pull,
@@ -547,14 +569,19 @@ export const useWebsocket = () => {
       async (data: WsRoomLivingType['data']) => {
         prettierReceiveWsMsg(WsMsgTypeEnum.roomLiving, data);
         roomLiving.value = true;
+        if (data.live_room_id !== Number(roomId.value)) {
+          return;
+        }
         if (
           route.name === routerName.pull ||
           route.name === routerName.h5Room
         ) {
           // 当前是拉流页面
-          if (data.live_room?.type === LiveRoomTypeEnum.wertc_meeting_one) {
+          if (
+            appStore.liveRoomInfo?.type === LiveRoomTypeEnum.wertc_meeting_one
+          ) {
             await handleMeeting();
-          } else if (data.live_room?.type === LiveRoomTypeEnum.pk) {
+          } else if (appStore.liveRoomInfo?.type === LiveRoomTypeEnum.pk) {
             await handlePk();
           }
         } else if (route.name === routerName.push) {
@@ -942,6 +969,7 @@ export const useWebsocket = () => {
     sendDanmuTxt,
     sendDanmuImg,
     sendDanmuReward,
+    keepRtcLivingTimer,
     isBilibili,
     connectStatus,
     mySocketId,

+ 5 - 18
src/layout/pc/head/index.vue

@@ -348,10 +348,11 @@
           class="qqlogin"
         >
           <template #btn>
-            <div
-              class="btn"
-              v-lazy:background-image="userStore.userInfo.avatar"
-            ></div>
+            <Avatar
+              :url="userStore.userInfo.avatar"
+              :name="userStore.userInfo.username"
+              :size="35"
+            ></Avatar>
           </template>
           <template #list>
             <div class="list">
@@ -981,20 +982,6 @@ function handleWebsiteJump() {
       .qqlogin {
         margin-right: 20px;
 
-        .btn {
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          box-sizing: border-box;
-          width: 35px;
-          height: 35px;
-          border-radius: 50%;
-          background-color: papayawhip;
-          font-size: 12px;
-          cursor: pointer;
-
-          @extend %containBg;
-        }
         .list {
           padding: 10px 0;
           width: 90px;

+ 4 - 4
src/main.ts

@@ -6,8 +6,8 @@ import 'webrtc-adapter';
 import { createApp } from 'vue';
 import VueLazyLoad from 'vue-lazyload';
 
-import lazyErrorWebp from '@/assets/img/lazy_error.webp';
-import lazyLoadingWebp from '@/assets/img/lazy_loading.webp';
+import lazyErrorPng from '@/assets/img/lazy_error.png';
+import lazyLoadingPng from '@/assets/img/lazy_loading.png';
 import Message from '@/components/Message/index.vue';
 import registerDirectives from '@/directives';
 import { i18n } from '@/hooks/use-i18n';
@@ -23,8 +23,8 @@ app.use(store);
 app.use(router);
 app.use(VueLazyLoad, {
   preLoad: 1,
-  error: lazyErrorWebp,
-  loading: lazyLoadingWebp,
+  error: lazyErrorPng,
+  loading: lazyLoadingPng,
   attempt: 2,
 });
 

+ 1 - 0
src/types/shims-vue.d.ts

@@ -6,6 +6,7 @@ declare module '*.vue' {
 }
 
 declare module '*.webp';
+declare module '*.png';
 
 interface Window {
   $message: import('naive-ui/es/message/src/MessageProvider').MessageApiInjection;

+ 162 - 71
src/types/websocket.ts

@@ -26,7 +26,6 @@ export enum WsMsgTypeEnum {
   join = 'join',
   /** 用户进入聊天完成 */
   joined = 'joined',
-  /** 用户进入聊天完成 */
   keepJoined = 'keepJoined',
   /** 用户进入聊天 */
   otherJoin = 'otherJoin',
@@ -58,6 +57,7 @@ export enum WsMsgTypeEnum {
   disableSpeaking = 'disableSpeaking',
   /** 主播踢掉用户 */
   kick = 'kick',
+  keepRtcLiving = 'keepRtcLiving',
 
   srsOffer = 'srsOffer',
   srsAnswer = 'srsAnswer',
@@ -69,6 +69,22 @@ export enum WsMsgTypeEnum {
 
   msrBlob = 'msrBlob',
   batchSendOffer = 'batchSendOffer',
+
+  changeMaxBitrate = 'changeMaxBitrate',
+  changeMaxFramerate = 'changeMaxFramerate',
+  changeResolutionRatio = 'changeResolutionRatio',
+  changeVideoContentHint = 'changeVideoContentHint',
+  changeAudioContentHint = 'changeAudioContentHint',
+
+  billdDeskJoin = 'billdDeskJoin',
+  billdDeskJoined = 'billdDeskJoined',
+  billdDeskUpdateUser = 'billdDeskUpdateUser',
+  billdDeskStartRemote = 'billdDeskStartRemote',
+  billdDeskStartRemoteResult = 'billdDeskStartRemoteResult',
+  billdDeskBehavior = 'billdDeskBehavior',
+  billdDeskOffer = 'billdDeskOffer',
+  billdDeskAnswer = 'billdDeskAnswer',
+  billdDeskCandidate = 'billdDeskCandidate',
 }
 
 /** 发送消息统一格式 */
@@ -95,78 +111,53 @@ export interface IResWsFormat<T> {
   data: T;
 }
 
-export interface IWsFormat<T> {
-  /** 消息id */
-  request_id: string;
-  /** 用户socket_id */
-  socket_id: string;
-  /** 用户token */
-  user_token?: string;
-  /** 消息时间戳 */
-  time: number;
-  data: T;
-}
+export type WsChangeMaxBitrateType = IReqWsFormat<{
+  live_room_id: number;
+  val: number;
+}>;
+
+export type WsChangeMaxFramerateType = IReqWsFormat<{
+  live_room_id: number;
+  val: number;
+}>;
 
-export type WsUpdateJoinInfoType = IWsFormat<{
+export type WsChangeResolutionRatioType = IReqWsFormat<{
   live_room_id: number;
-  track?: { audio: number; video: number };
+  val: number;
+}>;
+
+export type WsChangeVideoContentHintType = IReqWsFormat<{
+  live_room_id: number;
+  val: string;
+}>;
+
+export type WsChangeAudioContentHintType = IReqWsFormat<{
+  live_room_id: number;
+  val: string;
 }>;
 
 /** 直播pk秘钥 */
-export type WSLivePkKeyType = IWsFormat<{
+export type WsLivePkKeyType = IReqWsFormat<{
   live_room_id: number;
   key: string;
 }>;
 
 /** 获取在线用户 */
-export type WsGetLiveUserType = IWsFormat<{
+export type WsGetLiveUserType = IReqWsFormat<{
   live_room_id: number;
 }>;
 
 /** 直播间正在直播 */
-export type WsRoomLivingType = IWsFormat<{
-  live_room: ILiveRoom;
-  anchor_socket_id: string;
-  socket_list?: string[];
-}>;
+export type WsRoomLivingType = IResWsFormat<{ live_room_id: number }>;
 
 /** 直播间没在直播 */
 export type WsRoomNoLiveType = IResWsFormat<{ live_room_id: number }>;
 
-export enum RemoteDeskBehaviorEnum {
-  move,
-  drag,
-  pressButtonLeft,
-  pressButtonRight,
-  releaseButtonLeft,
-  releaseButtonRight,
-  setPosition,
-  doubleClick,
-  leftClick,
-  rightClick,
-  scrollDown,
-  scrollUp,
-  scrollLeft,
-  scrollRight,
-
-  keyboardType,
-}
-
-export type WsRemoteDeskBehaviorType = IWsFormat<{
-  roomId: string;
-  sender: string;
-  receiver: string;
-  type: RemoteDeskBehaviorEnum;
-  x: number;
-  y: number;
-  keyboardtype: string | number;
-}>;
-
 /** ws消息 */
-export type WsMessageType = IWsFormat<IWsMessage>;
+export type WsMessageType = IReqWsFormat<IWsMessage>;
 
 /** 禁言用户 */
-export type WsDisableSpeakingType = IWsFormat<{
+export type WsDisableSpeakingType = IReqWsFormat<{
   request_id?: string;
   /** 被禁言用户socket_id */
   socket_id: string;
@@ -191,7 +182,7 @@ export type WsDisableSpeakingType = IWsFormat<{
 }>;
 
 /** 其他用户加入直播间 */
-export type WsOtherJoinType = IWsFormat<{
+export type WsOtherJoinType = IResWsFormat<{
   live_room_id: number;
   join_user_info?: IUser;
   join_socket_id: string;
@@ -199,7 +190,7 @@ export type WsOtherJoinType = IWsFormat<{
 }>;
 
 /** 开始直播 */
-export type WsStartLiveType = IWsFormat<{
+export type WsStartLiveType = IReqWsFormat<{
   name: string;
   type: LiveRoomTypeEnum;
   /** 单位:毫秒 */
@@ -209,26 +200,37 @@ export type WsStartLiveType = IWsFormat<{
 }>;
 
 /** 用户加入直播间 */
-export type WsJoinType = IWsFormat<{
+export type WsJoinType = IReqWsFormat<{
   live_room_id: number;
   live_room?: ILiveRoom;
   socket_list?: string[];
   duration: number;
 }>;
 
+/** 用户加入直播间 */
+export type WsKeepRtcLivingType = IReqWsFormat<{
+  live_room_id: number;
+  duration: number;
+}>;
+
+/** 用户加入直播间 */
+export type WsJoinedType = IResWsFormat<{
+  live_room_id?: number;
+}>;
+
 /** 用户离开直播间 */
-export type WsLeavedType = IWsFormat<{
+export type WsLeavedType = IResWsFormat<{
   socket_id: string;
   user_info?: IUser;
 }>;
 
 /** 心跳检测 */
-export type WsHeartbeatType = IWsFormat<{
+export type WsHeartbeatType = IReqWsFormat<{
   live_room_id: number;
 }>;
 
 /** msr直播发送blob */
-export type WsMsrBlobType = IWsFormat<{
+export type WsMsrBlobType = IReqWsFormat<{
   live_room_id: number;
   blob: any;
   blob_id: string;
@@ -238,35 +240,124 @@ export type WsMsrBlobType = IWsFormat<{
   max_delay: number;
 }>;
 
-export type WsStartRemoteDesk = IWsFormat<{
-  sender: string;
-  receiver: string;
-  roomId: string;
-}>;
-
-export type WsBatchSendOffer = IWsFormat<{
+export type WsBatchSendOffer = IReqWsFormat<{
   roomId: string;
   socket_list?: string[];
 }>;
 
-export type WsOfferType = IWsFormat<{
+export type WsOfferType = IReqWsFormat<{
   live_room: ILiveRoom;
   sdp: any;
   sender: string;
   receiver: string;
-  live_room_id: number;
+  live_room_id: number | string;
+  isRemoteDesk?: boolean;
 }>;
 
-export type WsAnswerType = IWsFormat<{
+export type WsAnswerType = IReqWsFormat<{
   sdp: any;
   sender: string;
   receiver: string;
-  live_room_id: number;
+  live_room_id: number | string;
 }>;
 
-export type WsCandidateType = IWsFormat<{
-  live_room_id: number;
+export type WsCandidateType = IReqWsFormat<{
+  live_room_id: number | string;
   candidate: RTCIceCandidate;
   receiver: string;
   sender: string;
 }>;
+
+export enum RemoteDeskBehaviorEnum {
+  move,
+  drag,
+  pressButtonLeft,
+  pressButtonRight,
+  releaseButtonLeft,
+  releaseButtonRight,
+  setPosition,
+  doubleClick,
+  leftClick,
+  rightClick,
+  scrollDown,
+  scrollUp,
+  scrollLeft,
+  scrollRight,
+
+  keyboardType,
+}
+
+export type WsRemoteDeskBehaviorType = IReqWsFormat<{
+  roomId: string;
+  sender: string;
+  receiver: string;
+  type: RemoteDeskBehaviorEnum;
+  x: number;
+  y: number;
+  keyboardtype: string | number;
+}>;
+
+// ==========
+
+export enum BilldDeskBehaviorEnum {
+  mouseMove,
+  mouseDrag,
+  pressButtonLeft,
+  pressButtonRight,
+  releaseButtonLeft,
+  releaseButtonRight,
+  setPosition,
+  doubleClick,
+  leftClick,
+  rightClick,
+  scrollDown,
+  scrollUp,
+  scrollLeft,
+  scrollRight,
+
+  keyboardType,
+}
+
+export type WsBilldDeskStartRemote = IReqWsFormat<{
+  sender: string;
+  receiver: string;
+  roomId: string;
+  maxBitrate: number;
+  maxFramerate: number;
+  resolutionRatio: number;
+  audioContentHint: string;
+  videoContentHint: string;
+  deskUserUuid: string;
+  deskUserPassword: string;
+  remoteDeskUserUuid: string;
+  remoteDeskUserPassword: string;
+}>;
+
+export type WsBilldDeskBehaviorType = IReqWsFormat<{
+  roomId: string;
+  sender: string;
+  receiver: string;
+  type: BilldDeskBehaviorEnum;
+  x: number;
+  y: number;
+  amount: number;
+  key: string[] | number[];
+}>;
+
+/** 用户加入直播间 */
+export type WsBilldDeskJoinType = IReqWsFormat<{
+  deskUserUuid: string;
+  deskUserPassword: string;
+  live_room_id: string;
+}>;
+
+/** 用户加入直播间 */
+export type WsBilldDeskJoinedType = IResWsFormat<{
+  live_room_id?: string;
+}>;
+
+export type WsBilldDeskStartRemoteResult = IResWsFormat<{
+  code: number;
+  msg: string;
+  data?: WsBilldDeskStartRemote['data'];
+}>;

+ 2 - 2
src/views/area/id/index.vue

@@ -184,8 +184,8 @@ async function getData() {
         width: 100%;
         height: 150px;
         border-radius: 8px;
-        background-position: center center;
-        background-size: cover;
+
+        @extend %containBg;
         .living-ico {
           position: absolute;
           top: 0px;

+ 1 - 1
src/views/doc/privatizationDeployment/index.vue

@@ -216,7 +216,7 @@ const detail = ref({
     ],
   },
   openSource: {
-    slogan: ['billd直播开源至今,累计收获1k+ star', '值得信赖,欢迎部署~'],
+    slogan: ['billd直播开源至今,累计收获1.3k+ star', '值得信赖,欢迎部署~'],
     list: [
       {
         color: 'blue',

+ 4 - 3
src/views/h5/area/index.vue

@@ -153,8 +153,8 @@ function getListData() {
 
   .list {
     display: flex;
-    flex-wrap: wrap;
     align-content: flex-start;
+    flex-wrap: wrap;
     justify-content: space-between;
     .item {
       display: inline-block;
@@ -166,8 +166,9 @@ function getListData() {
         width: 100%;
         height: 100px;
         border-radius: 8px;
-        background-position: center center;
-        background-size: cover;
+
+        @extend %containBg;
+
         .living-ico {
           position: absolute;
           top: 0px;

+ 3 - 2
src/views/h5/index.vue

@@ -263,8 +263,9 @@ onUnmounted(() => {
             width: 100%;
             height: 100px;
             border-radius: 8px;
-            background-position: center center;
-            background-size: cover;
+
+            @extend %containBg;
+
             .living-ico {
               position: absolute;
               top: 0px;

+ 1 - 2
src/views/h5/room/index.vue

@@ -533,10 +533,9 @@ function startPull() {
     .cover {
       position: absolute;
       z-index: -1;
-      background-position: center center;
-      background-size: cover;
       filter: blur(10px);
 
+      @extend %containBg;
       inset: 0;
     }
     .no-live {

+ 4 - 3
src/views/home/index.vue

@@ -560,10 +560,10 @@ function joinRoom(data) {
           top: 10px;
           left: 10px;
           z-index: 2;
-          line-height: 1;
           color: rgba($color: #fff, $alpha: 0.5);
           font-weight: bold;
           font-size: 30px;
+          line-height: 1;
         }
 
         .cover {
@@ -790,8 +790,9 @@ function joinRoom(data) {
             width: 100%;
             height: 150px;
             border-radius: 8px;
-            background-position: center center;
-            background-size: cover;
+
+            @extend %containBg;
+
             .cdn-ico {
               position: absolute;
               top: -10px;

+ 2 - 2
src/views/my/index.vue

@@ -4,9 +4,9 @@
     <div class="avatar">
       <span class="txt">用户头像:</span>
       <Avatar
-        :avatar="userStore.userInfo?.avatar"
+        :url="userStore.userInfo?.avatar"
+        :name="userStore.userInfo?.username"
         :size="30"
-        :border="!userStore.userInfo?.avatar?.length"
       ></Avatar>
     </div>
     <div>用户昵称:{{ userStore.userInfo?.username }}</div>

+ 1 - 1
src/views/privatizationDeployment/index.vue

@@ -216,7 +216,7 @@ const detail = ref({
     ],
   },
   openSource: {
-    slogan: ['billd直播开源至今,累计收获1k+ star', '值得信赖,欢迎部署~'],
+    slogan: ['billd直播开源至今,累计收获1.3k+ star', '值得信赖,欢迎部署~'],
     list: [
       {
         color: 'blue',

+ 24 - 17
src/views/rank/index.vue

@@ -14,6 +14,7 @@
     <div
       v-if="rankList.length"
       class="rank-list"
+      v-loading="loading"
     >
       <div class="top">
         <div
@@ -33,9 +34,9 @@
           >
             <Avatar
               :size="100"
-              :avatar="item.users[0]?.avatar"
+              :url="item.users[0]?.avatar"
+              :name="item.users[0]?.username"
               :living="!!item.live?.live"
-              :border="!item.users[0]?.avatar?.length"
             ></Avatar>
           </div>
           <div class="username">{{ item.users[0]?.username }}</div>
@@ -83,9 +84,9 @@
           >
             <Avatar
               :size="28"
-              :avatar="item.users[0]?.avatar"
+              :url="item.users[0]?.avatar"
+              :name="item.users[0]?.username"
               :living="!!item.live?.live"
-              :border="!item.users[0]?.avatar?.length"
               disableLiving
             ></Avatar>
             <div class="username">{{ item.users[0]?.username }}</div>
@@ -118,6 +119,12 @@
         </div>
       </div>
     </div>
+    <div
+      class="null"
+      v-if="!rankList.length && !loading"
+    >
+      暂无数据
+    </div>
   </div>
 </template>
 
@@ -130,7 +137,6 @@ import { fetchLiveRoomList } from '@/api/liveRoom';
 import { fetchSigninList } from '@/api/signin';
 import { fetchUserList } from '@/api/user';
 import { fetchWalletList } from '@/api/wallet';
-import { fullLoading } from '@/components/FullLoading';
 import { RankTypeEnum } from '@/interface';
 import router, { routerName } from '@/router';
 import { useUserStore } from '@/store/user';
@@ -175,6 +181,7 @@ const pageParams = reactive({
 
 const currRankType = ref(RankTypeEnum.liveRoom);
 const { t } = useI18n();
+const loading = ref(true);
 const mockRank: {
   users: { id; username; avatar }[];
   rank: number;
@@ -270,7 +277,7 @@ function handleJoin(item) {
 
 async function getWalletList() {
   try {
-    fullLoading({ loading: true });
+    loading.value = true;
     const res = await fetchWalletList({
       ...pageParams,
       orderName: 'balance',
@@ -300,14 +307,13 @@ async function getWalletList() {
     }
   } catch (error) {
     console.log(error);
-  } finally {
-    fullLoading({ loading: false });
   }
+  loading.value = false;
 }
 
 async function getLiveRoomList() {
   try {
-    fullLoading({ loading: true });
+    loading.value = true;
     const res = await fetchLiveRoomList({
       is_show: LiveRoomIsShowEnum.yes,
       orderName: 'updated_at',
@@ -339,14 +345,13 @@ async function getLiveRoomList() {
     }
   } catch (error) {
     console.log(error);
-  } finally {
-    fullLoading({ loading: false });
   }
+  loading.value = false;
 }
 
 async function getUserList() {
   try {
-    fullLoading({ loading: true });
+    loading.value = true;
     const res = await fetchUserList({
       orderName: 'updated_at',
       orderBy: 'desc',
@@ -376,14 +381,13 @@ async function getUserList() {
     }
   } catch (error) {
     console.log(error);
-  } finally {
-    fullLoading({ loading: false });
   }
+  loading.value = false;
 }
 
 async function getSigninList() {
   try {
-    fullLoading({ loading: true });
+    loading.value = true;
     const res = await fetchSigninList({
       ...pageParams,
       orderName: 'sum_nums,max_nums,recently_signin_time',
@@ -413,9 +417,8 @@ async function getSigninList() {
     }
   } catch (error) {
     console.log(error);
-  } finally {
-    fullLoading({ loading: false });
   }
+  loading.value = false;
 }
 
 function changeCurrRankType(type: RankTypeEnum) {
@@ -617,5 +620,9 @@ onMounted(() => {
       }
     }
   }
+  .null {
+    width: 100%;
+    text-align: center;
+  }
 }
 </style>

+ 2 - 2
src/views/user/index.vue

@@ -7,9 +7,9 @@
     <div class="avatar">
       <span class="txt">用户头像:</span>
       <Avatar
-        :avatar="userInfo?.avatar"
+        :url="userInfo?.avatar"
+        :name="userInfo?.username"
         :size="30"
-        :border="!userInfo?.avatar?.length"
       ></Avatar>
     </div>
     <div>用户昵称:{{ userInfo?.username }}</div>