|
import { defineStore } from 'pinia'; |
|
import { ref, computed } from 'vue'; |
|
|
|
|
|
export interface SessionNode { |
|
id: string; |
|
text: string; |
|
translatedText?: string; |
|
timestamp: number; |
|
|
|
} |
|
|
|
|
|
export interface SessionSummary { |
|
startTime: number; |
|
title: string; |
|
outline: string[]; |
|
nodeCount: number; |
|
} |
|
|
|
const LOCAL_STORAGE_SESSION_PREFIX = 'rt_session_'; |
|
|
|
export const useSessionStore = defineStore('session', () => { |
|
|
|
|
|
|
|
const sessionSummaries = ref<SessionSummary[]>([]); |
|
|
|
|
|
const currentSessionNodes = ref<SessionNode[]>([]); |
|
|
|
const currentSessionStartTime = ref<number | null>(null); |
|
|
|
const isSessionActive = ref(false); |
|
|
|
|
|
|
|
|
|
const sortedSessionSummaries = computed(() => { |
|
|
|
return [...sessionSummaries.value].sort((a, b) => b.startTime - a.startTime); |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
function startSession() { |
|
if (isSessionActive.value) { |
|
console.warn("尝试在已有活动会话时开始新会话。"); |
|
|
|
|
|
return; |
|
} |
|
currentSessionStartTime.value = Date.now(); |
|
currentSessionNodes.value = []; |
|
isSessionActive.value = true; |
|
console.log(`新会话开始于: ${new Date(currentSessionStartTime.value).toLocaleString()}`); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function addNode(node: SessionNode) { |
|
if (!isSessionActive.value || !currentSessionStartTime.value) { |
|
console.warn("没有活动的会话来添加节点。"); |
|
return; |
|
} |
|
currentSessionNodes.value.push(node); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function endSession() { |
|
if (!isSessionActive.value || !currentSessionStartTime.value) { |
|
console.log("没有活动的会话可以结束。"); |
|
|
|
isSessionActive.value = false; |
|
currentSessionStartTime.value = null; |
|
currentSessionNodes.value = []; |
|
return; |
|
} |
|
|
|
const startTime = currentSessionStartTime.value; |
|
const nodes = [...currentSessionNodes.value]; |
|
|
|
|
|
isSessionActive.value = false; |
|
currentSessionStartTime.value = null; |
|
currentSessionNodes.value = []; |
|
|
|
if (nodes.length === 0) { |
|
console.log("会话结束,但没有节点需要保存。"); |
|
return; |
|
} |
|
|
|
|
|
const title = nodes[0]?.text.substring(0, 10) || '无标题会话'; |
|
const n1 = nodes[0]; |
|
const outline = [ |
|
`${n1?.text.substring(0, 56)}...\n`, |
|
`${n1?.translatedText?.substring(0, 56)}...\n`, |
|
] |
|
|
|
const summary: SessionSummary = { |
|
startTime, |
|
title, |
|
outline, |
|
nodeCount: nodes.length, |
|
}; |
|
|
|
|
|
try { |
|
const storageKey = `${LOCAL_STORAGE_SESSION_PREFIX}${startTime}`; |
|
localStorage.setItem(storageKey, JSON.stringify(nodes)); |
|
console.log(`完整会话 ${startTime} 已保存到 localStorage.`); |
|
|
|
|
|
|
|
const existingIndex = sessionSummaries.value.findIndex(s => s.startTime === startTime); |
|
if (existingIndex === -1) { |
|
sessionSummaries.value.push(summary); |
|
} else { |
|
console.warn(`会话摘要 ${startTime} 已存在,将进行覆盖。`); |
|
sessionSummaries.value[existingIndex] = summary; |
|
} |
|
|
|
|
|
console.log(`会话 ${startTime} 结束并已处理。`); |
|
|
|
} catch (error) { |
|
console.error("保存会话到 localStorage 时出错:", error); |
|
|
|
|
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function loadSessionContent(startTime: number): SessionNode[] | null { |
|
try { |
|
const storageKey = `${LOCAL_STORAGE_SESSION_PREFIX}${startTime}`; |
|
const storedData = localStorage.getItem(storageKey); |
|
if (storedData) { |
|
const nodes = JSON.parse(storedData) as SessionNode[]; |
|
console.log(`从 localStorage 加载了会话 ${startTime} 的内容 (${nodes.length} 个节点)`); |
|
return nodes; |
|
} |
|
console.warn(`在 localStorage 中未找到键为 ${storageKey} 的会话数据。`); |
|
return null; |
|
} catch (error) { |
|
console.error(`从 localStorage 加载会话 ${startTime} 时出错:`, error); |
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function deleteSession(startTime: number) { |
|
try { |
|
|
|
const index = sessionSummaries.value.findIndex(s => s.startTime === startTime); |
|
if (index > -1) { |
|
sessionSummaries.value.splice(index, 1); |
|
console.log(`会话摘要 ${startTime} 已从 Pinia store 中移除。`); |
|
|
|
} else { |
|
console.warn(`尝试删除一个不存在的会话摘要: ${startTime}`); |
|
} |
|
|
|
|
|
const storageKey = `${LOCAL_STORAGE_SESSION_PREFIX}${startTime}`; |
|
localStorage.removeItem(storageKey); |
|
console.log(`会话 ${startTime} 的完整内容已从 localStorage 中移除。`); |
|
|
|
} catch (error) { |
|
console.error(`删除会话 ${startTime} 时出错:`, error); |
|
} |
|
} |
|
|
|
|
|
return { |
|
|
|
sessionSummaries, |
|
currentSessionNodes, |
|
currentSessionStartTime, |
|
isSessionActive, |
|
|
|
|
|
sortedSessionSummaries, |
|
|
|
|
|
startSession, |
|
addNode, |
|
endSession, |
|
loadSessionContent, |
|
deleteSession, |
|
}; |
|
}, { |
|
|
|
persist: { |
|
|
|
paths: ['sessionSummaries'], |
|
|
|
|
|
}, |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function downloadSessionData(startTime: number, nodes: SessionNode[], format: 'json' | 'txt' = 'json') { |
|
if (!nodes || nodes.length === 0) { |
|
console.error("没有数据可供下载:", startTime); |
|
alert("没有内容可以下载。"); |
|
return; |
|
} |
|
try { |
|
const dateStr = new Date(startTime).toISOString().split('T')[0]; |
|
let dataStr: string; |
|
let mimeType: string; |
|
let fileExtension: string; |
|
|
|
if (format === 'txt') { |
|
dataStr = nodes.map(n => `${new Date(n.timestamp).toLocaleTimeString()} - ${n.text}`).join('\n'); |
|
mimeType = 'text/plain;charset=utf-8;'; |
|
fileExtension = 'txt'; |
|
} else { |
|
dataStr = JSON.stringify(nodes, null, 2); |
|
mimeType = 'application/json;charset=utf-8;'; |
|
fileExtension = 'json'; |
|
} |
|
|
|
const filename = `session_${dateStr}_${startTime}.${fileExtension}`; |
|
const blob = new Blob([dataStr], { type: mimeType }); |
|
const link = document.createElement("a"); |
|
|
|
|
|
const url = URL.createObjectURL(blob); |
|
link.setAttribute("href", url); |
|
link.setAttribute("download", filename); |
|
link.style.visibility = 'hidden'; |
|
document.body.appendChild(link); |
|
link.click(); |
|
|
|
|
|
document.body.removeChild(link); |
|
URL.revokeObjectURL(url); |
|
|
|
console.log(`已触发下载会话 ${startTime} 为 ${filename}`); |
|
|
|
} catch (error) { |
|
console.error(`下载会话 ${startTime} 时出错:`, error); |
|
alert("下载文件时发生错误。"); |
|
} |
|
} |
|
|