建房预检测

This commit is contained in:
mtvpls
2026-04-05 10:38:42 +08:00
parent 2ab48b678f
commit 14d4c483f3
2 changed files with 123 additions and 5 deletions
+69 -4
View File
@@ -8,12 +8,41 @@ import { useEffect,useState } from 'react';
import { getAuthInfoFromBrowserCookie } from '@/lib/auth';
import PageLayout from '@/components/PageLayout';
import Toast, { ToastProps } from '@/components/Toast';
import { useWatchRoomContext } from '@/components/WatchRoomProvider';
import type { Room, RoomType } from '@/types/watch-room';
type TabType = 'create' | 'join' | 'list';
function getScreenShareHostSupportError() {
if (typeof window === 'undefined') return null;
if (!window.isSecureContext) {
return '当前环境不是安全上下文(HTTPS/localhost),不支持屏幕共享';
}
if (!navigator.mediaDevices?.getDisplayMedia) {
return '当前浏览器不支持屏幕共享';
}
if (typeof window.RTCPeerConnection === 'undefined') {
return '当前浏览器不支持实时屏幕传输';
}
return null;
}
function getScreenShareViewerSupportError() {
if (typeof window === 'undefined') return null;
if (typeof window.RTCPeerConnection === 'undefined') {
return '当前浏览器不支持实时屏幕传输';
}
return null;
}
export default function WatchRoomPage() {
const router = useRouter();
const watchRoom = useWatchRoomContext();
@@ -48,6 +77,16 @@ export default function WatchRoomPage() {
const [loading, setLoading] = useState(false);
const [createLoading, setCreateLoading] = useState(false);
const [joinLoading, setJoinLoading] = useState(false);
const [toast, setToast] = useState<ToastProps | null>(null);
const showToast = (message: string, type: ToastProps['type'] = 'info') => {
setToast({
message,
type,
duration: 3000,
onClose: () => setToast(null),
});
};
// 加载房间列表
const loadRooms = async (showLoading = false) => {
@@ -82,10 +121,18 @@ export default function WatchRoomPage() {
const handleCreateRoom = async (e: React.FormEvent) => {
e.preventDefault();
if (!createForm.roomName.trim()) {
alert('请输入房间名称');
showToast('请输入房间名称', 'error');
return;
}
if (createForm.roomType === 'screen') {
const supportError = getScreenShareHostSupportError();
if (supportError) {
showToast(`当前设备无法创建屏幕共享房间:${supportError}`, 'error');
return;
}
}
setCreateLoading(true);
try {
await createRoom({
@@ -106,7 +153,7 @@ export default function WatchRoomPage() {
roomType: 'sync',
});
} catch (error: any) {
alert(error.message || '创建房间失败');
showToast(error.message || '创建房间失败', 'error');
} finally {
setCreateLoading(false);
}
@@ -117,10 +164,19 @@ export default function WatchRoomPage() {
e.preventDefault();
const targetRoomId = roomId || joinForm.roomId.trim().toUpperCase();
if (!targetRoomId) {
alert('请输入房间ID');
showToast('请输入房间ID', 'error');
return;
}
const targetRoom = rooms.find((room) => room.id === targetRoomId);
if (targetRoom?.roomType === 'screen') {
const supportError = getScreenShareViewerSupportError();
if (supportError) {
showToast(`当前设备无法加入屏幕共享房间:${supportError}`, 'error');
return;
}
}
setJoinLoading(true);
try {
const result = await joinRoom({
@@ -138,7 +194,7 @@ export default function WatchRoomPage() {
// 注意:加入房间后,isOwner 状态会在 useWatchRoom 中更新
// 跳转逻辑会在 useEffect 中处理
} catch (error: any) {
alert(error.message || '加入房间失败');
showToast(error.message || '加入房间失败', 'error');
} finally {
setJoinLoading(false);
}
@@ -219,6 +275,14 @@ export default function WatchRoomPage() {
// 从房间列表加入房间
const handleJoinFromList = (room: Room) => {
if (room.roomType === 'screen') {
const supportError = getScreenShareViewerSupportError();
if (supportError) {
showToast(`当前设备无法加入屏幕共享房间:${supportError}`, 'error');
return;
}
}
setJoinForm({
roomId: room.id,
password: '',
@@ -810,6 +874,7 @@ export default function WatchRoomPage() {
)}
</div>
</div>
{toast && <Toast {...toast} />}
</PageLayout>
);
}
+54 -1
View File
@@ -3,17 +3,47 @@
import { Monitor, MonitorPlay, Users } from 'lucide-react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import Toast, { ToastProps } from '@/components/Toast';
import { useWatchRoomContext } from '@/components/WatchRoomProvider';
import { useScreenShare } from '@/hooks/useScreenShare';
const NEW_TAB_KEY_PREFIX = 'watch_room_screen_home_opened_';
function getScreenShareHostSupportError() {
if (typeof window === 'undefined') return null;
if (!window.isSecureContext) {
return '当前环境不是安全上下文(HTTPS/localhost),不支持屏幕共享';
}
if (!navigator.mediaDevices?.getDisplayMedia) {
return '当前浏览器不支持屏幕共享';
}
if (typeof window.RTCPeerConnection === 'undefined') {
return '当前浏览器不支持实时屏幕传输';
}
return null;
}
function getScreenShareViewerSupportError() {
if (typeof window === 'undefined') return null;
if (typeof window.RTCPeerConnection === 'undefined') {
return '当前浏览器不支持实时屏幕传输';
}
return null;
}
export default function WatchRoomScreenPage() {
const router = useRouter();
const watchRoom = useWatchRoomContext();
const { currentRoom, members, leaveRoom } = watchRoom;
const [toast, setToast] = useState<ToastProps | null>(null);
const {
currentRoom: screenRoom,
isOwner,
@@ -26,6 +56,15 @@ export default function WatchRoomScreenPage() {
stopSharing,
} = useScreenShare();
const showToast = (message: string, type: ToastProps['type'] = 'info') => {
setToast({
message,
type,
duration: 3000,
onClose: () => setToast(null),
});
};
useEffect(() => {
if (!currentRoom) {
router.replace('/watch-room');
@@ -37,6 +76,19 @@ export default function WatchRoomScreenPage() {
}
}, [currentRoom, router]);
useEffect(() => {
if (!screenRoom || screenRoom.roomType !== 'screen') return;
const supportError = isOwner
? getScreenShareHostSupportError()
: getScreenShareViewerSupportError();
if (supportError) {
showToast(`当前设备无法使用屏幕共享房间:${supportError}`, 'error');
leaveRoom();
router.replace('/watch-room');
}
}, [isOwner, leaveRoom, router, screenRoom?.id, screenRoom?.roomType]);
useEffect(() => {
if (!screenRoom || !isOwner) return;
@@ -196,6 +248,7 @@ export default function WatchRoomScreenPage() {
</div>
</div>
</div>
{toast && <Toast {...toast} />}
</div>
);
}