package doc import ( "app/cfg" "app/models" "app/utils" "encoding/json" "errors" "fmt" "io" "os" "path/filepath" "strings" "time" "github.com/veypi/OneBD/rest" "gorm.io/gorm" ) var _ = Router.Get("/:id", getHandle) var _ = Router.Get("/:id/project", getProjectIDHandle) var _ = Router.Get("", getHandle) // 获取文档对应的项目ID func getProjectIDHandle(x *rest.X) (any, error) { utils.SetCORSHeaders(x) // 获取文档ID docID, ok := x.Params.Get("id") if !ok { return nil, errors.New("缺少文档ID") } // 查询文档信息 var doc models.Doc if err := cfg.DB().Where("id = ?", docID).First(&doc).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("文档不存在") } return nil, fmt.Errorf("查询文档失败: %v", err) } return map[string]interface{}{ "doc_id": docID, "project_id": doc.ProjectID, }, nil } // 获取文档 func getHandle(x *rest.X) (any, error) { utils.SetCORSHeaders(x) id, ok := x.Params.Get("id") // fmt.Println("getHandle", id) if !ok { // 获取所有文档 var docs []models.Doc if err := cfg.DB().Find(&docs).Error; err != nil { return nil, err } return docs, nil } // 获取特定文档 var docs []models.Doc if err := cfg.DB().Where("project_id = ?", id).Find(&docs).Error; err != nil { return nil, err } // fmt.Println("getHandle", doc) return docs, nil } var _ = Router.Post("", postHandle) // 创建文档 // 创建文档 func postHandle(x *rest.X) (any, error) { utils.SetCORSHeaders(x) // 解析表单数据 if err := x.Request.ParseMultipartForm(10 << 20); err != nil { // 10 MB return nil, fmt.Errorf("解析表单失败: %v", err) } // 获取项目ID projectID := x.Request.FormValue("project_id") if projectID == "" { return nil, errors.New("缺少project_id参数") } // 获取文档名称 name := x.Request.FormValue("name") if name == "" { return nil, errors.New("缺少name参数") } // 获取文档类型 docType := x.Request.FormValue("type") if docType == "" { docType = "other" // 默认类型 } // 获取文档描述 description := x.Request.FormValue("description") // 获取上传的文件 file, header, err := x.Request.FormFile("file") if err != nil { return nil, fmt.Errorf("获取文件失败: %v", err) } defer file.Close() // 验证文件类型 fileExt := strings.ToLower(filepath.Ext(header.Filename)) allowedTypes := map[string]bool{ ".docx": true, ".txt": true, ".pdf": true, } if !allowedTypes[fileExt] { return nil, fmt.Errorf("不支持的文件类型: %s", fileExt) } // 创建上传目录 uploadDir := filepath.Join("uploads", "docs", projectID) if err := os.MkdirAll(uploadDir, 0755); err != nil { return nil, fmt.Errorf("创建上传目录失败: %v", err) } // 生成唯一文件名 fileName := fmt.Sprintf("%d_%s", time.Now().UnixNano(), header.Filename) filePath := filepath.Join(uploadDir, fileName) // 保存文件 dst, err := os.Create(filePath) if err != nil { return nil, fmt.Errorf("创建目标文件失败: %v", err) } defer dst.Close() size, err := io.Copy(dst, file) if err != nil { os.Remove(filePath) // 清理失败的文件 return nil, fmt.Errorf("保存文件失败: %v", err) } // 创建文档记录 doc := &models.Doc{ ProjectID: projectID, Name: name, Description: description, FilePath: filePath, FileType: fileExt[1:], // 移除点号 FileSize: size, FileName: header.Filename, AnalysisCompleted: false, AnalysisPercent: 0, AnalysisError: "", Merged: false, } if err := cfg.DB().Create(doc).Error; err != nil { os.Remove(filePath) // 清理文件 return nil, fmt.Errorf("创建文档记录失败: %v", err) } // 将文档添加到处理队列 // GetDemandProcessor().AddTask(doc, filePath) GetAgenticDemandProcessor().AddTask(doc, filePath) return doc, nil } var _ = Router.Patch("/:id", patchHandle) // 更新文档 func patchHandle(x *rest.X) (any, error) { utils.SetCORSHeaders(x) // 从URL获取ID body, err := io.ReadAll(x.Request.Body) if err != nil { return nil, fmt.Errorf("读取请求体失败: %v", err) } id, ok := x.Params.Get("id") if !ok { return nil, errors.New("缺少id") } var updateMap map[string]interface{} if err := json.Unmarshal(body, &updateMap); err != nil { return nil, fmt.Errorf("解析JSON失败: %v", err) } // 先检查文档是否存在 var doc models.Doc if err := cfg.DB().Where("id = ?", id).First(&doc).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("文档不存在") } return nil, err } // 删除不允许更新的字段 delete(updateMap, "id") // 只更新提供的字段 if len(updateMap) > 0 { if err := cfg.DB().Model(&doc).Updates(updateMap).Error; err != nil { return nil, err } } // 重新查询更新后的完整数据 if err := cfg.DB().Where("id = ?", id).First(&doc).Error; err != nil { return nil, err } return doc, nil } var _ = Router.Delete("/:id", deleteHandle) // 删除文档 func deleteHandle(x *rest.X) (any, error) { utils.SetCORSHeaders(x) id, ok := x.Params.Get("id") if !ok { return nil, errors.New("缺少id") } var doc models.Doc if err := cfg.DB().Where("id = ?", id).First(&doc).Error; err != nil { return nil, err } // 删除文档 if err := cfg.DB().Delete(&doc).Error; err != nil { return nil, err } return map[string]interface{}{ "msg": "删除成功", }, nil } var _ = Router.Any("/*", anyHandle) func anyHandle(x *rest.X) (any, error) { utils.SetCORSHeaders(x) return nil, nil }