fix: 多次点击加入房间
parent
1270723821
commit
27edb84470
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>六维填报师</title>
|
||||
<title>六纬AI填报师</title>
|
||||
<meta name="description" content="AIGC对话" />
|
||||
<meta name="generator" content="React" />
|
||||
<meta name="keywords" content="music, music-site" />
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
|
|
@ -8,22 +8,22 @@ import { useSearchParams } from "react-router-dom";
|
|||
import { fetchUserToken } from "@/apis/user";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { useAbortController } from "@/hooks/useAbortController";
|
||||
// import { ReportContext } from "@/components/Provider/ReportResolveProvider";
|
||||
import AntechamberFile from "@/components/AntechamberFile";
|
||||
import AntechamberReport from "@/components/AntechamberReport";
|
||||
import AntechamberWishList from "@/components/AntechamberWishList";
|
||||
import { ReportContext } from "@/components/Provider/ReportResolveProvider";
|
||||
|
||||
export default function Antechamber() {
|
||||
|
||||
const { handleConnect} = useContext(RealtimeClientContext);
|
||||
const { hasHandledReport } = useContext(ReportContext);
|
||||
|
||||
|
||||
const [searchParams] = useSearchParams();
|
||||
const [disable,setDisable] = useState(true);
|
||||
const [isLoading,setIsLoading] = useState(false);
|
||||
|
||||
const token = searchParams.get("token") || '';
|
||||
// const reportId = searchParams.get("reportId") || '';
|
||||
// const reportType = searchParams.get("reportType") || '';
|
||||
|
||||
const { toast } = useToast();
|
||||
const { getSignal } = useAbortController();
|
||||
|
|
@ -57,54 +57,35 @@ export default function Antechamber() {
|
|||
}
|
||||
};
|
||||
|
||||
// const getReport = async () => {
|
||||
// try {
|
||||
// const { result, message } = await fetchReport({
|
||||
// params:{Type:reportType,Id:reportId},
|
||||
// options: {
|
||||
// signal: getSignal(),
|
||||
// headers: {
|
||||
// "Authorization": `Bearer ${encodeURIComponent(token)}`
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// if (message) {
|
||||
// console.log(message);
|
||||
// } else {
|
||||
// handleConnect({initMessage:result as string});
|
||||
// setHasHandledReport(true)
|
||||
// }
|
||||
// } catch (error: any) {
|
||||
// if (error.name !== 'AbortError') {
|
||||
// console.error('获取报告失败:', error);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
useEffect(() => {
|
||||
getUserToken();
|
||||
}, [token]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if(reportId && reportType && !hasHandledReport){
|
||||
// getReport();
|
||||
// }
|
||||
// }, [reportId, reportType,hasHandledReport]);
|
||||
|
||||
const toRoom = (params:{initMessage?:string,fileUrl?:string}) => {
|
||||
if(disable){
|
||||
if(!hasHandledReport && (disable || isLoading)){
|
||||
return;
|
||||
}
|
||||
handleConnect(params);
|
||||
setIsLoading(true)
|
||||
handleConnect(params).then(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div className="flex flex-col items-center h-full">
|
||||
<div className="flex flex-col items-center h-full overflow-y-auto relative">
|
||||
<AntechamberHeader />
|
||||
<AntechamberScore />
|
||||
<AntechamberWishList />
|
||||
<AntechamberFile />
|
||||
<AntechamberReport />
|
||||
<AntechamberFile handleLoading={setIsLoading} />
|
||||
<AntechamberReport handleLoading={setIsLoading} />
|
||||
<InvokeButton disable={disable} onClick={() => toRoom({})} />
|
||||
{
|
||||
isLoading ? <div className="w-[108px] h-[108px] absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] bg-black/60 rounded-[20px] flex flex-col items-center justify-center">
|
||||
<img src="/icons/loading.gif" alt="loading" className="w-[68px] h-[68px]" />
|
||||
<span className="text-[14px] text-[#fff]">加载中</span>
|
||||
</div> : <></>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import {
|
|||
} from "@/components/Provider/RealtimeClientProvider";
|
||||
import { ReportProvider } from "@/components/Provider/ReportResolveProvider";
|
||||
import { RealtimeUtils } from "@coze/realtime-api";
|
||||
|
||||
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
function MainContent() {
|
||||
const { isConnected } = useContext(RealtimeClientContext);
|
||||
const { isConnected, handleDisconnect } = useContext(RealtimeClientContext);
|
||||
const location = useLocation();
|
||||
|
||||
const handlePromise = async() => {
|
||||
await RealtimeUtils.checkDevicePermission(false);
|
||||
|
|
@ -21,11 +21,16 @@ function MainContent() {
|
|||
handlePromise();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isConnected) {
|
||||
handleDisconnect();
|
||||
}
|
||||
}, [location.pathname]);
|
||||
|
||||
return (
|
||||
<ReportProvider>
|
||||
{isConnected ? <Room /> : <Antechamber />}
|
||||
</ReportProvider>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
.wrapper {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
min-height: 88px;
|
||||
min-width: 88px;
|
||||
background: linear-gradient(180deg, #64c7ff 0%, #0165ff 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -8,8 +10,6 @@
|
|||
align-items: center;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
margin-top: auto;
|
||||
margin-bottom: 80px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@ export default function InvokeButton(props: IInvokeButtonProps) {
|
|||
|
||||
|
||||
return (
|
||||
<div className={`${style.wrapper} ${className}`} {...rest}>
|
||||
<div className={`${className} mt-auto mb-[80px]`} {...rest}>
|
||||
<div className={`mt-[20px] ${style.wrapper}`}>
|
||||
<img className={style.call} src={CallPng} alt="call" />
|
||||
<div className={style.text}>{disable ? '暂不可用':isConnecting?'连接中':'发起通话'}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -6,9 +6,11 @@ import { useSearchParams } from "react-router-dom";
|
|||
import { ReportContext } from "../Provider/ReportResolveProvider";
|
||||
import { FileInfo, RealtimeClientContext } from "../Provider/RealtimeClientProvider";
|
||||
|
||||
type Props = {
|
||||
handleLoading:(val:boolean) => void
|
||||
}
|
||||
|
||||
|
||||
export default function AntechamberFile() {
|
||||
export default function AntechamberFile({handleLoading}:Props) {
|
||||
const [searchParams] = useSearchParams();
|
||||
const fileId = searchParams.get("fileId") || "";
|
||||
const locationCode = searchParams.get("locationCode") || "";
|
||||
|
|
@ -32,7 +34,7 @@ export default function AntechamberFile() {
|
|||
});
|
||||
}
|
||||
let resp = result.result as FileInfo;
|
||||
|
||||
handleLoading(true)
|
||||
handleConnect({
|
||||
fileInfo: {type: resp.type,url: resp.url,tableName: resp.tableName,provinceName: resp.provinceName,subjectClaim: resp.subjectClaim},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
position: relative;
|
||||
z-index: 1;
|
||||
backdrop-filter:blur(10px);
|
||||
min-height: 213px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export default function HeaderGroup() {
|
|||
key={index}
|
||||
onClick={() => handleQuestion(item)}
|
||||
>
|
||||
<div>{item}</div>
|
||||
<div className="text-[14px] text-[#000]">{item}</div>
|
||||
<img
|
||||
src={RightIcon}
|
||||
alt="right-icon"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ import { useSearchParams } from "react-router-dom";
|
|||
import { useAbortController } from "@/hooks/useAbortController";
|
||||
import { RealtimeClientContext } from "../Provider/RealtimeClientProvider";
|
||||
|
||||
export default function AntechamberReport() {
|
||||
type Props = {
|
||||
handleLoading:(val:boolean) => void
|
||||
}
|
||||
|
||||
export default function AntechamberReport({handleLoading}:Props) {
|
||||
const [searchParams] = useSearchParams();
|
||||
const token = searchParams.get("token") || '';
|
||||
const reportId = searchParams.get("reportId") || '';
|
||||
|
|
@ -30,6 +34,7 @@ export default function AntechamberReport() {
|
|||
if (message) {
|
||||
console.log(message);
|
||||
} else {
|
||||
handleLoading(true)
|
||||
handleConnect({initMessage:result as string});
|
||||
setHasHandledReport(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
}
|
||||
|
||||
.innerWrapper {
|
||||
padding: 15px;
|
||||
padding: 12px 15px;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 13px;
|
||||
|
|
@ -21,7 +21,8 @@
|
|||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.right{
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export default function AntechamberWishList() {
|
|||
return (
|
||||
<>
|
||||
{wishList.length > 0 ? (
|
||||
<div className="w-full p-[15px]">
|
||||
<div className="w-full px-[15px]">
|
||||
<div className="px-[12px] pt-[14px] pb-[16px] rounded-[13px] bg-[#fff]">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="w-[96px] h-[16px] object-contain">
|
||||
|
|
@ -95,7 +95,6 @@ export default function AntechamberWishList() {
|
|||
<div className="text-[10px] px-[4px] py-[2px] rounded-[4px] text-[#636363] bg-[#fff]">
|
||||
{item.type}
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div className="text-[#303030] text-[11px] flex items-center">
|
||||
<span>
|
||||
|
|
@ -118,7 +117,7 @@ export default function AntechamberWishList() {
|
|||
<img
|
||||
src="/icons/rightBlue.png"
|
||||
alt=""
|
||||
className="ml-[2px]"
|
||||
className="ml-[2px] w-[10px] h-[10px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -163,7 +162,7 @@ export default function AntechamberWishList() {
|
|||
onClick={() => handleNavigate(wishList[0])}
|
||||
>
|
||||
智能分析
|
||||
<img src="/icons/rightBlue.png" alt="" className="ml-[2px]" />
|
||||
<img src="/icons/rightBlue.png" alt="" className="ml-[2px] w-[10px] h-[10px]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ export const RealtimeClientProvider = ({
|
|||
const connectorId = "1024";
|
||||
|
||||
const clientRef = useRef<RealtimeClient | null>(null);
|
||||
// 添加连接锁
|
||||
const connectingLockRef = useRef<boolean>(false);
|
||||
// 实时语音回复消息列表
|
||||
const [messageList, setMessageList] = useState<
|
||||
{ content: string; role: RoleType; event?: any }[]
|
||||
|
|
@ -166,6 +168,18 @@ export const RealtimeClientProvider = ({
|
|||
fileInfo?: FileInfo;
|
||||
}) => {
|
||||
try {
|
||||
// 使用连接锁确保原子性
|
||||
if (connectingLockRef.current) {
|
||||
return;
|
||||
}
|
||||
connectingLockRef.current = true;
|
||||
|
||||
// 如果已经连接或正在连接中,直接返回
|
||||
if (isConnected || isConnecting) {
|
||||
connectingLockRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clientRef.current) {
|
||||
await initClient({ initMessage, fileInfo });
|
||||
}
|
||||
|
|
@ -192,6 +206,9 @@ export const RealtimeClientProvider = ({
|
|||
} else {
|
||||
console.error("连接错误:" + error);
|
||||
}
|
||||
} finally {
|
||||
// 确保在任何情况下都释放连接锁
|
||||
connectingLockRef.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue