qixiaoning
2025-07-22 550492cb85ea7e01831939f2866259193378f2f7
新增修改实时监控和摄像机配置相关接口
9个文件已修改
3个文件已添加
956 ■■■■■ 已修改文件
api-gateway/models/base.go 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-common/models/Record.go 510 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-common/models/camera.go 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-common/models/db.go 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-common/models/task.go 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-service/controllers/camera.go 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-service/main.go 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-service/models/db.go 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
camera-service/models/milvus.go 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sync-service/models/camera.go 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sync-service/service/cameraService.go 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sync-service/vo/camera.go 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api-gateway/models/base.go
New file
@@ -0,0 +1,39 @@
package models
import (
    "gopkg.in/ini.v1"
)
type PathConfig struct {
    BasePath      string `json:"basePath"`
    DecodeUrl     string `json:"decodeUrl"`
    SmartUrl      string `json:"smartUrl"`
    MilvusUrl     string `json:"milvusUrl"`
    WvpToken      string `json:"wvpToken"`
    WvpUrl        string `json:"wvpUrl"`
    ZlmediaKitUrl string `json:"zlmediaKitUrl"`
    SqlitePath    string `json:"sqlitePath"`
}
func GetBasePath() string {
    cfg, _ := ini.Load("config.ini")
    // 读取默认分区
    basePath := cfg.Section("setting").Key("basepath").String()
    return basePath
}
func GetConfig() PathConfig {
    config := PathConfig{}
    cfg, _ := ini.Load("config.ini")
    // 读取默认分区
    config.DecodeUrl = cfg.Section("setting").Key("decodeBaseUrl").String()
    config.BasePath = cfg.Section("setting").Key("basepath").String()
    config.SmartUrl = cfg.Section("setting").Key("smartUrl").String()
    config.MilvusUrl = cfg.Section("setting").Key("milvusUrl").String()
    config.WvpToken = cfg.Section("setting").Key("wvpToken").String()
    config.WvpUrl = cfg.Section("setting").Key("wvpUrl").String()
    config.ZlmediaKitUrl = cfg.Section("setting").Key("zlmediaKitUrl").String()
    config.SqlitePath = cfg.Section("setting").Key("sqlitePath").String()
    return config
}
camera-common/models/Record.go
New file
@@ -0,0 +1,510 @@
package models
import (
    "context"
    "fmt"
    "math"
    "sort"
    "strings"
    "time"
    "github.com/milvus-io/milvus-sdk-go/v2/entity"
)
// DataOperator 数据操作相关方法
type DataOperator struct {
    client *MilvusClient
}
// NewDataOperator 创建数据操作器
func NewDataOperator(client *MilvusClient) *DataOperator {
    return &DataOperator{client: client}
}
type PicWidHei struct {
    PicW int `json:"picW"`
    PicH int `json:"picH"`
}
// 统计查询
type StaticRecord struct {
    Id                 int64                     `json:"id"`
    TaskId             []int64                   `json:"task_id"`
    RuleId             []int64                   `json:"rule_id"`
    EventLevelId       []int64                   `json:"event_level_id"`
    VideoPointId       int64                     `json:"video_point_id"`
    DetectId           []int64                   `json:"detect_id"`
    VideoName          string                    `json:"video_name"`
    TaskNames          []TaskOption              `json:"task_names"`
    CheckNames         []CheckOption             `json:"check_names"`
    RuleNames          []RuleOption              `json:"rule_names"`
    EventLevels        []DictOption              `json:"event_levels"`
    KnowledgeDocuments []KnowledgeDocumentOption `json:"knowledge_documents"`
    ImagePath          string                    `json:"image_path"`
    VideoPath          string                    `json:"video_path"`
    DetectTime         string                    `json:"detect_time"`
    IsWarning          int64                     `json:"is_warning"`
    ZhDescClass        string                    `json:"zh_desc_class"`
    TaskName           string                    `json:"task_name"`
    EventLevelName     string                    `json:"event_level_name"`
    DetectNum          int64                     `json:"detect_num"`
    Suggestion         string                    `json:"suggestion"`
    RiskDescription    string                    `json:"risk_description"`
    KnowledgeId        []int64                   `json:"knowledge_id"`
    IsDesc             int64                     `json:"is_desc"`
    CameraId           string                    `json:"cameraId"`
    CameraName         string                    `json:"cameraName"`
    CameraAddr         string                    `json:"cameraAddr"`
    PicDate            string                    `json:"picDate"`
    PicId              int64                     `json:"picId"`
    PicMaxUrl          []string                  `json:"picMaxUrl"`
    PicSrcUrl          []string                  `json:"picSrcUrl"`
    PicWH              PicWidHei                 `json:"picWH"`
    SdkName            string                    `json:"sdkName"`
    Content            string                    `json:"content"`
    AlarmRules         []AlarmRule               `json:"alarmRules"`
    LikeDate           string                    `json:"likeDate"`
    ShowLabels         string                    `json:"showLabels"`
    OtherLabels        string                    `json:"otherLabels"`
    VideoUrl           string                    `json:"videoUrl"`
    AnalyServerId      string                    `json:"analyServerId"`
    AnalyServerName    string                    `json:"analyServerName"`
    AnalyServerIp      string                    `json:"analyServerIp"`
    ClusterId          string                    `json:"clusterId"`
    IsAlarm            bool                      `json:"isAlarm"`
    IsAckAlarm         bool                      `json:"isAckAlarm"`
    IsCollect          bool                      `json:"isCollect"`
    IsDelete           bool                      `json:"isDelete"`
    BaseInfo           []*BaseCompareInfo        `json:"baseInfo"`
    TargetInfo         []TargetInfo              `json:"targetInfo"`
    FileId             string                    `json:"fileId"`     // 数据栈文件id
    DataSource         string                    `json:"dataSource"` // 数据来源:摄像机, 数据栈
}
type Point struct {
    X float64 `json:"x"`
    Y float64 `json:"y"`
}
type Points struct {
    TopLeft     Point `json:"topLeft"`
    BottomRight Point `json:"bottomRight"`
}
type BaseCompareInfo struct {
    TableId      string  `json:"tableId"`
    TableName    string  `json:"tableName"`
    BwType       string  `json:"bwType"`
    CompareScore float64 `json:"compareScore"`
    TargetId     string  `json:"targetId"`
    TargetName   string  `json:"targetName"`
    TargetPicUrl string  `json:"targetPicUrl"`
    MonitorLevel string  `json:"monitorLevel"`
    Content      string  `json:"content"`
    DbLabel      string  `json:"labels"`
}
type TargetInfo struct {
    TargetId        string  `json:"targetId"`
    AreaId          string  `json:"areaId"`
    AreaName        string  `json:"areaName"`
    TargetScore     float64 `json:"targetScore"`
    TargetType      string  `json:"targetType"`
    Feature         string  `json:"feature"`
    PicSmUrl        string  `json:"picSmUrl"`
    TargetLocation  Points  `json:"targetLocation"`
    BelongsTargetID string  `json:"belongsTargetId"`
    Attribute       string  `json:"attribute"`
}
type AlarmRule struct {
    AlarmLevel   string `db:"alarmLevel" json:"alarmLevel"`
    DefenceState bool   `db:"defenceState" json:"defenceState"`
    GroupId      string `db:"groupId" json:"groupId"`
    LinkInfo     string `db:"linkInfo" json:"linkInfo"`
    RuleText     string `db:"ruleText" json:"ruleText"`
}
type TaskOption struct {
    TaskId   int64  `db:"task_id" json:"taskId"`
    TaskName string `db:"task_name" json:"taskName"`
}
type CheckOption struct {
    TaskId   int64  `db:"task_id" json:"taskId,omitempty"`
    CheckId  int64  `db:"check_id" json:"checkId"`
    FileName string `db:"file_name" json:"fileName"`
}
type RuleOption struct {
    TaskId   int64  `db:"task_id" json:"taskId,omitempty"`
    RuleId   int64  `db:"rule_id" json:"ruleId"`
    FileName string `db:"file_name" json:"fileName"`
}
// 字典
type DictOption struct {
    DictId    int64  `db:"dict_id" json:"dictId"`
    DictName  string `db:"dict_name" json:"dictName"`
    DictValue string `db:"dict_value" json:"dictValue"`
    DictType  string `db:"dict_type" json:"dictType"`
}
// 知识库
type KnowledgeDocumentOption struct {
    Id      string `db:"id" json:"id"`
    Title   string `db:"file_name" json:"title"`
    KnowId  int64  `db:"know_id" json:"know_id"`
    FileUrl string `db:"file_name" json:"file_url"`
}
// Pagination 分页信息
type Pagination struct {
    Page      int `json:"page"`      // 当前页码
    PageSize  int `json:"pageSize"`  // 每页大小
    Total     int `json:"total"`     // 总记录数
    TotalPage int `json:"totalPage"` // 总页数
}
// PaginatedResult 分页结果
type PaginatedResult struct {
    Items      []StaticRecord `json:"list"`
    Pagination Pagination     `json:"pagination"`
}
type PaginatedResult2 struct {
    Items      map[string]interface{} `json:"list"`
    Pagination Pagination             `json:"pagination"`
}
// 记录
type RecordReq struct {
    Ids      []string `json:"ids"`
    VideoIds []string `json:"treeNodes"`
    TaskIds  []int64  `json:"taskIds`
    Warning  int64    `json:"warning`
    Page     int64    `json:"page"`
    PageSize int64    `json:"pageSize"`
}
// 根据分页取数据
func GetWithPage(collectionName string, pageNum int64, pageSize int64, filter string) (*PaginatedResult, error) {
    if pageNum < 1 {
        pageNum = 1
    }
    if pageSize < 1 {
        pageSize = 10
    }
    if dbClient == nil {
        return nil, nil
    }
    dataOp := &DataOperator{client: dbClient}
    fmt.Println(filter)
    records, err := dataOp.queryWithPagination(collectionName, filter, pageNum, pageSize)
    if err != nil {
        return nil, err
    }
    return records, nil
}
// 转换数据
func convertResultToMap(result []entity.Column) []StaticRecord {
    if len(result) == 0 {
        return nil
    }
    count := result[0].Len()
    var records []StaticRecord
    for i := 0; i < count; i++ {
        record := StaticRecord{}
        for _, field := range result {
            switch field.Name() {
            case "id":
                IdColumn := field.(*entity.ColumnInt64).Data()
                if len(IdColumn) > 0 {
                    record.Id = IdColumn[i]
                }
            case "task_id":
                TaskIdColumn := field.(*entity.ColumnInt64Array).Data()
                if len(TaskIdColumn) > 0 {
                    record.TaskId = TaskIdColumn[i]
                }
            case "rule_id":
                RuleIdColumn := field.(*entity.ColumnInt64Array).Data()
                if len(RuleIdColumn) > 0 {
                    record.RuleId = RuleIdColumn[i]
                }
            case "event_level_id":
                EventLevelIdColumn := field.(*entity.ColumnInt64Array).Data()
                if len(EventLevelIdColumn) > 0 {
                    record.EventLevelId = EventLevelIdColumn[i]
                }
            case "video_point_id":
                VideoPointIdColumn := field.(*entity.ColumnInt64).Data()
                if len(VideoPointIdColumn) > 0 {
                    record.VideoPointId = VideoPointIdColumn[i]
                }
            case "detect_id":
                DetectIdColumn := field.(*entity.ColumnInt64Array).Data()
                if len(DetectIdColumn) > 0 {
                    record.DetectId = DetectIdColumn[i]
                }
            case "image_path":
                ImagePathColumn := field.(*entity.ColumnVarChar).Data()
                if len(ImagePathColumn) > 0 {
                    record.ImagePath = ImagePathColumn[i]
                }
            case "video_path":
                VideoPathColumn := field.(*entity.ColumnVarChar).Data()
                if len(VideoPathColumn) > 0 {
                    record.VideoPath = VideoPathColumn[i]
                }
            case "zh_desc_class":
                zhColumn := field.(*entity.ColumnVarChar).Data()
                if len(zhColumn) > 0 {
                    record.ZhDescClass = zhColumn[i]
                }
            case "task_name":
                TNColumn := field.(*entity.ColumnVarChar).Data()
                if len(TNColumn) > 0 {
                    record.TaskName = TNColumn[i]
                }
            case "event_level_name":
                EVColumn := field.(*entity.ColumnVarChar).Data()
                if len(EVColumn) > 0 {
                    record.EventLevelName = EVColumn[i]
                }
            case "is_desc":
                descColumn := field.(*entity.ColumnInt64).Data()
                if len(descColumn) > 0 {
                    record.IsDesc = descColumn[i]
                }
            case "detect_num":
                DEColumn := field.(*entity.ColumnInt64).Data()
                if len(DEColumn) > 0 {
                    record.DetectNum = DEColumn[i]
                }
            case "is_waning":
                warnColumn := field.(*entity.ColumnInt64).Data()
                if len(warnColumn) > 0 {
                    record.IsWarning = warnColumn[i]
                }
            case "detect_time":
                DetectTimeColumn := field.(*entity.ColumnVarChar).Data()
                if len(DetectTimeColumn) > 0 {
                    record.DetectTime = DetectTimeColumn[i]
                }
            case "knowledge_id":
                KnowledgeIdColumn := field.(*entity.ColumnInt64Array).Data()
                if len(KnowledgeIdColumn) > 0 {
                    record.KnowledgeId = KnowledgeIdColumn[i]
                }
            case "suggestion":
                SuggestionColumn := field.(*entity.ColumnVarChar).Data()
                if len(SuggestionColumn) > 0 {
                    record.Suggestion = SuggestionColumn[i]
                }
            case "risk_description":
                RiskDescriptionColumn := field.(*entity.ColumnVarChar).Data()
                if len(RiskDescriptionColumn) > 0 {
                    record.RiskDescription = RiskDescriptionColumn[i]
                }
            }
        }
        records = append(records, record)
    }
    return records
}
// 分页查询
func (do *DataOperator) queryWithPagination(collectionName string, filterExpr string, pageNum int64, pageSize int64) (*PaginatedResult, error) {
    ctx := context.Background()
    // 计算偏移量
    //offset := (pageNum - 1) * pageSize
    // 构建查询表达式(Milvus 2.1+ 支持 limit/offset)
    //queryExpr := fmt.Sprintf("%s limit %d offset %d", filterExpr, pageSize, offset)
    total, err := do.getTotalCount(collectionName, filterExpr)
    if err != nil {
        return nil, err
    }
    // 计算总页数
    totalPages := int(math.Ceil(float64(total) / float64(pageSize)))
    // 执行查询
    result, err := do.client.client.Query(
        ctx,
        collectionName,
        []string{}, // 所有分区
        filterExpr,
        []string{"rule_id", "task_id", "is_waning", "zh_desc_class", "task_name", "event_level_name", "detect_num",
            "event_level_id", "video_point_id", "detect_id", "image_path",
            "video_path", "detect_time", "knowledge_id", "risk_description", "suggestion", "id", "is_desc"}, // 返回所有字段
        // client.WithLimit(pageSize),
        // client.WithOffset(offset),
    )
    if err != nil {
        return nil, fmt.Errorf("分页查询失败: %v", err)
    }
    lists := convertResultToMap(result)
    layout := "2006-01-02 15:04:05.999999"
    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)
    })
    items := Paginate(lists, int(pageNum), int(pageSize))
    return &PaginatedResult{
        Items: items,
        Pagination: Pagination{
            Page:      int(pageNum),
            PageSize:  int(pageSize),
            Total:     int(total),
            TotalPage: totalPages,
        },
    }, nil
}
// 分页数据
func Paginate(data []StaticRecord, page, pageSize int) []StaticRecord {
    start := (page - 1) * pageSize
    if start >= len(data) {
        return nil
    }
    end := start + pageSize
    if end > len(data) {
        end = len(data)
    }
    return data[start:end]
}
// 统计数量
func (do *DataOperator) getTotalCount(collectionName string, filterExpr string) (int64, error) {
    result, err := do.client.client.Query(
        context.Background(),
        collectionName,
        []string{},
        filterExpr,
        []string{"count(*)"},
    )
    if err != nil {
        return 0, err
    }
    return result[0].(*entity.ColumnInt64).Data()[0], nil
}
// 根据id获取任务
func GetTaskByIds(ids []int64) (items []TaskOption, err error) {
    placeholders := make([]string, len(ids))
    args := make([]interface{}, len(ids))
    for i, id := range ids {
        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 {
        return nil, err
    }
    return
}
// 根据id获取视频
func GetVideoById(vid int64) (video Camera, err error) {
    // 如果返回的是指针,需要初始化
    sqlStr := "select id,name,alias,type,addr,rtsp,is_running,run_type,run_enable FROM cameras where video_id=?"
    if err := db.Raw(sqlStr, vid).Scan(&video).Error; err != nil {
        return Camera{}, err
    }
    return
}
// 根据id获取检测内容
func GetCheckByIds(ids []int64) (items []CheckOption, err error) {
    placeholders := make([]string, len(ids))
    args := make([]interface{}, len(ids))
    for i, id := range ids {
        placeholders[i] = "?"
        args[i] = id
    }
    sqlStr := `select check_id,file_name from mal_check_content where check_id in (` + strings.Join(placeholders, ",") + `)`
    if err := db.Raw(sqlStr, args...).Scan(&items).Error; err != nil {
        return nil, err
    }
    return
}
// 根据id获取规则
func GetRuleByIds(ids []int64) (items []RuleOption, err error) {
    placeholders := make([]string, len(ids))
    args := make([]interface{}, len(ids))
    for i, id := range ids {
        placeholders[i] = "?"
        args[i] = id
    }
    sqlStr := `select rule_id,file_name from mal_warning_rule where rule_id in (` + strings.Join(placeholders, ",") + `)`
    if err := db.Raw(sqlStr, args...).Scan(&items).Error; err != nil {
        return nil, err
    }
    return
}
// 获取事件
func GetEventByIds(ids []int64) (items []DictOption, err error) {
    placeholders := make([]string, len(ids))
    args := make([]interface{}, len(ids))
    for i, id := range ids {
        placeholders[i] = "?"
        args[i] = id
    }
    sqlStr := `select dict_id,dict_name,dict_value from mal_dict_type where dict_id in (` + strings.Join(placeholders, ",") + `)`
    if err := db.Raw(sqlStr, args...).Scan(&items).Error; err != nil {
        return nil, err
    }
    return
}
// 根据知识库id查数据
func GetKnowledgeDocumentByIds(ids []int64) (items []KnowledgeDocumentOption, err error) {
    placeholders := make([]string, len(ids))
    args := make([]interface{}, len(ids))
    for i, id := range ids {
        placeholders[i] = "?"
        args[i] = id
    }
    sqlStr := `SELECT id, know_id, file_name FROM mal_knowledge_document where id in (` + strings.Join(placeholders, ",") + `)`
    if err := db.Raw(sqlStr, args...).Scan(&items).Error; err != nil {
        return nil, err
    }
    return
}
// 根据知识库id查数据
func GetCameraIds(ids []string) (items []Camera, err error) {
    placeholders := make([]string, len(ids))
    args := make([]interface{}, len(ids))
    for i, id := range ids {
        placeholders[i] = "?"
        args[i] = id
    }
    sqlStr := `select id,name,alias,type,addr,rtsp,is_running,run_type,run_enable,video_id FROM cameras where id in (` + strings.Join(placeholders, ",") + `)`
    if err := db.Raw(sqlStr, args...).Scan(&items).Error; err != nil {
        return nil, err
    }
    return
}
camera-common/models/camera.go
@@ -1,14 +1,15 @@
package models
import (
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/logger.git"
    "encoding/json"
    "fmt"
    "strconv"
    "strings"
    "vamicro/camera-common/pub"
    "vamicro/config"
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/logger.git"
)
const (
@@ -55,6 +56,7 @@
    VoiceEnable    bool   `gorm:"column:voiceEnable;default:0" json:"voiceEnable"`
    VoiceId        string `gorm:"column:voiceId" json:"voiceId"`
    CoordTransform string `gorm:"column:coordTransform" json:"coordTransform"` //坐标转换,长春追踪reid用
    VideoId        int    `gorm:"column:video_id" json:"video_id"`             //摄像机id
}
func (Camera) TableName() string {
camera-common/models/db.go
@@ -1,8 +1,17 @@
package models
import "github.com/jinzhu/gorm"
import (
    "github.com/jinzhu/gorm"
    "github.com/milvus-io/milvus-sdk-go/v2/client"
)
var db *gorm.DB
var dbClient *MilvusClient
// MilvusClient 封装Milvus操作的结构体
type MilvusClient struct {
    client client.Client
}
func SetDB(h *gorm.DB) {
    db = h
@@ -11,3 +20,11 @@
func GetDB() *gorm.DB {
    return db
}
func SetClientDB(h client.Client) {
    dbClient = &MilvusClient{client: h}
}
func GetClientDB() *MilvusClient {
    return dbClient
}
camera-common/models/task.go
@@ -1 +1,38 @@
package models
import (
    "fmt"
    "strings"
)
// 智查任务
type Task struct {
    TaskId   int64  `db:"task_id" json:"taskId"`
    TaskName string `db:"task_name" json:"taskName"`
}
// 视频
type Video struct {
    VideoIds []string `json:"videoIds"`
}
// 查询列表数据
func GetListTask(ids []string) (items []Task, err error) {
    //idList := strings.Join(ids, ",")
    idList := "'" + strings.Join(ids, "','") + "'"
    // 主查询SQL
    //sqlStr := `select c.task_id, c.task_name from mal_task_video_link a left join mal_smart_task c on a.task_id = c.task_id where a.video_id in(?) ORDER BY a.task_id desc`
    sqlStr := fmt.Sprintf(`
        SELECT c.task_id, c.task_name
        FROM mal_task_video_link a
        LEFT JOIN mal_smart_task c ON a.task_id = c.task_id
        WHERE a.video_id IN (%s)
        ORDER BY a.task_id DESC
    `, idList)
    if err := db.Raw(sqlStr).Scan(&items).Error; err != nil {
        fmt.Println(err.Error())
        return nil, err
    }
    return
}
camera-service/controllers/camera.go
@@ -2,8 +2,11 @@
import (
    "bytes"
    "database/sql"
    "encoding/json"
    "fmt"
    "image"
    "path/filepath"
    // "fmt"
    // "io/ioutil"
@@ -27,6 +30,7 @@
    "basic.com/valib/logger.git"
    //"vamicro/camera-common/service/uniquelCoordinate"
    commonModel "vamicro/api-gateway/models"
    "vamicro/config"
    "vamicro/extend/util"
    scs "vamicro/scene-service/controllers"
@@ -1002,9 +1006,190 @@
}
/**
 *  根据视频id获取任务
 *  获取抓拍记录
 */
func (cc CameraController) GetTaskById(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
    tasks := "hello,world"
func (cc CameraController) GetRecord(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
    //绑定json和结构体
    info := models.RecordReq{}
    if err := c.BindJSON(&info); err != nil {
        return &bhomeclient.Reply{Success: false, Msg: "参数有误"}
    }
    page := info.Page
    pageSize := info.PageSize
    idsStr := info.Ids
    TaskIds := info.TaskIds
    videoIdStr := info.VideoIds
    Warning := info.Warning
    filter := "zh_desc_class != '' "
    //根据id获取记录
    var ids []string
    if len(idsStr) > 0 {
        for _, tmp := range idsStr {
            id, _ := strconv.ParseInt(tmp, 10, 64)
            if id > 0 {
                ids = append(ids, tmp)
            }
        }
        filter += fmt.Sprintf(" and %s in [%s]", "id", strings.Join(ids, ","))
    }
    //根据视频id查询
    var videoIds []string
    if len(videoIdStr) > 0 {
        for _, tmp := range videoIdStr {
            if len(tmp) > 0 {
                videoIds = append(videoIds, tmp)
            }
        }
        //根据id查询视频id
        var vids []int
        cameras, _ := models.GetCameraIds(videoIds)
        for _, camera := range cameras {
            if len(camera.Id) > 0 {
                vids = append(vids, camera.VideoId)
            }
        }
        idStr := make([]string, len(vids))
        for i, id := range vids {
            idStr[i] = strconv.Itoa(id)
        }
        filter += fmt.Sprintf(" and %s in [%s]", "video_point_id", strings.Join(idStr, ","))
    }
    //根据任务查询
    if len(TaskIds) > 0 {
        filter += fmt.Sprintf(" and array_contains(task_id, %d)", TaskIds[0])
    }
    //是否预警
    if Warning > 0 {
        filter += fmt.Sprintf(" and is_waning == %d", Warning)
    }
    //filter += " ORDER BY detect_time DESC"
    if len(filter) > 0 {
        logger.Error("filter err:", filter)
    }
    result, err := models.GetWithPage("smartobject", int64(page), int64(pageSize), filter)
    // 通用响应
    if err != nil {
        if err == sql.ErrNoRows {
            return &bhomeclient.Reply{Success: false, Msg: "数据为空"}
        } else {
            return &bhomeclient.Reply{Success: false, Msg: "获取列表失败"}
        }
    }
    //组织数据
    //重新组织数据
    basePath := commonModel.GetBasePath()
    tmpAllDate := make(map[string]interface{})
    tmpDate := make(map[string][]interface{})
    for _, v := range result.Items {
        sources := make(map[string]interface{}, 0)
        temp := models.StaticRecord{
            Id:              v.Id,
            TaskId:          v.TaskId,
            RuleId:          v.RuleId,
            EventLevelId:    v.EventLevelId,
            VideoPointId:    v.VideoPointId,
            DetectId:        v.DetectId,
            ImagePath:       v.ImagePath,
            VideoPath:       v.VideoPath,
            DetectTime:      v.DetectTime,
            IsWarning:       v.IsWarning,
            DetectNum:       v.DetectNum,
            TaskName:        v.TaskName,
            ZhDescClass:     v.ZhDescClass,
            EventLevelName:  v.EventLevelName,
            KnowledgeId:     v.KnowledgeId,
            Suggestion:      v.Suggestion,
            RiskDescription: v.RiskDescription,
            IsDesc:          v.IsDesc,
            PicMaxUrl:       []string{v.ImagePath},
            PicSrcUrl:       []string{v.ImagePath},
            PicWH:           models.PicWidHei{PicH: 720, PicW: 1280},
            VideoUrl:        v.VideoPath,
            AnalyServerName: "智能服务节点",
            Content:         v.CameraName,
            PicDate:         v.PicDate,
            LikeDate:        v.LikeDate,
        }
        //任务名称
        items, _ := models.GetTaskByIds(v.TaskId)
        temp.TaskNames = items
        //视频内容
        items4, _ := models.GetVideoById(v.VideoPointId)
        temp.VideoName = items4.Name
        temp.CameraAddr = items4.Addr
        //检查内容
        items2, _ := models.GetCheckByIds(v.DetectId)
        temp.CheckNames = items2
        //规则内容
        items3, _ := models.GetRuleByIds(v.RuleId)
        temp.RuleNames = items3
        //事件
        items5, _ := models.GetEventByIds(v.EventLevelId)
        temp.EventLevels = items5
        //知识库
        items6, _ := models.GetKnowledgeDocumentByIds(v.KnowledgeId)
        // 知识库路径
        var KnowledgePath = "/txt/zs/"
        for i := range items6 {
            filePath := filepath.Join(basePath + KnowledgePath + items6[i].Title)
            newPath := filepath.ToSlash(filePath)
            items6[i].FileUrl = newPath
        }
        temp.KnowledgeDocuments = items6
        sources["list"] = []interface{}{
            temp,
        }
        sources["activeObject"] = temp
        tmpDate["datalist"] = append(tmpDate["datalist"], sources)
    }
    tmpAllDate["datalist"] = tmpDate["datalist"]
    var pageRes = &models.PaginatedResult2{
        Pagination: result.Pagination,
        Items:      tmpAllDate,
    }
    return &bhomeclient.Reply{Success: true, Msg: "获取成功", Data: pageRes}
}
/**
 *获取督查任务
 */
func (cc CameraController) GetTasks(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply {
    //绑定json和结构体
    info := models.Video{}
    if err := c.BindJSON(&info); err != nil {
        return &bhomeclient.Reply{Success: false, Msg: "参数有误"}
    }
    var tasks []models.Task
    if len(info.VideoIds) > 0 {
        tasks, _ = models.GetListTask(info.VideoIds)
    }
    return &bhomeclient.Reply{Success: true, Msg: "获取成功", Data: tasks}
}
camera-service/main.go
@@ -41,6 +41,8 @@
func main() {
    models.Init()
    models.InitVectorDb()
    defer models.CloseDBClient()
    defer models.CloseDB()
    ctx, cancel := context.WithCancel(context.Background())
@@ -126,8 +128,10 @@
    funcMap[urlPrefix+"/camera/getSyncSensorData"] = cc.GetSyncSensorData
    funcMap[urlPrefix+"/camera/saveNotExistOrUpdate"] = cc.SaveNotExistOrUpdate
    //摄像机关联督查任务
    funcMap[urlPrefix+"/camera/getTasks"] = cc.GetTaskById
    //获取抓拍预警信息
    funcMap[urlPrefix+"/camera/getRecord"] = cc.GetRecord
    //获取任务根据摄像机ids
    funcMap[urlPrefix+"/camera/getTasks"] = cc.GetTasks
    var pubTopics []string
    for key, _ := range funcMap {
camera-service/models/db.go
@@ -1,11 +1,12 @@
package models
import (
    commonModels "vamicro/camera-common/models"
    "vamicro/config"
    "basic.com/valib/logger.git"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/sqlite"
    "basic.com/valib/logger.git"
    "vamicro/config"
    commonModels "vamicro/camera-common/models"
)
var db *gorm.DB
camera-service/models/milvus.go
New file
@@ -0,0 +1,63 @@
package models
import (
    "context"
    "fmt"
    "log"
    "vamicro/api-gateway/models"
    commonModels "vamicro/camera-common/models"
    "github.com/milvus-io/milvus-sdk-go/v2/client"
)
var dbClient *MilvusClient
// MilvusClient 封装Milvus操作的结构体
type MilvusClient struct {
    client client.Client
}
// NewMilvusClient 创建Milvus客户端
func NewMilvusClient(ctx context.Context, addr string) (*MilvusClient, error) {
    milvusClient, err := client.NewGrpcClient(ctx, addr)
    if err != nil {
        return nil, fmt.Errorf("failed to connect to Milvus: %v", err)
    }
    return &MilvusClient{client: milvusClient}, nil
}
// Close 关闭连接
func (m *MilvusClient) Close() error {
    return m.client.Close()
}
// 初始化milvus
func InitVectorDb() {
    // 连接到Milvus服务器
    ctx := context.Background()
    //milvusClient, err := NewMilvusClient(ctx, "192.168.1.232:19530")
    config := models.GetConfig()
    url := config.MilvusUrl
    milvusClient, err := NewMilvusClient(ctx, url)
    if err != nil {
        log.Fatal("Failed to connect to Milvus:", err)
    }
    //defer milvusClient.client.Close()
    fmt.Println("Successfully connected to Milvus")
    //初始化
    dbClient = milvusClient
    commonModels.SetClientDB(dbClient.client)
}
// GetDB ...
func GetDBCient() *MilvusClient {
    return dbClient
}
func CloseDBClient() {
    dbClient.Close()
}
sync-service/models/camera.go
@@ -1,11 +1,12 @@
package models
import (
    "basic.com/valib/logger.git"
    "fmt"
    "strconv"
    "strings"
    "vamicro/config"
    "basic.com/valib/logger.git"
)
const (
@@ -22,6 +23,12 @@
    Camera_Status_Doing = 2  //处理中
    Camera_Status_Other = -1 //其他情况
)
// 智查任务
type Task struct {
    TaskId   int64  `db:"task_id" json:"taskId"`
    TaskName string `db:"task_name" json:"taskName"`
}
type Camera struct {
    Id                    string           `gorm:"primary_key;column:id;type:varchar(100);unique;" json:"id"`
@@ -60,7 +67,7 @@
    Rtsp   string `json:"rtsp"`
}
func (camera *Camera) GetIdNameMap() (map[string]string) {
func (camera *Camera) GetIdNameMap() map[string]string {
    cameraEMap :=make(map[string]string,0)
    allCams, err := camera.FindAll()
    if err ==nil && allCams !=nil && len(allCams) >0 {
@@ -275,3 +282,23 @@
    return dbdel.RowsAffected, nil
}
// 查询列表数据
func GetListTask(ids []string) (items []Task, err error) {
    //idList := strings.Join(ids, ",")
    idList := "'" + strings.Join(ids, "','") + "'"
    // 主查询SQL
    //sqlStr := `select c.task_id, c.task_name from mal_task_video_link a left join mal_smart_task c on a.task_id = c.task_id where a.video_id in(?) ORDER BY a.task_id desc`
    sqlStr := fmt.Sprintf(`
        SELECT c.task_id, c.task_name
        FROM mal_task_video_link a
        LEFT JOIN mal_smart_task c ON a.task_id = c.task_id
        WHERE a.video_id IN (%s)
        ORDER BY a.task_id DESC
    `, idList)
    if err := db.Raw(sqlStr).Scan(&items).Error; err != nil {
        fmt.Println(err.Error())
        return nil, err
    }
    return
}
sync-service/service/cameraService.go
@@ -1,19 +1,19 @@
package service
import (
    "errors"
    "strconv"
    "vamicro/config"
    "vamicro/sync-service/models"
    "vamicro/sync-service/vo"
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/bhomedbapi.git"
    "basic.com/valib/logger.git"
    "errors"
    "github.com/satori/go.uuid"
    "strconv"
    "vamicro/sync-service/models"
    "vamicro/sync-service/vo"
    "vamicro/config"
    uuid "github.com/satori/go.uuid"
)
type CameraService struct {
}
func (sv CameraService) CameraAdd(camVo vo.CameraEditVo) (bool,models.Camera){
@@ -294,18 +294,23 @@
                    }
                }
            }
            fb, cgs := crApi.FindAllTaskById(cE.Id)
            if fb && cgs.Rules != nil {
                for _, g :=range cgs.Rules {
                    var crTask vo.CameraRunTask
            // fb, cgs := crApi.FindAllTaskById(cE.Id)
            // if fb && cgs.Rules != nil {
            //     for _, g :=range cgs.Rules {
            //         var crTask vo.CameraRunTask
                    crTask.HasRule = g.Enable
                    crTask.TaskName = g.SceneName
                    cri.Tasks = append(cri.Tasks, crTask)
                }
            } else {
                cri.Tasks = []vo.CameraRunTask{}
            }
            //         crTask.HasRule = g.Enable
            //         crTask.TaskName = g.SceneName
            //         cri.Tasks = append(cri.Tasks, crTask)
            //     }
            // } else {
            //     cri.Tasks = []vo.CameraRunTask{}
            // }
            //根据摄像机查询任务
            var Ids []string
            Ids = append(Ids, cE.Id)
            cri.AllTasks, _ = models.GetListTask(Ids)
            //处理摄像机的状态
            if cE.RunType == models.TYPE_RUNTYPE_POLL || cE.RunType == models.TYPE_RUNTYPE_REALTIME {
                if crApi.ExistRunningTask(cE.Id) {
sync-service/vo/camera.go
@@ -1,8 +1,9 @@
package vo
import (
    "basic.com/pubsub/protomsg.git"
    "vamicro/sync-service/models"
    "basic.com/pubsub/protomsg.git"
)
type CameraEditVo struct {
@@ -33,6 +34,7 @@
    models.Camera
    RunServerName         string                     `json:"runServerName"`
    Tasks                 []CameraRunTask         `json:"tasks"`
    AllTasks      []models.Task   `json:"allTasks"`
    Status                 int                     `json:"status"`
}