fix: 优化后端各模块 handler

- database_handler, knowledge_handler, model_handler
- neo4j_handler, sub_table_handler
- system_handler, upload_handler
- knowledge_service, upload_service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 14:26:04 +08:00
parent ecb885ee5e
commit fdd6b2c17d
9 changed files with 427 additions and 60 deletions

View File

@@ -94,7 +94,7 @@ func (s *UploadService) Upload(file *multipart.FileHeader) (*UploadResponse, err
if s.cfg.UploadMode == "minio" {
return s.uploadToMinIO(f, filename, fileKey, file.Size)
}
return s.uploadToLocal(f, filename, fileKey)
return s.uploadToLocal(f, filename, fileKey, "")
}
// UploadWithConfig 上传文件(使用指定配置)
@@ -116,7 +116,29 @@ func (s *UploadService) UploadWithConfig(file *multipart.FileHeader, storageConf
return s.uploadToMinIOWithConfig(f, filename, fileKey, file.Size, storageConfig)
}
// 默认使用本地存储
return s.uploadToLocal(f, filename, fileKey)
return s.uploadToLocal(f, filename, fileKey, "")
}
// UploadToKnowledgeBase 上传文件到知识库(本地存储时按知识库名称分类)
func (s *UploadService) UploadToKnowledgeBase(file *multipart.FileHeader, storageConfig model.StorageConfig, knowledgeBaseName string) (*UploadResponse, error) {
// 打开文件
f, err := file.Open()
if err != nil {
return &UploadResponse{Success: false, Message: err.Error()}, nil
}
defer f.Close()
// 生成唯一文件名
ext := filepath.Ext(file.Filename)
filename := fmt.Sprintf("%s%s", uuid.New().String(), ext)
fileKey := strings.TrimSuffix(filename, ext)
// 根据配置选择存储方式
if storageConfig.Type == "minio" {
return s.uploadToMinIOWithConfig(f, filename, fileKey, file.Size, storageConfig)
}
// 本地存储,使用知识库名称作为子目录
return s.uploadToLocal(f, filename, fileKey, knowledgeBaseName)
}
// uploadToMinIOWithConfig 使用指定配置上传到 MinIO
@@ -217,9 +239,18 @@ func (s *UploadService) uploadToMinIO(f multipart.File, filename, fileKey string
}
// uploadToLocal 上传到本地
func (s *UploadService) uploadToLocal(f multipart.File, filename, fileKey string) (*UploadResponse, error) {
// 确保目录存在
uploadPath := s.cfg.UploadLocalPath
// knowledgeBaseName: 知识库名称,如果为空则使用全局配置目录,否则使用 resources/{知识库名称}/
func (s *UploadService) uploadToLocal(f multipart.File, filename, fileKey string, knowledgeBaseName string) (*UploadResponse, error) {
// 确定存储路径
var uploadPath string
if knowledgeBaseName != "" {
// 使用 resources/{知识库名称}/ 路径
uploadPath = filepath.Join("resources", knowledgeBaseName)
} else {
// 使用全局配置路径
uploadPath = s.cfg.UploadLocalPath
}
if err := os.MkdirAll(uploadPath, 0755); err != nil {
return &UploadResponse{Success: false, Message: fmt.Sprintf("failed to create directory: %v", err)}, nil
}
@@ -259,7 +290,8 @@ func (s *UploadService) DeleteFile(filename string) error {
}
// DeleteFileWithConfig 使用指定配置删除文件
func (s *UploadService) DeleteFileWithConfig(filename string, storageConfig model.StorageConfig) error {
// 注意:此方法需要知识库名称才能正确删除本地文件
func (s *UploadService) DeleteFileWithConfig(filename string, storageConfig model.StorageConfig, knowledgeBaseName string) error {
if storageConfig.Type == "minio" {
// 创建 MinIO 客户端
client, err := minio.New(storageConfig.Endpoint, &minio.Options{
@@ -275,7 +307,12 @@ func (s *UploadService) DeleteFileWithConfig(filename string, storageConfig mode
}
// 本地删除
path := filepath.Join(s.cfg.UploadLocalPath, filename)
var path string
if knowledgeBaseName != "" {
path = filepath.Join("resources", knowledgeBaseName, filename)
} else {
path = filepath.Join(s.cfg.UploadLocalPath, filename)
}
return os.Remove(path)
}