From 76573cb18b25731e9c1f2186b767038e958b7588 Mon Sep 17 00:00:00 2001 From: digua Date: Sat, 20 Dec 2025 12:47:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=97=A5=E5=BF=97=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=92=8C=E6=96=87=E6=A1=88=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/main/ai/logger.ts | 4 +- electron/main/ipc/cache.ts | 2 +- electron/main/logger.ts | 65 +++++++++++++++++++ electron/main/update.ts | 13 ++-- electron/main/worker/core/perfLogger.ts | 3 +- .../common/settings/AIPromptConfigTab.vue | 2 +- src/components/common/settings/AboutTab.vue | 2 +- src/pages/home/components/AgreementModal.vue | 4 +- 8 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 electron/main/logger.ts diff --git a/electron/main/ai/logger.ts b/electron/main/ai/logger.ts index a60bbbb7..9679ad3f 100644 --- a/electron/main/ai/logger.ts +++ b/electron/main/ai/logger.ts @@ -20,9 +20,9 @@ function getLogDir(): string { try { const docPath = app.getPath('documents') - LOG_DIR = path.join(docPath, 'ChatLab', 'logs') + LOG_DIR = path.join(docPath, 'ChatLab', 'logs', 'ai') } catch { - LOG_DIR = path.join(process.cwd(), 'logs') + LOG_DIR = path.join(process.cwd(), 'logs', 'ai') } return LOG_DIR diff --git a/electron/main/ipc/cache.ts b/electron/main/ipc/cache.ts index e38f245c..8b4ddead 100644 --- a/electron/main/ipc/cache.ts +++ b/electron/main/ipc/cache.ts @@ -105,7 +105,7 @@ export function registerCacheHandlers(_context: IpcContext): void { { id: 'logs', name: '日志文件', - description: '调试日志和错误日志', + description: '软件的运行日志,包含导入、AI、错误等日志', path: path.join(chatLabDir, 'logs'), icon: 'i-heroicons-document-text', canClear: true, // 可以清理 diff --git a/electron/main/logger.ts b/electron/main/logger.ts new file mode 100644 index 00000000..7c35634c --- /dev/null +++ b/electron/main/logger.ts @@ -0,0 +1,65 @@ +/** + * 简单的日志工具 + * 日志保存到 Documents/ChatLab/logs/ 目录 + */ + +import { app } from 'electron' +import * as fs from 'fs' +import * as path from 'path' + +// 日志目录(与 cache.ts 保持一致) +function getLogDir(): string { + try { + const docPath = app.getPath('documents') + return path.join(docPath, 'ChatLab', 'logs') + } catch { + return path.join(process.cwd(), 'ChatLab', 'logs') + } +} + +// 日志文件路径 +function getLogPath(): string { + return path.join(getLogDir(), 'app.log') +} + +// 确保日志目录存在 +function ensureLogDir(): void { + const logDir = getLogDir() + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir, { recursive: true }) + } +} + +// 格式化时间 +function formatTime(): string { + const now = new Date() + const year = now.getFullYear() + const month = String(now.getMonth() + 1).padStart(2, '0') + const day = String(now.getDate()).padStart(2, '0') + const hour = String(now.getHours()).padStart(2, '0') + const minute = String(now.getMinutes()).padStart(2, '0') + const second = String(now.getSeconds()).padStart(2, '0') + return `${year}-${month}-${day} ${hour}:${minute}:${second}` +} + +// 写入日志 +function writeLog(level: string, message: string): void { + try { + ensureLogDir() + const logLine = `[${formatTime()}] [${level}] ${message}\n` + fs.appendFileSync(getLogPath(), logLine, 'utf-8') + } catch (error) { + // 日志写入失败时静默处理,避免影响主程序 + console.error('[Logger] 写入日志失败:', error) + } +} + +/** + * 日志工具 + */ +export const logger = { + info: (message: string) => writeLog('INFO', message), + warn: (message: string) => writeLog('WARN', message), + error: (message: string) => writeLog('ERROR', message), + debug: (message: string) => writeLog('DEBUG', message), +} diff --git a/electron/main/update.ts b/electron/main/update.ts index 0532c8df..51827cb7 100644 --- a/electron/main/update.ts +++ b/electron/main/update.ts @@ -1,6 +1,7 @@ import { dialog, app } from 'electron' import { autoUpdater } from 'electron-updater' import { platform } from '@electron-toolkit/utils' +import { logger } from './logger' let isFirstShow = true const checkUpdate = (win) => { @@ -59,7 +60,8 @@ const checkUpdate = (win) => { console.log('wait for post download operation') }) .catch((downloadError) => { - dialog.showErrorBox('客户端下载失败', `err:${downloadError}`) + // 下载失败记录到日志,不显示给用户 + logger.error(`[Update] 下载更新失败: ${downloadError}`) }) } }) @@ -109,11 +111,10 @@ const checkUpdate = (win) => { } }) - // 错误处理 - autoUpdater.on('error', (err, ev) => { - // 更新出错,其中一步错误都会emit - console.log('error事件:', err, ev) - dialog.showErrorBox('遇到错误', `err:${err}, ev:${ev}`) + // 错误处理(静默处理,记录到日志) + autoUpdater.on('error', (err) => { + // 更新错误记录到日志,不显示给用户 + logger.error(`[Update] 更新错误: ${err.message || err}`) }) // 等待 3 秒再检查更新,确保窗口准备完成,用户进入系统 diff --git a/electron/main/worker/core/perfLogger.ts b/electron/main/worker/core/perfLogger.ts index da6cef0d..a0ffecf9 100644 --- a/electron/main/worker/core/perfLogger.ts +++ b/electron/main/worker/core/perfLogger.ts @@ -17,7 +17,7 @@ let currentLogFile: string | null = null */ function getLogDir(): string { const dbDir = getDbDir() - const logDir = path.join(path.dirname(dbDir), 'logs') + const logDir = path.join(path.dirname(dbDir), 'logs', 'import') if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) } @@ -106,4 +106,3 @@ export function resetPerfLog(): void { export function getCurrentLogFile(): string | null { return currentLogFile } - diff --git a/src/components/common/settings/AIPromptConfigTab.vue b/src/components/common/settings/AIPromptConfigTab.vue index a750cae8..cb6d8b05 100644 --- a/src/components/common/settings/AIPromptConfigTab.vue +++ b/src/components/common/settings/AIPromptConfigTab.vue @@ -95,7 +95,7 @@ function isActivePreset(presetId: string, chatType: 'group' | 'private'): boolea

发送条数限制

- 每次发送给 AI 的最大消息条数,用于控制上下文长度(建议在500以上) + 每次发送给 AI 的最大消息条数,用于控制上下文长度(建议大于500)

diff --git a/src/components/common/settings/AboutTab.vue b/src/components/common/settings/AboutTab.vue index 3df2d29a..b10c02d2 100644 --- a/src/components/common/settings/AboutTab.vue +++ b/src/components/common/settings/AboutTab.vue @@ -102,7 +102,7 @@ onMounted(() => {

匿名使用统计

- 开启该选项后,软件会收集版本号、操作系统等非敏感数据,用于协助优化产品 + 开启后,软件会收集版本号、操作系统版本等非敏感数据,用于帮助优化产品(●'◡'●)ノ♥

diff --git a/src/pages/home/components/AgreementModal.vue b/src/pages/home/components/AgreementModal.vue index cb3f4c2b..bd24e476 100644 --- a/src/pages/home/components/AgreementModal.vue +++ b/src/pages/home/components/AgreementModal.vue @@ -19,13 +19,13 @@ onMounted(() => { }) // 倒计时状态 -const countdown = ref(10) +const countdown = ref(20) let timer: ReturnType | null = null // 监听 modal 打开状态,启动倒计时 watch(isOpen, (open) => { if (open) { - countdown.value = 10 + countdown.value = 20 timer = setInterval(() => { if (countdown.value > 0) { countdown.value--