|
|
@@ -215,6 +215,9 @@ export const ChatBotPage = () => {
|
|
|
const hasSentScenarioContextRef = useRef(false);
|
|
|
// 特殊场景:用户点击录音后收起凳子上形象、恢复中间动画形象
|
|
|
const [specialSceneAvatarDismissed, setSpecialSceneAvatarDismissed] = useState(false);
|
|
|
+ // 首句场景是否已确定:未确定前不显示中间动画,避免「先出现再消失」的闪烁;确定后按 default/特殊场景分别显示
|
|
|
+ const [hasGreetingScenarioResolved, setHasGreetingScenarioResolved] = useState(false);
|
|
|
+ const hasReceivedGreetingContextRef = useRef(false);
|
|
|
const greetingContextRef = useRef(greetingContext);
|
|
|
useEffect(() => {
|
|
|
greetingContextRef.current = greetingContext;
|
|
|
@@ -2266,6 +2269,8 @@ export const ChatBotPage = () => {
|
|
|
|
|
|
switch (message.type) {
|
|
|
case 'greeting_context': {
|
|
|
+ hasReceivedGreetingContextRef.current = true;
|
|
|
+ setHasGreetingScenarioResolved(true); // 已收到场景,可直接按场景展示(中间动画或凳子上 GIF)
|
|
|
const ctx = message as unknown as GreetingContextMessage;
|
|
|
if (ctx.scene && ctx.scene !== 'default' && Array.isArray(ctx.topics) && ctx.topics.length > 0) {
|
|
|
setGreetingContext({
|
|
|
@@ -2291,6 +2296,10 @@ export const ChatBotPage = () => {
|
|
|
if (message.source === 'user') {
|
|
|
break;
|
|
|
}
|
|
|
+ // 首句为 default 时后端不发 greeting_context,收到 greeting_ 的 text_result 即表示场景已确定为 default
|
|
|
+ if (isGreetingMessage && !hasReceivedGreetingContextRef.current) {
|
|
|
+ setHasGreetingScenarioResolved(true);
|
|
|
+ }
|
|
|
const cleaned = cleanSubtitleText(message.text);
|
|
|
// 🔥 首句/切换话题首句消息:直接处理,不检查 activeRequestId
|
|
|
if (isGreetingOrTopicFirstLine) {
|
|
|
@@ -2387,6 +2396,9 @@ export const ChatBotPage = () => {
|
|
|
case 'emotion':
|
|
|
// 🔥 首句/切换话题首句:直接处理,不检查 activeRequestId
|
|
|
if (isGreetingOrTopicFirstLine) {
|
|
|
+ if (isGreetingMessage && !hasReceivedGreetingContextRef.current) {
|
|
|
+ setHasGreetingScenarioResolved(true); // 首句为 default 时先收到 emotion,场景已确定
|
|
|
+ }
|
|
|
performanceLogger.recordEmotion(requestId, message.emotion, message.timestamp);
|
|
|
setEmotion(message.emotion);
|
|
|
// 🔥 仅缓存情绪,不立即切换 GIF,等待首句音频真正开始播放时再驱动动画
|
|
|
@@ -3305,9 +3317,8 @@ export const ChatBotPage = () => {
|
|
|
);
|
|
|
})}
|
|
|
|
|
|
- {/* AnimaZone 动画形象 - 双 img 固定角色:default 层永远 default;对话层 emotion→talking,放下时静默换 default;
|
|
|
- 特殊场景下未点击录音时隐藏,点击录音后显示 */}
|
|
|
- {!(greetingContext?.scene && greetingContext.scene !== 'default' && !specialSceneAvatarDismissed) && (
|
|
|
+ {/* AnimaZone 动画形象 - 场景未确定前不显示,避免特殊场景下「先出现再消失」;确定后:默认场景直接显示,特殊场景下未点击录音时隐藏、点击录音后显示 */}
|
|
|
+ {hasGreetingScenarioResolved && !(greetingContext?.scene && greetingContext.scene !== 'default' && !specialSceneAvatarDismissed) && (
|
|
|
<div
|
|
|
className="chatbot-anima-zone-avatar absolute"
|
|
|
style={{
|
|
|
@@ -3459,8 +3470,8 @@ export const ChatBotPage = () => {
|
|
|
</div>
|
|
|
)}
|
|
|
|
|
|
- {/* Yp 图片 - 设计稿 393×852,相对动画形象顶部 191,64×14;特殊场景下点击录音后再显示 */}
|
|
|
- {!(greetingContext?.scene && greetingContext.scene !== 'default' && !specialSceneAvatarDismissed) && (
|
|
|
+ {/* Yp 图片 - 设计稿 393×852,相对动画形象顶部 191,64×14;场景确定后且非特殊场景未点录音时才显示 */}
|
|
|
+ {hasGreetingScenarioResolved && !(greetingContext?.scene && greetingContext.scene !== 'default' && !specialSceneAvatarDismissed) && (
|
|
|
<div
|
|
|
className="absolute"
|
|
|
style={{
|