feat:实现任务历史加载功能 - 完整还原对话样式
主要改进: 1. 实现selectConversation功能,支持点击任务历史列表加载会话 2. 优化会话存储格式,保存完整的segments信息(包括工具调用) 3. 添加旧格式到新格式的自动转换,兼容历史数据 4. 改进错误处理,自动清理无效的空任务目录 5. 优化路径编码逻辑,确保跨平台一致性 6. 前端支持clearChat、addUserMessage、addAiMessage命令 技术细节: - 扩展AiMessage数据结构,添加segments字段 - 修改messageHandler保存逻辑,将完整segments保存到一条消息 - 实现loadTaskSession方法,加载指定任务的完整会话 - 添加自动清理机制,删除无效的空任务目录
This commit is contained in:
@ -111,6 +111,10 @@ export function getConversationHistoryBarStyles(): string {
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
border-bottom: 1px solid var(--vscode-panel-border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.history-item:last-child {
|
||||
@ -124,15 +128,17 @@ export function getConversationHistoryBarStyles(): string {
|
||||
.history-item-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 4px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.history-item-time {
|
||||
font-size: 12px;
|
||||
opacity: 0.7;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.history-empty {
|
||||
@ -142,6 +148,14 @@ export function getConversationHistoryBarStyles(): string {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.history-load-more {
|
||||
padding: 12px 16px;
|
||||
text-align: center;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
font-size: 12px;
|
||||
border-top: 1px solid var(--vscode-panel-border);
|
||||
}
|
||||
|
||||
.new-conversation-button {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
@ -199,6 +213,12 @@ export function getConversationHistoryBarScript(): string {
|
||||
// 会话历史相关变量
|
||||
let conversationHistory = [];
|
||||
let currentConversationId = null;
|
||||
let currentOffset = 0;
|
||||
let totalHistory = 0;
|
||||
let hasMoreHistory = false;
|
||||
let isLoadingHistory = false;
|
||||
const HISTORY_PAGE_SIZE = 10;
|
||||
const MAX_HISTORY_ITEMS = 100;
|
||||
|
||||
// 切换历史记录下拉菜单
|
||||
function toggleHistoryDropdown() {
|
||||
@ -211,33 +231,90 @@ export function getConversationHistoryBarScript(): string {
|
||||
} else {
|
||||
menu.classList.add('active');
|
||||
button.classList.add('active');
|
||||
// 加载会话历史
|
||||
loadConversationHistory();
|
||||
// 重置并加载会话历史
|
||||
resetAndLoadHistory();
|
||||
}
|
||||
}
|
||||
|
||||
// 加载会话历史
|
||||
function loadConversationHistory() {
|
||||
vscode.postMessage({ command: 'loadConversationHistory' });
|
||||
// 重置并加载会话历史
|
||||
function resetAndLoadHistory() {
|
||||
conversationHistory = [];
|
||||
currentOffset = 0;
|
||||
totalHistory = 0;
|
||||
hasMoreHistory = false;
|
||||
const historyList = document.getElementById('historyList');
|
||||
if (historyList) {
|
||||
historyList.innerHTML = '<div class="history-empty">加载中...</div>';
|
||||
}
|
||||
loadMoreHistory();
|
||||
}
|
||||
|
||||
// 渲染会话历史列表
|
||||
function renderConversationHistory(history) {
|
||||
conversationHistory = history;
|
||||
const historyList = document.getElementById('historyList');
|
||||
// 加载更多会话历史
|
||||
function loadMoreHistory() {
|
||||
if (isLoadingHistory || (currentOffset > 0 && !hasMoreHistory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!history || history.length === 0) {
|
||||
// 检查是否已达到最大数量
|
||||
if (currentOffset >= MAX_HISTORY_ITEMS) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingHistory = true;
|
||||
vscode.postMessage({
|
||||
command: 'loadConversationHistory',
|
||||
offset: currentOffset,
|
||||
limit: HISTORY_PAGE_SIZE
|
||||
});
|
||||
}
|
||||
|
||||
// 渲染会话历史列表(支持追加)
|
||||
function renderConversationHistory(data) {
|
||||
isLoadingHistory = false;
|
||||
|
||||
if (!data || !data.items) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 追加新数据
|
||||
conversationHistory = conversationHistory.concat(data.items);
|
||||
totalHistory = data.total;
|
||||
hasMoreHistory = data.hasMore;
|
||||
currentOffset += data.items.length;
|
||||
|
||||
const historyList = document.getElementById('historyList');
|
||||
if (!historyList) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果没有任何历史记录
|
||||
if (conversationHistory.length === 0) {
|
||||
historyList.innerHTML = '<div class="history-empty">暂无会话历史</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
historyList.innerHTML = history.map(item => \`
|
||||
<div class="history-item"
|
||||
onclick="selectConversation('\${item.id}')">
|
||||
// 渲染所有历史记录
|
||||
historyList.innerHTML = conversationHistory.map(item => \`
|
||||
<div class="history-item" onclick="selectConversation('\${item.id}')">
|
||||
<div class="history-item-title">\${item.title || '未命名会话'}</div>
|
||||
<div class="history-item-time">\${formatTime(item.timestamp)}</div>
|
||||
</div>
|
||||
\`).join('');
|
||||
|
||||
// 如果还有更多数据,添加"加载更多"提示
|
||||
if (hasMoreHistory && currentOffset < MAX_HISTORY_ITEMS) {
|
||||
historyList.innerHTML += \`
|
||||
<div class="history-load-more" id="loadMoreIndicator">
|
||||
<span>滚动加载更多...</span>
|
||||
</div>
|
||||
\`;
|
||||
} else if (currentOffset >= MAX_HISTORY_ITEMS && hasMoreHistory) {
|
||||
historyList.innerHTML += \`
|
||||
<div class="history-load-more">
|
||||
<span>已显示最近 \${MAX_HISTORY_ITEMS} 条记录</span>
|
||||
</div>
|
||||
\`;
|
||||
}
|
||||
}
|
||||
|
||||
// 选择会话
|
||||
@ -291,6 +368,22 @@ export function getConversationHistoryBarScript(): string {
|
||||
});
|
||||
}
|
||||
|
||||
// 监听下拉菜单滚动事件
|
||||
const historyDropdownMenu = document.getElementById('historyDropdownMenu');
|
||||
if (historyDropdownMenu) {
|
||||
historyDropdownMenu.addEventListener('scroll', () => {
|
||||
const menu = historyDropdownMenu;
|
||||
const scrollTop = menu.scrollTop;
|
||||
const scrollHeight = menu.scrollHeight;
|
||||
const clientHeight = menu.clientHeight;
|
||||
|
||||
// 当滚动到距离底部 50px 时,加载更多
|
||||
if (scrollHeight - scrollTop - clientHeight < 50) {
|
||||
loadMoreHistory();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 点击外部关闭下拉菜单
|
||||
document.addEventListener('click', (event) => {
|
||||
const container = document.querySelector('.history-dropdown-container');
|
||||
|
||||
@ -525,6 +525,37 @@ export function getWebviewContent(iconUri?: string): string {
|
||||
showQuestion(message.askId, message.question, message.options);
|
||||
break;
|
||||
|
||||
case 'conversationHistory':
|
||||
// 渲染会话历史列表(支持分页)
|
||||
renderConversationHistory({
|
||||
items: message.items || [],
|
||||
total: message.total || 0,
|
||||
hasMore: message.hasMore || false
|
||||
});
|
||||
break;
|
||||
|
||||
case 'clearChat':
|
||||
// 清空聊天界面
|
||||
const messagesContainer = document.getElementById('messages');
|
||||
if (messagesContainer) {
|
||||
messagesContainer.innerHTML = '';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'addUserMessage':
|
||||
// 添加用户消息
|
||||
if (message.text) {
|
||||
addMessage(message.text, 'user');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'addAiMessage':
|
||||
// 添加AI消息
|
||||
if (message.text) {
|
||||
addMessage(message.text, 'bot');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('[WebView] 未处理的消息类型:', message.command);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user