1.完成app端新的聊天页面效果

This commit is contained in:
2025-08-14 15:38:29 +08:00
parent 114a30acb8
commit 2462260bb3

View File

@@ -29,16 +29,41 @@
<!-- 用户消息纯文本 -->
<text v-else-if="item.content">{{ item.content }}</text>
<!-- AI操作区域 -->
<view v-if="item.sender === 'ai'" class="ai-actions">
<text class="ai-text">回答由AI生成</text>
<view class="icon-group">
<img src="/static/good.svg"
:class="['btn-icon', { 'btn-icon-active': item.feedback && item.feedback.rating === 'like' }]"
@click="handleThumbUp(item.messageId, index)" />
<img src="/static/tread.svg"
:class="['btn-icon', { 'btn-icon-active': item.feedback && item.feedback.rating === 'dislike' }]"
@click="handleThumbDown(item.messageId, index)" />
<!-- AI特有内容 -->
<view v-if="item.sender === 'ai'" class="ai-hint">
<!-- 引用来源部分 -->
<view v-if="item.retrieverResources && item.retrieverResources.length" class="reference-section">
<text class="reference-title">引用来源</text>
<!-- 遍历合并后的引用资源 -->
<view v-for="(groupedRef, groupIdx) in getGroupedReferences(item.retrieverResources)" :key="groupIdx" class="reference-item-wrapper">
<!-- 可点击的文档名 -->
<text class="doc-name-link" @click="toggleSingleReference(index, groupIdx)">
{{ groupedRef.document_name }}
</text>
<!-- 展开的详情仅当前项 -->
<view v-if="showSingleReference[index] && showSingleReference[index][groupIdx]" class="reference-details-item">
<!-- 分段显示内容 -->
<view v-for="(ref, refIdx) in groupedRef.references" :key="refIdx" class="reference-segment">
<text class="reference-meta">{{ ref.name }}{{ ref.document_name }}</text>
<text class="reference-content" v-if="ref.content">{{ ref.content }}</text>
<view v-if="refIdx < groupedRef.references.length - 1" class="reference-divider"></view>
</view>
</view>
</view>
</view>
<!-- AI操作区域 -->
<view class="ai-actions">
<text class="ai-text">AI回答也可能会犯错请核查重要信息</text>
<view class="icon-group">
<img src="/static/good.svg"
:class="['btn-icon', { 'btn-icon-active': item.feedback && item.feedback.rating === 'like' }]"
@click="handleThumbUp(item.messageId, index)" />
<img src="/static/tread.svg"
:class="['btn-icon', { 'btn-icon-active': item.feedback && item.feedback.rating === 'dislike' }]"
@click="handleThumbDown(item.messageId, index)" />
</view>
</view>
</view>
</view>
@@ -102,8 +127,11 @@ export default {
// 分页加载
isLoadingHistory: false,
hasMoreHistory: true,
earliestMessageId: null
};
earliestMessageId: null,
// 引用信息展示控制
showSingleReference: {}
};
},
onLoad() {
@@ -169,7 +197,8 @@ export default {
messageId: 'ai-' + msg.id,
conversationId: msg.conversation_id,
created_at: msg.created_at,
feedback: msg.feedback || null // 添加反馈状态
feedback: msg.feedback || null, // 添加反馈状态
retrieverResources: msg.retriever_resources || [] // 添加引用资源
});
}
});
@@ -276,7 +305,8 @@ export default {
messageId: 'ai-' + msg.id,
conversationId: msg.conversation_id,
created_at: msg.created_at,
feedback: msg.feedback || null // 添加反馈状态
feedback: msg.feedback || null, // 添加反馈状态
retrieverResources: msg.retriever_resources || [] // 添加引用资源
});
}
});
@@ -552,6 +582,45 @@ export default {
});
},
/**
* 将引用资源按文档名称分组合并
* @param {Array} references - 原始引用资源数组
* @returns {Array} 分组后的引用资源数组
*/
getGroupedReferences(references) {
if (!references || !references.length) return [];
const grouped = {};
// 按文档名称分组
references.forEach(ref => {
const docName = ref.document_name;
if (!grouped[docName]) {
grouped[docName] = {
document_name: docName,
references: []
};
}
grouped[docName].references.push(ref);
});
// 转换为数组
return Object.values(grouped);
},
/**
* 切换单个引用的显示状态
* @param {number} msgIdx - 消息索引
* @param {number} refIdx - 引用索引
*/
toggleSingleReference(msgIdx, refIdx) {
if (!this.showSingleReference[msgIdx]) {
this.$set(this.showSingleReference, msgIdx, {});
}
const current = this.showSingleReference[msgIdx][refIdx];
this.$set(this.showSingleReference[msgIdx], refIdx, !current);
},
/**
* 显示提示
*/
@@ -644,6 +713,94 @@ export default {
border: 1px solid #eee;
}
/* AI提示区域 */
.ai-hint {
margin-top: 8px;
font-size: 12px;
color: #666;
}
/* 引用来源部分 */
.reference-section {
margin-top: 8px;
margin-bottom: 8px;
padding: 8px;
background-color: #f8f9fa;
border-radius: 6px;
border-left: 3px solid #007aff;
}
.reference-title {
font-size: 12px;
font-weight: 500;
color: #333;
margin-bottom: 6px;
display: block;
}
/* 每个引用项容器 */
.reference-item-wrapper {
margin-top: 6px;
}
/* 可点击文档名 */
.doc-name-link {
color: #007aff;
text-decoration: underline;
margin-right: 8px;
font-size: 11px;
font-weight: 500;
cursor: pointer;
}
/* 引用详情 */
.reference-details-item {
margin-top: 6px;
padding: 8px;
background-color: #f9f9f9;
border-radius: 4px;
border: 1px solid #e0e0e0;
font-size: 11px;
color: #555;
line-height: 1.5;
}
.reference-meta {
font-weight: bold;
color: #333;
display: block;
margin-bottom: 4px;
font-size: 12px;
}
.reference-content {
color: #444;
line-height: 1.6;
font-size: 10px;
}
/* 引用分段样式 */
.reference-segment {
margin-bottom: 12px;
padding: 8px;
background-color: #fafafa;
border-left: 3px solid #007aff;
border-radius: 4px;
}
.reference-segment:last-child {
margin-bottom: 0;
}
/* 分段分隔线 */
.reference-divider {
height: 2px;
background: linear-gradient(to right, #e8e8e8, #f5f5f5, #e8e8e8);
margin: 12px 0;
width: 100%;
border-radius: 1px;
}
/* AI操作区域 */
.ai-actions {
display: flex;
@@ -656,6 +813,10 @@ export default {
.ai-text {
color: #999;
font-size: 11px;
line-height: 1.4;
flex: 1;
margin-right: 8px;
}
.icon-group {
@@ -701,13 +862,14 @@ export default {
}
.send-button {
padding: 8px 16px;
padding: 6px 12px;
background-color: #007aff;
color: white;
border: none;
border-radius: 20px;
font-size: 14px;
border-radius: 16px;
font-size: 12px;
cursor: pointer;
min-width: 60px;
}
.send-button:disabled {