251 lines
5.6 KiB
Go
251 lines
5.6 KiB
Go
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
|
|
}
|