| 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("下载文件时发生错误。"); |
| } |
| } |
|
|