|
|
@@ -142,19 +142,10 @@
|
|
|
<div class="message-content" :data-message-index="index" :ref="el => messageContentRefs[index] = el">
|
|
|
<!-- AI响应内容 -->
|
|
|
<div class="ai-response-content">
|
|
|
- <!-- 进度统计卡片 - 与PC端一致,只要showStats为true就显示 -->
|
|
|
- <div
|
|
|
- v-if="message.showStats"
|
|
|
+ <!-- 进度统计卡片 -->
|
|
|
+ <div
|
|
|
+ v-if="message.showStats"
|
|
|
class="stats-card"
|
|
|
- :class="{ 'is-sticky': messageScrollStates[index]?.isSticky && messageScrollStates[index]?.initialized && !messageScrollStates[index]?.isInitializing }"
|
|
|
- :style="(messageScrollStates[index]?.isSticky && messageScrollStates[index]?.initialized && !messageScrollStates[index]?.isInitializing && messageScrollStates[index]?.initialLeft > 0 && messageScrollStates[index]?.initialWidth > 0) ? {
|
|
|
- position: 'fixed',
|
|
|
- top: '60px',
|
|
|
- left: messageScrollStates[index].initialLeft + 'px',
|
|
|
- width: messageScrollStates[index].initialWidth + 'px',
|
|
|
- zIndex: 999
|
|
|
- } : {}"
|
|
|
- :data-message-index="index"
|
|
|
>
|
|
|
<div class="stats-left">
|
|
|
<StatusAvatar
|
|
|
@@ -173,15 +164,6 @@
|
|
|
</div>
|
|
|
<span class="progress-percentage">{{ message.progress }}%</span>
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- 导出按钮 -->
|
|
|
- <div v-if="message.progress === 100 && message.reports && message.reports.length > 0" class="stats-right">
|
|
|
- <ExportButton
|
|
|
- :reports="message.reports.filter(r => r.status === 'completed' && r.type !== 'category_title')"
|
|
|
- :disabled="false"
|
|
|
- :title="exportTitle"
|
|
|
- />
|
|
|
- </div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 问题总结 -->
|
|
|
@@ -452,7 +434,14 @@
|
|
|
</svg>
|
|
|
<p>{{ fileError }}</p>
|
|
|
</div>
|
|
|
- <iframe v-else-if="previewFilePath" :src="previewFilePath" frameborder="0" class="file-iframe"></iframe>
|
|
|
+ <iframe
|
|
|
+ v-else-if="previewFilePath"
|
|
|
+ :src="previewFilePath"
|
|
|
+ frameborder="0"
|
|
|
+ class="file-iframe"
|
|
|
+ @load="fileLoading = false"
|
|
|
+ @error="fileError = '文件加载失败'"
|
|
|
+ ></iframe>
|
|
|
<div v-else class="file-empty">
|
|
|
<svg class="empty-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
|
<path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" />
|
|
|
@@ -475,7 +464,6 @@ import MobileToast from '@/components/MobileToast.vue'
|
|
|
import MobileHistoryDrawer from '@/components/MobileHistoryDrawer.vue'
|
|
|
import CategoryTitle from '@/components/CategoryTitle.vue'
|
|
|
import FileReportCard from '@/components/FileReportCard.vue'
|
|
|
-import ExportButton from '@/components/ExportButton.vue'
|
|
|
import StreamMarkdown from '@/components/StreamMarkdown.vue'
|
|
|
import WebSearchCapsule from '@/components/WebSearchCapsule.vue'
|
|
|
import WebSearchSummary from '@/components/WebSearchSummary.vue'
|
|
|
@@ -571,9 +559,8 @@ const previewFileName = ref('')
|
|
|
const fileLoading = ref(false)
|
|
|
const fileError = ref('')
|
|
|
|
|
|
-// 进度卡片悬浮状态 - 使用与PC端一致的状态管理
|
|
|
+// 消息内容引用
|
|
|
const messageContentRefs = ref({})
|
|
|
-const messageScrollStates = ref({})
|
|
|
|
|
|
// 语音识别功能
|
|
|
const {
|
|
|
@@ -622,7 +609,6 @@ let sseConnection = null
|
|
|
// 报告生成相关状态
|
|
|
const categoryExpandStates = ref({}) // 分类展开状态
|
|
|
const currentQuestion = ref('') // 当前问题
|
|
|
-const exportTitle = ref('知识库文件') // 导出标题
|
|
|
const streamingReports = ref(new Map()) // 流式报告缓存
|
|
|
const reportTypewriters = new Map() // 存储每个报告字段的打字机定时器
|
|
|
const typewriterIntervals = new Map() // 存储打字机定时器
|
|
|
@@ -2110,31 +2096,38 @@ const openInNewTab = () => {
|
|
|
}
|
|
|
|
|
|
// 处理文件预览
|
|
|
-const handleFilePreview = async (data) => {
|
|
|
+const handleFilePreview = (data) => {
|
|
|
console.log('移动端打开文件预览:', data)
|
|
|
-
|
|
|
+
|
|
|
// 重置状态
|
|
|
fileError.value = ''
|
|
|
fileLoading.value = false
|
|
|
-
|
|
|
- if (!data || (!data.filePath && !data.fileName)) {
|
|
|
- fileError.value = '文件路径为空'
|
|
|
- previewFilePath.value = ''
|
|
|
+
|
|
|
+ // 处理不同类型的输入参数
|
|
|
+ if (typeof data === 'string') {
|
|
|
+ previewFilePath.value = data
|
|
|
previewFileName.value = ''
|
|
|
- } else {
|
|
|
+ } else if (data && data.filePath) {
|
|
|
previewFilePath.value = data.filePath
|
|
|
previewFileName.value = data.fileName || ''
|
|
|
-
|
|
|
- // 显示加载状态
|
|
|
- if (data.filePath) {
|
|
|
- fileLoading.value = true
|
|
|
- // 模拟加载延迟,实际iframe会自己处理加载
|
|
|
- setTimeout(() => {
|
|
|
+ } else {
|
|
|
+ fileError.value = '文件路径为空'
|
|
|
+ previewFilePath.value = ''
|
|
|
+ previewFileName.value = ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示加载状态
|
|
|
+ if (previewFilePath.value) {
|
|
|
+ fileLoading.value = true
|
|
|
+ // 设置超时,如果5秒后还在加载,显示错误
|
|
|
+ setTimeout(() => {
|
|
|
+ if (fileLoading.value) {
|
|
|
fileLoading.value = false
|
|
|
- }, 500)
|
|
|
- }
|
|
|
+ fileError.value = '😔 抱歉,未找到文件链接,正在快马加鞭修复中!'
|
|
|
+ }
|
|
|
+ }, 5000)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
showFilePreview.value = true
|
|
|
}
|
|
|
|
|
|
@@ -2470,37 +2463,34 @@ const handleSSEMessage = (data, aiMessageIndex) => {
|
|
|
|
|
|
switch (data.type) {
|
|
|
case 'intent':
|
|
|
- // 意图识别完成,更新为查询知识库状态
|
|
|
- updateMessageStatus(aiMessage, 'querying_kb')
|
|
|
-
|
|
|
- // 如果启用联网搜索,稍后会更新为web_searching状态
|
|
|
- // (当收到web_search_raw事件时)
|
|
|
-
|
|
|
// 检查是否为专业问题
|
|
|
if (data.is_professional_question === false) {
|
|
|
+ // 非专业问题:立即隐藏状态显示组件
|
|
|
+ aiMessage.showStats = false
|
|
|
+
|
|
|
// 非专业问题,只输出summary字段内容并终止流程
|
|
|
const summaryContent = data.summary || '抱歉,我暂时无法回答您的问题。'
|
|
|
-
|
|
|
+
|
|
|
// 只设置summary,不设置content和displayContent,避免重复显示
|
|
|
aiMessage.summary = summaryContent
|
|
|
aiMessage.isTyping = false // 停止加载动画
|
|
|
-
|
|
|
+
|
|
|
// 保存到数据库
|
|
|
if (aiMessage.ai_message_id) {
|
|
|
updateAIMessageContent(aiMessage.ai_message_id, summaryContent, summaryContent)
|
|
|
.catch(err => console.error('回写AI消息失败:', err))
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 关闭SSE连接
|
|
|
if (sseConnection) {
|
|
|
closeSSEConnection(sseConnection)
|
|
|
sseConnection = null
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 重置发送状态
|
|
|
isSending.value = false
|
|
|
streamingReports.value.clear()
|
|
|
-
|
|
|
+
|
|
|
// 重置AI回复流程状态
|
|
|
isAIReplyProcessComplete.value = true
|
|
|
|
|
|
@@ -2556,18 +2546,24 @@ const handleSSEMessage = (data, aiMessageIndex) => {
|
|
|
|
|
|
return // 终止处理
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // 专业问题:意图识别完成,更新为查询知识库状态
|
|
|
+ updateMessageStatus(aiMessage, 'querying_kb')
|
|
|
+
|
|
|
+ // 如果启用联网搜索,稍后会更新为web_searching状态
|
|
|
+ // (当收到web_search_raw事件时)
|
|
|
+
|
|
|
// 保存问题总结并使用打字机效果
|
|
|
if (data.summary) {
|
|
|
const fullSummary = data.summary
|
|
|
aiMessage._fullSummary = fullSummary
|
|
|
aiMessage.summary = ''
|
|
|
-
|
|
|
+
|
|
|
// 使用打字机效果显示问题总结
|
|
|
startReportFieldTypewriter(
|
|
|
- { file_index: 'summary', report: aiMessage, _typewriterStates: {} },
|
|
|
- 'summary',
|
|
|
- fullSummary,
|
|
|
+ { file_index: 'summary', report: aiMessage, _typewriterStates: {} },
|
|
|
+ 'summary',
|
|
|
+ fullSummary,
|
|
|
50
|
|
|
).catch(err => {
|
|
|
console.error('问题总结打字机效果失败:', err)
|
|
|
@@ -2589,11 +2585,6 @@ const handleSSEMessage = (data, aiMessageIndex) => {
|
|
|
// 如果没有联网搜索,直接显示检索结果
|
|
|
updateMessageStatus(aiMessage, 'data_retrieved')
|
|
|
}
|
|
|
-
|
|
|
- // 文档数量更新后,触发滚动检测以初始化进度卡片
|
|
|
- nextTick(() => {
|
|
|
- handleProgressCardScroll()
|
|
|
- })
|
|
|
break
|
|
|
|
|
|
case 'category_title':
|
|
|
@@ -2969,12 +2960,6 @@ const handleSSEComplete = () => {
|
|
|
if (message.showStats && message.reports && message.reports.length > 0) {
|
|
|
message.progress = 100
|
|
|
console.log('✅ SSE完成,设置进度为100%')
|
|
|
- console.log('📊 导出按钮条件检查:', {
|
|
|
- progress: message.progress,
|
|
|
- hasReports: !!message.reports,
|
|
|
- reportsLength: message.reports?.length,
|
|
|
- showStats: message.showStats
|
|
|
- })
|
|
|
}
|
|
|
|
|
|
// 只有在进度达到100%或没有报告时才停止typing状态
|
|
|
@@ -3268,35 +3253,34 @@ const handleReportGeneratorSubmit = async (data) => {
|
|
|
rawData: null,
|
|
|
userFeedback: null
|
|
|
})
|
|
|
-
|
|
|
- // 等待DOM更新后触发滚动检测,初始化进度卡片状态
|
|
|
- nextTick(() => {
|
|
|
- setTimeout(() => {
|
|
|
- handleProgressCardScroll()
|
|
|
- }, 100)
|
|
|
- })
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
- const params = new URLSearchParams({
|
|
|
+ const apiPrefix = getApiPrefix()
|
|
|
+ const url = `${apiPrefix}/report/complete-flow`
|
|
|
+
|
|
|
+ // 构建 POST 请求体
|
|
|
+ const requestBody = {
|
|
|
user_question: data.question,
|
|
|
window_size: data.windowSize,
|
|
|
- // n_results: data.nResults,
|
|
|
n_results: 2,
|
|
|
- // ===== 已删除:user_id - 后端从token解析 =====
|
|
|
ai_conversation_id: ai_conversation_id.value,
|
|
|
is_network_search_enabled: isNetworkSearchEnabled.value
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('📤 发起 SSE POST 请求:', {
|
|
|
+ url,
|
|
|
+ body: requestBody
|
|
|
})
|
|
|
-
|
|
|
- const apiPrefix = getApiPrefix()
|
|
|
- const url = `${apiPrefix}/report/complete-flow?${params.toString()}`
|
|
|
-
|
|
|
+
|
|
|
sseConnection = createSSEConnection(url, {
|
|
|
onMessage: (eventData) => handleSSEMessage(eventData, aiMessageIndex),
|
|
|
onError: handleSSEError,
|
|
|
onComplete: handleSSEComplete,
|
|
|
onInterrupted: handleSSEInterrupted
|
|
|
+ }, {
|
|
|
+ body: requestBody
|
|
|
})
|
|
|
-
|
|
|
+
|
|
|
} catch (error) {
|
|
|
console.error('启动失败:', error)
|
|
|
showToastMessage(`启动失败: ${error.message}`, 2000)
|
|
|
@@ -3502,12 +3486,7 @@ onMounted(async () => {
|
|
|
// 移动端使用 window 滚动而不是容器滚动
|
|
|
console.log('✅ 移动端:添加 window 滚动监听')
|
|
|
|
|
|
- // 添加测试监听器来确认滚动事件能触发
|
|
|
- window.addEventListener('scroll', () => {
|
|
|
- console.log('🔄 移动端滚动事件触发!scrollY:', window.scrollY)
|
|
|
- }, { once: true })
|
|
|
-
|
|
|
- window.addEventListener('scroll', handleProgressCardScroll)
|
|
|
+
|
|
|
|
|
|
// 测试TTS服务连接
|
|
|
try {
|
|
|
@@ -4171,129 +4150,7 @@ const editUserMessage = (message) => {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// 处理滚动事件,实现进度卡片悬浮效果(与PC端一致的逻辑)
|
|
|
-const handleProgressCardScroll = () => {
|
|
|
- console.log('📱 移动端 handleProgressCardScroll 被触发')
|
|
|
- const mobileHeader = document.querySelector('.mobile-header')
|
|
|
- const headerBottom = mobileHeader ? mobileHeader.getBoundingClientRect().bottom : 60
|
|
|
- console.log('📐 移动端 headerBottom:', headerBottom)
|
|
|
- console.log('📊 移动端 messageContentRefs 数量:', Object.keys(messageContentRefs.value).length)
|
|
|
-
|
|
|
- Object.keys(messageContentRefs.value).forEach(index => {
|
|
|
- const message = chatMessages.value[index]
|
|
|
- if (!message || message.type !== 'ai' || !message.showStats) {
|
|
|
- console.log(`⏭️ 移动端跳过消息 ${index}:`, {
|
|
|
- exists: !!message,
|
|
|
- type: message?.type,
|
|
|
- showStats: message?.showStats
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- console.log(`✅ 移动端处理消息 ${index}`)
|
|
|
-
|
|
|
- const contentEl = messageContentRefs.value[index]
|
|
|
- if (!contentEl) {
|
|
|
- console.log(`❌ 移动端消息 ${index} 没有找到 contentEl`)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 查找进度统计卡片
|
|
|
- const statsCard = contentEl.querySelector('.stats-card')
|
|
|
- if (!statsCard) {
|
|
|
- console.log(`❌ 移动端消息 ${index} 没有找到 .stats-card`)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- console.log(`✅ 移动端消息 ${index} 找到进度卡片`)
|
|
|
-
|
|
|
- const cardRect = statsCard.getBoundingClientRect()
|
|
|
- const contentRect = contentEl.getBoundingClientRect()
|
|
|
-
|
|
|
- // 如果还没有保存状态,先初始化
|
|
|
- if (!messageScrollStates.value[index]) {
|
|
|
- messageScrollStates.value[index] = {
|
|
|
- initialLeft: cardRect.left,
|
|
|
- initialWidth: cardRect.width,
|
|
|
- isSticky: false,
|
|
|
- offsetTop: cardRect.top - contentRect.top,
|
|
|
- initialized: false,
|
|
|
- isInitializing: true,
|
|
|
- initStartTime: Date.now()
|
|
|
- }
|
|
|
-
|
|
|
- // 使用nextTick确保DOM渲染完成后再标记初始化完成
|
|
|
- nextTick(() => {
|
|
|
- requestAnimationFrame(() => {
|
|
|
- if (messageScrollStates.value[index]) {
|
|
|
- const updatedStatsCard = contentEl.querySelector('.stats-card')
|
|
|
- if (updatedStatsCard) {
|
|
|
- const updatedCardRect = updatedStatsCard.getBoundingClientRect()
|
|
|
- messageScrollStates.value[index].initialLeft = updatedCardRect.left
|
|
|
- messageScrollStates.value[index].initialWidth = updatedCardRect.width
|
|
|
- }
|
|
|
-
|
|
|
- const elapsed = Date.now() - messageScrollStates.value[index].initStartTime
|
|
|
- const remainingTime = Math.max(0, 100 - elapsed)
|
|
|
-
|
|
|
- setTimeout(() => {
|
|
|
- if (messageScrollStates.value[index]) {
|
|
|
- messageScrollStates.value[index].initialized = true
|
|
|
- messageScrollStates.value[index].isInitializing = false
|
|
|
- }
|
|
|
- }, remainingTime)
|
|
|
- }
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 如果还没初始化完成或正在初始化,跳过吸附判断
|
|
|
- if (!messageScrollStates.value[index].initialized || messageScrollStates.value[index].isInitializing) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 额外检查:确保初始化后至少过了100ms才允许吸附
|
|
|
- const timeSinceInit = Date.now() - messageScrollStates.value[index].initStartTime
|
|
|
- if (timeSinceInit < 100) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 计算卡片的"自然"位置(如果不吸附的话应该在哪里)
|
|
|
- const naturalTop = contentRect.top + messageScrollStates.value[index].offsetTop
|
|
|
-
|
|
|
- // 判断是否需要吸附
|
|
|
- // 条件:卡片的自然位置已经到达或超过顶部域,且消息内容还在可视范围内
|
|
|
- const shouldStick = naturalTop <= headerBottom && contentRect.bottom > headerBottom + 60
|
|
|
-
|
|
|
- console.log(`📍 移动端消息 ${index} 吸附判断:`, {
|
|
|
- naturalTop,
|
|
|
- headerBottom,
|
|
|
- 'naturalTop <= headerBottom': naturalTop <= headerBottom,
|
|
|
- 'contentRect.bottom': contentRect.bottom,
|
|
|
- 'headerBottom + 60': headerBottom + 60,
|
|
|
- shouldStick,
|
|
|
- currentlySticky: messageScrollStates.value[index].isSticky
|
|
|
- })
|
|
|
-
|
|
|
- // 如果从吸附变为非吸附,或从非吸附变为吸附,更新位置信息
|
|
|
- if (messageScrollStates.value[index].isSticky !== shouldStick) {
|
|
|
- if (!shouldStick) {
|
|
|
- // 解除吸附时,重新计算位置
|
|
|
- messageScrollStates.value[index].initialLeft = cardRect.left
|
|
|
- messageScrollStates.value[index].initialWidth = cardRect.width
|
|
|
- } else {
|
|
|
- // 开始吸附时,使用当前位置
|
|
|
- messageScrollStates.value[index].initialLeft = cardRect.left
|
|
|
- messageScrollStates.value[index].initialWidth = cardRect.width
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- messageScrollStates.value[index].isSticky = shouldStick
|
|
|
- messageScrollStates.value[index].stickyTop = headerBottom
|
|
|
- })
|
|
|
-}
|
|
|
+
|
|
|
|
|
|
// 语音输入相关方法
|
|
|
const handleVoiceClick = () => {
|
|
|
@@ -4573,10 +4430,7 @@ onBeforeUnmount(() => {
|
|
|
window.removeEventListener('beforeunload', handlePageUnload)
|
|
|
window.removeEventListener('unload', handlePageUnload)
|
|
|
document.removeEventListener('visibilitychange', handleVisibilityChange)
|
|
|
-
|
|
|
- // 清理滚动监听器
|
|
|
- window.removeEventListener('scroll', handleProgressCardScroll)
|
|
|
-
|
|
|
+
|
|
|
// 清理规范引用点击事件监听器
|
|
|
document.removeEventListener('click', handleStandardReferenceClick)
|
|
|
})
|
|
|
@@ -4827,47 +4681,55 @@ onActivated(async () => {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 0;
|
|
|
-
|
|
|
+ overflow-x: hidden;
|
|
|
+ max-width: 100%;
|
|
|
+
|
|
|
.ai-message-main {
|
|
|
display: flex;
|
|
|
gap: 12px;
|
|
|
+ overflow-x: hidden;
|
|
|
+ max-width: 100%;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.ai-avatar-small {
|
|
|
width: 52px;
|
|
|
height: 52px;
|
|
|
flex-shrink: 0;
|
|
|
-
|
|
|
+
|
|
|
.ai-icon {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
object-fit: contain;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 网络搜索胶囊外层容器
|
|
|
.web-search-capsule-outer {
|
|
|
margin-bottom: 8px;
|
|
|
display: flex;
|
|
|
justify-content: flex-start;
|
|
|
padding-left: 62px; // 为头像留空间
|
|
|
+ overflow-x: hidden;
|
|
|
+ max-width: 100%;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// AI消息主体容器
|
|
|
.ai-message-main {
|
|
|
display: flex;
|
|
|
gap: 10px;
|
|
|
align-items: flex-start;
|
|
|
margin-bottom: 16px;
|
|
|
+ overflow-x: hidden;
|
|
|
+ max-width: 100%;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// AI头像样式 - 移动端(用户已设置为52px)
|
|
|
.ai-avatar-small {
|
|
|
width: 52px;
|
|
|
height: 52px;
|
|
|
flex-shrink: 0;
|
|
|
animation: avatar-pulse 2s ease-in-out infinite;
|
|
|
-
|
|
|
+
|
|
|
.ai-icon {
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
@@ -4875,7 +4737,7 @@ onActivated(async () => {
|
|
|
filter: drop-shadow(0 2px 8px rgba(91, 141, 239, 0.15));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@keyframes avatar-pulse {
|
|
|
0%, 100% {
|
|
|
transform: scale(1);
|
|
|
@@ -4884,16 +4746,20 @@ onActivated(async () => {
|
|
|
transform: scale(1.05);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 白色气泡容器 - 包裹所有AI内容
|
|
|
.message-content {
|
|
|
flex: 1;
|
|
|
min-width: 0;
|
|
|
+ max-width: 100%;
|
|
|
background: white;
|
|
|
border-radius: 12px;
|
|
|
padding: 16px;
|
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
text-align: left;
|
|
|
+ overflow-x: hidden;
|
|
|
+ word-wrap: break-word;
|
|
|
+ overflow-wrap: break-word;
|
|
|
}
|
|
|
|
|
|
// AI响应内容容器
|
|
|
@@ -4972,22 +4838,35 @@ onActivated(async () => {
|
|
|
// AI文本内容
|
|
|
.ai-text {
|
|
|
text-align: left;
|
|
|
-
|
|
|
+ max-width: 100%;
|
|
|
+ overflow-x: hidden;
|
|
|
+ word-wrap: break-word;
|
|
|
+
|
|
|
.ai-markdown-content {
|
|
|
text-align: left;
|
|
|
-
|
|
|
+ max-width: 100%;
|
|
|
+ overflow-x: hidden;
|
|
|
+ word-wrap: break-word;
|
|
|
+
|
|
|
* {
|
|
|
text-align: left !important;
|
|
|
+ max-width: 100%;
|
|
|
+ word-wrap: break-word;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.question-summary {
|
|
|
text-align: left;
|
|
|
margin-bottom: 12px;
|
|
|
-
|
|
|
+ max-width: 100%;
|
|
|
+ overflow-x: hidden;
|
|
|
+ word-wrap: break-word;
|
|
|
+
|
|
|
* {
|
|
|
text-align: left !important;
|
|
|
+ max-width: 100%;
|
|
|
+ word-wrap: break-word;
|
|
|
}
|
|
|
}
|
|
|
|