feat(desktop): 优化一些逻辑

1. 优化通知配置

2. 优化命名规范

3. 优化代码逻辑
This commit is contained in:
2026-01-10 23:37:28 +08:00
parent bce411af7e
commit 36cf521851
30 changed files with 674 additions and 575 deletions

View File

@@ -1,4 +1,4 @@
import { app, BrowserWindow, ipcMain, shell } from 'electron'
import { app, BrowserWindow, shell } from 'electron'
import { join } from 'path'
import { electronApp, is, optimizer } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
@@ -8,11 +8,11 @@ import { createIPCHandler } from 'electron-trpc/main'
import { initDB } from '@main/db/data-source'
function createWindow(): void {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false,
title: '读书心得助手',
resizable: false,
autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}),
@@ -38,8 +38,6 @@ function createWindow(): void {
return { action: 'deny' }
})
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
@@ -47,41 +45,22 @@ function createWindow(): void {
}
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(async () => {
await initDB()
// Set app user model id for windows
electronApp.setAppUserModelId('com.electron')
electronApp.setAppUserModelId('com.reading_book')
// Default open or close DevTools by F12 in development
// and ignore CommandOrControl + R in production.
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
app.on('browser-window-created', (_, window) => {
optimizer.watchWindowShortcuts(window)
})
// IPC test
ipcMain.on('ping', () => console.log('pong'))
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -4,9 +4,16 @@ import { readingReflectionGraph } from '@main/services/ai/graph/readingReflectio
import { AppDataSource } from '@main/db/data-source'
import { ReadingReflectionTaskBatch } from '@main/db/entities/ReadingReflectionTaskBatch'
import { ReadingReflectionTaskItem } from '@main/db/entities/ReadingReflectionTaskItem'
import Store from 'electron-store'
import { CONFIG_STORE_KEY } from '@rpc/constants/store_key'
import { Notification } from 'electron'
export const readingReflectionTaskEvent = new EventEmitter()
// 兼容性处理获取 Store 构造函数
const StoreClass = (Store as any).default || Store
const store = new StoreClass({ encryptionKey: CONFIG_STORE_KEY })
class TaskManager {
private limit = pLimit(2)
private batchRepo = AppDataSource.getRepository(ReadingReflectionTaskBatch)
@@ -113,6 +120,7 @@ class TaskManager {
result?: any
) {
const displayId = total === 1 ? taskId : `${taskId}-${index}`
//发送 tRPC 实时事件(驱动前端 UI 进度条)
readingReflectionTaskEvent.emit('readingReflectionTaskProgress', {
taskId: displayId,
progress,
@@ -120,6 +128,44 @@ class TaskManager {
statusText: `[任务${index + 1}/${total}] ${status}`, // 传描述文字
result
})
// 2. 添加任务状态通知判断
this.handleNotification(status, progress, total, index)
}
/**
* 内部私有方法:处理通知逻辑
*/
private handleNotification(status: string, progress: number, total: number, index: number) {
// 从 electron-store 获取用户偏好
const config = store.get('notification') || {
masterSwitch: true,
taskCompleted: true,
taskFailed: true
}
// 如果总开关关闭,直接拦截
if (!config.masterSwitch) return
// 场景 A: 任务全部完成 (100%)
if (progress === 100 && config.taskCompleted) {
// 只有当所有子任务都完成,或者当前是单任务时才弹出
// 如果是批量任务,你可以选择在最后一个子任务完成时通知
if (index + 1 === total) {
new Notification({
title: '🎉 读书心得已生成',
body: total > 1 ? `${total} 篇心得已全部处理完成。` : '您的书籍心得已准备就绪。',
silent: config.silentMode
}).show()
}
}
// 场景 B: 任务失败 (假设你传入的 status 是 'FAILED')
if (status === 'FAILED' && config.taskFailed) {
new Notification({
title: '❌ 任务生成失败',
body: `${index + 1} 项任务执行异常,请检查网络或 API 余额。`,
silent: config.silentMode
}).show()
}
}
}

View File

@@ -1,5 +1,5 @@
import { Annotation } from '@langchain/langgraph'
import { Occupation } from '@shared/types/reflections'
import { Occupation } from '@shared/types/IReadingReflectionTask'
export const ReadingReflectionState = Annotation.Root({
// 输入任务