Files
rag-local/kb/service/evidence_service.go
T
2026-08-20 12:05:53 +08:00

162 lines
4.2 KiB
Go

package service
import (
"context"
"encoding/json"
"io"
"os"
"path/filepath"
"strings"
"time"
"rag-local/common"
"rag-local/kb/dao"
"rag-local/kb/model/entity"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gconv"
)
var EvidenceService = &evidenceService{}
type evidenceService struct{}
// 合同类文件扩展名(上传时自动触发合同审计)
var contractExts = map[string]bool{
"pdf": true, "docx": true, "doc": true,
"txt": true, "md": true, "html": true, "htm": true,
}
// 图片类扩展名
var imageExts = map[string]bool{
"jpg": true, "jpeg": true, "png": true, "gif": true, "bmp": true, "webp": true,
}
// 音视频类扩展名
var mediaExts = map[string]bool{
"mp3": true, "wav": true, "flac": true, "aac": true, "ogg": true,
"mp4": true, "avi": true, "mov": true, "mkv": true, "wmv": true, "flv": true,
}
func (s *evidenceService) Upload(ctx context.Context, file *ghttp.UploadFile, evidenceType, description, datasetIdsJSON string, caseId int64) (int64, error) {
if file == nil {
return 0, gerror.New("请选择文件")
}
f, err := file.Open()
if err != nil {
return 0, err
}
defer func() { _ = f.Close() }()
data, err := io.ReadAll(f)
if err != nil {
return 0, err
}
if len(data) == 0 {
return 0, gerror.New("文件内容为空")
}
ext := strings.TrimPrefix(strings.ToLower(filepath.Ext(file.Filename)), ".")
if ext == "" {
return 0, gerror.New("无法识别文件类型")
}
// 自动推断证据类型
if evidenceType == "" {
if imageExts[ext] {
evidenceType = "image"
} else if mediaExts[ext] {
evidenceType = "video"
} else {
evidenceType = "document"
}
}
// 保存文件
relDir := filepath.Join("evidence", time.Now().Format("20060102"))
relPath := filepath.Join(relDir, common.RandomToken(16)+"."+ext)
absPath := filepath.Join("workspace", relPath)
if err := os.MkdirAll(filepath.Dir(absPath), 0o755); err != nil {
return 0, err
}
if err := os.WriteFile(absPath, data, 0o644); err != nil {
return 0, err
}
// 插入证物记录
evidence := &entity.Evidence{
Filename: file.Filename,
FilePath: relPath,
FileType: ext,
EvidenceType: evidenceType,
Description: description,
DatasetIds: datasetIdsJSON,
CaseId: caseId,
Status: 0,
}
id, err := dao.Evidence.Insert(ctx, evidence)
if err != nil {
_ = os.Remove(absPath)
return 0, err
}
// 文档类证物如果是合同类文件,自动创建合同审计任务
if evidenceType == "document" && contractExts[ext] && datasetIdsJSON != "" {
var dsIds []int64
if err := json.Unmarshal([]byte(datasetIdsJSON), &dsIds); err == nil && len(dsIds) > 0 {
ids := make([]string, 0, len(dsIds))
for _, did := range dsIds {
ids = append(ids, strings.TrimSpace(gconv.String(did)))
}
contractTaskId, err := dao.ContractTask.Insert(ctx, file.Filename, relPath, strings.Join(ids, ","), 0)
if err == nil && contractTaskId > 0 {
_ = dao.Evidence.Update(ctx, id, g.Map{"contract_task_id": contractTaskId})
evidence.ContractTaskId = contractTaskId
}
}
}
return id, nil
}
func (s *evidenceService) List(ctx context.Context, page, pageSize int) ([]*entity.Evidence, int, error) {
return dao.Evidence.List(ctx, page, pageSize)
}
func (s *evidenceService) Detail(ctx context.Context, id int64) (*entity.Evidence, error) {
return dao.Evidence.GetOne(ctx, id)
}
func (s *evidenceService) Delete(ctx context.Context, id int64) error {
ev, err := dao.Evidence.GetOne(ctx, id)
if err != nil {
return err
}
if ev == nil {
return gerror.New("证物不存在")
}
// 删除文件
absPath := filepath.Join("workspace", ev.FilePath)
_ = os.Remove(absPath)
// 删除关联记录
if ev.CaseId > 0 {
_ = dao.CaseEvidence.DeleteByCaseAndEvidence(ctx, ev.CaseId, id)
}
return dao.Evidence.Delete(ctx, id)
}
func (s *evidenceService) Update(ctx context.Context, id int64, description, datasetIds string) error {
data := g.Map{}
if description != "" {
data["description"] = description
}
if datasetIds != "" {
data["dataset_ids"] = datasetIds
}
if len(data) == 0 {
return nil
}
return dao.Evidence.Update(ctx, id, data)
}