Merge pull request '优化无麦克风和摄像头场景的使用' (#65) from frontend-11 into develop

Reviewed-on: http://8.161.227.145:3000/XEngineers/CamTalk/pulls/65
This commit was merged in pull request #65.
This commit is contained in:
2026-06-14 13:19:15 +08:00
4 changed files with 75 additions and 29 deletions

View File

@@ -265,6 +265,11 @@ body {
margin-bottom: 4px; margin-bottom: 4px;
} }
.video-placeholder__hint {
font-size: 0.72rem;
opacity: 0.6;
}
.video-indicator { .video-indicator {
position: absolute; position: absolute;
bottom: 16px; bottom: 16px;
@@ -488,6 +493,32 @@ body {
gap: 12px; gap: 12px;
} }
.chat-panel__welcome {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
gap: 12px;
color: var(--color-text-muted);
font-size: 0.85rem;
padding: 40px 0;
}
.chat-panel__welcome-icon {
font-size: 2.4rem;
opacity: 0.12;
margin-bottom: 4px;
}
.chat-panel__welcome-hint {
font-size: 0.75rem;
opacity: 0.6;
max-width: 240px;
text-align: center;
line-height: 1.5;
}
.chat-panel--empty { .chat-panel--empty {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -173,6 +173,16 @@ function App() {
<span></span> <span></span>
</div> </div>
)} )}
{isConnected && !isCameraOn && (
<div className="video-placeholder">
<svg className="video-placeholder__icon" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round">
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" />
<circle cx="12" cy="13" r="4" />
</svg>
<span></span>
<span className="video-placeholder__hint"></span>
</div>
)}
</div> </div>
{/* 视频下方控制栏 */} {/* 视频下方控制栏 */}

View File

@@ -51,22 +51,13 @@ export function ChatPanel({ messages, currentReply, connectionStatus, onSendText
setInputText(""); setInputText("");
}; };
// 空状态 // 未连接时的空状态
if (messages.length === 0 && !currentReply) {
if (!isConnected) { if (!isConnected) {
return ( return (
<div className="chat-panel chat-panel--empty"> <div className="chat-panel chat-panel--empty">
<span className="chat-panel--empty-icon">💬</span> <span className="chat-panel--empty-icon">💬</span>
<p></p> <p></p>
<span className="chat-panel--empty-hint"> AI </span> <span className="chat-panel--empty-hint"> AI </span>
</div>
);
}
return (
<div className="chat-panel chat-panel--empty">
<span className="chat-panel--empty-icon">🎙</span>
<p></p>
<span className="chat-panel--empty-hint">AI </span>
</div> </div>
); );
} }
@@ -74,6 +65,15 @@ export function ChatPanel({ messages, currentReply, connectionStatus, onSendText
return ( return (
<div className="chat-panel"> <div className="chat-panel">
<div className="chat-panel__messages" ref={containerRef}> <div className="chat-panel__messages" ref={containerRef}>
{/* 空状态提示 */}
{messages.length === 0 && !currentReply && (
<div className="chat-panel__welcome">
<span className="chat-panel__welcome-icon">💬</span>
<p></p>
<span className="chat-panel__welcome-hint"></span>
</div>
)}
{messages.map((msg, index) => ( {messages.map((msg, index) => (
<div key={index} className={`chat-message chat-message--${msg.role}`}> <div key={index} className={`chat-message chat-message--${msg.role}`}>
<div className="chat-message__role"> <div className="chat-message__role">
@@ -104,8 +104,8 @@ export function ChatPanel({ messages, currentReply, connectionStatus, onSendText
<div ref={bottomRef} /> <div ref={bottomRef} />
</div> </div>
{/* 文本输入框 */} {/* 文本输入框 - 连接后始终显示 */}
{isConnected && onSendText && ( {onSendText && (
<form className="chat-input" onSubmit={handleSubmit}> <form className="chat-input" onSubmit={handleSubmit}>
<input <input
type="text" type="text"

View File

@@ -284,21 +284,26 @@ export function useVisionSession() {
/** 启动会话 */ /** 启动会话 */
const startSession = useCallback(async () => { const startSession = useCallback(async () => {
// 1. 获取摄像头和麦克风 // 1. 连接 WebSocket必须
await startCamera();
setIsCameraOn(true);
const micStream = await startMic();
if (!micStream) {
showToast("无法获取麦克风权限", "error");
return;
}
setIsMicOn(true);
// 2. 连接 WebSocket
connect(); connect();
// 3. 启动 VAD传入麦克风 stream // 2. 尝试获取摄像头(可选
try {
await startCamera();
setIsCameraOn(true);
} catch {
console.warn("[Session] 无法获取摄像头权限,将以纯文本模式运行");
}
// 3. 尝试获取麦克风(可选)
const micStream = await startMic();
if (micStream) {
setIsMicOn(true);
// 4. 启动 VAD仅在麦克风可用时
await startVAD(micStream); await startVAD(micStream);
} else {
console.warn("[Session] 无法获取麦克风权限,将以文本输入模式运行");
}
}, [startCamera, startMic, connect, startVAD]); }, [startCamera, startMic, connect, startVAD]);
/** 结束会话 */ /** 结束会话 */