feat: add resolveFilePath functionality to resolve restoring from different computer (#5980)

* feat: add resolveFilePath functionality to file management

* Added new IPC channel for resolving file paths.
* Implemented resolveFilePath method in FileStorage service.
* Updated FileManager to utilize the new resolveFilePath method.
* Enhanced preload API to expose resolveFilePath to the renderer.
* Updated KnowledgeService to ensure file paths are correctly resolved in knowledge bases.

* refactor: remove unused path import from preload index

* Removed the unused 'resolve' import to clean up the codebase.
* Improved code readability by eliminating unnecessary dependencies.

---------

Co-authored-by: beyondkmp <beyondkmkp@gmail.com>
This commit is contained in:
beyondkmp 2025-05-19 21:58:44 +08:00 committed by GitHub
parent a18c2b3f0a
commit 6ed6376707
7 changed files with 38 additions and 1 deletions

View File

@ -112,7 +112,7 @@ export enum IpcChannel {
File_BinaryImage = 'file:binaryImage',
File_Base64File = 'file:base64File',
Fs_Read = 'fs:read',
File_ResolveFilePath = 'file:resolveFilePath',
Export_Word = 'export:word',
Shortcuts_Update = 'shortcuts:update',

View File

@ -242,6 +242,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
ipcMain.handle(IpcChannel.File_Download, fileManager.downloadFile)
ipcMain.handle(IpcChannel.File_Copy, fileManager.copyFile)
ipcMain.handle(IpcChannel.File_BinaryImage, fileManager.binaryImage)
ipcMain.handle(IpcChannel.File_ResolveFilePath, (_, name) => fileManager.resolveFilePath(name))
// fs
ipcMain.handle(IpcChannel.Fs_Read, FileService.readFile)

View File

@ -27,6 +27,10 @@ class FileStorage {
this.initStorageDir()
}
public resolveFilePath = (name: string): string => {
return path.join(this.storageDir, name)
}
private initStorageDir = (): void => {
try {
if (!fs.existsSync(this.storageDir)) {

View File

@ -55,6 +55,7 @@ const api = {
},
file: {
select: (options?: OpenDialogOptions) => ipcRenderer.invoke(IpcChannel.File_Select, options),
resolveFilePath: (name: string) => ipcRenderer.invoke(IpcChannel.File_ResolveFilePath, name),
upload: (file: FileType) => ipcRenderer.invoke(IpcChannel.File_Upload, file),
delete: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_Delete, fileId),
read: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_Read, fileId),

View File

@ -3,6 +3,7 @@ import db from '@renderer/databases'
import { upgradeToV7 } from '@renderer/databases/upgrades'
import i18n from '@renderer/i18n'
import store from '@renderer/store'
import { updateKnowledgeBaseFilePath } from '@renderer/services/KnowledgeService'
import { setWebDAVSyncState } from '@renderer/store/backup'
import dayjs from 'dayjs'
@ -32,6 +33,7 @@ export async function restore() {
}
await handleData(data)
await updateKnowledgeBaseFilePath()
} catch (error) {
Logger.error('[Backup] restore: Error restoring backup file:', error)
window.message.error({ content: i18n.t('error.backup.file_format'), key: 'restore' })
@ -211,6 +213,7 @@ export async function restoreFromWebdav(fileName?: string) {
try {
await handleData(JSON.parse(data))
await updateKnowledgeBaseFilePath()
} catch (error) {
console.error('[Backup] Error downloading file from WebDAV:', error)
window.message.error({ content: i18n.t('error.backup.file_format'), key: 'restore' })

View File

@ -12,6 +12,10 @@ class FileManager {
return files
}
static async resolveFilePath(name: string): Promise<string> {
return window.api.file.resolveFilePath(name)
}
static async addFile(file: FileType): Promise<FileType> {
const fileRecord = await db.files.get(file.id)

View File

@ -4,6 +4,7 @@ import { getEmbeddingMaxContext } from '@renderer/config/embedings'
import Logger from '@renderer/config/logger'
import AiProvider from '@renderer/providers/AiProvider'
import store from '@renderer/store'
import { updateBases } from '@renderer/store/knowledge'
import { FileType, KnowledgeBase, KnowledgeBaseParams, KnowledgeReference } from '@renderer/types'
import { ExtractResults } from '@renderer/utils/extract'
import { isEmpty } from 'lodash'
@ -11,6 +12,29 @@ import { isEmpty } from 'lodash'
import { getProviderByModel } from './AssistantService'
import FileManager from './FileManager'
export const updateKnowledgeBaseFilePath = async () => {
const bases = store.getState().knowledge.bases
const updatedBases = await Promise.all(
bases.map(async (base) => {
const updatedBase = { ...base }
updatedBase.items = await Promise.all(
base.items.map(async (item) => {
const updatedItem = { ...item }
if (item.type === 'file' || item.type === 'directory') {
updatedItem.content = { ...(item.content as FileType) }
updatedItem.content.path = await FileManager.resolveFilePath(updatedItem.content.name)
}
return updatedItem
})
)
return updatedBase
})
)
// 使用 dispatch 更新状态
store.dispatch(updateBases(updatedBases))
}
export const getKnowledgeBaseParams = (base: KnowledgeBase): KnowledgeBaseParams => {
const provider = getProviderByModel(base.model)
const rerankProvider = getProviderByModel(base.rerankModel)