mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 10:42:25 +08:00
✨ 新增會話歷史保存本地和匯出功能
This commit is contained in:
parent
c254602531
commit
f9df4386f8
@ -224,6 +224,28 @@
|
|||||||
"unknown": "Unknown"
|
"unknown": "Unknown"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sessionHistory": {
|
||||||
|
"management": {
|
||||||
|
"title": "Session History Management",
|
||||||
|
"retentionPeriod": "Retention Period",
|
||||||
|
"retentionHours": "hours",
|
||||||
|
"export": "Export",
|
||||||
|
"clear": "Clear",
|
||||||
|
"exportAll": "Export All",
|
||||||
|
"exportSingle": "Export This Session",
|
||||||
|
"confirmClear": "Are you sure you want to clear all session history?",
|
||||||
|
"exportSuccess": "Session history exported successfully",
|
||||||
|
"clearSuccess": "Session history cleared successfully",
|
||||||
|
"description": "Manage locally stored session history records, including retention period settings and data export functionality"
|
||||||
|
},
|
||||||
|
"retention": {
|
||||||
|
"24hours": "24 hours",
|
||||||
|
"72hours": "72 hours",
|
||||||
|
"168hours": "7 days",
|
||||||
|
"720hours": "30 days",
|
||||||
|
"custom": "Custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
"connectionMonitor": {
|
"connectionMonitor": {
|
||||||
"connecting": "Connecting...",
|
"connecting": "Connecting...",
|
||||||
"connected": "Connected",
|
"connected": "Connected",
|
||||||
|
@ -224,6 +224,28 @@
|
|||||||
"unknown": "未知"
|
"unknown": "未知"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sessionHistory": {
|
||||||
|
"management": {
|
||||||
|
"title": "会话历史管理",
|
||||||
|
"retentionPeriod": "保存期限",
|
||||||
|
"retentionHours": "小时",
|
||||||
|
"export": "导出",
|
||||||
|
"clear": "清空",
|
||||||
|
"exportAll": "导出全部",
|
||||||
|
"exportSingle": "导出此会话",
|
||||||
|
"confirmClear": "确定要清空所有会话历史吗?",
|
||||||
|
"exportSuccess": "会话历史已导出",
|
||||||
|
"clearSuccess": "会话历史已清空",
|
||||||
|
"description": "管理本地存储的会话历史记录,包括保存期限设定和数据导出功能"
|
||||||
|
},
|
||||||
|
"retention": {
|
||||||
|
"24hours": "24 小时",
|
||||||
|
"72hours": "72 小时",
|
||||||
|
"168hours": "7 天",
|
||||||
|
"720hours": "30 天",
|
||||||
|
"custom": "自定义"
|
||||||
|
}
|
||||||
|
},
|
||||||
"connectionMonitor": {
|
"connectionMonitor": {
|
||||||
"connecting": "连接中...",
|
"connecting": "连接中...",
|
||||||
"connected": "已连接",
|
"connected": "已连接",
|
||||||
|
@ -229,6 +229,28 @@
|
|||||||
},
|
},
|
||||||
"noSummary": "無摘要"
|
"noSummary": "無摘要"
|
||||||
},
|
},
|
||||||
|
"sessionHistory": {
|
||||||
|
"management": {
|
||||||
|
"title": "會話歷史管理",
|
||||||
|
"retentionPeriod": "保存期限",
|
||||||
|
"retentionHours": "小時",
|
||||||
|
"export": "匯出",
|
||||||
|
"clear": "清空",
|
||||||
|
"exportAll": "匯出全部",
|
||||||
|
"exportSingle": "匯出此會話",
|
||||||
|
"confirmClear": "確定要清空所有會話歷史嗎?",
|
||||||
|
"exportSuccess": "會話歷史已匯出",
|
||||||
|
"clearSuccess": "會話歷史已清空",
|
||||||
|
"description": "管理本地儲存的會話歷史記錄,包括保存期限設定和資料匯出功能"
|
||||||
|
},
|
||||||
|
"retention": {
|
||||||
|
"24hours": "24 小時",
|
||||||
|
"72hours": "72 小時",
|
||||||
|
"168hours": "7 天",
|
||||||
|
"720hours": "30 天",
|
||||||
|
"custom": "自訂"
|
||||||
|
}
|
||||||
|
},
|
||||||
"connectionMonitor": {
|
"connectionMonitor": {
|
||||||
"connecting": "連接中...",
|
"connecting": "連接中...",
|
||||||
"connected": "已連接",
|
"connected": "已連接",
|
||||||
|
@ -539,6 +539,40 @@
|
|||||||
border-color: var(--accent-color);
|
border-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 匯出按鈕樣式 */
|
||||||
|
.btn-export {
|
||||||
|
background: var(--bg-primary) !important;
|
||||||
|
border-color: var(--success-color) !important;
|
||||||
|
color: var(--success-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-export:hover {
|
||||||
|
background: var(--success-color) !important;
|
||||||
|
color: white !important;
|
||||||
|
border-color: var(--success-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 會話歷史管理按鈕樣式 */
|
||||||
|
#exportSessionHistoryBtn {
|
||||||
|
background: var(--success-color);
|
||||||
|
border-color: var(--success-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#exportSessionHistoryBtn:hover {
|
||||||
|
background: var(--success-color-dark, #28a745);
|
||||||
|
border-color: var(--success-color-dark, #28a745);
|
||||||
|
}
|
||||||
|
|
||||||
|
#clearSessionHistoryBtn {
|
||||||
|
background: var(--bg-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
#clearSessionHistoryBtn:hover {
|
||||||
|
background: var(--error-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== 會話統計 ===== */
|
/* ===== 會話統計 ===== */
|
||||||
.session-stats-section {
|
.session-stats-section {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
|
|
||||||
// 最後初始化數據管理器(確保 UI 組件已準備好接收回調)
|
// 最後初始化數據管理器(確保 UI 組件已準備好接收回調)
|
||||||
this.dataManager = new window.MCPFeedback.Session.DataManager({
|
this.dataManager = new window.MCPFeedback.Session.DataManager({
|
||||||
|
settingsManager: this.settingsManager,
|
||||||
onSessionChange: function(sessionData) {
|
onSessionChange: function(sessionData) {
|
||||||
self.handleSessionChange(sessionData);
|
self.handleSessionChange(sessionData);
|
||||||
},
|
},
|
||||||
@ -569,6 +570,97 @@
|
|||||||
this.uiRenderer.renderStats(stats);
|
this.uiRenderer.renderStats(stats);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匯出會話歷史
|
||||||
|
*/
|
||||||
|
SessionManager.prototype.exportSessionHistory = function() {
|
||||||
|
if (!this.dataManager) {
|
||||||
|
console.error('📋 DataManager 未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filename = this.dataManager.exportSessionHistory();
|
||||||
|
|
||||||
|
// 顯示成功訊息
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
const message = window.i18nManager ?
|
||||||
|
window.i18nManager.t('sessionHistory.management.exportSuccess') :
|
||||||
|
'會話歷史已匯出';
|
||||||
|
window.MCPFeedback.Utils.showMessage(message + ': ' + filename, 'success');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📋 匯出會話歷史失敗:', error);
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage('匯出失敗: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匯出單一會話
|
||||||
|
*/
|
||||||
|
SessionManager.prototype.exportSingleSession = function(sessionId) {
|
||||||
|
if (!this.dataManager) {
|
||||||
|
console.error('📋 DataManager 未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filename = this.dataManager.exportSingleSession(sessionId);
|
||||||
|
if (filename) {
|
||||||
|
// 顯示成功訊息
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
const message = window.i18nManager ?
|
||||||
|
window.i18nManager.t('sessionHistory.management.exportSuccess') :
|
||||||
|
'會話已匯出';
|
||||||
|
window.MCPFeedback.Utils.showMessage(message + ': ' + filename, 'success');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📋 匯出單一會話失敗:', error);
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage('匯出失敗: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空會話歷史
|
||||||
|
*/
|
||||||
|
SessionManager.prototype.clearSessionHistory = function() {
|
||||||
|
if (!this.dataManager) {
|
||||||
|
console.error('📋 DataManager 未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 確認對話框
|
||||||
|
const confirmMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('sessionHistory.management.confirmClear') :
|
||||||
|
'確定要清空所有會話歷史嗎?';
|
||||||
|
|
||||||
|
if (!confirm(confirmMessage)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.dataManager.clearHistory();
|
||||||
|
|
||||||
|
// 顯示成功訊息
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
const message = window.i18nManager ?
|
||||||
|
window.i18nManager.t('sessionHistory.management.clearSuccess') :
|
||||||
|
'會話歷史已清空';
|
||||||
|
window.MCPFeedback.Utils.showMessage(message, 'success');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📋 清空會話歷史失敗:', error);
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage('清空失敗: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理資源
|
* 清理資源
|
||||||
*/
|
*/
|
||||||
@ -618,6 +710,33 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 全域匯出會話歷史方法
|
||||||
|
window.MCPFeedback.SessionManager.exportSessionHistory = function() {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.app && window.MCPFeedback.app.sessionManager) {
|
||||||
|
window.MCPFeedback.app.sessionManager.exportSessionHistory();
|
||||||
|
} else {
|
||||||
|
console.warn('找不到 SessionManager 實例');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 全域匯出單一會話方法
|
||||||
|
window.MCPFeedback.SessionManager.exportSingleSession = function(sessionId) {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.app && window.MCPFeedback.app.sessionManager) {
|
||||||
|
window.MCPFeedback.app.sessionManager.exportSingleSession(sessionId);
|
||||||
|
} else {
|
||||||
|
console.warn('找不到 SessionManager 實例');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 全域清空會話歷史方法
|
||||||
|
window.MCPFeedback.SessionManager.clearSessionHistory = function() {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.app && window.MCPFeedback.app.sessionManager) {
|
||||||
|
window.MCPFeedback.app.sessionManager.clearSessionHistory();
|
||||||
|
} else {
|
||||||
|
console.warn('找不到 SessionManager 實例');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
console.log('✅ SessionManager (重構版) 模組載入完成');
|
console.log('✅ SessionManager (重構版) 模組載入完成');
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -33,12 +33,18 @@
|
|||||||
totalSessions: 0
|
totalSessions: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// localStorage 相關設定
|
||||||
|
this.localStorageKey = 'mcp-session-history';
|
||||||
|
this.settingsManager = options.settingsManager || null;
|
||||||
|
|
||||||
// 回調函數
|
// 回調函數
|
||||||
this.onSessionChange = options.onSessionChange || null;
|
this.onSessionChange = options.onSessionChange || null;
|
||||||
this.onHistoryChange = options.onHistoryChange || null;
|
this.onHistoryChange = options.onHistoryChange || null;
|
||||||
this.onStatsChange = options.onStatsChange || null;
|
this.onStatsChange = options.onStatsChange || null;
|
||||||
|
|
||||||
// 初始化統計資訊
|
// 初始化:載入歷史記錄並清理過期資料
|
||||||
|
this.loadFromLocalStorage();
|
||||||
|
this.cleanupExpiredSessions();
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
|
|
||||||
console.log('📊 SessionDataManager 初始化完成');
|
console.log('📊 SessionDataManager 初始化完成');
|
||||||
@ -196,6 +202,9 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新增儲存時間戳記
|
||||||
|
sessionData.saved_at = TimeUtils.getCurrentTimestamp();
|
||||||
|
|
||||||
// 避免重複新增
|
// 避免重複新增
|
||||||
const existingIndex = this.sessionHistory.findIndex(s => s.session_id === sessionData.session_id);
|
const existingIndex = this.sessionHistory.findIndex(s => s.session_id === sessionData.session_id);
|
||||||
if (existingIndex !== -1) {
|
if (existingIndex !== -1) {
|
||||||
@ -209,6 +218,9 @@
|
|||||||
this.sessionHistory = this.sessionHistory.slice(0, 10);
|
this.sessionHistory = this.sessionHistory.slice(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存到 localStorage
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
|
|
||||||
// 觸發回調
|
// 觸發回調
|
||||||
@ -295,6 +307,10 @@
|
|||||||
*/
|
*/
|
||||||
SessionDataManager.prototype.clearHistory = function() {
|
SessionDataManager.prototype.clearHistory = function() {
|
||||||
this.sessionHistory = [];
|
this.sessionHistory = [];
|
||||||
|
|
||||||
|
// 清空 localStorage
|
||||||
|
this.clearLocalStorage();
|
||||||
|
|
||||||
this.updateStats();
|
this.updateStats();
|
||||||
if (this.onHistoryChange) {
|
if (this.onHistoryChange) {
|
||||||
this.onHistoryChange(this.sessionHistory);
|
this.onHistoryChange(this.sessionHistory);
|
||||||
@ -358,6 +374,191 @@
|
|||||||
return '暫無摘要';
|
return '暫無摘要';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 從 localStorage 載入會話歷史
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.loadFromLocalStorage = function() {
|
||||||
|
if (!window.localStorage) {
|
||||||
|
console.warn('📊 localStorage 不可用');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem(this.localStorageKey);
|
||||||
|
if (stored) {
|
||||||
|
const data = JSON.parse(stored);
|
||||||
|
if (data && Array.isArray(data.sessions)) {
|
||||||
|
this.sessionHistory = data.sessions;
|
||||||
|
console.log('📊 從 localStorage 載入', this.sessionHistory.length, '個會話');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📊 從 localStorage 載入會話歷史失敗:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存會話歷史到 localStorage
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.saveToLocalStorage = function() {
|
||||||
|
if (!window.localStorage) {
|
||||||
|
console.warn('📊 localStorage 不可用');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = {
|
||||||
|
sessions: this.sessionHistory,
|
||||||
|
lastCleanup: TimeUtils.getCurrentTimestamp()
|
||||||
|
};
|
||||||
|
localStorage.setItem(this.localStorageKey, JSON.stringify(data));
|
||||||
|
console.log('📊 已保存', this.sessionHistory.length, '個會話到 localStorage');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📊 保存會話歷史到 localStorage 失敗:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空 localStorage 中的會話歷史
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.clearLocalStorage = function() {
|
||||||
|
if (!window.localStorage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(this.localStorageKey);
|
||||||
|
console.log('📊 已清空 localStorage 中的會話歷史');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📊 清空 localStorage 失敗:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理過期的會話
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.cleanupExpiredSessions = function() {
|
||||||
|
if (!this.settingsManager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const retentionHours = this.settingsManager.get('sessionHistoryRetentionHours', 72);
|
||||||
|
const retentionMs = retentionHours * 60 * 60 * 1000;
|
||||||
|
const now = TimeUtils.getCurrentTimestamp();
|
||||||
|
|
||||||
|
const originalCount = this.sessionHistory.length;
|
||||||
|
this.sessionHistory = this.sessionHistory.filter(function(session) {
|
||||||
|
const sessionAge = now - (session.saved_at || session.completed_at || session.created_at || 0);
|
||||||
|
return sessionAge < retentionMs;
|
||||||
|
});
|
||||||
|
|
||||||
|
const cleanedCount = originalCount - this.sessionHistory.length;
|
||||||
|
if (cleanedCount > 0) {
|
||||||
|
console.log('📊 清理了', cleanedCount, '個過期會話');
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 檢查會話是否過期
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.isSessionExpired = function(session) {
|
||||||
|
if (!this.settingsManager) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const retentionHours = this.settingsManager.get('sessionHistoryRetentionHours', 72);
|
||||||
|
const retentionMs = retentionHours * 60 * 60 * 1000;
|
||||||
|
const now = TimeUtils.getCurrentTimestamp();
|
||||||
|
const sessionTime = session.saved_at || session.completed_at || session.created_at || 0;
|
||||||
|
|
||||||
|
return (now - sessionTime) > retentionMs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匯出會話歷史
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.exportSessionHistory = function() {
|
||||||
|
const exportData = {
|
||||||
|
exportedAt: new Date().toISOString(),
|
||||||
|
totalSessions: this.sessionHistory.length,
|
||||||
|
sessions: this.sessionHistory.map(function(session) {
|
||||||
|
return {
|
||||||
|
session_id: session.session_id,
|
||||||
|
created_at: session.created_at,
|
||||||
|
completed_at: session.completed_at,
|
||||||
|
duration: session.duration,
|
||||||
|
status: session.status,
|
||||||
|
project_directory: session.project_directory,
|
||||||
|
ai_summary: session.summary || session.ai_summary,
|
||||||
|
saved_at: session.saved_at
|
||||||
|
};
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const filename = 'session-history-' + new Date().toISOString().split('T')[0] + '.json';
|
||||||
|
this.downloadJSON(exportData, filename);
|
||||||
|
|
||||||
|
console.log('📊 匯出了', this.sessionHistory.length, '個會話');
|
||||||
|
return filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匯出單一會話
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.exportSingleSession = function(sessionId) {
|
||||||
|
const session = this.sessionHistory.find(function(s) {
|
||||||
|
return s.session_id === sessionId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
console.error('📊 找不到會話:', sessionId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exportData = {
|
||||||
|
exportedAt: new Date().toISOString(),
|
||||||
|
session: {
|
||||||
|
session_id: session.session_id,
|
||||||
|
created_at: session.created_at,
|
||||||
|
completed_at: session.completed_at,
|
||||||
|
duration: session.duration,
|
||||||
|
status: session.status,
|
||||||
|
project_directory: session.project_directory,
|
||||||
|
ai_summary: session.summary || session.ai_summary,
|
||||||
|
saved_at: session.saved_at
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const shortId = sessionId.substring(0, 8);
|
||||||
|
const filename = 'session-' + shortId + '-' + new Date().toISOString().split('T')[0] + '.json';
|
||||||
|
this.downloadJSON(exportData, filename);
|
||||||
|
|
||||||
|
console.log('📊 匯出會話:', sessionId);
|
||||||
|
return filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下載 JSON 檔案
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.downloadJSON = function(data, filename) {
|
||||||
|
try {
|
||||||
|
const jsonString = JSON.stringify(data, null, 2);
|
||||||
|
const blob = new Blob([jsonString], { type: 'application/json' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('📊 下載檔案失敗:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理資源
|
* 清理資源
|
||||||
*/
|
*/
|
||||||
|
@ -328,19 +328,39 @@
|
|||||||
(window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '查看') :
|
(window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '查看') :
|
||||||
(window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '詳細資訊');
|
(window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '詳細資訊');
|
||||||
|
|
||||||
const button = DOMUtils.createElement('button', {
|
const viewButton = DOMUtils.createElement('button', {
|
||||||
className: 'btn-small',
|
className: 'btn-small',
|
||||||
textContent: buttonText
|
textContent: buttonText
|
||||||
});
|
});
|
||||||
|
|
||||||
// 添加點擊事件
|
// 添加查看詳情點擊事件
|
||||||
DOMUtils.addEventListener(button, 'click', function() {
|
DOMUtils.addEventListener(viewButton, 'click', function() {
|
||||||
if (window.MCPFeedback && window.MCPFeedback.SessionManager) {
|
if (window.MCPFeedback && window.MCPFeedback.SessionManager) {
|
||||||
window.MCPFeedback.SessionManager.viewSessionDetails(sessionData.session_id);
|
window.MCPFeedback.SessionManager.viewSessionDetails(sessionData.session_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.appendChild(button);
|
actions.appendChild(viewButton);
|
||||||
|
|
||||||
|
// 如果是歷史會話,新增匯出按鈕
|
||||||
|
if (isHistory) {
|
||||||
|
const exportButton = DOMUtils.createElement('button', {
|
||||||
|
className: 'btn-small btn-export',
|
||||||
|
textContent: window.i18nManager ? window.i18nManager.t('sessionHistory.management.exportSingle') : '匯出',
|
||||||
|
style: 'margin-left: 4px; font-size: 11px; padding: 2px 6px;'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加匯出點擊事件
|
||||||
|
DOMUtils.addEventListener(exportButton, 'click', function(e) {
|
||||||
|
e.stopPropagation(); // 防止觸發父元素事件
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.SessionManager) {
|
||||||
|
window.MCPFeedback.SessionManager.exportSingleSession(sessionData.session_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
actions.appendChild(exportButton);
|
||||||
|
}
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,7 +35,9 @@
|
|||||||
audioNotificationEnabled: false,
|
audioNotificationEnabled: false,
|
||||||
audioNotificationVolume: 50,
|
audioNotificationVolume: 50,
|
||||||
selectedAudioId: 'default-beep',
|
selectedAudioId: 'default-beep',
|
||||||
customAudios: []
|
customAudios: [],
|
||||||
|
// 會話歷史設定
|
||||||
|
sessionHistoryRetentionHours: 72
|
||||||
};
|
};
|
||||||
|
|
||||||
// 當前設定
|
// 當前設定
|
||||||
@ -407,6 +409,9 @@
|
|||||||
|
|
||||||
// 應用自動提交設定
|
// 應用自動提交設定
|
||||||
this.applyAutoSubmitSettingsToUI();
|
this.applyAutoSubmitSettingsToUI();
|
||||||
|
|
||||||
|
// 應用會話歷史設定
|
||||||
|
this.applySessionHistorySettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -549,7 +554,20 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 應用會話歷史設定
|
||||||
|
*/
|
||||||
|
SettingsManager.prototype.applySessionHistorySettings = function() {
|
||||||
|
// 更新會話歷史保存期限選擇器
|
||||||
|
const sessionHistoryRetentionSelect = Utils.safeQuerySelector('#sessionHistoryRetentionHours');
|
||||||
|
if (sessionHistoryRetentionSelect) {
|
||||||
|
sessionHistoryRetentionSelect.value = this.currentSettings.sessionHistoryRetentionHours.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('會話歷史設定已應用到 UI:', {
|
||||||
|
retentionHours: this.currentSettings.sessionHistoryRetentionHours
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 設置事件監聽器
|
* 設置事件監聽器
|
||||||
@ -731,6 +749,44 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 會話歷史保存期限設定
|
||||||
|
const sessionHistoryRetentionSelect = Utils.safeQuerySelector('#sessionHistoryRetentionHours');
|
||||||
|
if (sessionHistoryRetentionSelect) {
|
||||||
|
sessionHistoryRetentionSelect.addEventListener('change', function(e) {
|
||||||
|
const hours = parseInt(e.target.value);
|
||||||
|
self.set('sessionHistoryRetentionHours', hours);
|
||||||
|
console.log('會話歷史保存期限已更新:', hours, '小時');
|
||||||
|
|
||||||
|
// 觸發清理過期會話
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.app && window.MCPFeedback.app.sessionManager) {
|
||||||
|
const sessionManager = window.MCPFeedback.app.sessionManager;
|
||||||
|
if (sessionManager.dataManager && sessionManager.dataManager.cleanupExpiredSessions) {
|
||||||
|
sessionManager.dataManager.cleanupExpiredSessions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 會話歷史匯出按鈕
|
||||||
|
const exportHistoryBtn = Utils.safeQuerySelector('#exportSessionHistoryBtn');
|
||||||
|
if (exportHistoryBtn) {
|
||||||
|
exportHistoryBtn.addEventListener('click', function() {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.SessionManager) {
|
||||||
|
window.MCPFeedback.SessionManager.exportSessionHistory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 會話歷史清空按鈕
|
||||||
|
const clearHistoryBtn = Utils.safeQuerySelector('#clearSessionHistoryBtn');
|
||||||
|
if (clearHistoryBtn) {
|
||||||
|
clearHistoryBtn.addEventListener('click', function() {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.SessionManager) {
|
||||||
|
window.MCPFeedback.SessionManager.clearSessionHistory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 重置設定
|
// 重置設定
|
||||||
const resetBtn = Utils.safeQuerySelector('#resetSettingsBtn');
|
const resetBtn = Utils.safeQuerySelector('#resetSettingsBtn');
|
||||||
if (resetBtn) {
|
if (resetBtn) {
|
||||||
|
@ -884,6 +884,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 會話歷史管理卡片 -->
|
||||||
|
<div class="settings-card">
|
||||||
|
<div class="settings-card-header">
|
||||||
|
<h3 class="settings-card-title" data-i18n="sessionHistory.management.title">📚 會話歷史管理</h3>
|
||||||
|
</div>
|
||||||
|
<div class="settings-card-body">
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-info">
|
||||||
|
<div class="setting-label" data-i18n="sessionHistory.management.retentionPeriod">保存期限</div>
|
||||||
|
<div class="setting-description" data-i18n="sessionHistory.management.description">
|
||||||
|
管理本地儲存的會話歷史記錄,包括保存期限設定和資料匯出功能
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control">
|
||||||
|
<select id="sessionHistoryRetentionHours" class="form-select" style="width: 150px;">
|
||||||
|
<option value="24" data-i18n="sessionHistory.retention.24hours">24 小時</option>
|
||||||
|
<option value="72" data-i18n="sessionHistory.retention.72hours">72 小時</option>
|
||||||
|
<option value="168" data-i18n="sessionHistory.retention.168hours">7 天</option>
|
||||||
|
<option value="720" data-i18n="sessionHistory.retention.720hours">30 天</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item" style="border-bottom: none;">
|
||||||
|
<div class="setting-info">
|
||||||
|
<div class="setting-label" data-i18n="sessionHistory.management.export">資料管理</div>
|
||||||
|
<div class="setting-description">
|
||||||
|
匯出或清空本地儲存的會話歷史記錄
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control" style="display: flex; gap: 8px;">
|
||||||
|
<button id="exportSessionHistoryBtn" class="btn btn-secondary" style="font-size: 12px; padding: 6px 12px;">
|
||||||
|
<span data-i18n="sessionHistory.management.exportAll">匯出全部</span>
|
||||||
|
</button>
|
||||||
|
<button id="clearSessionHistoryBtn" class="btn btn-secondary" style="font-size: 12px; padding: 6px 12px; color: var(--error-color); border-color: var(--error-color);">
|
||||||
|
<span data-i18n="sessionHistory.management.clear">清空</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 提示詞管理卡片 -->
|
<!-- 提示詞管理卡片 -->
|
||||||
<div class="settings-card">
|
<div class="settings-card">
|
||||||
<div class="settings-card-header">
|
<div class="settings-card-header">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user