import { defineStore } from 'pinia'; import { ref, watch } from 'vue'; export type LogLevel = 'info' | 'warn' | 'error' | 'debug'; export interface LogEntry { id: number; time: string; level: LogLevel; module: string; message: string; detail?: any; } const MAX_LOGS = 500; const STORAGE_KEY = 'qz-app-logs'; const LEVEL_ORDER: Record = { debug: 0, info: 1, warn: 2, error: 3 }; function loadFromStorage(): LogEntry[] { try { const raw = localStorage.getItem(STORAGE_KEY); if (raw) { const parsed = JSON.parse(raw); if (Array.isArray(parsed)) return parsed as LogEntry[]; } } catch { // ignore } return []; } export const useLogStore = defineStore('log', () => { const logs = ref(loadFromStorage()); let nextId = logs.value.length > 0 ? Math.max(...logs.value.map((l) => l.id)) + 1 : 1; watch( logs, (newLogs) => { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(newLogs)); } catch { // ignore quota issues } }, { deep: true } ); const add = (level: LogLevel, module: string, message: string, detail?: any) => { const now = new Date(); const hh = now.getHours().toString().padStart(2, '0'); const mm = now.getMinutes().toString().padStart(2, '0'); const ss = now.getSeconds().toString().padStart(2, '0'); const ms = now.getMilliseconds().toString().padStart(3, '0'); const entry: LogEntry = { id: nextId++, time: `${hh}:${mm}:${ss}.${ms}`, level, module, message, detail, }; logs.value.push(entry); if (logs.value.length > MAX_LOGS) { logs.value = logs.value.slice(-MAX_LOGS); } // 同步到浏览器控制台,方便调试 const consoleArgs = [`[${entry.time}] [${level.toUpperCase()}] [${module}]`, message]; if (detail !== undefined) consoleArgs.push(detail); try { if (level === 'error') console.error(...consoleArgs); else if (level === 'warn') console.warn(...consoleArgs); else if (level === 'debug') console.debug(...consoleArgs); else console.log(...consoleArgs); } catch { // ignore } }; const info = (module: string, message: string, detail?: any) => add('info', module, message, detail); const warn = (module: string, message: string, detail?: any) => add('warn', module, message, detail); const error = (module: string, message: string, detail?: any) => add('error', module, message, detail); const debug = (module: string, message: string, detail?: any) => add('debug', module, message, detail); const clear = () => { logs.value = []; nextId = 1; }; const filter = (module?: string, level?: LogLevel) => { return logs.value.filter((l) => { if (module && l.module !== module) return false; if (level && LEVEL_ORDER[l.level] < LEVEL_ORDER[level]) return false; return true; }); }; const moduleList = () => { const set = new Set(); for (const l of logs.value) set.add(l.module); return Array.from(set).sort(); }; const countByLevel = () => { const c = { info: 0, warn: 0, error: 0, debug: 0 }; for (const l of logs.value) c[l.level]++; return c; }; return { logs, info, warn, error, debug, add, clear, filter, moduleList, countByLevel, }; });