chore:更新欢迎语和快捷问题的样式,点击输入框隐藏欢迎语整体
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user