@@ -61,7 +61,8 @@
:key="getMessageKey(message, index)"
:id="getMessageKey(message, index)"
class="message-item"
:class="[message.role, { 'first-message': index === 0, 'search-current': showSearchBar && searchResultFilteredIndex === index, 'search-flash': showSearchBar && searchFlashAnimatingIndex === index }]">
:class="[message.role, { 'first-message': index === 0, 'is-welcome': message.isWelcome, ' search-current': showSearchBar && searchResultFilteredIndex === index, 'search-flash': showSearchBar && searchFlashAnimatingIndex === index }]"
v-if="!(message.isWelcome && (inputFocused || hasUserMessage))">
<!-- 用户消息 (WorkBuddy 风格: 右对齐 + 浅灰气泡 + 头像在右) -->
<view v-if="message.role === 'user'" class="user-message">
@@ -223,8 +224,8 @@
</view>
</view>
<!-- AI 回答上方只显示时间(昵称"智能助手"已按需求移除) -->
<view class="message-nickname ai-nickname" v-if="chatUiConfig.ui_show_message_time">
<!-- AI 回答上方只显示时间(昵称"智能助手"已按需求移除);欢迎语消息不显示时间 -->
<view class="message-nickname ai-nickname" v-if="chatUiConfig.ui_show_message_time && !message.isWelcome ">
<text class="message-time">{{ formatTime(message.timestamp) }}</text>
</view>
<view class="message-bubble">
@@ -377,14 +378,17 @@
<!-- 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>
<view
class="quick-question-icon"
:style="{ backgroundImage: 'url(' + quickQuestionIconList[(qi + (message._qqBatchIndex || 0) * 4) % quickQuestionIconList.length] + ')' }">
</view>
<text class="quick-question-text">{{ getQuickQuestionText(q) }}</text>
</view>
</view>
@@ -440,20 +444,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>
@@ -835,6 +846,17 @@ export default {
_voiceHoldStartY: 0,
_voiceHoldLastLevel: 0,
voiceLevel: 0,
// PR-WELCOME-QUICK-ICONS: 快捷问题前面的随机图标库 (base64 SVG)
quickQuestionIconList: [
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48Y2lyY2xlIGN4PSIxMSIgY3k9IjExIiByPSI3Ii8+PHBhdGggZD0iTTIxIDIxbC00LjM1LTQuMzUiLz48L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNNCA0aDE2djE2SDR6Ii8+PHBhdGggZD0iTTggOWg4TTggMTNoOE04IDE3aDUiLz48L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMyAzdjE4aDE4Ii8+PHBhdGggZD0iTTcgMTZsNC00IDMgMyA1LTYiLz48L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTYgMThsNi02LTYtNk04IDZsLTYgNiA2IDYiLz48L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTQuNyA2LjNhMSAxIDAgMCAwIDAgMS40bDEuNiAxLjZhMSAxIDAgMCAwIDEuNCAwbDMuNzctMy43N2E2IDYgMCAwIDEtNy45NCA3Ljk0bC02LjkxIDYuOTFhMi4xMiAyLjEyIDAgMCAxLTMtM2w2LjkxLTYuOTFhNiA2IDAgMCAxIDcuOTQtNy45NGwtMy43NiAzLjc2eiIvPjwvc3ZnPg==',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cG9seWdvbiBwb2ludHM9IjEyIDIgMTUuMDkgOC4yNiAyMiA5LjI3IDE3IDE0LjE0IDE4LjE4IDIxLjAyIDEyIDE3Ljc3IDUuODIgMjEuMDIgNyAxNC4xNCAyIDkuMjcgOC45MSA4LjI2IDEyIDIiLz48L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjxwYXRoIGQ9Ik0yIDEyaDIwIi8+PHBhdGggZD0iTTEyIDJhMTUuMyAxNS4zIDAgMCAxIDQgMTAgMTUuMyAxNS4zIDAgMCAxLTQgMTAgMTUuMyAxNS4zIDAgMCAxLTQtMTAgMTUuMyAxNS4zIDAgMCAxIDQtMTB6Ii8+PC9zdmc+',
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2NjY2IiBzdHJva2Utd2lkdGg9IjEuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNOSAxOGg2Ii8+PHBhdGggZD0iTTEwIDIyaDQiLz48cGF0aCBkPSJNMTIgMmE3IDcgMCAwIDAtNyA3YzAgMi41IDEuNSA0LjUgMyA2djJoOHYtMmMxLjUtMS41IDMtMy41IDMtNmE3IDcgMCAwIDAtNy03eiIvPjwvc3ZnPg=='
],
// 失焦定时器: 用于延迟收起文字输入态, 避免 H5 布局变化触发的瞬时 blur 误收起
_blurTimer: null,
// 平台相关: H5 让浏览器自动把输入框顶起(adjust-position=true), 小程序用键盘垫高自行处理
@@ -982,6 +1004,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): 文字输入态
// 聚焦 或 已有文字时展开为"输入框一行 + 工具栏一行", 否则回到单行胶囊。
// 用聚焦(而不是只判断文字)是为了: 删除最后一个字时布局不会突然塌回胶囊。
@@ -1717,9 +1743,9 @@ export default {
// 等路径再触发会造成欢迎气泡重复 push; 网络慢时尤其容易)
if (this._welcomeLoading) return
this._welcomeLoading = true
// 仅全新会话才需要欢迎语
if (this.currentConversationId ) {
console.log('[AI Chat] 已有会话 ,跳过欢迎语')
// 只要当前没有消息(或历史为空)就展示欢迎语;已有消息/历史时会话 ID 不影响
if (this.messages.length > 0 ) {
console.log('[AI Chat] 已有消息 ,跳过欢迎语')
this._welcomeLoading = false
return
}
@@ -1767,8 +1793,10 @@ export default {
}
}
// 3. 插入欢迎语(再次检查是否仍是全新会话 )
if (!this.currentConversationId && this.messages.length === 0) {
// 3. 插入欢迎语:只要当前消息列表仍为空就展示(兼容真机残留会话 ID 但无历史消息 )
if (this.messages.length === 0) {
// PR-WELCOME-QUICK-BATCH: 所有快捷问题先存起来, 前端每 4 个一批轮播
const allQuickQuestions = this.normalizeQuickQuestions(welcomeInfo && welcomeInfo.quick_questions)
const welcomeMsg = {
id: ++this.messageId,
role: 'ai',
@@ -1779,7 +1807,12 @@ 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)
// PR-WELCOME-QUICK-BATCH: 每 4 个一批展示, 点击换一换循环切换
quickQuestions: (allQuickQuestions || []).slice(0, 4),
allQuickQuestions: allQuickQuestions || [],
_qqBatchIndex: 0,
// PR-WELCOME-HIDE-AFTER-SEND: 标记这是欢迎语消息, 发送第一条用户消息后永久隐藏
isWelcome: true
}
this.messages.push(welcomeMsg)
this.$nextTick(() => this.scrollToBottom())
@@ -2797,6 +2830,9 @@ async onNewChat() {
}
}
this.clearMessages()
// 新对话后重新加载欢迎语
this._welcomeLoading = false
this._loadWelcomeMessage()
uni.showToast({ title: '已开始新对话', icon: 'success' })
},
@@ -2967,7 +3003,7 @@ _handleStreamError(msg) {
// 之前行内代码是粉色(#d63384)、删除线是灰色(#999), 回答里颜色太杂。
t = t
.replace(/`([^`]+)`/g, '<code style="background:#f2f3f5;padding:2rpx 10rpx;border-radius:6rpx;font-size:24rpx;font-family:monospace;color:' + TEXT + ';">$1</code>')
.replace(/\*\*(.+?)\*\*/g, '<strong style="font-weight:700; color:' + TEXT + ';">$1</strong >')
.replace(/\*\*(.+?)\*\*/g, '<span style="color:' + TEXT + ';">$1</span >')
.replace(/\*(.+?)\*/g, '<em style="font-style:italic;color:' + TEXT + ';">$1</em>')
.replace(/~~(.+?)~~/g, '<del style="text-decoration:line-through;color:' + TEXT + ';">$1</del>')
@@ -3018,7 +3054,7 @@ _handleStreamError(msg) {
const flushTable = () => {
if (!inTable || tableRows.length === 0) return
const thead = tableRows[0].map(c =>
`<th style="padding:8rpx 12rpx;border:1rpx solid #eaecef;font-weight:6 00;background:#f6f8fa;text-align:left;font-size:24rpx;color:${TEXT};">${parseInline(c)}</th>`
`<th style="padding:8rpx 12rpx;border:1rpx solid #eaecef;font-weight:4 00;background:#f6f8fa;text-align:left;font-size:24rpx;color:${TEXT};">${parseInline(c)}</th>`
).join('')
const tbody = tableRows.slice(1).map(row =>
'<tr>' + row.map(c =>
@@ -3066,7 +3102,7 @@ _handleStreamError(msg) {
flushBuf(); out.push(closeList())
const lv = hMatch[1].length
const size = ['', '36rpx', '32rpx', '30rpx', '28rpx', '26rpx', '24rpx'][lv]
const wgt = ['', '7 00', '7 00', '6 00', '6 00', '5 00', '5 00'][lv]
const wgt = ['', '4 00', '4 00', '4 00', '4 00', '4 00', '4 00'][lv]
const mg = COMPACT ? ['', '14rpx 0 7rpx', '12rpx 0 6rpx', '10rpx 0 5rpx', '8rpx 0 5rpx', '7rpx 0 3rpx', '6rpx 0 3rpx'][lv] : ['', '20rpx 0 10rpx', '16rpx 0 8rpx', '14rpx 0 6rpx', '12rpx 0 6rpx', '10rpx 0 4rpx', '8rpx 0 4rpx'][lv]
out.push(`<h${lv} style="font-size:${size};font-weight:${wgt};margin:${mg};line-height:1.35;color:${TEXT};">${parseInline(hMatch[2])}</h${lv}>`)
continue
@@ -3752,6 +3788,26 @@ _handleStreamError(msg) {
} catch (e) { /* noop */ }
},
// 欢迎语"换一换": 快捷问题每 4 个一批, 点击后切换到下一批, 末尾循环回第一批
onAiActionRefreshWelcome(message) {
try {
const all = message.allQuickQuestions || []
if (!all.length) {
uni.showToast({ title: '暂无更多问题', icon: 'none' })
return
}
const batchSize = 4
const total = all.length
const batchCount = Math.ceil(total / batchSize) || 1
const current = message._qqBatchIndex || 0
const next = (current + 1) % batchCount
const start = next * batchSize
const end = Math.min(start + batchSize, total)
this.$set(message, '_qqBatchIndex', next)
this.$set(message, 'quickQuestions', all.slice(start, end))
} catch (e) { /* noop */ }
},
// 去掉 markdown 标记, 用于 TTS 朗读
_stripMarkdown(text) {
if (!text) return ''
@@ -4719,6 +4775,16 @@ _handleStreamError(msg) {
scroll-margin-top: 300rpx;
scroll-margin-bottom: 200rpx;
// 欢迎语消息: 气泡背景纯白, 让快捷问题更明显
&.is-welcome .ai-message .message-bubble {
background: #ffffff !important;
}
// 欢迎语消息: 隐藏上方时间戳
&.is-welcome .ai-message .message-nickname.ai-nickname {
display: none;
}
// 搜索定位 - 当前结果: 用柔和的浅绿底色提示 (WorkBuddy 风格, 无气泡 box-shadow)
&.search-current {
position: relative;
@@ -4869,7 +4935,7 @@ _handleStreamError(msg) {
color: #1a1a1a;
strong {
font-weight: 6 00;
font-weight: 4 00;
color: #1a1a1a;
}
@@ -4888,8 +4954,9 @@ _handleStreamError(msg) {
}
a {
/* 网址/链接: 蓝色 (与 parseMarkdown 里的 LINK 常量保持一致) */
color: #3a7afe ;
/* 网址/链接: 黑色, 不加粗 */
color: #1f1f1f !important ;
font-weight: 400 !important;
text-decoration: underline;
text-underline-offset: 4rpx;
transition: color 0.2s ease;
@@ -5097,7 +5164,7 @@ _handleStreamError(msg) {
.link-url {
display: block;
font-size: 22rpx;
color: $color-primary ;
color: #1f1f1f ;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -5246,19 +5313,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: 3 2rpx;
border: 1rpx solid #d9d9d9 ;
border-radius: 20 rpx;
font-size: 26rpx;
color: #1a1a1a;
cursor: pointer;
@@ -5266,10 +5332,18 @@ _handleStreamError(msg) {
max-width: 100%;
line-height: 1.4;
&:last-child {
margin-bottom: 0;
}
.quick-question-icon {
font-size : 24 rpx;
width : 28 rpx;
height: 28rpx;
flex-shrink: 0;
margin-right: 8rpx;
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
.quick-question-text {
@@ -5280,10 +5354,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 ;
}
}
@@ -5436,7 +5508,7 @@ _handleStreamError(msg) {
max-width: 100%;
.message-text {
font-size: 20 rpx !important; // 还原为用户消息原字号
font-size: 25 rpx !important; // 还原为用户消息原字号
}
&::before {
@@ -5520,10 +5592,25 @@ _handleStreamError(msg) {
}
}
// AI 回答文字字号统一为 25rpx
.message-text,
.ai-message-text {
font-size: 25rpx !important;
line-height: 1.7;
// H5 / 微信 AI 回答里的链接统一黑色
a {
color: #1f1f1f !important;
font-weight: 400 !important;
text-decoration: underline;
text-underline-offset: 4rpx;
}
}
// 微信端 AI 富文本(豆包风格)容器: 行高/字号/字色统一兜底
.ai-message-rich {
display: block;
font-size: 30 rpx;
font-size: 25 rpx;
line-height: 1.75;
color: #1a1a1a;
letter-spacing: 0.2rpx;
@@ -5545,7 +5632,7 @@ _handleStreamError(msg) {
align-items: center;
margin-top: 12rpx;
padding-top: 4rpx;
color: $color-primary ;
color: #1f1f1f ;
font-size: 24rpx;
font-weight: 500;
line-height: 1;
@@ -5569,7 +5656,7 @@ _handleStreamError(msg) {
}
.streaming-tail-text {
color: $color-primary ;
color: #1f1f1f ;
font-weight: 500;
}
@@ -5660,6 +5747,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 ;
}
@@ -5817,7 +5927,7 @@ _handleStreamError(msg) {
.voice -icon -bg {
width : 48rpx ;
height : 48rpx ;
background-image: url( "data : image / svg + xml ; base64 , PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMi IgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWYxZjFmIiBzdHJva2Utd2lkdGg9IjIuMi Igc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTAgMTIgaDYgbDYgLTQgdjE2IGwtNiAtNCBoLTYgYTIgMiAwIDAgMSAtMiAtMiB2LTQgYTIgMiAwIDAgMSAyIC0yIHoiLz48cGF0aCBkPSJNMjQgMTAgYzIgMyAy IDk gMCAxMi IvPjwvc3ZnPg = = " ) ;
background -image: url ( "data : image / svg + xml ; base64 , PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNC IgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWYxZjFmIiBzdHJva2Utd2lkdGg9IjEuOC Igc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48Y2lyY2xlIGN4PSIzLjUiIGN5PSIxMiIgcj0iMi4yIiBmaWxsPSIjMWYxZjFmIiBzdHJva2U9Im5vbmUiLz48cGF0aCBkPSJNMTAgNy4xIEE3IDcgMCAwIDEgMTAgMTYuOSIvPjxwYXRoIGQ9Ik0xNS4zIDEuNyBBMTQuNSAxNC41 IDA gMCAxIDE1LjMgMjIuMy IvPjwvc3ZnPg = = " ) ;
background -repeat : no -repeat ;
background -position : center ;
background -size : contain ;
@@ -6567,6 +6677,20 @@ _handleStreamError(msg) {
line - height : 1.7 ;
letter - spacing : 0.8 rpx ;
}
// AI 回答不加粗(兜底),同时统一 H5 markdown 容器字号为 25rpx
. ai - message {
. message - bubble ,
. selectable - md {
strong , b , h1 , h2 , h3 , h4 , h5 , h6 , th {
font - weight : normal ! important ;
}
}
. selectable - md {
font - size : 25 rpx ! important ;
}
}
}
/* ========== AI 回答: 无气泡 ==========
@@ -6596,15 +6720,14 @@ _handleStreamError(msg) {
padding : 10 rpx 22 rpx ;
border - radius : 999 rpx ;
background : # f4f5f7 ;
color : # 1 f6cf f ;
color : # 1 f1f1 f ;
font - size : 24 rpx ;
/* 新对话图标: 圆角气泡 + 中间加号 + 左下角小尾巴的线性图标
微信小程序不支持内联 SVG, 沿用 base64 背景图方案 (与 svg-icon / voice-icon-bg 一致) */
/* 新对话图标: 圆角气泡 + 中间加号 + 左下角小尾巴的线性图标 (已改为黑色) */
. new - chat - icon {
width : 32 rpx ;
height : 32 rpx ;
flex - shrink : 0 ;
background - image : url ( "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWY2Y2Z mIiBzdHJva2Utd2lkdGg9IjEuNyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNOC41IDIuNUgxNkE1LjUgNS41IDAgMCAxIDIxLjUgOFYxMi41QTUuNSA1LjUgMCAwIDEgMTYgMThIOC42TDMgMjJWOEE1LjUgNS41IDAgMCAxIDguNSAyLjVaIi8+PHBhdGggZD0iTTEyIDcuNVYxMy41TTkuMiAxMC41SDE0LjgiLz48L3N2Zz4=" ) ;
background - image : url ( "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWYxZjF mIiBzdHJva2Utd2lkdGg9IjEuNyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNOC41IDIuNUgxNkE1LjUgNS41IDAgMCAxIDIxLjUgOFYxMi41QTUuNSA1LjUgMCAwIDEgMTYgMThIOC42TDMgMjJWOEE1LjUgNS41IDAgMCAxIDguNSAyLjVaIi8+PHBhdGggZD0iTTEyIDcuNVYxMy41TTkuMiAxMC41SDE0LjgiLz48L3N2Zz4=" ) ;
background - repeat : no - repeat ;
background - position : center ;
background - size : contain ;