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
f9df4386f8
commit
8316cb6572
@ -236,7 +236,8 @@
|
|||||||
"confirmClear": "Are you sure you want to clear all session history?",
|
"confirmClear": "Are you sure you want to clear all session history?",
|
||||||
"exportSuccess": "Session history exported successfully",
|
"exportSuccess": "Session history exported successfully",
|
||||||
"clearSuccess": "Session history cleared successfully",
|
"clearSuccess": "Session history cleared successfully",
|
||||||
"description": "Manage locally stored session history records, including retention period settings and data export functionality"
|
"description": "Manage locally stored session history records, including retention period settings and data export functionality",
|
||||||
|
"exportDescription": "Export or clear locally stored session history records"
|
||||||
},
|
},
|
||||||
"retention": {
|
"retention": {
|
||||||
"24hours": "24 hours",
|
"24hours": "24 hours",
|
||||||
@ -244,6 +245,32 @@
|
|||||||
"168hours": "7 days",
|
"168hours": "7 days",
|
||||||
"720hours": "30 days",
|
"720hours": "30 days",
|
||||||
"custom": "Custom"
|
"custom": "Custom"
|
||||||
|
},
|
||||||
|
"userMessages": {
|
||||||
|
"title": "User Message Recording",
|
||||||
|
"description": "Control whether to record user submitted feedback messages in session history",
|
||||||
|
"recordingEnabled": "Enable Message Recording",
|
||||||
|
"privacyLevel": "Privacy Level",
|
||||||
|
"privacyLevels": {
|
||||||
|
"full": "Full Recording",
|
||||||
|
"basic": "Basic Statistics",
|
||||||
|
"disabled": "Disable Recording"
|
||||||
|
},
|
||||||
|
"privacyDescription": {
|
||||||
|
"full": "Record complete message content and image information",
|
||||||
|
"basic": "Only record message length, image count and other statistics",
|
||||||
|
"disabled": "Do not record any user message content"
|
||||||
|
},
|
||||||
|
"messageCount": "Message Count",
|
||||||
|
"submissionMethod": "Submission Method",
|
||||||
|
"manual": "Manual Submit",
|
||||||
|
"auto": "Auto Submit",
|
||||||
|
"contentLength": "Content Length",
|
||||||
|
"imageCount": "Image Count",
|
||||||
|
"timestamp": "Timestamp",
|
||||||
|
"clearAll": "Clear Message Records",
|
||||||
|
"confirmClearAll": "Are you sure you want to clear all user message records from all sessions? This action cannot be undone.",
|
||||||
|
"clearSuccess": "User message records cleared successfully"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"connectionMonitor": {
|
"connectionMonitor": {
|
||||||
|
@ -236,7 +236,8 @@
|
|||||||
"confirmClear": "确定要清空所有会话历史吗?",
|
"confirmClear": "确定要清空所有会话历史吗?",
|
||||||
"exportSuccess": "会话历史已导出",
|
"exportSuccess": "会话历史已导出",
|
||||||
"clearSuccess": "会话历史已清空",
|
"clearSuccess": "会话历史已清空",
|
||||||
"description": "管理本地存储的会话历史记录,包括保存期限设定和数据导出功能"
|
"description": "管理本地存储的会话历史记录,包括保存期限设定和数据导出功能",
|
||||||
|
"exportDescription": "导出或清空本地存储的会话历史记录"
|
||||||
},
|
},
|
||||||
"retention": {
|
"retention": {
|
||||||
"24hours": "24 小时",
|
"24hours": "24 小时",
|
||||||
@ -244,6 +245,32 @@
|
|||||||
"168hours": "7 天",
|
"168hours": "7 天",
|
||||||
"720hours": "30 天",
|
"720hours": "30 天",
|
||||||
"custom": "自定义"
|
"custom": "自定义"
|
||||||
|
},
|
||||||
|
"userMessages": {
|
||||||
|
"title": "用户消息记录",
|
||||||
|
"description": "控制是否记录用户提交的反馈消息到会话历史中",
|
||||||
|
"recordingEnabled": "启用消息记录",
|
||||||
|
"privacyLevel": "隐私等级",
|
||||||
|
"privacyLevels": {
|
||||||
|
"full": "完整记录",
|
||||||
|
"basic": "基本统计",
|
||||||
|
"disabled": "停用记录"
|
||||||
|
},
|
||||||
|
"privacyDescription": {
|
||||||
|
"full": "记录完整的消息内容和图片信息",
|
||||||
|
"basic": "仅记录消息长度、图片数量等统计信息",
|
||||||
|
"disabled": "不记录任何用户消息内容"
|
||||||
|
},
|
||||||
|
"messageCount": "消息数量",
|
||||||
|
"submissionMethod": "提交方式",
|
||||||
|
"manual": "手动提交",
|
||||||
|
"auto": "自动提交",
|
||||||
|
"contentLength": "内容长度",
|
||||||
|
"imageCount": "图片数量",
|
||||||
|
"timestamp": "时间戳",
|
||||||
|
"clearAll": "清空消息记录",
|
||||||
|
"confirmClearAll": "确定要清空所有会话的用户消息记录吗?此操作无法撤销。",
|
||||||
|
"clearSuccess": "用户消息记录已清空"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"connectionMonitor": {
|
"connectionMonitor": {
|
||||||
|
@ -241,7 +241,8 @@
|
|||||||
"confirmClear": "確定要清空所有會話歷史嗎?",
|
"confirmClear": "確定要清空所有會話歷史嗎?",
|
||||||
"exportSuccess": "會話歷史已匯出",
|
"exportSuccess": "會話歷史已匯出",
|
||||||
"clearSuccess": "會話歷史已清空",
|
"clearSuccess": "會話歷史已清空",
|
||||||
"description": "管理本地儲存的會話歷史記錄,包括保存期限設定和資料匯出功能"
|
"description": "管理本地儲存的會話歷史記錄,包括保存期限設定和資料匯出功能",
|
||||||
|
"exportDescription": "匯出或清空本地儲存的會話歷史記錄"
|
||||||
},
|
},
|
||||||
"retention": {
|
"retention": {
|
||||||
"24hours": "24 小時",
|
"24hours": "24 小時",
|
||||||
@ -249,6 +250,32 @@
|
|||||||
"168hours": "7 天",
|
"168hours": "7 天",
|
||||||
"720hours": "30 天",
|
"720hours": "30 天",
|
||||||
"custom": "自訂"
|
"custom": "自訂"
|
||||||
|
},
|
||||||
|
"userMessages": {
|
||||||
|
"title": "用戶訊息記錄",
|
||||||
|
"description": "控制是否記錄用戶提交的回饋訊息到會話歷史中",
|
||||||
|
"recordingEnabled": "啟用訊息記錄",
|
||||||
|
"privacyLevel": "隱私等級",
|
||||||
|
"privacyLevels": {
|
||||||
|
"full": "完整記錄",
|
||||||
|
"basic": "基本統計",
|
||||||
|
"disabled": "停用記錄"
|
||||||
|
},
|
||||||
|
"privacyDescription": {
|
||||||
|
"full": "記錄完整的訊息內容和圖片資訊",
|
||||||
|
"basic": "僅記錄訊息長度、圖片數量等統計資訊",
|
||||||
|
"disabled": "不記錄任何用戶訊息內容"
|
||||||
|
},
|
||||||
|
"messageCount": "訊息數量",
|
||||||
|
"submissionMethod": "提交方式",
|
||||||
|
"manual": "手動提交",
|
||||||
|
"auto": "自動提交",
|
||||||
|
"contentLength": "內容長度",
|
||||||
|
"imageCount": "圖片數量",
|
||||||
|
"timestamp": "時間戳記",
|
||||||
|
"clearAll": "清空訊息記錄",
|
||||||
|
"confirmClearAll": "確定要清空所有會話的用戶訊息記錄嗎?此操作無法復原。",
|
||||||
|
"clearSuccess": "用戶訊息記錄已清空"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"connectionMonitor": {
|
"connectionMonitor": {
|
||||||
|
@ -877,6 +877,148 @@
|
|||||||
border-color: var(--accent-color);
|
border-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== 用戶訊息記錄樣式 ===== */
|
||||||
|
.user-messages-section {
|
||||||
|
margin-top: 16px;
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-messages-summary {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-messages-list {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--bg-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-message-item {
|
||||||
|
padding: 12px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
transition: background var(--transition-fast) ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-message-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-message-item:hover {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-index {
|
||||||
|
background: var(--accent-color);
|
||||||
|
color: white;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-time {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-method {
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-method:contains("自動") {
|
||||||
|
background: rgba(255, 152, 0, 0.2);
|
||||||
|
color: var(--warning-color);
|
||||||
|
border: 1px solid var(--warning-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-method:contains("手動") {
|
||||||
|
background: rgba(76, 175, 80, 0.2);
|
||||||
|
color: var(--success-color);
|
||||||
|
border: 1px solid var(--success-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content,
|
||||||
|
.message-stats {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: var(--text-primary);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 3px solid var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content strong,
|
||||||
|
.message-stats strong {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-images {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 隱私等級選擇器樣式增強 */
|
||||||
|
#userMessagePrivacyLevel {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
color: var(--text-primary);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#userMessagePrivacyLevel:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#userMessagePrivacyLevel option {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 用戶訊息記錄開關樣式已整合到標準切換開關樣式中 */
|
||||||
|
|
||||||
|
/* 切換開關容器樣式 */
|
||||||
|
.toggle-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* 減少動畫偏好 */
|
/* 減少動畫偏好 */
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
* {
|
* {
|
||||||
|
@ -831,6 +831,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
// 記錄用戶訊息到會話歷史
|
||||||
|
this.recordUserMessage(feedbackData);
|
||||||
|
|
||||||
// 清空表單
|
// 清空表單
|
||||||
this.clearFeedback();
|
this.clearFeedback();
|
||||||
console.log('📤 回饋已發送,等待服務器確認...');
|
console.log('📤 回饋已發送,等待服務器確認...');
|
||||||
@ -850,6 +853,44 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 記錄用戶訊息到會話歷史
|
||||||
|
*/
|
||||||
|
FeedbackApp.prototype.recordUserMessage = function(feedbackData) {
|
||||||
|
console.log('📝 記錄用戶訊息到會話歷史...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 檢查是否有會話管理器
|
||||||
|
if (!this.sessionManager || !this.sessionManager.dataManager) {
|
||||||
|
console.warn('📝 會話管理器未初始化,跳過用戶訊息記錄');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判斷提交方式
|
||||||
|
const submissionMethod = this.autoSubmitManager && this.autoSubmitManager.isEnabled ? 'auto' : 'manual';
|
||||||
|
|
||||||
|
// 建立訊息記錄資料
|
||||||
|
const messageData = {
|
||||||
|
content: feedbackData.feedback || '',
|
||||||
|
images: feedbackData.images || [],
|
||||||
|
submission_method: submissionMethod
|
||||||
|
};
|
||||||
|
|
||||||
|
// 記錄到會話歷史
|
||||||
|
const success = this.sessionManager.dataManager.addUserMessage(messageData);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log('📝 用戶訊息已記錄到會話歷史');
|
||||||
|
} else {
|
||||||
|
console.log('📝 用戶訊息記錄被跳過(可能因隱私設定或其他原因)');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 記錄用戶訊息失敗:', error);
|
||||||
|
// 不影響主要功能,只記錄錯誤
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空回饋內容
|
* 清空回饋內容
|
||||||
*/
|
*/
|
||||||
|
@ -205,9 +205,19 @@
|
|||||||
// 新增儲存時間戳記
|
// 新增儲存時間戳記
|
||||||
sessionData.saved_at = TimeUtils.getCurrentTimestamp();
|
sessionData.saved_at = TimeUtils.getCurrentTimestamp();
|
||||||
|
|
||||||
|
// 確保 user_messages 陣列存在(向後相容)
|
||||||
|
if (!sessionData.user_messages) {
|
||||||
|
sessionData.user_messages = [];
|
||||||
|
}
|
||||||
|
|
||||||
// 避免重複新增
|
// 避免重複新增
|
||||||
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) {
|
||||||
|
// 合併用戶訊息記錄
|
||||||
|
const existingSession = this.sessionHistory[existingIndex];
|
||||||
|
if (existingSession.user_messages && sessionData.user_messages) {
|
||||||
|
sessionData.user_messages = this.mergeUserMessages(existingSession.user_messages, sessionData.user_messages);
|
||||||
|
}
|
||||||
this.sessionHistory[existingIndex] = sessionData;
|
this.sessionHistory[existingIndex] = sessionData;
|
||||||
} else {
|
} else {
|
||||||
this.sessionHistory.unshift(sessionData);
|
this.sessionHistory.unshift(sessionData);
|
||||||
@ -231,6 +241,185 @@
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合併用戶訊息記錄
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.mergeUserMessages = function(existingMessages, newMessages) {
|
||||||
|
const merged = existingMessages.slice(); // 複製現有訊息
|
||||||
|
|
||||||
|
// 新增不重複的訊息(基於時間戳記去重)
|
||||||
|
newMessages.forEach(function(newMsg) {
|
||||||
|
const exists = merged.some(function(existingMsg) {
|
||||||
|
return existingMsg.timestamp === newMsg.timestamp;
|
||||||
|
});
|
||||||
|
if (!exists) {
|
||||||
|
merged.push(newMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 按時間戳記排序
|
||||||
|
merged.sort(function(a, b) {
|
||||||
|
return a.timestamp - b.timestamp;
|
||||||
|
});
|
||||||
|
|
||||||
|
return merged;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增用戶訊息到當前會話
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.addUserMessage = function(messageData) {
|
||||||
|
console.log('📊 新增用戶訊息:', messageData);
|
||||||
|
|
||||||
|
// 檢查隱私設定
|
||||||
|
if (!this.isUserMessageRecordingEnabled()) {
|
||||||
|
console.log('📊 用戶訊息記錄已停用,跳過記錄');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 檢查是否有當前會話
|
||||||
|
if (!this.currentSession || !this.currentSession.session_id) {
|
||||||
|
console.warn('📊 沒有當前會話,無法記錄用戶訊息');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 確保當前會話有 user_messages 陣列
|
||||||
|
if (!this.currentSession.user_messages) {
|
||||||
|
this.currentSession.user_messages = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 建立用戶訊息記錄
|
||||||
|
const userMessage = this.createUserMessageRecord(messageData);
|
||||||
|
|
||||||
|
// 新增到當前會話
|
||||||
|
this.currentSession.user_messages.push(userMessage);
|
||||||
|
|
||||||
|
console.log('📊 用戶訊息已記錄到當前會話:', this.currentSession.session_id);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 建立用戶訊息記錄
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.createUserMessageRecord = function(messageData) {
|
||||||
|
const timestamp = TimeUtils.getCurrentTimestamp();
|
||||||
|
const privacyLevel = this.getUserMessagePrivacyLevel();
|
||||||
|
|
||||||
|
const record = {
|
||||||
|
timestamp: timestamp,
|
||||||
|
submission_method: messageData.submission_method || 'manual',
|
||||||
|
type: 'feedback'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根據隱私等級決定記錄內容
|
||||||
|
if (privacyLevel === 'full') {
|
||||||
|
record.content = messageData.content || '';
|
||||||
|
record.images = this.processImageDataForRecord(messageData.images || []);
|
||||||
|
} else if (privacyLevel === 'basic') {
|
||||||
|
record.content_length = (messageData.content || '').length;
|
||||||
|
record.image_count = (messageData.images || []).length;
|
||||||
|
record.has_content = !!(messageData.content && messageData.content.trim());
|
||||||
|
} else if (privacyLevel === 'disabled') {
|
||||||
|
// 停用記錄時,只記錄最基本的時間戳記和提交方式
|
||||||
|
record.privacy_note = 'Content recording disabled by user privacy settings';
|
||||||
|
}
|
||||||
|
|
||||||
|
return record;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 處理圖片資料用於記錄
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.processImageDataForRecord = function(images) {
|
||||||
|
if (!Array.isArray(images)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return images.map(function(img) {
|
||||||
|
return {
|
||||||
|
name: img.name || 'unknown',
|
||||||
|
size: img.size || 0,
|
||||||
|
type: img.type || 'unknown'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 檢查是否啟用用戶訊息記錄
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.isUserMessageRecordingEnabled = function() {
|
||||||
|
if (!this.settingsManager) {
|
||||||
|
return true; // 預設啟用
|
||||||
|
}
|
||||||
|
|
||||||
|
// 檢查總開關
|
||||||
|
const recordingEnabled = this.settingsManager.get('userMessageRecordingEnabled', true);
|
||||||
|
if (!recordingEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 檢查隱私等級(disabled 等級視為停用記錄)
|
||||||
|
const privacyLevel = this.settingsManager.get('userMessagePrivacyLevel', 'full');
|
||||||
|
return privacyLevel !== 'disabled';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 獲取用戶訊息隱私等級
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.getUserMessagePrivacyLevel = function() {
|
||||||
|
if (!this.settingsManager) {
|
||||||
|
return 'full'; // 預設完整記錄
|
||||||
|
}
|
||||||
|
return this.settingsManager.get('userMessagePrivacyLevel', 'full');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空所有會話的用戶訊息記錄
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.clearAllUserMessages = function() {
|
||||||
|
console.log('📊 清空所有會話的用戶訊息記錄...');
|
||||||
|
|
||||||
|
// 清空當前會話的用戶訊息
|
||||||
|
if (this.currentSession && this.currentSession.user_messages) {
|
||||||
|
this.currentSession.user_messages = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空歷史會話的用戶訊息
|
||||||
|
this.sessionHistory.forEach(function(session) {
|
||||||
|
if (session.user_messages) {
|
||||||
|
session.user_messages = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 保存到 localStorage
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
|
||||||
|
console.log('📊 所有用戶訊息記錄已清空');
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空指定會話的用戶訊息記錄
|
||||||
|
*/
|
||||||
|
SessionDataManager.prototype.clearSessionUserMessages = function(sessionId) {
|
||||||
|
console.log('📊 清空會話用戶訊息記錄:', sessionId);
|
||||||
|
|
||||||
|
// 查找並清空指定會話的用戶訊息
|
||||||
|
const session = this.sessionHistory.find(function(s) {
|
||||||
|
return s.session_id === sessionId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (session && session.user_messages) {
|
||||||
|
session.user_messages = [];
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
console.log('📊 會話用戶訊息記錄已清空:', sessionId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('📊 找不到指定會話或該會話沒有用戶訊息記錄:', sessionId);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 獲取當前會話
|
* 獲取當前會話
|
||||||
*/
|
*/
|
||||||
@ -479,11 +668,12 @@
|
|||||||
* 匯出會話歷史
|
* 匯出會話歷史
|
||||||
*/
|
*/
|
||||||
SessionDataManager.prototype.exportSessionHistory = function() {
|
SessionDataManager.prototype.exportSessionHistory = function() {
|
||||||
|
const self = this;
|
||||||
const exportData = {
|
const exportData = {
|
||||||
exportedAt: new Date().toISOString(),
|
exportedAt: new Date().toISOString(),
|
||||||
totalSessions: this.sessionHistory.length,
|
totalSessions: this.sessionHistory.length,
|
||||||
sessions: this.sessionHistory.map(function(session) {
|
sessions: this.sessionHistory.map(function(session) {
|
||||||
return {
|
const sessionData = {
|
||||||
session_id: session.session_id,
|
session_id: session.session_id,
|
||||||
created_at: session.created_at,
|
created_at: session.created_at,
|
||||||
completed_at: session.completed_at,
|
completed_at: session.completed_at,
|
||||||
@ -493,6 +683,14 @@
|
|||||||
ai_summary: session.summary || session.ai_summary,
|
ai_summary: session.summary || session.ai_summary,
|
||||||
saved_at: session.saved_at
|
saved_at: session.saved_at
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 包含用戶訊息記錄(如果存在且允許匯出)
|
||||||
|
if (session.user_messages && self.isUserMessageRecordingEnabled()) {
|
||||||
|
sessionData.user_messages = session.user_messages;
|
||||||
|
sessionData.user_message_count = session.user_messages.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionData;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -516,18 +714,26 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sessionData = {
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
// 包含用戶訊息記錄(如果存在且允許匯出)
|
||||||
|
if (session.user_messages && this.isUserMessageRecordingEnabled()) {
|
||||||
|
sessionData.user_messages = session.user_messages;
|
||||||
|
sessionData.user_message_count = session.user_messages.length;
|
||||||
|
}
|
||||||
|
|
||||||
const exportData = {
|
const exportData = {
|
||||||
exportedAt: new Date().toISOString(),
|
exportedAt: new Date().toISOString(),
|
||||||
session: {
|
session: sessionData
|
||||||
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 shortId = sessionId.substring(0, 8);
|
||||||
|
@ -88,6 +88,10 @@
|
|||||||
const statusText = StatusUtils.getStatusText(status);
|
const statusText = StatusUtils.getStatusText(status);
|
||||||
const statusColor = StatusUtils.getStatusColor(status);
|
const statusColor = StatusUtils.getStatusColor(status);
|
||||||
|
|
||||||
|
// 處理用戶訊息記錄
|
||||||
|
const userMessages = sessionData.user_messages || [];
|
||||||
|
const userMessageCount = userMessages.length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessionId: sessionId,
|
sessionId: sessionId,
|
||||||
status: statusText,
|
status: statusText,
|
||||||
@ -95,7 +99,9 @@
|
|||||||
createdTime: createdTime,
|
createdTime: createdTime,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
projectDirectory: sessionData.project_directory || (window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.unknown') : '未知'),
|
projectDirectory: sessionData.project_directory || (window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.unknown') : '未知'),
|
||||||
summary: sessionData.summary || (window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.noSummary') : '暫無摘要')
|
summary: sessionData.summary || (window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.noSummary') : '暫無摘要'),
|
||||||
|
userMessages: userMessages,
|
||||||
|
userMessageCount: userMessageCount
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -162,6 +168,7 @@
|
|||||||
<span class="detail-label">${i18n ? i18n.t('sessionManagement.aiSummary') : 'AI 摘要'}:</span>
|
<span class="detail-label">${i18n ? i18n.t('sessionManagement.aiSummary') : 'AI 摘要'}:</span>
|
||||||
<div class="detail-value summary">${this.escapeHtml(details.summary)}</div>
|
<div class="detail-value summary">${this.escapeHtml(details.summary)}</div>
|
||||||
</div>
|
</div>
|
||||||
|
${this.createUserMessagesSection(details)}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn-secondary" id="closeSessionDetailsBtn">${closeLabel}</button>
|
<button class="btn-secondary" id="closeSessionDetailsBtn">${closeLabel}</button>
|
||||||
@ -171,6 +178,95 @@
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 創建用戶訊息記錄區段
|
||||||
|
*/
|
||||||
|
SessionDetailsModal.prototype.createUserMessagesSection = function(details) {
|
||||||
|
const i18n = window.i18nManager;
|
||||||
|
const userMessages = details.userMessages || [];
|
||||||
|
|
||||||
|
if (userMessages.length === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const sectionTitle = i18n ? i18n.t('sessionHistory.userMessages.title') : '用戶訊息記錄';
|
||||||
|
const messageCountLabel = i18n ? i18n.t('sessionHistory.userMessages.messageCount') : '訊息數量';
|
||||||
|
|
||||||
|
let messagesHtml = '';
|
||||||
|
|
||||||
|
userMessages.forEach((message, index) => {
|
||||||
|
const timestamp = message.timestamp ? TimeUtils.formatTimestamp(message.timestamp) : '未知時間';
|
||||||
|
const submissionMethod = message.submission_method === 'auto' ?
|
||||||
|
(i18n ? i18n.t('sessionHistory.userMessages.auto') : '自動提交') :
|
||||||
|
(i18n ? i18n.t('sessionHistory.userMessages.manual') : '手動提交');
|
||||||
|
|
||||||
|
let contentHtml = '';
|
||||||
|
|
||||||
|
if (message.content !== undefined) {
|
||||||
|
// 完整記錄模式
|
||||||
|
const contentPreview = message.content.length > 100 ?
|
||||||
|
message.content.substring(0, 100) + '...' :
|
||||||
|
message.content;
|
||||||
|
contentHtml = `
|
||||||
|
<div class="message-content">
|
||||||
|
<strong>內容:</strong> ${this.escapeHtml(contentPreview)}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (message.images && message.images.length > 0) {
|
||||||
|
const imageCountText = i18n ? i18n.t('sessionHistory.userMessages.imageCount') : '圖片數量';
|
||||||
|
contentHtml += `
|
||||||
|
<div class="message-images">
|
||||||
|
<strong>${imageCountText}:</strong> ${message.images.length}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
} else if (message.content_length !== undefined) {
|
||||||
|
// 基本統計模式
|
||||||
|
const contentLengthLabel = i18n ? i18n.t('sessionHistory.userMessages.contentLength') : '內容長度';
|
||||||
|
const imageCountLabel = i18n ? i18n.t('sessionHistory.userMessages.imageCount') : '圖片數量';
|
||||||
|
contentHtml = `
|
||||||
|
<div class="message-stats">
|
||||||
|
<strong>${contentLengthLabel}:</strong> ${message.content_length} 字元<br>
|
||||||
|
<strong>${imageCountLabel}:</strong> ${message.image_count || 0}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (message.privacy_note) {
|
||||||
|
// 隱私保護模式
|
||||||
|
contentHtml = `
|
||||||
|
<div class="message-privacy">
|
||||||
|
<em style="color: var(--text-secondary);">內容記錄已停用(隱私設定)</em>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
messagesHtml += `
|
||||||
|
<div class="user-message-item">
|
||||||
|
<div class="message-header">
|
||||||
|
<span class="message-index">#${index + 1}</span>
|
||||||
|
<span class="message-time">${timestamp}</span>
|
||||||
|
<span class="message-method">${submissionMethod}</span>
|
||||||
|
</div>
|
||||||
|
${contentHtml}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="detail-row user-messages-section">
|
||||||
|
<span class="detail-label">${sectionTitle}:</span>
|
||||||
|
<div class="detail-value">
|
||||||
|
<div class="user-messages-summary">
|
||||||
|
<strong>${messageCountLabel}:</strong> ${userMessages.length}
|
||||||
|
</div>
|
||||||
|
<div class="user-messages-list">
|
||||||
|
${messagesHtml}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 設置事件監聽器
|
* 設置事件監聽器
|
||||||
*/
|
*/
|
||||||
|
@ -37,7 +37,10 @@
|
|||||||
selectedAudioId: 'default-beep',
|
selectedAudioId: 'default-beep',
|
||||||
customAudios: [],
|
customAudios: [],
|
||||||
// 會話歷史設定
|
// 會話歷史設定
|
||||||
sessionHistoryRetentionHours: 72
|
sessionHistoryRetentionHours: 72,
|
||||||
|
// 用戶訊息記錄設定
|
||||||
|
userMessageRecordingEnabled: true,
|
||||||
|
userMessagePrivacyLevel: 'full' // 'full', 'basic', 'disabled'
|
||||||
};
|
};
|
||||||
|
|
||||||
// 當前設定
|
// 當前設定
|
||||||
@ -263,17 +266,22 @@
|
|||||||
*/
|
*/
|
||||||
SettingsManager.prototype.handleLanguageChange = function(newLanguage) {
|
SettingsManager.prototype.handleLanguageChange = function(newLanguage) {
|
||||||
console.log('語言設定變更: ' + newLanguage);
|
console.log('語言設定變更: ' + newLanguage);
|
||||||
|
|
||||||
// 同步到 localStorage
|
// 同步到 localStorage
|
||||||
if (Utils.isLocalStorageSupported()) {
|
if (Utils.isLocalStorageSupported()) {
|
||||||
localStorage.setItem('language', newLanguage);
|
localStorage.setItem('language', newLanguage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通知國際化系統
|
// 通知國際化系統
|
||||||
if (window.i18nManager) {
|
if (window.i18nManager) {
|
||||||
window.i18nManager.setLanguage(newLanguage);
|
window.i18nManager.setLanguage(newLanguage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 延遲更新動態文字,確保 i18n 已經載入新語言
|
||||||
|
setTimeout(() => {
|
||||||
|
this.updatePrivacyLevelDescription(this.currentSettings.userMessagePrivacyLevel);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// 觸發語言變更回調
|
// 觸發語言變更回調
|
||||||
if (this.onLanguageChange) {
|
if (this.onLanguageChange) {
|
||||||
this.onLanguageChange(newLanguage);
|
this.onLanguageChange(newLanguage);
|
||||||
@ -412,6 +420,9 @@
|
|||||||
|
|
||||||
// 應用會話歷史設定
|
// 應用會話歷史設定
|
||||||
this.applySessionHistorySettings();
|
this.applySessionHistorySettings();
|
||||||
|
|
||||||
|
// 應用用戶訊息記錄設定
|
||||||
|
this.applyUserMessageSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -569,6 +580,63 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 應用用戶訊息記錄設定
|
||||||
|
*/
|
||||||
|
SettingsManager.prototype.applyUserMessageSettings = function() {
|
||||||
|
// 更新用戶訊息記錄啟用開關
|
||||||
|
const userMessageRecordingToggle = Utils.safeQuerySelector('#userMessageRecordingToggle');
|
||||||
|
if (userMessageRecordingToggle) {
|
||||||
|
userMessageRecordingToggle.checked = this.currentSettings.userMessageRecordingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新隱私等級選擇器
|
||||||
|
const userMessagePrivacySelect = Utils.safeQuerySelector('#userMessagePrivacyLevel');
|
||||||
|
if (userMessagePrivacySelect) {
|
||||||
|
userMessagePrivacySelect.value = this.currentSettings.userMessagePrivacyLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('用戶訊息記錄設定已應用到 UI:', {
|
||||||
|
recordingEnabled: this.currentSettings.userMessageRecordingEnabled,
|
||||||
|
privacyLevel: this.currentSettings.userMessagePrivacyLevel
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新隱私等級描述
|
||||||
|
this.updatePrivacyLevelDescription(this.currentSettings.userMessagePrivacyLevel);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新隱私等級描述文字
|
||||||
|
*/
|
||||||
|
SettingsManager.prototype.updatePrivacyLevelDescription = function(privacyLevel) {
|
||||||
|
const descriptionElement = Utils.safeQuerySelector('#userMessagePrivacyDescription');
|
||||||
|
if (!descriptionElement || !window.i18nManager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let descriptionKey = '';
|
||||||
|
switch (privacyLevel) {
|
||||||
|
case 'full':
|
||||||
|
descriptionKey = 'sessionHistory.userMessages.privacyDescription.full';
|
||||||
|
break;
|
||||||
|
case 'basic':
|
||||||
|
descriptionKey = 'sessionHistory.userMessages.privacyDescription.basic';
|
||||||
|
break;
|
||||||
|
case 'disabled':
|
||||||
|
descriptionKey = 'sessionHistory.userMessages.privacyDescription.disabled';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
descriptionKey = 'sessionHistory.userMessages.privacyDescription.full';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新 data-i18n 屬性,這樣在語言切換時會自動更新
|
||||||
|
descriptionElement.setAttribute('data-i18n', descriptionKey);
|
||||||
|
|
||||||
|
// 立即更新文字內容
|
||||||
|
const description = window.i18nManager.t(descriptionKey);
|
||||||
|
descriptionElement.textContent = description;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 設置事件監聽器
|
* 設置事件監聽器
|
||||||
*/
|
*/
|
||||||
@ -787,6 +855,50 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清空用戶訊息記錄按鈕
|
||||||
|
const clearUserMessagesBtn = Utils.safeQuerySelector('#clearUserMessagesBtn');
|
||||||
|
if (clearUserMessagesBtn) {
|
||||||
|
clearUserMessagesBtn.addEventListener('click', function() {
|
||||||
|
const i18n = window.i18nManager;
|
||||||
|
const confirmMessage = i18n ?
|
||||||
|
i18n.t('sessionHistory.userMessages.confirmClearAll') :
|
||||||
|
'確定要清空所有會話的用戶訊息記錄嗎?此操作無法復原。';
|
||||||
|
|
||||||
|
if (confirm(confirmMessage)) {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.app && window.MCPFeedback.app.sessionManager) {
|
||||||
|
const success = window.MCPFeedback.app.sessionManager.dataManager.clearAllUserMessages();
|
||||||
|
if (success) {
|
||||||
|
const successMessage = i18n ?
|
||||||
|
i18n.t('sessionHistory.userMessages.clearSuccess') :
|
||||||
|
'用戶訊息記錄已清空';
|
||||||
|
alert(successMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用戶訊息記錄啟用開關
|
||||||
|
const userMessageRecordingToggle = Utils.safeQuerySelector('#userMessageRecordingToggle');
|
||||||
|
if (userMessageRecordingToggle) {
|
||||||
|
userMessageRecordingToggle.addEventListener('change', function() {
|
||||||
|
const newValue = userMessageRecordingToggle.checked;
|
||||||
|
self.set('userMessageRecordingEnabled', newValue);
|
||||||
|
console.log('用戶訊息記錄狀態已更新:', newValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用戶訊息隱私等級選擇
|
||||||
|
const userMessagePrivacySelect = Utils.safeQuerySelector('#userMessagePrivacyLevel');
|
||||||
|
if (userMessagePrivacySelect) {
|
||||||
|
userMessagePrivacySelect.addEventListener('change', function(e) {
|
||||||
|
const privacyLevel = e.target.value;
|
||||||
|
self.set('userMessagePrivacyLevel', privacyLevel);
|
||||||
|
self.updatePrivacyLevelDescription(privacyLevel);
|
||||||
|
console.log('用戶訊息隱私等級已更新:', privacyLevel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 重置設定
|
// 重置設定
|
||||||
const resetBtn = Utils.safeQuerySelector('#resetSettingsBtn');
|
const resetBtn = Utils.safeQuerySelector('#resetSettingsBtn');
|
||||||
if (resetBtn) {
|
if (resetBtn) {
|
||||||
|
@ -907,17 +907,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-info">
|
||||||
|
<div class="setting-label" data-i18n="sessionHistory.userMessages.title">用戶訊息記錄</div>
|
||||||
|
<div class="setting-description" data-i18n="sessionHistory.userMessages.description">
|
||||||
|
控制是否記錄用戶提交的回饋訊息到會話歷史中
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control">
|
||||||
|
<div class="toggle-container">
|
||||||
|
<label class="toggle-switch">
|
||||||
|
<input type="checkbox" id="userMessageRecordingToggle" class="toggle-input">
|
||||||
|
<span class="toggle-slider"></span>
|
||||||
|
</label>
|
||||||
|
<span class="toggle-label" data-i18n="sessionHistory.userMessages.recordingEnabled">啟用訊息記錄</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-info">
|
||||||
|
<div class="setting-label" data-i18n="sessionHistory.userMessages.privacyLevel">隱私等級</div>
|
||||||
|
<div class="setting-description" id="userMessagePrivacyDescription" data-i18n="sessionHistory.userMessages.privacyDescription.full">
|
||||||
|
記錄完整的訊息內容和圖片資訊
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting-control">
|
||||||
|
<select id="userMessagePrivacyLevel" class="form-select" style="width: 150px;">
|
||||||
|
<option value="full" data-i18n="sessionHistory.userMessages.privacyLevels.full">完整記錄</option>
|
||||||
|
<option value="basic" data-i18n="sessionHistory.userMessages.privacyLevels.basic">基本統計</option>
|
||||||
|
<option value="disabled" data-i18n="sessionHistory.userMessages.privacyLevels.disabled">停用記錄</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="setting-item" style="border-bottom: none;">
|
<div class="setting-item" style="border-bottom: none;">
|
||||||
<div class="setting-info">
|
<div class="setting-info">
|
||||||
<div class="setting-label" data-i18n="sessionHistory.management.export">資料管理</div>
|
<div class="setting-label" data-i18n="sessionHistory.management.export">資料管理</div>
|
||||||
<div class="setting-description">
|
<div class="setting-description" data-i18n="sessionHistory.management.exportDescription">
|
||||||
匯出或清空本地儲存的會話歷史記錄
|
匯出或清空本地儲存的會話歷史記錄
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-control" style="display: flex; gap: 8px;">
|
<div class="setting-control" style="display: flex; gap: 8px; flex-wrap: wrap;">
|
||||||
<button id="exportSessionHistoryBtn" class="btn btn-secondary" style="font-size: 12px; padding: 6px 12px;">
|
<button id="exportSessionHistoryBtn" class="btn btn-secondary" style="font-size: 12px; padding: 6px 12px;">
|
||||||
<span data-i18n="sessionHistory.management.exportAll">匯出全部</span>
|
<span data-i18n="sessionHistory.management.exportAll">匯出全部</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button id="clearUserMessagesBtn" class="btn btn-secondary" style="font-size: 12px; padding: 6px 12px; color: var(--warning-color); border-color: var(--warning-color);">
|
||||||
|
<span data-i18n="sessionHistory.userMessages.clearAll">清空訊息記錄</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);">
|
<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>
|
<span data-i18n="sessionHistory.management.clear">清空</span>
|
||||||
</button>
|
</button>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user