|
@@ -203,6 +203,8 @@ export const ChatBotPage = () => {
|
|
|
firstLine: string;
|
|
firstLine: string;
|
|
|
} | null>(null);
|
|
} | null>(null);
|
|
|
const [currentTopicIndex, setCurrentTopicIndex] = useState(0);
|
|
const [currentTopicIndex, setCurrentTopicIndex] = useState(0);
|
|
|
|
|
+ // 情景对话:是否已经在当前场景当前话题下真正开始对话(首条语音已发送)
|
|
|
|
|
+ const [scenarioConversationStarted, setScenarioConversationStarted] = useState(false);
|
|
|
const hasSentScenarioContextRef = useRef(false);
|
|
const hasSentScenarioContextRef = useRef(false);
|
|
|
const greetingContextRef = useRef(greetingContext);
|
|
const greetingContextRef = useRef(greetingContext);
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
@@ -2266,9 +2268,11 @@ export const ChatBotPage = () => {
|
|
|
const idx = ctx.topics.findIndex((t) => t.key === ctx.topic);
|
|
const idx = ctx.topics.findIndex((t) => t.key === ctx.topic);
|
|
|
setCurrentTopicIndex(idx >= 0 ? idx : 0);
|
|
setCurrentTopicIndex(idx >= 0 ? idx : 0);
|
|
|
hasSentScenarioContextRef.current = false;
|
|
hasSentScenarioContextRef.current = false;
|
|
|
|
|
+ setScenarioConversationStarted(false);
|
|
|
if (ctx.firstLine) setRecognizedText(ctx.firstLine);
|
|
if (ctx.firstLine) setRecognizedText(ctx.firstLine);
|
|
|
} else {
|
|
} else {
|
|
|
setGreetingContext(null);
|
|
setGreetingContext(null);
|
|
|
|
|
+ setScenarioConversationStarted(false);
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
@@ -2677,6 +2681,7 @@ export const ChatBotPage = () => {
|
|
|
!hasSentScenarioContextRef.current
|
|
!hasSentScenarioContextRef.current
|
|
|
? (() => {
|
|
? (() => {
|
|
|
hasSentScenarioContextRef.current = true;
|
|
hasSentScenarioContextRef.current = true;
|
|
|
|
|
+ setScenarioConversationStarted(true);
|
|
|
return { scene: ctx.scene, topic: ctx.topic };
|
|
return { scene: ctx.scene, topic: ctx.topic };
|
|
|
})()
|
|
})()
|
|
|
: undefined;
|
|
: undefined;
|
|
@@ -2787,6 +2792,7 @@ export const ChatBotPage = () => {
|
|
|
ctx && ctx.scene !== 'default' && !hasSentScenarioContextRef.current
|
|
ctx && ctx.scene !== 'default' && !hasSentScenarioContextRef.current
|
|
|
? (() => {
|
|
? (() => {
|
|
|
hasSentScenarioContextRef.current = true;
|
|
hasSentScenarioContextRef.current = true;
|
|
|
|
|
+ setScenarioConversationStarted(true);
|
|
|
return { scene: ctx.scene, topic: ctx.topic };
|
|
return { scene: ctx.scene, topic: ctx.topic };
|
|
|
})()
|
|
})()
|
|
|
: undefined;
|
|
: undefined;
|
|
@@ -3289,7 +3295,8 @@ export const ChatBotPage = () => {
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- {/* 情景对话:字幕区域上方话题名称 + 切换话题按钮(仅特殊场景展示),与字幕左对齐 */}
|
|
|
|
|
|
|
+ {/* 情景对话:字幕区域上方话题名称 + 切换话题按钮(仅特殊场景展示),与字幕左对齐;
|
|
|
|
|
+ 用户在该场景该话题下开始对话后仅隐藏“切换话题按钮”,话题标签仍保留 */}
|
|
|
{greetingContext && greetingContext.scene !== 'default' && greetingContext.topics.length > 0 && (() => {
|
|
{greetingContext && greetingContext.scene !== 'default' && greetingContext.topics.length > 0 && (() => {
|
|
|
const currentTopic = greetingContext.topics[currentTopicIndex];
|
|
const currentTopic = greetingContext.topics[currentTopicIndex];
|
|
|
const topicLabel = currentTopic
|
|
const topicLabel = currentTopic
|
|
@@ -3299,7 +3306,8 @@ export const ChatBotPage = () => {
|
|
|
<div
|
|
<div
|
|
|
className="absolute flex items-center"
|
|
className="absolute flex items-center"
|
|
|
style={{
|
|
style={{
|
|
|
- top: px2vmin(530 - 32 - 8, 'v2'),
|
|
|
|
|
|
|
+ // 保持与字幕容器间距 5px,字幕 top=540、高度 72
|
|
|
|
|
+ top: px2vmin(540 - 32 - 5, 'v2'),
|
|
|
left: '50%',
|
|
left: '50%',
|
|
|
transform: 'translateX(-50%)',
|
|
transform: 'translateX(-50%)',
|
|
|
width: px2vmin(312, 'v2'),
|
|
width: px2vmin(312, 'v2'),
|
|
@@ -3322,6 +3330,7 @@ export const ChatBotPage = () => {
|
|
|
>
|
|
>
|
|
|
{topicLabel}
|
|
{topicLabel}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ {!scenarioConversationStarted && (
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
aria-label="Switch topic"
|
|
aria-label="Switch topic"
|
|
@@ -3333,6 +3342,10 @@ export const ChatBotPage = () => {
|
|
|
minHeight: px2vmin(32, 'v2'),
|
|
minHeight: px2vmin(32, 'v2'),
|
|
|
}}
|
|
}}
|
|
|
onClick={wrapTrackedClick('chatbot', 'topic_toggle', () => {
|
|
onClick={wrapTrackedClick('chatbot', 'topic_toggle', () => {
|
|
|
|
|
+ // AI 语音播放中或发送中时禁止切换话题,避免话题与字幕不一致
|
|
|
|
|
+ if (currentState === 'playing' || currentState === 'sending') {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
const next = (currentTopicIndex + 1) % greetingContext.topics.length;
|
|
const next = (currentTopicIndex + 1) % greetingContext.topics.length;
|
|
|
setCurrentTopicIndex(next);
|
|
setCurrentTopicIndex(next);
|
|
|
const nextTopic = greetingContext.topics[next];
|
|
const nextTopic = greetingContext.topics[next];
|
|
@@ -3353,18 +3366,19 @@ export const ChatBotPage = () => {
|
|
|
draggable={false}
|
|
draggable={false}
|
|
|
/>
|
|
/>
|
|
|
</button>
|
|
</button>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|
|
|
})()}
|
|
})()}
|
|
|
- {/* 字幕区域 - 设计稿 393×852:top 500,高 92,宽 312,左右居中 */}
|
|
|
|
|
|
|
+ {/* 字幕区域 - 设计稿 393×852:top 510(按钮上方 10px),高 72,宽 312,左右居中 */}
|
|
|
{subtitleOn && subtitleVisible && recognizedText && (
|
|
{subtitleOn && subtitleVisible && recognizedText && (
|
|
|
<div
|
|
<div
|
|
|
ref={subtitleContainerRef}
|
|
ref={subtitleContainerRef}
|
|
|
className="chatbot-subtitle-container"
|
|
className="chatbot-subtitle-container"
|
|
|
style={{
|
|
style={{
|
|
|
position: 'absolute',
|
|
position: 'absolute',
|
|
|
- // 设计稿 393×852:top 500px → 使用 px2vmin 按 min(vw, vh) 适配
|
|
|
|
|
- top: px2vmin(530, 'v2'),
|
|
|
|
|
|
|
+ // 设计稿 393×852:在原基础上整体向下移动 30px → 顶部 540
|
|
|
|
|
+ top: px2vmin(540, 'v2'),
|
|
|
left: '50%',
|
|
left: '50%',
|
|
|
transform: 'translateX(-50%)',
|
|
transform: 'translateX(-50%)',
|
|
|
// 设计稿宽度 312px、高度 92px
|
|
// 设计稿宽度 312px、高度 92px
|