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:
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
{/* 视频下方控制栏 */}
|
{/* 视频下方控制栏 */}
|
||||||
|
|||||||
@@ -51,22 +51,13 @@ export function ChatPanel({ messages, currentReply, connectionStatus, onSendText
|
|||||||
setInputText("");
|
setInputText("");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 空状态
|
// 未连接时的空状态
|
||||||
if (messages.length === 0 && !currentReply) {
|
if (!isConnected) {
|
||||||
if (!isConnected) {
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
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>
|
</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"
|
||||||
|
|||||||
@@ -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. 尝试获取摄像头(可选)
|
||||||
await startVAD(micStream);
|
try {
|
||||||
|
await startCamera();
|
||||||
|
setIsCameraOn(true);
|
||||||
|
} catch {
|
||||||
|
console.warn("[Session] 无法获取摄像头权限,将以纯文本模式运行");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 尝试获取麦克风(可选)
|
||||||
|
const micStream = await startMic();
|
||||||
|
if (micStream) {
|
||||||
|
setIsMicOn(true);
|
||||||
|
// 4. 启动 VAD(仅在麦克风可用时)
|
||||||
|
await startVAD(micStream);
|
||||||
|
} else {
|
||||||
|
console.warn("[Session] 无法获取麦克风权限,将以文本输入模式运行");
|
||||||
|
}
|
||||||
}, [startCamera, startMic, connect, startVAD]);
|
}, [startCamera, startMic, connect, startVAD]);
|
||||||
|
|
||||||
/** 结束会话 */
|
/** 结束会话 */
|
||||||
|
|||||||
Reference in New Issue
Block a user