// VaultService — 统筹库管理:默认库、切换、最近库(FR-V) import nodePath from 'node:path'; import { promises as fs } from 'node:fs'; import { app, dialog } from 'electron'; import { DEFAULT_VAULT_NAME } from '@hunter/shared'; import type { VaultMeta } from '@hunter/shared'; import { ConfigStore } from './config-store.js'; import { FileService } from './file-service.js'; import { SearchService } from './search-service.js'; export class VaultService { fileService: FileService | null = null; searchService: SearchService | null = null; private config: ConfigStore; constructor() { this.config = new ConfigStore(app.getPath('userData')); } // 启动时初始化:确保有当前库(无则创建默认库) async init(): Promise { let meta = await this.config.getVaultMeta(); if (!meta.currentRoot) { const defaultRoot = nodePath.join(app.getPath('userData'), DEFAULT_VAULT_NAME); await fs.mkdir(defaultRoot, { recursive: true }); meta = await this.config.setCurrentRoot(defaultRoot); } this.fileService = new FileService(meta.currentRoot); this.searchService = new SearchService(meta.currentRoot, this.fileService); return meta; } async getMeta(): Promise { return this.config.getVaultMeta(); } // 通过系统对话框选择并切换库(FR-V3) async pickAndSwitch(): Promise { const result = await dialog.showOpenDialog({ properties: ['openDirectory'] }); if (result.canceled || result.filePaths.length === 0) return null; return this.switch(result.filePaths[0]); } // 仅浏览选择目录路径,不切换(FR-V5 设置页浏览按钮) async pickDirectory(): Promise { const result = await dialog.showOpenDialog({ properties: ['openDirectory'] }); if (result.canceled || result.filePaths.length === 0) return null; return result.filePaths[0]; } async switch(root: string): Promise { // 校验是存在的目录 const stat = await fs.stat(root).catch(() => null); if (!stat || !stat.isDirectory()) throw new Error('目标路径不是有效目录: ' + root); const meta = await this.config.setCurrentRoot(root); this.fileService = new FileService(root); this.searchService = new SearchService(root, this.fileService); return meta; } async setDefaultRoot(root: string): Promise { await this.config.setDefaultRoot(root); } getAppearance() { return this.config.getAppearance(); } saveAppearance(data: { themeId: string; params: Record; effect: string; bgImage: string | null }) { return this.config.saveAppearance(data); } getKeymaps() { return this.config.getKeymaps(); } saveKeymaps(data: { id: string; combo: string }[]) { return this.config.saveKeymaps(data); } }