Files
ChatLab/electron/main/ipc/cache.ts
T
2025-12-05 01:11:37 +08:00

214 lines
5.6 KiB
TypeScript

// electron/main/ipc/cache.ts
import { ipcMain, app, shell } from 'electron'
import * as fs from 'fs/promises'
import * as fsSync from 'fs'
import * as path from 'path'
import type { IpcContext } from './types'
/**
* 获取 ChatLab 数据目录
*/
function getChatLabDir(): string {
try {
const docPath = app.getPath('documents')
return path.join(docPath, 'ChatLab')
} catch {
return path.join(process.cwd(), 'ChatLab')
}
}
/**
* 递归计算目录大小
*/
async function getDirSize(dirPath: string): Promise<number> {
let totalSize = 0
try {
const exists = fsSync.existsSync(dirPath)
if (!exists) return 0
const files = await fs.readdir(dirPath, { withFileTypes: true })
for (const file of files) {
const filePath = path.join(dirPath, file.name)
if (file.isDirectory()) {
totalSize += await getDirSize(filePath)
} else {
const stat = await fs.stat(filePath)
totalSize += stat.size
}
}
} catch (error) {
console.error('[Cache] Error getting dir size:', dirPath, error)
}
return totalSize
}
/**
* 获取目录中的文件数量
*/
async function getFileCount(dirPath: string): Promise<number> {
let count = 0
try {
const exists = fsSync.existsSync(dirPath)
if (!exists) return 0
const files = await fs.readdir(dirPath, { withFileTypes: true })
for (const file of files) {
const filePath = path.join(dirPath, file.name)
if (file.isDirectory()) {
count += await getFileCount(filePath)
} else {
count++
}
}
} catch (error) {
console.error('[Cache] Error getting file count:', dirPath, error)
}
return count
}
export function registerCacheHandlers(_context: IpcContext): void {
console.log('[IPC] Registering cache handlers...')
/**
* 获取所有缓存目录信息
*/
ipcMain.handle('cache:getInfo', async () => {
const chatLabDir = getChatLabDir()
// 定义缓存目录
const cacheDirectories = [
{
id: 'databases',
name: '聊天记录数据库',
description: '导入的聊天记录分析数据',
path: path.join(chatLabDir, 'databases'),
icon: 'i-heroicons-circle-stack',
canClear: false, // 不允许一键清理,因为是重要数据
},
{
id: 'ai',
name: 'AI 数据',
description: 'AI 对话历史和配置文件',
path: path.join(chatLabDir, 'ai'),
icon: 'i-heroicons-sparkles',
canClear: false, // 不允许一键清理
},
{
id: 'temp',
name: '临时文件',
description: '合并功能产生的临时数据库',
path: path.join(chatLabDir, 'temp'),
icon: 'i-heroicons-clock',
canClear: true, // 可以清理
},
{
id: 'logs',
name: '日志文件',
description: 'AI 调试日志',
path: path.join(chatLabDir, 'logs'),
icon: 'i-heroicons-document-text',
canClear: true, // 可以清理
},
]
// 获取每个目录的信息
const results = await Promise.all(
cacheDirectories.map(async (dir) => {
const size = await getDirSize(dir.path)
const fileCount = await getFileCount(dir.path)
const exists = fsSync.existsSync(dir.path)
return {
...dir,
size,
fileCount,
exists,
}
})
)
return {
baseDir: chatLabDir,
directories: results,
totalSize: results.reduce((sum, dir) => sum + dir.size, 0),
}
})
/**
* 清理指定缓存目录
*/
ipcMain.handle('cache:clear', async (_, cacheId: string) => {
const chatLabDir = getChatLabDir()
// 只允许清理 temp 和 logs
const allowedDirs: Record<string, string> = {
temp: path.join(chatLabDir, 'temp'),
logs: path.join(chatLabDir, 'logs'),
}
const dirPath = allowedDirs[cacheId]
if (!dirPath) {
return { success: false, error: '不允许清理此目录' }
}
try {
const exists = fsSync.existsSync(dirPath)
if (!exists) {
return { success: true, message: '目录不存在,无需清理' }
}
// 删除目录下的所有文件
const files = await fs.readdir(dirPath)
for (const file of files) {
const filePath = path.join(dirPath, file)
const stat = await fs.stat(filePath)
if (stat.isDirectory()) {
await fs.rm(filePath, { recursive: true })
} else {
await fs.unlink(filePath)
}
}
console.log(`[Cache] Cleared directory: ${dirPath}`)
return { success: true }
} catch (error) {
console.error('[Cache] Error clearing cache:', error)
return { success: false, error: String(error) }
}
})
/**
* 在文件管理器中打开缓存目录
*/
ipcMain.handle('cache:openDir', async (_, cacheId: string) => {
const chatLabDir = getChatLabDir()
const dirPaths: Record<string, string> = {
base: chatLabDir,
databases: path.join(chatLabDir, 'databases'),
ai: path.join(chatLabDir, 'ai'),
temp: path.join(chatLabDir, 'temp'),
logs: path.join(chatLabDir, 'logs'),
}
const dirPath = dirPaths[cacheId]
if (!dirPath) {
return { success: false, error: '未知的目录' }
}
try {
// 确保目录存在
if (!fsSync.existsSync(dirPath)) {
await fs.mkdir(dirPath, { recursive: true })
}
await shell.openPath(dirPath)
return { success: true }
} catch (error) {
console.error('[Cache] Error opening directory:', error)
return { success: false, error: String(error) }
}
})
}