feat: 增加掉线处理

master
xjs 2025-04-11 16:43:39 +08:00
parent 3083f2422a
commit 1c1f281789
7 changed files with 169 additions and 6 deletions

View File

@ -5,6 +5,7 @@
"private": true,
"dependencies": {
"@arco-design/web-react": "^2.65.0",
"@microsoft/signalr": "^8.0.7",
"@reduxjs/toolkit": "^1.8.3",
"@volcengine/rtc": "4.66.1",
"autolinker": "^4.0.0",
@ -25,7 +26,7 @@
"server:start": "node Server/app.js",
"build": "craco build",
"upload": "bash ./upload.sh",
"build-and-upload": "pnpm run build && pnpm run upload",
"build-and-upload": "pnpm run build && pnpm run upload",
"test": "craco test",
"eject": "react-scripts eject",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",

View File

@ -184,7 +184,7 @@ export class ConfigFactory {
},
IgnoreBracketText: [1, 2, 3, 4, 5],
BidirectionAdditions:{
disable_markdown_filter:false,
disable_markdown_filter:true,
}
};
}

69
src/lib/signal.ts Normal file
View File

@ -0,0 +1,69 @@
import * as signalR from '@microsoft/signalr';
import { useEffect, useRef } from 'react';
import { Message } from '@arco-design/web-react';
import { useLeave } from './useCommon';
export const useSignalRConnection = (params: { access_token: string; roomId: string }) => {
const connectionRef = useRef<signalR.HubConnection | null>(null);
const leaveRoom = useLeave();
useEffect(() => {
if (!params.access_token || !params.roomId) {
return;
}
const connection = new signalR.HubConnectionBuilder()
.withServerTimeout(30000)
.withAutomaticReconnect()
.withUrl(`https://api.v3.ycymedu.com/hubs/weminpro?access_token=${params.access_token}&roomId=${params.roomId}`)
.configureLogging(signalR.LogLevel.Information)
.build();
connectionRef.current = connection;
connection.on('connected', () => {
console.log('Connected to SignalR hub');
});
connection.on('disconnected', () => {
console.log('Disconnected from SignalR hub');
});
connection.on("ForceOffline", function (msg) {
// 可加逻辑:注销用户、跳转登录页等
leaveRoom()
});
connection.on("SendWarn", function (msg) {
console.warn(`下线提醒:${msg}"`);
// 也可以弹窗提醒用户保存数据
Message.warning(msg)
});
connection.start()
.then(() => {
console.log("SignalR连接已建立");
setInterval(() => {
connection.invoke("Ping");
}, 5000);
})
.catch(err => {
console.error("SignalR连接失败:", err);
});
return () => {
if (connectionRef.current) {
connectionRef.current.stop()
.then(() => {
console.log("SignalR连接已关闭");
})
.catch(err => {
console.error("关闭SignalR连接失败:", err);
});
}
};
}, [params.access_token, params.roomId]);
return connectionRef.current;
};

View File

@ -103,7 +103,6 @@ export const useJoin = (): [
const token = room.aiConfig.user_token;
const initMsg = room.initMsg
/** 1. Create RTC Engine */
await RtcClient.createEngine({
appId: aigcConfig.BaseConfig.AppId,

View File

@ -5,6 +5,9 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useSearchParams } from 'react-router-dom';
import {useSignalRConnection} from "@/lib/signal"
import { RootState } from '@/store';
import RtcClient from '@/lib/RtcClient';
import { setInterruptMsg } from '@/store/slices/room';
@ -13,18 +16,24 @@ import { COMMAND } from '@/utils/handler';
import style from './index.module.less';
import LockMicroIcon from '@/assets/img/lockmicrophone.png';
import MicroIcon from '@/assets/img/microphone.png';
import HandleOffIcon from "@/assets/img/handoff.png"
import HandleOffIcon from '@/assets/img/handoff.png';
const THRESHOLD_VOLUME = 18;
function AudioController(props: React.HTMLAttributes<HTMLDivElement>) {
const { className, ...rest } = props;
const dispatch = useDispatch();
const room = useSelector((state: RootState) => state.room);
const volume = room.localUser.audioPropertiesInfo?.linearVolume || 0;
const { isAudioPublished,switchMic } = useDeviceState();
const { isAudioPublished, switchMic } = useDeviceState();
const { isAITalking} = useSelector((state: RootState) => state.room);
const [searchParams] = useSearchParams();
useSignalRConnection({access_token:searchParams.get('token') ||'',roomId:room.roomId || ''})
const { isAITalking } = useSelector((state: RootState) => state.room);
const isLoading = volume >= THRESHOLD_VOLUME && isAudioPublished;
const leaveRoom = useLeave();

View File

@ -137,6 +137,7 @@
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 16px;
background-color: #fff;
padding: 8px 15px;
@ -218,6 +219,19 @@
padding: 10px 15px;
border-radius: 400px;
}
.timerWrapper {
display: flex;
align-items: center;
justify-content: center;
background-color: #f6f6f6;
padding: 8px 14px;
border-radius: 400px;
color: #0078ff;
font-size: 14px;
font-weight: 500;
width:100%;
}
}
}

View File

@ -1536,6 +1536,17 @@
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
"@microsoft/signalr@^8.0.7":
version "8.0.7"
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-8.0.7.tgz#94419ddbf9418753e493f4ae4c13990316ec2ea5"
integrity sha512-PHcdMv8v5hJlBkRHAuKG5trGViQEkPYee36LnJQx4xHOQ5LL4X0nEWIxOp5cCtZ7tu+30quz5V3k0b1YNuc6lw==
dependencies:
abort-controller "^3.0.0"
eventsource "^2.0.2"
fetch-cookie "^2.0.3"
node-fetch "^2.6.7"
ws "^7.4.5"
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@ -2353,6 +2364,13 @@ abab@^2.0.3, abab@^2.0.5:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
dependencies:
event-target-shim "^5.0.0"
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
@ -4350,6 +4368,11 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
eventemitter3@^4.0.0, eventemitter3@^4.0.7:
version "4.0.7"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
@ -4360,6 +4383,11 @@ events@^3.2.0:
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
eventsource@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508"
integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@ -4491,6 +4519,14 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
fetch-cookie@^2.0.3:
version "2.2.0"
resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-2.2.0.tgz#01086b6b5b1c3e08f15ffd8647b02ca100377365"
integrity sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==
dependencies:
set-cookie-parser "^2.4.8"
tough-cookie "^4.0.0"
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@ -6519,6 +6555,13 @@ no-case@^3.0.4:
lower-case "^2.0.2"
tslib "^2.0.3"
node-fetch@^2.6.7:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
dependencies:
whatwg-url "^5.0.0"
node-forge@^1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
@ -8364,6 +8407,11 @@ serve-static@1.15.0:
parseurl "~1.3.3"
send "0.18.0"
set-cookie-parser@^2.4.8:
version "2.7.1"
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943"
integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
@ -9035,6 +9083,11 @@ tr46@^2.1.0:
dependencies:
punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
trim-newlines@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
@ -9368,6 +9421,11 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@ -9526,6 +9584,14 @@ whatwg-mimetype@^2.3.0:
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
@ -9775,6 +9841,11 @@ write-file-atomic@^4.0.1:
imurmurhash "^0.1.4"
signal-exit "^3.0.7"
ws@^7.4.5:
version "7.5.10"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
ws@^7.4.6:
version "7.5.9"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"