shuisheng 1 سال پیش
والد
کامیت
ab02b94ac1

+ 4 - 2
package.json

@@ -24,7 +24,8 @@
     "start:preview": "cross-env VUE_APP_RELEASE_PROJECT_ENV=preview VUE_APP_RELEASE_PROJECT_NAME=billd-live webpack serve --config ./script/config/webpack.common.ts --env development",
     "start:prod": "cross-env VUE_APP_RELEASE_PROJECT_ENV=prod VUE_APP_RELEASE_PROJECT_NAME=billd-live webpack serve --config ./script/config/webpack.common.ts --env production",
     "start:stats": "cross-env WEBPACK_ANALYZER_SWITCH=true webpack serve --config ./script/config/webpack.common.ts --env development",
-    "typecheck": "tsc -p ./tsconfig.json --noEmit"
+    "typecheck": "tsc -p ./tsconfig.json --noEmit",
+    "oxclint": "pnpm dlx oxlint@latest"
   },
   "config": {
     "commitizen": {
@@ -105,6 +106,7 @@
     "lint-staged": "^12.1.4",
     "mini-css-extract-plugin": "^2.6.0",
     "node-emoji": "^1.11.0",
+    "oxlint": "^0.9.9",
     "portfinder": "^1.0.28",
     "postcss": "^8.4.8",
     "postcss-loader": "^6.2.1",
@@ -133,4 +135,4 @@
     "webpackbar": "^5.0.2",
     "windicss-webpack-plugin": "^1.7.7"
   }
-}
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 58 - 661
pnpm-lock.yaml


+ 5 - 0
src/api/live.ts

@@ -6,8 +6,13 @@ export function fetchLiveList(params) {
     params,
   });
 }
+
 export function fetchLiveRoomOnlineUser(params) {
   return request.get('/live/live_room_online_user', {
     params,
   });
 }
+
+export function fetchLiveLiveRoomIsLive(liveRoomId: number) {
+  return request.get(`/live/live_room_is_live/${liveRoomId}`);
+}

+ 2 - 2
src/api/liveRoom.ts

@@ -25,6 +25,6 @@ export function fetchUpdateMyLiveRoom(data: ILiveRoom) {
   return request.put('/live_room/update_my_live_room', data);
 }
 
-export function fetchFindLiveRoom(roomId: string) {
-  return request.get<ILiveRoom>(`/live_room/find/${roomId}`);
+export function fetchFindLiveRoom(roomId: number) {
+  return request.get<ILiveRoom | null>(`/live_room/find/${roomId}`);
 }

+ 2 - 2
src/components/Modal/index.vue

@@ -36,8 +36,8 @@ import { useSlots } from 'vue';
 const slots = useSlots();
 const props = withDefaults(
   defineProps<{
-    hiddenClose?: Boolean;
-    maskClosable?: Boolean;
+    hiddenClose?: boolean;
+    maskClosable?: boolean;
     title?: string;
     width?: string;
   }>(),

+ 3 - 3
src/components/VideoControls/index.vue

@@ -42,7 +42,7 @@
               :step="1"
               vertical
               :tooltip="false"
-              @update-value="(v) => cacheStore.setVolume(v)"
+              @update-value="(v) => (cacheStore.volume = v)"
             />
           </div>
         </n-popover>
@@ -270,7 +270,7 @@ function changeLiveLine(item: LiveLineEnum) {
       LiveRoomTypeEnum.wertc_live,
       LiveRoomTypeEnum.wertc_meeting_one,
       LiveRoomTypeEnum.wertc_meeting_two,
-    ].includes(appStore.liveRoomInfo?.type!) &&
+    ].includes(appStore.liveRoomInfo!.type!) &&
     item !== LiveLineEnum.rtc
   ) {
     window.$message.info('不支持该线路!');
@@ -280,7 +280,7 @@ function changeLiveLine(item: LiveLineEnum) {
       LiveRoomTypeEnum.wertc_live,
       LiveRoomTypeEnum.wertc_meeting_one,
       LiveRoomTypeEnum.wertc_meeting_two,
-    ].includes(appStore.liveRoomInfo?.type!) &&
+    ].includes(appStore.liveRoomInfo!.type!) &&
     item === LiveLineEnum.rtc
   ) {
     window.$message.info('不支持该线路!');

+ 11 - 6
src/hooks/use-pull.ts

@@ -23,14 +23,16 @@ import {
 import { WsMessageType, WsMsgTypeEnum } from '@/types/websocket';
 import { videoFullBox, videoToCanvas } from '@/utils';
 
-export function usePull(roomId: string) {
+export function usePull() {
   const route = useRoute();
   const networkStore = useNetworkStore();
   const cacheStore = usePiniaCacheStore();
   const appStore = useAppStore();
   const danmuStr = ref('');
+  const roomId = ref('');
   const msgIsFile = ref(WsMessageMsgIsFileEnum.no);
   const danmuMsgType = ref<DanmuMsgTypeEnum>(DanmuMsgTypeEnum.danmu);
+  const liveRoomInfo = ref<ILiveRoom>();
   const autoplayVal = ref(false);
   const videoLoading = ref(false);
   const isPlaying = ref(false);
@@ -403,19 +405,20 @@ export function usePull(roomId: string) {
     }
   );
 
-  function initPull(data: { autolay?: boolean; isRemoteDesk?: boolean }) {
+  function initPull(data: {
+    roomId: string;
+    autolay?: boolean;
+    isRemoteDesk?: boolean;
+  }) {
     if (data.autolay === undefined) {
       autoplayVal.value = true;
     } else {
       autoplayVal.value = data.autolay;
     }
-    if (autoplayVal.value) {
-      videoLoading.value = true;
-    }
     isRemoteDesk.value = !!data.isRemoteDesk;
     initWs({
       isRemoteDesk: data.isRemoteDesk,
-      roomId,
+      roomId: data.roomId,
       isAnchor: false,
     });
   }
@@ -478,6 +481,7 @@ export function usePull(roomId: string) {
       window.$message.warning('请输入弹幕内容!');
       return;
     }
+    console.log('sendDanmuTxt', roomId, txt);
     const instance = networkStore.wsMap.get(roomId);
     if (!instance) return;
     const messageData: WsMessageType['data'] = {
@@ -548,6 +552,7 @@ export function usePull(roomId: string) {
     damuList,
     liveUserList,
     danmuStr,
+    liveRoomInfo,
     anchorInfo,
   };
 }

+ 1 - 1
src/hooks/use-push.ts

@@ -178,7 +178,7 @@ export function usePush() {
   );
 
   async function handleUserHasLiveRoom() {
-    const res = await fetchUserHasLiveRoom(userStore.userInfo?.id!);
+    const res = await fetchUserHasLiveRoom(userStore.userInfo!.id!);
     if (res.code === 200 && res.data) {
       liveRoomInfo.value = res.data.live_room;
       router.push({

+ 28 - 37
src/hooks/use-websocket.ts

@@ -15,6 +15,7 @@ import { useWebRtcTencentcloudCss } from '@/hooks/webrtc/tencentcloudCss';
 import {
   DanmuMsgTypeEnum,
   ILiveUser,
+  IWsMessage,
   WsMessageContentTypeEnum,
 } from '@/interface';
 import router, { routerName } from '@/router';
@@ -96,7 +97,6 @@ export const useWebsocket = () => {
   const isRemoteDesk = ref(false);
   const isBilibili = ref(false);
   const anchorInfo = ref<IUser>();
-  const anchorSocketId = ref('');
   const canvasVideoStream = ref<MediaStream>();
   const userStream = ref<MediaStream>();
   const lastCoverImg = ref('');
@@ -106,7 +106,7 @@ export const useWebsocket = () => {
   const currentVideoContentHint = ref(videoContentHint.value[3].value);
   const currentAudioContentHint = ref(audioContentHint.value[0].value);
   const timerObj = ref({});
-  const damuList = ref<WsMessageType[]>([]);
+  const damuList = ref<IWsMessage[]>([]);
 
   onUnmounted(() => {
     clearInterval(loopHeartbeatTimer.value);
@@ -144,7 +144,6 @@ export const useWebsocket = () => {
         msgType: WsMsgTypeEnum.heartbeat,
         data: {
           live_room_id: Number(roomId.value),
-          roomLiving: isAnchor.value && roomLiving.value,
         },
       });
     }, 1000 * 5);
@@ -305,9 +304,7 @@ export const useWebsocket = () => {
       data: {
         isBilibili: isBilibili.value,
         isRemoteDesk: isRemoteDesk.value,
-        socket_id: mySocketId.value,
         live_room_id: Number(roomId.value),
-        user_info: userStore.userInfo,
       },
     });
   }
@@ -579,9 +576,6 @@ export const useWebsocket = () => {
       async (data: WsRoomLivingType['data']) => {
         prettierReceiveWsMsg(WsMsgTypeEnum.roomLiving, data);
         roomLiving.value = true;
-        if (data.anchor_socket_id) {
-          anchorSocketId.value = data.anchor_socket_id;
-        }
         if (
           route.name === routerName.pull ||
           route.name === routerName.h5Room
@@ -616,7 +610,18 @@ export const useWebsocket = () => {
     // 收到用户发送消息
     ws.socketIo.on(WsMsgTypeEnum.message, (data: WsMessageType) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.message, data);
-      damuList.value.push(data);
+      damuList.value.push({
+        /** 消息类型 */
+        msg_type: data.data.msg_type,
+        /** 消息内容类型 */
+        content_type: data.data.content_type,
+        /** 消息内容 */
+        content: data.data.content,
+        live_room_id: data.data.live_room_id,
+        redbag_send_id: data.data.redbag_send_id,
+        /** 消息id */
+        id: data.data.msg_id,
+      });
     });
 
     // 收到disableSpeaking
@@ -726,8 +731,6 @@ export const useWebsocket = () => {
     // 用户加入房间完成
     ws.socketIo.on(WsMsgTypeEnum.joined, async (data: WsJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.joined, data);
-      appStore.setLiveRoomInfo(data.live_room);
-      anchorInfo.value = data.anchor_info;
       if (route.name === routerName.pull || route.name === routerName.h5Room) {
         // 当前是拉流页面
         if (
@@ -791,18 +794,13 @@ export const useWebsocket = () => {
     // 其他用户加入房间
     ws.socketIo.on(WsMsgTypeEnum.otherJoin, (data: WsOtherJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.otherJoin, data);
-      const danmu: WsMessageType = {
-        request_id: '',
-        socket_id: '',
-        time: +new Date(),
-        user_agent: navigator.userAgent,
-        data: {
-          live_room_id: data.live_room.id!,
-          msg_id: -1,
-          content: '',
-          content_type: WsMessageContentTypeEnum.txt,
-          msg_type: DanmuMsgTypeEnum.otherJoin,
-        },
+      const danmu: IWsMessage = {
+        send_msg_time: +new Date(),
+        live_room_id: data.live_room.id!,
+        id: -1,
+        content: '',
+        content_type: WsMessageContentTypeEnum.txt,
+        msg_type: DanmuMsgTypeEnum.otherJoin,
       };
       damuList.value.push(danmu);
       if (route.name === routerName.push) {
@@ -926,22 +924,15 @@ export const useWebsocket = () => {
     // 用户离开房间完成
     ws.socketIo.on(WsMsgTypeEnum.leaved, (data: WsLeavedType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.leaved, data);
-      if (anchorSocketId.value === data.socket_id) {
-        roomLiving.value = false;
-      }
+      console.log('用户离开房间完成', data);
       networkStore.removeRtc(data.socket_id);
       damuList.value.push({
-        request_id: '',
-        socket_id: '',
-        time: +new Date(),
-        user_agent: navigator.userAgent,
-        data: {
-          live_room_id: Number(roomId.value),
-          msg_id: -1,
-          content: '',
-          content_type: WsMessageContentTypeEnum.txt,
-          msg_type: DanmuMsgTypeEnum.userLeaved,
-        },
+        send_msg_time: +new Date(),
+        live_room_id: Number(roomId.value),
+        id: -1,
+        content: '',
+        content_type: WsMessageContentTypeEnum.txt,
+        msg_type: DanmuMsgTypeEnum.userLeaved,
       });
     });
   }

+ 1 - 0
src/hooks/webrtc/forwardAll.ts

@@ -113,6 +113,7 @@ export const useForwardAll = () => {
         }
       } catch (error) {
         console.error('ForwardAll的sendOffer错误');
+        console.log(error);
       }
     },
   };

+ 1 - 0
src/hooks/webrtc/forwardBilibili.ts

@@ -119,6 +119,7 @@ export const useForwardBilibili = () => {
         }
       } catch (error) {
         console.error('ForwardBilibili的sendOffer错误');
+        console.log(error);
       }
     },
   };

+ 1 - 0
src/hooks/webrtc/forwardHuya.ts

@@ -113,6 +113,7 @@ export const useForwardHuya = () => {
         }
       } catch (error) {
         console.error('ForwardHuya的sendOffer错误');
+        console.log(error);
       }
     },
   };

+ 2 - 0
src/hooks/webrtc/live.ts

@@ -91,6 +91,7 @@ export const useWebRtcLive = () => {
         }
       } catch (error) {
         console.error('webRtcLive的sendOffer错误');
+        console.log(error);
       }
     },
     /**
@@ -136,6 +137,7 @@ export const useWebRtcLive = () => {
         }
       } catch (error) {
         console.error('webRtcLive的sendAnswer错误');
+        console.log(error);
       }
     },
   };

+ 1 - 0
src/hooks/webrtc/meetingOne.ts

@@ -93,6 +93,7 @@ export const useWebRtcMeetingOne = () => {
         }
       } catch (error) {
         console.error('meetingOne的sendOffer错误');
+        console.log(error);
       }
     },
     /**

+ 1 - 0
src/hooks/webrtc/meetingPk.ts

@@ -93,6 +93,7 @@ export const useWebRtcMeetingPk = () => {
         }
       } catch (error) {
         console.error('meetingPk的sendOffer错误');
+        console.log(error);
       }
     },
     /**

+ 2 - 0
src/hooks/webrtc/meetingTwo.ts

@@ -98,6 +98,7 @@ export const useWebRtcManyToManyMeeting = () => {
         }
       } catch (error) {
         console.error('webRtcManyToManyMeeting的sendOffer错误');
+        console.log(error);
       }
     },
     /**
@@ -153,6 +154,7 @@ export const useWebRtcManyToManyMeeting = () => {
         }
       } catch (error) {
         console.error('webRtcManyToManyMeeting的sendAnswer错误');
+        console.log(error);
       }
     },
   };

+ 1 - 0
src/hooks/webrtc/srs.ts

@@ -118,6 +118,7 @@ export const useWebRtcSrs = () => {
         }
       } catch (error) {
         console.error('webRtcSrs的sendOffer错误');
+        console.log(error);
       }
     },
   };

+ 1 - 0
src/hooks/webrtc/tencentcloudCss.ts

@@ -83,6 +83,7 @@ export const useWebRtcTencentcloudCss = () => {
         }
       } catch (error) {
         console.error('webRtcTencentcloudCss的sendOffer错误');
+        console.log(error);
       }
     },
   };

+ 1 - 0
src/store/user/index.ts

@@ -52,6 +52,7 @@ export const useUserStore = defineStore('user', {
         return token;
       } catch (error: any) {
         // 错误返回401,全局的响应拦截会打印报错信息
+        console.log(error);
         return null;
       }
     },

+ 0 - 4
src/types/websocket.ts

@@ -93,7 +93,6 @@ export interface IWsFormat<T> {
   user_token?: string;
   /** 消息时间戳 */
   time: number;
-  user_agent: string;
   data: T;
 }
 
@@ -227,11 +226,9 @@ export type WsUpdateLiveRoomCoverImg = IWsFormat<{
 
 /** 用户加入直播间 */
 export type WsJoinType = IWsFormat<{
-  socket_id: string;
   live_room_id: number;
   live_room?: ILiveRoom;
   anchor_info?: IUser;
-  user_info?: IUser;
   isRemoteDesk?: boolean;
   isBilibili?: boolean;
   socket_list?: string[];
@@ -246,7 +243,6 @@ export type WsLeavedType = IWsFormat<{
 /** 心跳检测 */
 export type WsHeartbeatType = IWsFormat<{
   live_room_id: number;
-  roomLiving?: boolean;
 }>;
 
 /** msr直播发送blob */

+ 0 - 1
src/utils/network/webSocket.ts

@@ -74,7 +74,6 @@ export class WebSocketClass {
       socket_id: this.socketIo.id,
       user_info: userStore.userInfo,
       user_token: userStore.token || undefined,
-      user_agent: navigator.userAgent,
       time: +new Date(),
       data: data || {},
     };

+ 39 - 54
src/views/h5/room/index.vue

@@ -81,15 +81,15 @@
                 :key="index"
                 class="item"
               >
-                <template v-if="item.data.msg_type === DanmuMsgTypeEnum.danmu">
-                  <span class="time"> [{{ formatTimeHour(item.time) }}] </span>
+                <template v-if="item.msg_type === DanmuMsgTypeEnum.danmu">
+                  <span class="time">
+                    [{{ formatTimeHour(item.send_msg_time!) }}]
+                  </span>
                   <span class="name">
-                    <span v-if="item.user_info">
-                      <span>{{ item.user_info.username }}</span>
+                    <span v-if="item.user">
+                      <span>{{ item.user.username }}</span>
                       <span>
-                        [{{
-                          item.user_info.roles?.map((v) => v.role_name).join()
-                        }}]
+                        [{{ item.user.roles?.map((v) => v.role_name).join() }}]
                       </span>
                     </span>
                     <span v-else>
@@ -100,50 +100,46 @@
                   </span>
                   <span
                     class="msg"
-                    v-if="
-                      item.data.content_type === WsMessageContentTypeEnum.txt
-                    "
+                    v-if="item.content_type === WsMessageContentTypeEnum.txt"
                   >
-                    {{ item.data.content }}
+                    {{ item.content }}
                   </span>
                   <div
                     class="msg img"
                     v-else
                   >
                     <img
-                      v-lazy="item.data.content"
+                      v-lazy="item.content"
                       alt=""
                       @load="handleScrollTop"
                     />
                   </div>
                 </template>
                 <template
-                  v-else-if="item.data.msg_type === DanmuMsgTypeEnum.otherJoin"
+                  v-else-if="item.msg_type === DanmuMsgTypeEnum.otherJoin"
                 >
                   <span class="name system">系统通知:</span>
                   <span class="msg">
-                    {{ item.user_info?.username || item.socket_id }}进入直播!
+                    {{ item.user?.username || item.socket_id }}进入直播!
                   </span>
                 </template>
                 <template
-                  v-else-if="item.data.msg_type === DanmuMsgTypeEnum.userLeaved"
+                  v-else-if="item.msg_type === DanmuMsgTypeEnum.userLeaved"
                 >
                   <span class="name system">系统通知:</span>
                   <span class="msg">
-                    {{ item.user_info?.username || item.socket_id }}离开直播!
+                    {{ item.user?.username || item.socket_id }}离开直播!
                   </span>
                 </template>
-                <template
-                  v-else-if="item.data.msg_type === DanmuMsgTypeEnum.reward"
-                >
-                  <span class="time"> [{{ formatTimeHour(item.time) }}] </span>
+                <template v-else-if="item.msg_type === DanmuMsgTypeEnum.reward">
+                  <span class="time">
+                    [{{ formatTimeHour(item.send_msg_time!) }}]
+                  </span>
                   <span class="name">
-                    <span v-if="item.user_info">
-                      <span>{{ item.user_info.username }}</span>
+                    <span v-if="item.user">
+                      <span>{{ item.user.username }}</span>
                       <span>
-                        [{{
-                          item.user_info.roles?.map((v) => v.role_name).join()
-                        }}]
+                        [{{ item.user.roles?.map((v) => v.role_name).join() }}]
                       </span>
                     </span>
                     <span v-else>
@@ -152,7 +148,7 @@
                     </span>
                     <span>:</span>
                   </span>
-                  <span class="msg"> 打赏了:{{ item.data.content }} </span>
+                  <span class="msg"> 打赏了:{{ item.content }} </span>
                 </template>
               </div>
             </div>
@@ -408,19 +404,14 @@ async function handleHistoryMsg() {
     if (res.code === 200) {
       res.data.rows.forEach((v) => {
         damuList.value.unshift({
-          request_id: '',
-          socket_id: '',
-          time: v.send_msg_time!,
-          user_agent: v.user_agent!,
-          user_info: v.user,
-          data: {
-            live_room_id: v.live_room_id!,
-            msg_id: v.id!,
-            content: v.content!,
-            content_type: v.content_type!,
-            msg_type: v.msg_type!,
-            redbag_send_id: v.redbag_send_id,
-          },
+          send_msg_time: v.send_msg_time!,
+          user: v.user,
+          live_room_id: v.live_room_id!,
+          id: v.id!,
+          content: v.content!,
+          content_type: v.content_type!,
+          msg_type: v.msg_type!,
+          redbag_send_id: v.redbag_send_id,
         });
       });
       if (
@@ -428,17 +419,12 @@ async function handleHistoryMsg() {
         appStore.liveRoomInfo?.system_msg !== ''
       ) {
         damuList.value.push({
-          request_id: '',
-          socket_id: '',
-          time: +new Date(),
-          user_agent: navigator.userAgent,
-          data: {
-            live_room_id: Number(roomId.value),
-            msg_id: -1,
-            content: appStore.liveRoomInfo?.system_msg,
-            content_type: WsMessageContentTypeEnum.txt,
-            msg_type: DanmuMsgTypeEnum.system,
-          },
+          send_msg_time: +new Date(),
+          live_room_id: Number(roomId.value),
+          id: -1,
+          content: appStore.liveRoomInfo?.system_msg,
+          content_type: WsMessageContentTypeEnum.txt,
+          msg_type: DanmuMsgTypeEnum.system,
         });
       }
     }
@@ -507,16 +493,15 @@ function handleFullScreen() {
 async function getLiveRoomInfo() {
   try {
     videoLoading.value = true;
-    const res = await fetchFindLiveRoom(roomId.value);
+    const res = await fetchFindLiveRoom(Number(roomId.value));
     if (res.code === 200) {
-      appStore.setLiveRoomInfo(res.data);
-      if (res.data.type === LiveRoomTypeEnum.wertc_live) {
+      if (res.data?.type === LiveRoomTypeEnum.wertc_live) {
         autoplayVal.value = true;
         showPlayBtn.value = false;
       } else {
         showPlayBtn.value = true;
       }
-      initPull({ autolay: autoplayVal.value });
+      initPull({ roomId: roomId.value, autolay: autoplayVal.value });
     }
   } catch (error) {
     console.error(error);

+ 5 - 9
src/views/home/index.vue

@@ -48,7 +48,7 @@
               [
                 LiveRoomTypeEnum.tencent_css,
                 LiveRoomTypeEnum.tencent_css_pk,
-              ].includes(currentLiveRoom?.live_room?.type!)
+              ].includes(currentLiveRoom?.live_room!.type!)
             "
             class="cdn-ico"
           >
@@ -127,7 +127,7 @@
                     [
                       LiveRoomTypeEnum.tencent_css,
                       LiveRoomTypeEnum.tencent_css_pk,
-                    ].includes(item.live_room?.type!)
+                    ].includes(item.live_room!.type!)
                   "
                 >
                   <div class="txt">CDN</div>
@@ -184,7 +184,7 @@
                   [
                     LiveRoomTypeEnum.tencent_css,
                     LiveRoomTypeEnum.tencent_css_pk,
-                  ].includes(iten.live_room?.type!)
+                  ].includes(iten.live_room!.type!)
                 "
                 class="cdn-ico"
               >
@@ -229,7 +229,7 @@
                   [
                     LiveRoomTypeEnum.tencent_css,
                     LiveRoomTypeEnum.tencent_css_pk,
-                  ].includes(iten.live_room?.type!)
+                  ].includes(iten.live_room!.type!)
                 "
                 class="cdn-ico"
               >
@@ -445,7 +445,6 @@ function playLive(item: ILive) {
   canvasRef.value?.childNodes?.forEach((item) => {
     item.remove();
   });
-  appStore.setLiveRoomInfo(item.live_room!);
   roomLiving.value = true;
   handlePlay(item.live_room!);
 }
@@ -457,7 +456,7 @@ function changeLiveRoom(item: ILive) {
       LiveRoomTypeEnum.wertc_live,
       LiveRoomTypeEnum.wertc_meeting_one,
       LiveRoomTypeEnum.wertc_meeting_two,
-    ].includes(item.live_room?.type!)
+    ].includes(item.live_room!.type!)
   ) {
     appStore.setLiveLine(LiveLineEnum.hls);
   }
@@ -480,7 +479,6 @@ async function getLiveRoomList() {
       otherLiveRoomList.value = res.data.rows.slice(topNums.value);
       if (res.data.total) {
         currentLiveRoom.value = topLiveRoomList.value[0];
-        appStore.setLiveRoomInfo(currentLiveRoom.value.live_room!);
         roomLiving.value = true;
       }
     }
@@ -900,8 +898,6 @@ function joinRoom(data) {
             max-height: calc($w-900 / $video-ratio);
           }
         }
-        .right {
-        }
       }
     }
     .area-container {

+ 90 - 85
src/views/pull/index.vue

@@ -1,5 +1,12 @@
 <template>
   <div
+    class="pull-wrap"
+    v-if="!appStore.liveRoomInfo"
+  >
+    暂无该直播间
+  </div>
+  <div
+    v-else
     class="pull-wrap"
     :class="{ isPageFull: appStore.videoControlsValue.pageFullMode }"
   >
@@ -90,10 +97,7 @@
             </div>
           </div>
         </div>
-        <div
-          class="other"
-          @click="handlePk"
-        >
+        <div class="other">
           <div class="top">
             <div class="item">666人看过</div>
             <div class="item">666点赞</div>
@@ -153,6 +157,7 @@
           ref="remoteVideoRef"
         ></div>
         <VideoControls
+          v-if="roomLiving"
           :resolution="videoResolution"
           @refresh="handleRefresh"
           @full-screen="handleFullScreen"
@@ -262,47 +267,44 @@
           :key="index"
           class="item"
         >
-          <template v-if="item.data.msg_type === DanmuMsgTypeEnum.reward">
+          <template v-if="item.msg_type === DanmuMsgTypeEnum.reward">
             <div class="reward">
-              <span>[{{ formatTimeHour(item.time) }}]</span>
+              <span>[{{ formatTimeHour(item.send_msg_time!) }}]</span>
               <span>
-                {{ item.user_info?.username }} 打赏了{{ item.data.content }}!
+                {{ item.user?.username }} 打赏了{{ item.content }}!
               </span>
             </div>
           </template>
-          <template v-if="item.data.msg_type === DanmuMsgTypeEnum.danmu">
-            <span class="time">[{{ formatTimeHour(item.time) }}]</span>
+          <template v-if="item.msg_type === DanmuMsgTypeEnum.danmu">
+            <span class="time"
+              >[{{ formatTimeHour(item.send_msg_time!) }}]</span
+            >
             <span class="name">
-              <span
-                v-if="
-                  item.user_info && userStore.userInfo?.id === item.user_info.id
-                "
-              >
-                <span>{{ item.user_info.username }}</span>
+              <span v-if="item.user && userStore.userInfo?.id === item.user.id">
+                <span>{{ item.user.username }}</span>
                 <span>
-                  [{{ item.user_info.roles?.map((v) => v.role_name).join() }}]
+                  [{{ item.user.roles?.map((v) => v.role_name).join() }}]
                 </span>
               </span>
               <Dropdown
                 trigger="click"
                 positon="left"
-                v-else-if="item.user_info"
+                v-else-if="item.user"
               >
                 <template #btn>
-                  <span>{{ item.user_info.username }}</span>
+                  <span>{{ item.user.username }}</span>
                   <span>
-                    [{{ item.user_info.roles?.map((v) => v.role_name).join() }}]
+                    [{{ item.user.roles?.map((v) => v.role_name).join() }}]
                   </span>
                 </template>
                 <template #list>
                   <div class="list">
-                    <div class="item">{{ item.user_info.username }}</div>
+                    <div class="item">{{ item.user.username }}</div>
                     <div
                       class="item operator"
                       @click="
                         handleDisableSpeakingUser({
-                          userId: item.user_info.id,
-                          socketId: item.socket_id,
+                          userId: item.user.id,
                         })
                       "
                     >
@@ -312,8 +314,7 @@
                       class="item operator"
                       @click="
                         handleRestoreSpeakingUser({
-                          userId: item.user_info.id,
-                          socketId: item.socket_id,
+                          userId: item.user.id,
                         })
                       "
                     >
@@ -329,43 +330,35 @@
                 </template>
               </Dropdown>
               <span v-else>
-                <span>{{ item.socket_id }}</span>
+                <span>{{ item }}</span>
                 <span>[游客]</span>
               </span>
             </span>
             <span>:</span>
             <span
               class="msg"
-              v-if="item.data.content_type === WsMessageContentTypeEnum.txt"
+              v-if="item.content_type === WsMessageContentTypeEnum.txt"
             >
-              {{ item.data.content }}
+              {{ item.content }}
             </span>
             <div
               class="msg img"
               v-else
             >
               <img
-                :src="item.data.content"
+                :src="item.content"
                 alt=""
                 @load="handleScrollTop"
               />
             </div>
           </template>
-          <template
-            v-else-if="item.data.msg_type === DanmuMsgTypeEnum.otherJoin"
-          >
+          <template v-else-if="item.msg_type === DanmuMsgTypeEnum.otherJoin">
             <span class="name system">系统通知:</span>
-            <span class="msg">
-              {{ item.user_info?.username || item.socket_id }}进入直播!
-            </span>
+            <span class="msg">{{ item.user?.username }}进入直播! </span>
           </template>
-          <template
-            v-else-if="item.data.msg_type === DanmuMsgTypeEnum.userLeaved"
-          >
+          <template v-else-if="item.msg_type === DanmuMsgTypeEnum.userLeaved">
             <span class="name system">系统通知:</span>
-            <span class="msg">
-              {{ item.user_info?.username || item.socket_id }}离开直播!
-            </span>
+            <span class="msg">{{ item.user?.username }}离开直播! </span>
           </template>
         </div>
       </div>
@@ -469,6 +462,7 @@ import {
 } from '@/api/giftRecord';
 import { fetchGoodsList } from '@/api/goods';
 import { fetchLiveRoomOnlineUser } from '@/api/live';
+import { fetchFindLiveRoom } from '@/api/liveRoom';
 import { fetchGetWsMessageList } from '@/api/wsMessage';
 import { liveRoomTypeEnumMap, QINIU_RESOURCE } from '@/constant';
 import { emojiArray } from '@/emoji';
@@ -494,8 +488,9 @@ import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { useUserStore } from '@/store/user';
 import { LiveRoomTypeEnum } from '@/types/ILiveRoom';
+import { IUser } from '@/types/IUser';
 import { WsDisableSpeakingType, WsMsgTypeEnum } from '@/types/websocket';
-import { formatMoney, formatTimeHour, handleUserMedia } from '@/utils';
+import { formatMoney, formatTimeHour } from '@/utils';
 import { initAdsbygoogle } from '@/utils/google-ad';
 import { NODE_ENV } from 'script/constant';
 
@@ -507,7 +502,8 @@ const appStore = useAppStore();
 const networkStore = useNetworkStore();
 const { t } = useI18n();
 
-const roomId = ref(route.params.roomId as string);
+const roomId = ref('-1');
+const anchorInfo = ref<IUser>();
 const configBg = ref();
 const configVideo = ref();
 const giftGoodsList = ref<IGoods[]>([]);
@@ -546,7 +542,6 @@ const {
   damuList,
   liveUserList,
   danmuStr,
-  anchorInfo,
 } = usePull(roomId.value);
 
 const rtcRtt = computed(() => {
@@ -587,8 +582,11 @@ const rtcBytesReceived = computed(() => {
   return arr.join();
 });
 
-onMounted(() => {
+onMounted(async () => {
+  roomId.value = route.params.roomId as string;
   initAdsbygoogle();
+  await handleFindLiveRoomInfo();
+  if (!appStore.liveRoomInfo) return;
   appStore.videoControls.fps = true;
   appStore.videoControls.fullMode = true;
   appStore.videoControls.kbs = true;
@@ -616,7 +614,7 @@ onMounted(() => {
   getBg();
   if (route.query.is_bilibili !== '1') {
     isBilibili.value = false;
-    initPull({});
+    initPull({ roomId: roomId.value });
   } else {
     initWs({
       roomId: roomId.value,
@@ -638,6 +636,25 @@ onUnmounted(() => {
   clearInterval(loopGetLiveUserTimer.value);
 });
 
+async function handleFindLiveRoomInfo() {
+  try {
+    const res = await fetchFindLiveRoom(Number(roomId.value));
+    if (res.code === 200) {
+      if (res.data) {
+        appStore.liveRoomInfo = res.data;
+        anchorInfo.value = res.data.user_live_room?.user;
+        if (res.data.live) {
+          roomLiving.value = true;
+        } else {
+          videoLoading.value = false;
+        }
+      }
+    }
+  } catch (error) {
+    console.log(error);
+  }
+}
+
 async function handleBilibil() {
   if (route.query.is_bilibili === '1') {
     const flv = await fetchLiveBilibiliPlayUrl({
@@ -651,7 +668,6 @@ async function handleBilibil() {
     const roomInfo = await fetchLiveBilibiliRoomGetInfo({
       room_id: route.params.roomId,
     });
-    console.log('roomInfo', roomInfo);
     console.log(flv?.data?.data?.durl?.[0].url, 'flv');
     console.log(hls?.data?.data?.durl?.[0].url, 'hls');
     roomLiving.value = true;
@@ -731,19 +747,14 @@ async function handleHistoryMsg() {
     if (res.code === 200) {
       res.data.rows.forEach((v) => {
         damuList.value.unshift({
-          request_id: '',
-          socket_id: '',
-          time: v.send_msg_time!,
-          user_agent: v.user_agent!,
-          user_info: v.user,
-          data: {
-            live_room_id: v.live_room_id!,
-            msg_id: v.id!,
-            content: v.content!,
-            content_type: v.content_type!,
-            msg_type: v.msg_type!,
-            redbag_send_id: v.redbag_send_id,
-          },
+          send_msg_time: v.send_msg_time!,
+          user: v.user,
+          live_room_id: v.live_room_id!,
+          id: v.id!,
+          content: v.content!,
+          content_type: v.content_type!,
+          msg_type: v.msg_type!,
+          redbag_send_id: v.redbag_send_id,
         });
       });
       if (
@@ -751,17 +762,12 @@ async function handleHistoryMsg() {
         appStore.liveRoomInfo?.system_msg !== ''
       ) {
         damuList.value.push({
-          request_id: '',
-          socket_id: '',
-          time: +new Date(),
-          user_agent: navigator.userAgent,
-          data: {
-            live_room_id: Number(roomId.value),
-            msg_id: -1,
-            content: appStore.liveRoomInfo.system_msg,
-            content_type: WsMessageContentTypeEnum.txt,
-            msg_type: DanmuMsgTypeEnum.system,
-          },
+          send_msg_time: +new Date(),
+          live_room_id: Number(roomId.value),
+          id: -1,
+          content: appStore.liveRoomInfo.system_msg,
+          content_type: WsMessageContentTypeEnum.txt,
+          msg_type: DanmuMsgTypeEnum.system,
         });
       }
     }
@@ -770,19 +776,6 @@ async function handleHistoryMsg() {
   }
 }
 
-async function handlePk() {
-  const stream = await handleUserMedia({ video: true, audio: true });
-  const rtc = networkStore.rtcMap.get(`${roomId.value}`)!;
-  if (rtc?.peerConnection) {
-    rtc.peerConnection.onnegotiationneeded = () => {
-      console.log('onnegotiationneeded');
-    };
-    stream?.getTracks().forEach((track) => {
-      rtc.peerConnection?.addTrack(track, stream);
-    });
-  }
-}
-
 watch(
   () => damuList.value.length,
   () => {
@@ -807,7 +800,13 @@ watch(
  * 主播开播了,可以禁言所有看自己直播的用户
  * 使用redis存储记录,key是主播直播间id,value是禁言用户id
  */
-function handleDisableSpeakingUser({ socketId, userId }) {
+function handleDisableSpeakingUser({
+  socketId,
+  userId,
+}: {
+  socketId?;
+  userId;
+}) {
   console.log('handleDisableSpeakingUser');
   const instance = networkStore.wsMap.get(roomId.value);
   if (instance) {
@@ -824,7 +823,13 @@ function handleDisableSpeakingUser({ socketId, userId }) {
   }
 }
 
-function handleRestoreSpeakingUser({ socketId, userId }) {
+function handleRestoreSpeakingUser({
+  socketId,
+  userId,
+}: {
+  socketId?;
+  userId;
+}) {
   console.log('handleRestoreSpeakingUser');
   const instance = networkStore.wsMap.get(roomId.value);
   if (instance) {

+ 29 - 37
src/views/push/index.vue

@@ -313,49 +313,51 @@
               :key="index"
               class="item"
             >
-              <template v-if="item.data.msg_type === DanmuMsgTypeEnum.danmu">
-                <span class="time"> [{{ formatTimeHour(item.time) }}] </span>
+              <template v-if="item.msg_type === DanmuMsgTypeEnum.danmu">
+                <span class="time">
+                  [{{ formatTimeHour(item.send_msg_time!) }}]
+                </span>
                 <span class="name">
-                  <span v-if="item.user_info">
-                    {{ item.user_info.username }}[{{
-                      item.user_info.roles?.map((v) => v.role_name).join()
+                  <span v-if="item.user">
+                    {{ item.user.username }}[{{
+                      item.user.roles?.map((v) => v.role_name).join()
                     }}]
                   </span>
-                  <span v-else>{{ item.socket_id }}[游客]</span>
+                  <span v-else>{{ item }}[游客]</span>
                 </span>
                 <span>:</span>
                 <span
                   class="msg"
-                  v-if="item.data.content_type === WsMessageContentTypeEnum.txt"
+                  v-if="item.content_type === WsMessageContentTypeEnum.txt"
                 >
-                  {{ item.data.content }}
+                  {{ item.content }}
                 </span>
                 <div
                   class="msg img"
                   v-else
                 >
                   <img
-                    v-lazy="item.data.content"
+                    v-lazy="item.content"
                     alt=""
                     @load="handleScrollTop"
                   />
                 </div>
               </template>
               <template
-                v-else-if="item.data.msg_type === DanmuMsgTypeEnum.otherJoin"
+                v-else-if="item.msg_type === DanmuMsgTypeEnum.otherJoin"
               >
                 <span class="name system">系统通知:</span>
                 <span class="msg">
-                  <span>{{ item.user_info?.username || item.socket_id }}</span>
+                  <span>{{ item.user?.username }}</span>
                   <span>进入直播!</span>
                 </span>
               </template>
               <template
-                v-else-if="item.data.msg_type === DanmuMsgTypeEnum.userLeaved"
+                v-else-if="item.msg_type === DanmuMsgTypeEnum.userLeaved"
               >
                 <span class="name system">系统通知:</span>
                 <span class="msg">
-                  <span>{{ item.user_info?.username || item.socket_id }}</span>
+                  <span>{{ item.user?.username }}</span>
                   <span>离开直播!</span>
                 </span>
               </template>
@@ -1142,19 +1144,14 @@ async function handleHistoryMsg() {
     if (res.code === 200) {
       res.data.rows.forEach((v) => {
         damuList.value.unshift({
-          request_id: '',
-          socket_id: '',
-          time: v.send_msg_time!,
-          user_agent: v.user_agent!,
-          user_info: v.user,
-          data: {
-            live_room_id: v.live_room_id!,
-            msg_id: v.id!,
-            content: v.content!,
-            content_type: v.content_type!,
-            msg_type: v.msg_type!,
-            redbag_send_id: v.redbag_send_id,
-          },
+          send_msg_time: v.send_msg_time!,
+          user: v.user,
+          live_room_id: v.live_room_id!,
+          id: v.id!,
+          content: v.content!,
+          content_type: v.content_type!,
+          msg_type: v.msg_type!,
+          redbag_send_id: v.redbag_send_id,
         });
       });
       if (
@@ -1162,17 +1159,12 @@ async function handleHistoryMsg() {
         appStore.liveRoomInfo?.system_msg !== ''
       ) {
         damuList.value.push({
-          request_id: '',
-          socket_id: '',
-          time: +new Date(),
-          user_agent: navigator.userAgent,
-          data: {
-            live_room_id: Number(roomId.value),
-            msg_id: -1,
-            content: appStore.liveRoomInfo?.system_msg,
-            content_type: WsMessageContentTypeEnum.txt,
-            msg_type: DanmuMsgTypeEnum.system,
-          },
+          send_msg_time: +new Date(),
+          live_room_id: Number(roomId.value),
+          id: -1,
+          content: appStore.liveRoomInfo?.system_msg,
+          content_type: WsMessageContentTypeEnum.txt,
+          msg_type: DanmuMsgTypeEnum.system,
         });
       }
     }

+ 3 - 3
src/views/push/mediaModal/index.vue

@@ -162,20 +162,20 @@ function handleOk() {
     return;
   }
   if (props.mediaType === MediaTypeEnum.txt) {
-    if (txtInfo.value?.txt?.length! < 3 || txtInfo.value?.txt?.length! > 100) {
+    if (txtInfo.value!.txt!.length! < 3 || txtInfo.value!.txt!.length! > 100) {
       window.$message.info('内容要求3-100个字符!');
       return;
     }
   }
   if (!props.isEdit) {
     if (props.mediaType === MediaTypeEnum.img) {
-      if (imgInfo.value?.length! !== 1) {
+      if (imgInfo.value!.length! !== 1) {
         window.$message.info('请选择图片!');
         return;
       }
     }
     if (props.mediaType === MediaTypeEnum.media) {
-      if (mediaInfo.value?.length! !== 1) {
+      if (mediaInfo.value!.length! !== 1) {
         window.$message.info('请选择视频!');
         return;
       }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است