qixiaoning
2025-10-29 9b17a8dcbc1f94eb117a37b3b24ca9dae0d2d588
camera-common/models/Record.go
@@ -4,11 +4,14 @@
   "context"
   "fmt"
   "math"
   "os"
   "path/filepath"
   "sort"
   "strconv"
   "strings"
   "time"
   "basic.com/valib/logger.git"
   "github.com/milvus-io/milvus-sdk-go/v2/entity"
)
@@ -47,6 +50,7 @@
   IsWarning          int64                     `json:"is_warning"`
   ZhDescClass        string                    `json:"zh_desc_class"`
   TaskName           string                    `json:"task_name"`
   WarnTaskName       string                    `json:"warn_task_name"`
   EventLevelName     string                    `json:"event_level_name"`
   DetectNum          int64                     `json:"detect_num"`
   Suggestion         string                    `json:"suggestion"`
@@ -127,8 +131,9 @@
}
type TaskOption struct {
   TaskId   int64  `db:"task_id" json:"taskId"`
   TaskName string `db:"task_name" json:"taskName"`
   TaskId     int64  `db:"task_id" json:"taskId"`
   TaskName   string `db:"task_name" json:"taskName"`
   EventLevel int64  `db:"event_level" json:"eventLevel"`
}
type CheckOption struct {
@@ -187,6 +192,136 @@
   Warning  int64    `json:"warning`
   Page     int64    `json:"page"`
   PageSize int64    `json:"pageSize"`
}
// 时间段
type TimeRange struct {
   StartTime string `json:"startTime"`
   EndTime   string `json:"endTime"`
}
// 删除日志
func DeleteRecord(collectionName string, filterExpr string) (int, error) {
   dataOp := &DataOperator{client: dbClient}
   deletedFiles, err := dataOp.DelRecord(collectionName, filterExpr)
   return deletedFiles, err
}
// 清理日志
func (do *DataOperator) DelRecord(collectionName string, filterExpr string) (int, error) {
   ctx := context.Background()
   queryResult, err := do.client.client.Query(
      ctx,
      collectionName,
      []string{}, // 所有分区
      filterExpr,
      []string{"id", "image_path", "video_path", "image_desc_path"}, // 返回所有字段
      // client.WithLimit(pageSize),
      // client.WithOffset(offset),
   )
   // 2. 提取ID和文件路径
   var ids []int64
   var imgPaths []string
   var videoPaths []string
   var imgDesPaths []string
   if len(queryResult) == 0 {
      return 0, nil
   }
   count := queryResult[0].Len()
   for i := 0; i < count; i++ {
      for _, field := range queryResult {
         switch field.Name() {
         case "id":
            IdColumn := field.(*entity.ColumnInt64).Data()
            if len(IdColumn) > 0 {
               id := IdColumn[i]
               ids = append(ids, id)
            }
         case "image_path":
            ImagePathColumn := field.(*entity.ColumnVarChar).Data()
            if len(ImagePathColumn) > 0 {
               imagePath := ImagePathColumn[i]
               imgPaths = append(imgPaths, imagePath)
            }
         case "image_desc_path":
            ImageDesPathColumn := field.(*entity.ColumnVarChar).Data()
            if len(ImageDesPathColumn) > 0 {
               imageDesPath := ImageDesPathColumn[i]
               imgDesPaths = append(imgDesPaths, imageDesPath)
            }
         case "video_path":
            VideoPathColumn := field.(*entity.ColumnVarChar).Data()
            if len(VideoPathColumn) > 0 {
               VideoPath := VideoPathColumn[i]
               videoPaths = append(videoPaths, VideoPath)
            }
         }
      }
   }
   if len(ids) > 0 {
      idField := entity.NewColumnInt64("id", ids)
      err = do.client.client.DeleteByPks(ctx, collectionName, "", idField)
      if err != nil {
         return 0, fmt.Errorf("failed to delete from Milvus: %v", err)
      }
      err = do.client.client.DeleteByPks(ctx, "smartrag", "", idField)
      if err != nil {
         return 0, fmt.Errorf("failed to delete from Milvus: %v", err)
      }
   }
   // 图片删除文件
   deletedFiles := 0
   for _, path := range imgPaths {
      if err := do.deleteFile(path); err != nil {
         logger.Debug("failed to delete file " + path + " " + err.Error())
      } else {
         deletedFiles++
      }
   }
   //删除描述图片
   for _, path := range imgDesPaths {
      if err := do.deleteFile(path); err != nil {
         logger.Debug("failed to delete file " + path + " " + err.Error())
      } else {
         deletedFiles++
      }
   }
   //删除视频文件
   for _, path := range videoPaths {
      if err := do.deleteFile(path); err != nil {
         logger.Debug("failed to delete file " + path + " " + err.Error())
      } else {
         deletedFiles++
      }
   }
   return deletedFiles, err
}
func (do *DataOperator) deleteFile(relativePath string) error {
   fullPath := relativePath
   // 安全检查,防止路径遍历攻击
   if !isSafePath(fullPath) {
      return fmt.Errorf("invalid file path")
   }
   if _, err := os.Stat(fullPath); os.IsNotExist(err) {
      return fmt.Errorf("file does not exist")
   }
   return os.Remove(fullPath)
}
// isSafePath 检查路径是否安全,防止路径遍历攻击
func isSafePath(targetPath string) bool {
   rel := targetPath
   return rel != ".." && rel[:2] != ".."+string(filepath.Separator)
}
// 根据分页取数据
@@ -280,6 +415,11 @@
            if len(TNColumn) > 0 {
               record.TaskName = TNColumn[i]
            }
         case "warn_task_id":
            WarnColumn := field.(*entity.ColumnVarChar).Data()
            if len(WarnColumn) > 0 {
               record.WarnTaskName = WarnColumn[i]
            }
         case "event_level_name":
            EVColumn := field.(*entity.ColumnVarChar).Data()
            if len(EVColumn) > 0 {
@@ -353,7 +493,7 @@
      filterExpr,
      []string{"rule_id", "task_id", "is_waning", "zh_desc_class", "task_name", "event_level_name", "detect_num",
         "event_level_id", "video_point_id", "video_point_name", "detect_id", "image_path",
         "video_path", "detect_time", "knowledge_id", "risk_description", "suggestion", "id", "is_desc"}, // 返回所有字段
         "video_path", "detect_time", "knowledge_id", "risk_description", "suggestion", "id", "is_desc", "warn_task_id"}, // 返回所有字段
      // client.WithLimit(pageSize),
      // client.WithOffset(offset),
   )
@@ -363,15 +503,27 @@
   lists := convertResultToMap(result)
   layout := "2006-01-02 15:04:05.999999"
   var temp1 time.Time
   var temp2 time.Time
   // var temp1 time.Time
   // var temp2 time.Time
   //排序
   // //排序
   // sort.Slice(lists, func(i, j int) bool {
   //    //return lists[i].DetectTime > lists[j].:DetectTime
   //    temp1, _ = time.Parse(layout, lists[i].DetectTime)
   //    temp2, _ = time.Parse(layout, lists[j].DetectTime)
   //    return temp1.After(temp2)
   // })
   sort.Slice(lists, func(i, j int) bool {
      //return lists[i].DetectTime > lists[j].:DetectTime
      temp1, _ = time.Parse(layout, lists[i].DetectTime)
      temp2, _ = time.Parse(layout, lists[j].DetectTime)
      return temp1.After(temp2)
      t1, err1 := time.Parse(layout, lists[i].DetectTime)
      t2, err2 := time.Parse(layout, lists[j].DetectTime)
      // 错误处理:解析错误的时间排在后面
      if err1 != nil || err2 != nil {
         return err1 == nil && err2 != nil
      }
      return t1.After(t2)
   })
   items := Paginate(lists, int(pageNum), int(pageSize))
@@ -422,8 +574,8 @@
      placeholders[i] = "?"
      args[i] = id
   }
   sqlStr := `select task_id,task_name from mal_smart_task where task_id in (` + strings.Join(placeholders, ",") + `)`
   if err := db.Raw(sqlStr).Scan(&items).Error; err != nil {
   sqlStr := `select task_id,task_name,event_level from mal_smart_task where task_id in (` + strings.Join(placeholders, ",") + `)`
   if err := db.Raw(sqlStr, args...).Scan(&items).Error; err != nil {
      return nil, err
   }
   return