chore:更新欢迎语和快捷问题的样式,点击输入框隐藏欢迎语整体

This commit is contained in:
2026-09-30 16:02:20 +08:00
parent 53be343159
commit 4172da6201

View File

@@ -195,8 +195,8 @@
</view>
</view>
<!-- AI消息 -->
<view v-else class="ai-message">
<!-- AI消息: 欢迎语(含快捷问题)在输入框聚焦 或 已发送用户消息后整体隐藏 -->
<view v-else class="ai-message" v-show="!(message.isWelcome && (inputFocused || hasUserMessage))">
<!-- PR-CHAT-UI-CONFIG-V3 (2026-09-24): ui_show_assistant_avatar 控制头像显隐; 自定义头像在 aiAvatarUrl computed 优先 -->
<view class="avatar" v-if="chatUiConfig.ui_show_assistant_avatar">
<!-- 智能客服头像 -->
@@ -377,14 +377,13 @@
<!-- PR-WELCOME-QUICK-CHIPS (2026-09-19): 欢迎语配套快捷问题
欢迎语气泡下方显示快捷问题 chips, 点击直接作为用户消息发送
一次性,点了之后从 message 上摘除 (避免重复点) -->
<view v-if="message.quickQuestions && message.quickQuestions.length > 0" class="quick-questions-row">
<view v-if="message.quickQuestions && message.quickQuestions.length > 0 && !inputFocused" class="quick-questions-row">
<view
v-for="(q, qi) in message.quickQuestions"
:key="qi"
class="quick-question-chip"
hover-class="quick-question-chip--hover"
@click="onQuickQuestionClick(message, q)">
<text class="quick-question-icon">💬</text>
<text class="quick-question-text">{{ getQuickQuestionText(q) }}</text>
</view>
</view>
@@ -440,20 +439,27 @@
<!-- AI 消息下方操作栏: 复制 / 点赞 / 不喜欢 / 更多 -->
<!-- PR-CHAT-UI-CONFIG (2026-09-20): 后端可关闭 ui_enable_feedback (隐藏点赞/点踩/更多), 默认 true -->
<!-- PR-AI-ACTIONS-AFTER-DONE (2026-09-28): 仅在 AI 完全回答完成后才显示操作栏 (排除流式中), 避免一边打字一边出现复制/点赞按钮的"半成品"感 -->
<view class="ai-actions" v-if="message.role === 'ai' && message.type !== 'loading' && !message.isStreaming && chatUiConfig.ui_enable_feedback">
<view class="ai-action-btn" @click="onAiActionCopy(message)">
<text class="iconfont icon-copy">⎘</text>
</view>
<view class="ai-action-btn" :class="{ active: message._liked }" @click="onAiActionLike(message)">
<!-- PR-FRONTEND-ACTION-SVG-ICON (2026-09-18): 点赞/点踩改用线性 SVG 矢量图, 不再用彩色 emoji -->
<view class="svg-icon icon-like"></view>
</view>
<view class="ai-action-btn" :class="{ active: message._disliked }" @click="onAiActionDislike(message)">
<view class="svg-icon icon-dislike"></view>
</view>
<view class="ai-action-btn more-btn" @click="onAiActionMore(message)">
<text class="iconfont icon-more">···</text>
<view class="ai-actions" v-if="message.role === 'ai' && message.type !== 'loading' && !message.isStreaming && (chatUiConfig.ui_enable_feedback || message.isWelcome)">
<!-- 欢迎语下方操作栏: 换成"换一换" -->
<view v-if="message.isWelcome" class="ai-action-btn refresh-welcome-btn" @click="onAiActionRefreshWelcome(message)">
<view class="refresh-icon"></view>
<text class="refresh-text">换一换</text>
</view>
<template v-else>
<view class="ai-action-btn" @click="onAiActionCopy(message)">
<text class="iconfont icon-copy">⎘</text>
</view>
<view class="ai-action-btn" :class="{ active: message._liked }" @click="onAiActionLike(message)">
<!-- PR-FRONTEND-ACTION-SVG-ICON (2026-09-18): 点赞/点踩改用线性 SVG 矢量图, 不再用彩色 emoji -->
<view class="svg-icon icon-like"></view>
</view>
<view class="ai-action-btn" :class="{ active: message._disliked }" @click="onAiActionDislike(message)">
<view class="svg-icon icon-dislike"></view>
</view>
<view class="ai-action-btn more-btn" @click="onAiActionMore(message)">
<text class="iconfont icon-more">···</text>
</view>
</template>
</view>
</view>
@@ -982,6 +988,10 @@ export default {
hasInputText() {
return this.inputText && this.inputText.trim() !== ''
},
// PR-WELCOME-HIDE-AFTER-SEND: 一旦用户发送过消息, 欢迎语消息就不再显示
hasUserMessage() {
return this.messages.some(m => m.role === 'user' && m.content && m.content.trim() !== '')
},
// PR-FRONTEND-INPUT-3STATES (2026-09-17): 文字输入态
// 聚焦 或 已有文字时展开为"输入框一行 + 工具栏一行", 否则回到单行胶囊。
// 用聚焦(而不是只判断文字)是为了: 删除最后一个字时布局不会突然塌回胶囊。
@@ -1779,7 +1789,9 @@ export default {
// PR-WELCOME-QUICK-CHIPS (2026-09-19): 欢迎语配套快捷问题 (chips)
// 后端可存 string[] 或 {id,text}[] ,前端统一归一化为 string[]
// message.quickQuestions 数组非空 → 模板渲染 chips;点击调 onQuickQuestionClick
quickQuestions: this.normalizeQuickQuestions(welcomeInfo && welcomeInfo.quick_questions)
quickQuestions: this.normalizeQuickQuestions(welcomeInfo && welcomeInfo.quick_questions),
// PR-WELCOME-HIDE-AFTER-SEND: 标记这是欢迎语消息, 发送第一条用户消息后永久隐藏
isWelcome: true
}
this.messages.push(welcomeMsg)
this.$nextTick(() => this.scrollToBottom())
@@ -3752,6 +3764,16 @@ _handleStreamError(msg) {
} catch (e) { /* noop */ }
},
// 欢迎语"换一换": 移除当前欢迎语并重新加载(刷新快捷问题)
onAiActionRefreshWelcome(message) {
try {
const idx = this.messages.findIndex(m => m && m.id === message.id)
if (idx !== -1) this.messages.splice(idx, 1)
this._welcomeLoading = false
this._loadWelcomeMessage()
} catch (e) { /* noop */ }
},
// 去掉 markdown 标记, 用于 TTS 朗读
_stripMarkdown(text) {
if (!text) return ''
@@ -5247,19 +5269,18 @@ _handleStreamError(msg) {
.quick-questions-row {
margin-top: 16rpx;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
flex-direction: column;
align-items: flex-start;
max-width: 100%;
.quick-question-chip {
display: inline-flex;
align-items: center;
margin-right: 16rpx;
margin-bottom: 16rpx;
padding: 12rpx 24rpx;
background: #ffffff;
border: 1rpx solid #1a1a1a;
border-radius: 32rpx;
border: 1rpx solid #d9d9d9;
border-radius: 28rpx;
font-size: 26rpx;
color: #1a1a1a;
cursor: pointer;
@@ -5267,10 +5288,8 @@ _handleStreamError(msg) {
max-width: 100%;
line-height: 1.4;
.quick-question-icon {
font-size: 24rpx;
flex-shrink: 0;
margin-right: 8rpx;
&:last-child {
margin-bottom: 0;
}
.quick-question-text {
@@ -5281,10 +5300,8 @@ _handleStreamError(msg) {
}
.quick-question-chip--hover {
background: #1a1a1a;
color: #ffffff;
transform: translateY(-1rpx);
box-shadow: 0 4rpx 12rpx rgba(26, 26, 26, 0.2);
background: #e4e5e7;
color: #1a1a1a;
}
}
@@ -5676,6 +5693,29 @@ _handleStreamError(msg) {
}
}
/* 欢迎语操作栏: 换一换按钮 */
&.refresh-welcome-btn {
height: 56rpx;
padding: 0 20rpx;
gap: 8rpx;
.refresh-icon {
width: 28rpx;
height: 28rpx;
flex-shrink: 0;
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMjEgMTJhOSA5IDAgMSAxLTktOSA5Ljc1IDkuNzUgMCAwIDEgNi4zNiAyLjM2TDIxIDMiLz48cGF0aCBkPSJNMjEgM3Y2aC02Ii8+PC9zdmc+");
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
.refresh-text {
font-size: 24rpx;
color: #666;
line-height: 1;
}
}
&:active {
background: #ebebeb;
}