Przeglądaj źródła

temp:调通告警快照数据下载与数据库导入

Jerry Liang 1 rok temu
rodzic
commit
7c56e7cf1a

+ 90 - 0
service/cmd/gen/pgsql/alarm_snapshot.go

@@ -0,0 +1,90 @@
+package main
+
+import (
+	"fwh-toolbox-server/config"
+	"log"
+
+	"gorm.io/driver/postgres"
+	"gorm.io/gen"
+	"gorm.io/gorm"
+	"gorm.io/gorm/logger"
+)
+
+// Dynamic SQL
+type DataQuerier interface {
+	// SELECT * FROM @@table
+	// WHERE log_time BETWEEN @start AND @end
+	FilterByTimeRange(start, end string) ([]gen.T, error)
+}
+
+type FileRecordQuerier interface {
+	// SELECT state FROM @@table WHERE id = @id LIMIT 1
+	QueryState(id int64) (gen.M, error)
+}
+
+func main() {
+	// 指定生成代码的具体相对目录(相对于当前文件),默认:./query
+	// 默认生成需要使用WithContext之后才可以查询的代码,但可以通过设置gen.WithoutContext禁用该模式
+	g := gen.NewGenerator(gen.Config{
+		// 默认会在 OutPath 目录生成CRUD代码,并且同目录下生成 model 包
+		// 所以OutPath最终package不能设置为model,在有数据库表同步的情况下会产生冲突
+		// 若一定要使用,可以通过ModelPkgPath单独指定model package的名称
+		OutPath:      "./models/model_pgsql/query_alarm_snapshot",
+		ModelPkgPath: "model_alarm_snapshot",
+
+		// gen.WithoutContext: 禁用WithContext模式
+		// gen.WithDefaultQuery: 生成一个全局Query对象Q
+		// gen.WithQueryInterface: 生成Query接口
+		Mode: gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
+	})
+
+	// 通常复用项目中已有的SQL连接配置db(*grom.DB)
+	// 非必须,但如果需要复用连接是的gorm.Config或需要连接数据库同步表信息则必须设置
+	// gormdb, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
+	// g.UseDB(gormdb) // reuse your gorm db
+	cfg, _ := config.LoadConfig()
+	db, err := InitPostgreSQL(cfg.PostgresDSN)
+	if err != nil {
+		log.Printf("PgSql Database Open Filed!\n%s\n", err.Error())
+		return
+	}
+
+	// 切换到指定 schema
+	db.Exec("SET search_path TO alarm_snapshot")
+
+	g.UseDB(db)
+
+	// 从连接的数据库为所有表生成Model结构体和CRUD代码
+	// g.ApplyBasic(g.GenerateAllTable()...)
+	// 也可以手动指定需要生成代码的数据表
+	SiteAlarmSnapshotDataModel := g.GenerateModelAs("alarm_snapshot.site_alarm_snapshot_data", "SiteAlarmSnapshotData")
+	SiteAlarmSnapshotFileRecordModel := g.GenerateModelAs("alarm_snapshot.site_alarm_snapshot_file_record", "SiteAlarmSnapshotFileRecord")
+	g.ApplyBasic(SiteAlarmSnapshotDataModel, SiteAlarmSnapshotFileRecordModel)
+	// Generate basic type-safe DAO API for struct `model.User` following conventions
+	// g.ApplyBasic(model.User{})
+
+	// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
+	// g.ApplyInterface(func(Querier) {}, model.User{}, model.Company{})
+	g.ApplyInterface(func(DataQuerier) {}, SiteAlarmSnapshotDataModel)
+	g.ApplyInterface(func(FileRecordQuerier) {}, SiteAlarmSnapshotFileRecordModel)
+
+	// Set Default DIY TableName method for the generated all struct
+	g.WithOpts(gen.WithMethod(gen.DefaultMethodTableWithNamer))
+
+	// Generate the code
+	g.Execute()
+}
+
+func InitPostgreSQL(dsn string) (*gorm.DB, error) {
+	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
+		Logger: logger.Default.LogMode(logger.Info),
+	})
+	if err != nil {
+		log.Printf("failed to connect to PostgreSQL: %v", err)
+		return nil, err
+	}
+
+	// 自动迁移
+	// db.AutoMigrate(&models.User{}, …)
+	return db, nil
+}

+ 582 - 0
service/function/SnapFile/parserSnapFile.go

@@ -0,0 +1,582 @@
+package function
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/sigurn/crc16"
+	"go.uber.org/zap"
+)
+
+var (
+	gCrc16Table = crc16.MakeTable(crc16.CRC16_MODBUS) // 选择 Modbus
+)
+
+/************** 快照文件结构体 **************/
+
+type SegmentOfCIBuffer struct {
+	Len       uint16 `json:"len"`
+	Crc16     uint16 `json:"crc16"`
+	TimeStamp uint32 `json:"timeStamp"`
+}
+
+type EquipmentSn struct {
+	Len  int32  `json:"len"`
+	Data string `json:"data"`
+}
+
+type HwfAlarmDataItem struct {
+	AlarmCode uint16 `json:"alarmCode"` //故障编码
+	Level     uint8  `json:"level"`     //故障等级
+	NeedSave  uint8  `json:"needSave"`  //该故障是否需要保存
+	TimeStart uint32 `json:"timeStart"` //该故障的开始时间
+}
+
+type AlarmList struct {
+	Count    int32              `json:"count"`
+	DataItem []HwfAlarmDataItem `json:"dataItem"`
+}
+
+type SnapXid struct {
+	IdType   uint8  `json:"idType"`   // PID : 1, VID : 0
+	DataType uint8  `json:"dataType"` // 0-UINT32 1-INT32 2-FLOAT 3-PCHAR
+	ID       uint16 `json:"id"`       // 在PID和VID配置表中对应的id, 可基于此找到对应的PID/VID
+}
+
+type XidDataType interface {
+	uint32 | int32 | float32 | string
+}
+
+type XidSegmentHeader struct {
+	Xid SnapXid `json:"xid"`
+	Len int32   `json:"len"` // DATA 的长度
+}
+
+type XidSegment[T XidDataType] struct {
+	Header XidSegmentHeader `json:"header"`
+	Data   T                `json:"data"` // DATA 取决于 SnapXid.DataType
+}
+
+type XidSegmentType interface {
+	XidSegment[uint32] | XidSegment[int32] | XidSegment[float32] | XidSegment[string]
+}
+
+type XidSegmentIf interface {
+	GetXid() any
+	CreateXid(v any) error
+}
+
+func (x *XidSegment[T]) GetXid() any {
+	return x
+}
+
+func (x *XidSegment[T]) CreateXid(v any) error {
+	val, ok := v.(XidSegment[T])
+	if !ok {
+		return fmt.Errorf("invalid type: expected %T", x.Data)
+	}
+	*x = val
+	return nil
+}
+
+type InfoSegmentPackage struct {
+	Header  SegmentOfCIBuffer `json:"header"`
+	HeadStr [4]byte           `json:"headerStr"` // "HEAD"
+	GateSn  EquipmentSn       `json:"aGateSn"`
+	PowerSn EquipmentSn       `json:"aPowerSn"`
+	Alarm   AlarmList         `json:"alarm"`
+}
+
+type XidSegmentPackage struct {
+	Header  SegmentOfCIBuffer `json:"header"`
+	XidList []XidSegmentIf    `json:"xidList"`
+}
+
+type SnapFilePackage struct {
+	Info InfoSegmentPackage `json:"info"`
+	Xid  XidSegmentPackage  `json:"xid"`
+}
+
+/************** 快照JSON数据结构体 **************/
+
+type AlarmCodeInfo struct {
+	AlarmCode uint16 `json:"alarmCode"` //故障编码
+	Level     uint8  `json:"level"`     //故障等级
+	TimeStart uint32 `json:"timeStart"` //该故障的开始时间
+}
+
+type AlarmInfoJson struct {
+	Total     int32           `json:"total"`
+	AlarmList []AlarmCodeInfo `json:"alarmList"`
+}
+
+type XID[T XidDataType] struct {
+	ID   uint16 `json:"id"`
+	Type string `json:"type"` // "PID" or "VID"
+	// Macro string `json:"macro"` // 代码中的宏名称
+	// Brief string `json:"brief"` // 简介
+	Data T `json:"data"`
+}
+
+type XidIf interface {
+	GetXid() any
+	CreateXid(v any) error
+}
+
+func (x *XID[T]) GetXid() any {
+	return x
+}
+
+func (x *XID[T]) CreateXid(v any) error {
+	val, ok := v.(XID[T])
+	if !ok {
+		return fmt.Errorf("invalid type: expected %T", x.Data)
+	}
+	*x = val
+	return nil
+}
+
+type SnapInfoJson struct {
+	XidList []XidIf `json:"xidList"`
+}
+
+type SnapJson struct {
+	TimeStamp uint32        `json:"timeStamp"`
+	SiteSn    string        `json:"aGateSn"`
+	PowerSn   []string      `json:"aPowerSn"`
+	AlarmInfo AlarmInfoJson `json:"alarmInfo"`
+	SnapInfo  SnapInfoJson  `json:"snapInfo"`
+}
+
+/************** 解析数据结构体 **************/
+
+type ParserAlarmSnapshot struct {
+	FilePath    string            `json:"filePath"`
+	FilePackage []SnapFilePackage `json:"filePackage"`
+	SnapJson    []SnapJson        `json:"snapJson"`
+}
+
+type SegmentDataType struct {
+	Header SegmentOfCIBuffer
+	Data   []byte
+}
+
+type SegmentType struct {
+	InfoSegment SegmentDataType
+	XidSegment  SegmentDataType
+	BinData     []byte
+}
+
+// 创建ParserAlarmSnapshot结果体必须使用函数NewParserAlarmSnapshot
+func NewParserAlarmSnapshot(filePath string) *ParserAlarmSnapshot {
+	return &ParserAlarmSnapshot{
+		FilePath: filePath,
+	}
+}
+
+func (parser *ParserAlarmSnapshot) ParserSnapFile() error {
+	binData, err := os.ReadFile(parser.FilePath)
+	if err != nil {
+		zap.L().Error("snap文件读取失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+		return err
+	}
+
+	var newBinData []byte
+	// 寻找第一个有效 "HEAD" 的位置,生成新的连续数据段
+	pRemainingData := binData
+	startIdx := int(0)
+	for {
+		idx := bytes.Index(pRemainingData, []byte("HEAD"))
+		if idx == -1 {
+			fmt.Println("未找到 HEAD 结束")
+			break
+		} else if idx < 8 {
+			// 数据开头不完整,跳到下一个数据
+			pRemainingData = pRemainingData[idx+4:]
+			startIdx = startIdx + idx + 4
+			continue
+		}
+
+		// 计算前8个字节的开始位置
+		start := idx - 8
+		startIdx = startIdx + start
+
+		// 检查有效性
+		_, err := parser.checkSnapData(pRemainingData[start:])
+		if err != nil {
+			fmt.Println("第一个数据段无效")
+			continue
+		}
+
+		pHeaderData := binData[:startIdx]
+		pRemainingData = pRemainingData[start:]
+
+		// 重新拼接循环数据
+		newBinData = make([]byte, len(binData))
+		copy(newBinData, pRemainingData)
+		copy(newBinData[len(pRemainingData):], pHeaderData)
+
+		break
+	}
+
+	// 声明一个切片,用来存放多个 Segment
+	var segmentList []*SegmentType
+
+	pNewBinData := newBinData
+	pBinIdx := startIdx
+	// 生成数据段列表
+	for {
+		// 检查 HEAD 头
+		if !bytes.Equal(pNewBinData[8:8+4], []byte("HEAD")) {
+			// 往下寻找新的 HEAD 头
+			idx := bytes.Index(pNewBinData, []byte("HEAD"))
+			if idx == -1 {
+				fmt.Println("未找到 HEAD 结束")
+				break
+			} else if idx < 8 {
+				// 数据开头不完整,跳到下一个数据
+				pNewBinData = pNewBinData[idx+4:]
+				pBinIdx = pBinIdx + idx + 4
+				continue
+			}
+
+			pNewBinData = pNewBinData[idx-8:]
+			pBinIdx = pBinIdx + idx - 8
+		}
+
+		// 检查有效性
+		segData, err := parser.checkSnapData(pNewBinData)
+		if err != nil {
+			fmt.Printf("数据段格式错误 index: %d\n", pBinIdx)
+			// 数据开头不完整,跳到下一个数据
+			pNewBinData = pNewBinData[8+4:]
+			pBinIdx = pBinIdx + 8 + 4
+			continue
+		}
+
+		segmentList = append(segmentList, segData)
+
+		pNewBinData = pNewBinData[len(segData.BinData):]
+		pBinIdx = pBinIdx + len(segData.BinData)
+		if len(pNewBinData) == 0 {
+			// 数据刚好处理完,无剩余无效数据
+			break
+		}
+	}
+
+	// 处理每个数据段
+	for _, pData := range segmentList {
+		var filePackage SnapFilePackage
+		var snapJson SnapJson
+		if err := parser.parserInfoSegment(&filePackage, &snapJson, pData.InfoSegment); err != nil {
+			return err
+		}
+
+		if err := parser.parserXidSegment(&filePackage, &snapJson, pData.XidSegment); err != nil {
+			return err
+		}
+
+		parser.FilePackage = append(parser.FilePackage, filePackage)
+		parser.SnapJson = append(parser.SnapJson, snapJson)
+	}
+
+	return nil
+}
+
+// 检验数据的正确性和完整性
+// 1、校验两段SegmentOfCIBuffer的CRC
+// 2、同时检查数据长度是否完整
+func (parser *ParserAlarmSnapshot) checkSnapData(binData []byte) (*SegmentType, error) {
+	// 处理数据段一
+	var infoHeader SegmentOfCIBuffer
+	headerSize := binary.Size(infoHeader)
+	if len(binData) < headerSize {
+		zap.L().Error("snap文件长度异常", zap.String("FilePath", parser.FilePath))
+		return nil, fmt.Errorf("snap文件长度异常")
+	}
+
+	headerRaw := binData[:headerSize] // 头部数据
+	headerReader := bytes.NewReader(headerRaw)
+
+	if err := binary.Read(headerReader, binary.LittleEndian, &infoHeader); err != nil {
+		zap.L().Error("snap文件读取转换失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+		return nil, err
+	}
+
+	// 获取数据长度
+	infoBufferLen := int(infoHeader.Len)
+	if len(binData[headerSize:]) < infoBufferLen {
+		zap.L().Error("snap文件长度异常", zap.String("FilePath", parser.FilePath))
+		return nil, fmt.Errorf("snap文件长度异常")
+	}
+
+	// Info Buffer
+	pInfoBufferRaw := binData[headerSize:]
+	pInfoBufferRaw = pInfoBufferRaw[:infoBufferLen]
+
+	// 校验CRC
+	bufferCrc := infoHeader.Crc16
+	calcCrc := crc16.Checksum(pInfoBufferRaw, gCrc16Table)
+	if bufferCrc != calcCrc {
+		zap.L().Error("snap文件CRC校验失败", zap.String("FilePath", parser.FilePath))
+		return nil, fmt.Errorf("snap文件CRC校验失败")
+	}
+
+	pInfoBufferRaw = pInfoBufferRaw[4:] // 排除 “HEAD” 头
+
+	// 处理数据段二
+	var xidHeader SegmentOfCIBuffer
+	headerSize = binary.Size(xidHeader)
+	secBinData := binData[headerSize+infoBufferLen:]
+	if len(secBinData) < headerSize {
+		zap.L().Error("snap文件长度异常", zap.String("FilePath", parser.FilePath))
+		return nil, fmt.Errorf("snap文件长度异常")
+	}
+
+	headerRaw = secBinData[:headerSize] // 头部数据
+	headerReader = bytes.NewReader(headerRaw)
+
+	if err := binary.Read(headerReader, binary.LittleEndian, &xidHeader); err != nil {
+		zap.L().Error("snap文件读取转换失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+		return nil, err
+	}
+
+	// 获取数据长度
+	xidBufferLen := int(xidHeader.Len)
+	if len(secBinData[headerSize:]) < xidBufferLen {
+		zap.L().Error("snap文件长度异常", zap.String("FilePath", parser.FilePath))
+		return nil, fmt.Errorf("snap文件长度异常")
+	}
+
+	// Xid Buffer
+	pXidBufferRaw := secBinData[headerSize:]
+	pXidBufferRaw = pXidBufferRaw[:xidBufferLen]
+
+	// 校验CRC
+	bufferCrc = xidHeader.Crc16
+	calcCrc = crc16.Checksum(pXidBufferRaw, gCrc16Table)
+	if bufferCrc != calcCrc {
+		zap.L().Error("snap文件CRC校验失败", zap.String("FilePath", parser.FilePath))
+		return nil, fmt.Errorf("snap文件CRC校验失败")
+	}
+
+	// 计算数据总长度
+	dataLen := headerSize + infoBufferLen + headerSize + xidBufferLen
+
+	return &SegmentType{
+		InfoSegment: SegmentDataType{
+			Header: infoHeader,
+			Data:   pInfoBufferRaw,
+		},
+		XidSegment: SegmentDataType{
+			Header: xidHeader,
+			Data:   pXidBufferRaw,
+		},
+		BinData: binData[:dataLen],
+	}, nil
+}
+
+func (parser *ParserAlarmSnapshot) parserInfoSegment(pkg *SnapFilePackage, snapJson *SnapJson, segData SegmentDataType) error {
+	header := segData.Header
+	pkg.Info.Header = header
+
+	// 填充JSON数据
+	snapJson.TimeStamp = header.TimeStamp
+
+	pInfoBufferRaw := segData.Data // Info Buffer
+
+	// 写入数据头标签 HEAD
+	copy(pkg.Info.HeadStr[:], "HEAD")
+
+	equipmentSnLenReader := bytes.NewReader(pInfoBufferRaw[:binary.Size(pkg.Info.GateSn.Len)])
+	if err := binary.Read(equipmentSnLenReader, binary.LittleEndian, &pkg.Info.GateSn.Len); err != nil {
+		zap.L().Error("snap文件读取设备aGate SN长度失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+		return err
+	}
+	if pkg.Info.GateSn.Len < 0 {
+		zap.L().Error("snap文件读取设备aGate SN长度小于0", zap.String("len", strconv.Itoa(int(pkg.Info.GateSn.Len))), zap.String("FilePath", parser.FilePath))
+		return fmt.Errorf("snap文件读取设备aGate SN长度小于0")
+	}
+	pInfoBufferRaw = pInfoBufferRaw[binary.Size(pkg.Info.GateSn.Len):]
+
+	// 提取aGate SN
+	equipmentSnDataRaw := pInfoBufferRaw[:pkg.Info.GateSn.Len]
+	pkg.Info.GateSn.Data = string(equipmentSnDataRaw)
+	snapJson.SiteSn = string(equipmentSnDataRaw)
+
+	pInfoBufferRaw = pInfoBufferRaw[pkg.Info.GateSn.Len:]
+
+	equipmentSnLenReader = bytes.NewReader(pInfoBufferRaw[:binary.Size(pkg.Info.PowerSn.Len)])
+	if err := binary.Read(equipmentSnLenReader, binary.LittleEndian, &pkg.Info.PowerSn.Len); err != nil {
+		zap.L().Error("snap文件读取设备aPower SN长度失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+		return err
+	}
+	if pkg.Info.PowerSn.Len < 0 {
+		zap.L().Error("snap文件读取设备aPower SN长度小于0", zap.String("len", strconv.Itoa(int(pkg.Info.PowerSn.Len))), zap.String("FilePath", parser.FilePath))
+		return fmt.Errorf("snap文件读取设备aPower SN长度小于0")
+	}
+	pInfoBufferRaw = pInfoBufferRaw[binary.Size(pkg.Info.PowerSn.Len):]
+
+	// 提取aPower SN
+	equipmentSnDataRaw = pInfoBufferRaw[:pkg.Info.PowerSn.Len]
+	pkg.Info.PowerSn.Data = string(equipmentSnDataRaw)
+	snapJson.PowerSn = strings.Split(string(equipmentSnDataRaw), ",")
+
+	pInfoBufferRaw = pInfoBufferRaw[pkg.Info.PowerSn.Len:]
+
+	alarmCountReader := bytes.NewReader(pInfoBufferRaw[:binary.Size(pkg.Info.Alarm.Count)])
+	if err := binary.Read(alarmCountReader, binary.LittleEndian, &pkg.Info.Alarm.Count); err != nil {
+		zap.L().Error("snap文件读取告警数量失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+		return err
+	}
+	snapJson.AlarmInfo.Total = pkg.Info.Alarm.Count
+
+	pInfoBufferRaw = pInfoBufferRaw[binary.Size(pkg.Info.Alarm.Count):]
+
+	for i := 0; i < int(pkg.Info.Alarm.Count); i++ {
+		var alarmDataItem HwfAlarmDataItem
+		alarmDataItemReader := bytes.NewBuffer(pInfoBufferRaw[:binary.Size(alarmDataItem)])
+		if err := binary.Read(alarmDataItemReader, binary.LittleEndian, &alarmDataItem); err != nil {
+			zap.L().Error("snap文件读取告警项失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+			return err
+		}
+		pkg.Info.Alarm.DataItem = append(pkg.Info.Alarm.DataItem, alarmDataItem)
+		snapJson.AlarmInfo.AlarmList = append(snapJson.AlarmInfo.AlarmList, AlarmCodeInfo{
+			AlarmCode: alarmDataItem.AlarmCode,
+			Level:     alarmDataItem.Level,
+			TimeStart: alarmDataItem.TimeStart,
+		})
+
+		pInfoBufferRaw = pInfoBufferRaw[binary.Size(alarmDataItem):]
+	}
+
+	return nil
+}
+
+func (parser *ParserAlarmSnapshot) parserXidSegment(pkg *SnapFilePackage, snapJson *SnapJson, segData SegmentDataType) error {
+	header := segData.Header
+
+	pkg.Xid.Header = header
+
+	pXidBufferRaw := segData.Data // Xid Buffer
+
+	for len(pXidBufferRaw) > 0 {
+		var xidHeader XidSegmentHeader
+		snapXidHeaderReader := bytes.NewReader(pXidBufferRaw[:binary.Size(xidHeader)])
+		if err := binary.Read(snapXidHeaderReader, binary.LittleEndian, &xidHeader); err != nil {
+			zap.L().Error("snap文件读取XID数据头失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+			return err
+		}
+
+		pXidBufferRaw = pXidBufferRaw[binary.Size(xidHeader):]
+
+		var IdTypeStr string
+		switch xidHeader.Xid.IdType {
+		case 0:
+			IdTypeStr = "VID"
+		case 1:
+			IdTypeStr = "PID"
+		default:
+			zap.L().Error("snap文件读取XID数据ID类型错误", zap.String("id_type", strconv.Itoa(int(xidHeader.Xid.IdType))), zap.String("FilePath", parser.FilePath))
+			return fmt.Errorf("snap文件读取XID数据ID类型错误")
+		}
+
+		switch xidHeader.Xid.DataType {
+		case 0:
+			var xid XidSegment[uint32]
+			xid.Header = xidHeader
+			var data uint32
+			if xidHeader.Len != int32(binary.Size(data)) {
+				zap.L().Error("snap文件读取XID数据长度错误", zap.String("type", strconv.Itoa(int(xidHeader.Xid.DataType))), zap.String("len", strconv.Itoa(int(xidHeader.Len))), zap.String("FilePath", parser.FilePath))
+				return fmt.Errorf("snap文件读取XID数据长度错误")
+			}
+			dataReader := bytes.NewReader(pXidBufferRaw[:binary.Size(data)])
+			if err := binary.Read(dataReader, binary.LittleEndian, &data); err != nil {
+				zap.L().Error("snap文件读取XID数据失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+				return err
+			}
+			xid.Data = data
+			pkg.Xid.XidList = append(pkg.Xid.XidList, &xid)
+
+			// 赋值到JSON数据
+			snapJson.SnapInfo.XidList = append(snapJson.SnapInfo.XidList, &XID[uint32]{
+				ID:   xidHeader.Xid.ID,
+				Type: IdTypeStr,
+				Data: data,
+			})
+		case 1:
+			var xid XidSegment[int32]
+			xid.Header = xidHeader
+			var data int32
+			if xidHeader.Len != int32(binary.Size(data)) {
+				zap.L().Error("snap文件读取XID数据长度错误", zap.String("type", strconv.Itoa(int(xidHeader.Xid.DataType))), zap.String("len", strconv.Itoa(int(xidHeader.Len))), zap.String("FilePath", parser.FilePath))
+				return fmt.Errorf("snap文件读取XID数据长度错误")
+			}
+			dataReader := bytes.NewReader(pXidBufferRaw[:binary.Size(data)])
+			if err := binary.Read(dataReader, binary.LittleEndian, &data); err != nil {
+				zap.L().Error("snap文件读取XID数据失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+				return err
+			}
+			xid.Data = data
+			pkg.Xid.XidList = append(pkg.Xid.XidList, &xid)
+
+			// 赋值到JSON数据
+			snapJson.SnapInfo.XidList = append(snapJson.SnapInfo.XidList, &XID[int32]{
+				ID:   xidHeader.Xid.ID,
+				Type: IdTypeStr,
+				Data: data,
+			})
+		case 2:
+			var xid XidSegment[float32]
+			xid.Header = xidHeader
+			var data float32
+			if xidHeader.Len != int32(binary.Size(data)) {
+				zap.L().Error("snap文件读取XID数据长度错误", zap.String("type", strconv.Itoa(int(xidHeader.Xid.DataType))), zap.String("len", strconv.Itoa(int(xidHeader.Len))), zap.String("FilePath", parser.FilePath))
+				return fmt.Errorf("snap文件读取XID数据长度错误")
+			}
+			dataReader := bytes.NewReader(pXidBufferRaw[:binary.Size(data)])
+			if err := binary.Read(dataReader, binary.LittleEndian, &data); err != nil {
+				zap.L().Error("snap文件读取XID数据失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+				return err
+			}
+			xid.Data = data
+			pkg.Xid.XidList = append(pkg.Xid.XidList, &xid)
+
+			// 赋值到JSON数据
+			snapJson.SnapInfo.XidList = append(snapJson.SnapInfo.XidList, &XID[float32]{
+				ID:   xidHeader.Xid.ID,
+				Type: IdTypeStr,
+				Data: data,
+			})
+		case 3:
+			var xid XidSegment[string]
+			xid.Header = xidHeader
+			strBytes := make([]byte, xidHeader.Len)
+			dataReader := bytes.NewReader(pXidBufferRaw[:xidHeader.Len])
+			if err := binary.Read(dataReader, binary.LittleEndian, &strBytes); err != nil {
+				zap.L().Error("snap文件读取XID数据失败", zap.String("err", err.Error()), zap.String("FilePath", parser.FilePath))
+				return err
+			}
+			xid.Data = string(strBytes)
+			pkg.Xid.XidList = append(pkg.Xid.XidList, &xid)
+
+			// 赋值到JSON数据
+			snapJson.SnapInfo.XidList = append(snapJson.SnapInfo.XidList, &XID[string]{
+				ID:   xidHeader.Xid.ID,
+				Type: IdTypeStr,
+				Data: xid.Data,
+			})
+		default:
+			zap.L().Error("snap文件读取XID类型错误", zap.String("type", strconv.Itoa(int(xidHeader.Xid.DataType))), zap.String("FilePath", parser.FilePath))
+			return fmt.Errorf("snap文件读取XID类型错误")
+		}
+
+		pXidBufferRaw = pXidBufferRaw[xidHeader.Len:]
+	}
+
+	return nil
+}

+ 26 - 0
service/models/model_pgsql/model_alarm_snapshot/alarm_snapshot.site_alarm_snapshot_data.gen.go

@@ -0,0 +1,26 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model_alarm_snapshot
+
+import (
+	"time"
+)
+
+const TableNameSiteAlarmSnapshotData = "alarm_snapshot.site_alarm_snapshot_data"
+
+// SiteAlarmSnapshotData mapped from table <alarm_snapshot.site_alarm_snapshot_data>
+type SiteAlarmSnapshotData struct {
+	ID           int64     `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	Sn           string    `gorm:"column:sn;not null;comment:站点SN" json:"sn"`                             // 站点SN
+	FileRecordID int64     `gorm:"column:file_record_id;not null;comment:文件记录表的id" json:"file_record_id"` // 文件记录表的id
+	LogTime      time.Time `gorm:"column:log_time;not null;comment:日志记录时间(UTC时间)" json:"log_time"`        // 日志记录时间(UTC时间)
+	JSONData     string    `gorm:"column:json_data;not null;comment:json数据(二进制)" json:"json_data"`        // json数据(二进制)
+	ZoneInfo     string    `gorm:"column:zone_info;comment:时区信息" json:"zone_info"`                        // 时区信息
+}
+
+// TableName SiteAlarmSnapshotData's table name
+func (*SiteAlarmSnapshotData) TableName() string {
+	return TableNameSiteAlarmSnapshotData
+}

+ 30 - 0
service/models/model_pgsql/model_alarm_snapshot/alarm_snapshot.site_alarm_snapshot_file_record.gen.go

@@ -0,0 +1,30 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package model_alarm_snapshot
+
+import (
+	"time"
+)
+
+const TableNameSiteAlarmSnapshotFileRecord = "alarm_snapshot.site_alarm_snapshot_file_record"
+
+// SiteAlarmSnapshotFileRecord mapped from table <alarm_snapshot.site_alarm_snapshot_file_record>
+type SiteAlarmSnapshotFileRecord struct {
+	ID           int64     `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"`
+	CodeType     int32     `gorm:"column:code_type" json:"code_type"`
+	FileName     string    `gorm:"column:file_name;not null" json:"file_name"`
+	FileURL      string    `gorm:"column:file_url;not null" json:"file_url"`
+	Sn           string    `gorm:"column:sn;not null;comment:site SN" json:"sn"`                                                    // site SN
+	LogTime      time.Time `gorm:"column:log_time;not null;comment:日志记录日期(format YYYY-MM-DD)" json:"log_time"`                      // 日志记录日期(format YYYY-MM-DD)
+	StartTime    time.Time `gorm:"column:start_time;not null;comment:记录开始时间(format YYYY-MM-DD HH:mm:SS)" json:"start_time"`         // 记录开始时间(format YYYY-MM-DD HH:mm:SS)
+	EndTime      time.Time `gorm:"column:end_time;not null;comment:记录结束时间(format YYYY-MM-DD HH:mm:SS)" json:"end_time"`             // 记录结束时间(format YYYY-MM-DD HH:mm:SS)
+	CompleteTime time.Time `gorm:"column:complete_time;not null;comment:记录上传完成时间(format YYYY-MM-DD HH:mm:SS)" json:"complete_time"` // 记录上传完成时间(format YYYY-MM-DD HH:mm:SS)
+	State        int16     `gorm:"column:state;not null;comment:文件分析状态(0-分析中;1-完成;-1-失败)" json:"state"`                             // 文件分析状态(0-分析中;1-完成;-1-失败)
+}
+
+// TableName SiteAlarmSnapshotFileRecord's table name
+func (*SiteAlarmSnapshotFileRecord) TableName() string {
+	return TableNameSiteAlarmSnapshotFileRecord
+}

+ 435 - 0
service/models/model_pgsql/query_alarm_snapshot/alarm_snapshot.site_alarm_snapshot_data.gen.go

@@ -0,0 +1,435 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query_alarm_snapshot
+
+import (
+	"context"
+	"database/sql"
+	"strings"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"fwh-toolbox-server/models/model_pgsql/model_alarm_snapshot"
+)
+
+func newSiteAlarmSnapshotData(db *gorm.DB, opts ...gen.DOOption) siteAlarmSnapshotData {
+	_siteAlarmSnapshotData := siteAlarmSnapshotData{}
+
+	_siteAlarmSnapshotData.siteAlarmSnapshotDataDo.UseDB(db, opts...)
+	_siteAlarmSnapshotData.siteAlarmSnapshotDataDo.UseModel(&model_alarm_snapshot.SiteAlarmSnapshotData{})
+
+	tableName := _siteAlarmSnapshotData.siteAlarmSnapshotDataDo.TableName()
+	_siteAlarmSnapshotData.ALL = field.NewAsterisk(tableName)
+	_siteAlarmSnapshotData.ID = field.NewInt64(tableName, "id")
+	_siteAlarmSnapshotData.Sn = field.NewString(tableName, "sn")
+	_siteAlarmSnapshotData.FileRecordID = field.NewInt64(tableName, "file_record_id")
+	_siteAlarmSnapshotData.LogTime = field.NewTime(tableName, "log_time")
+	_siteAlarmSnapshotData.JSONData = field.NewString(tableName, "json_data")
+	_siteAlarmSnapshotData.ZoneInfo = field.NewString(tableName, "zone_info")
+
+	_siteAlarmSnapshotData.fillFieldMap()
+
+	return _siteAlarmSnapshotData
+}
+
+type siteAlarmSnapshotData struct {
+	siteAlarmSnapshotDataDo siteAlarmSnapshotDataDo
+
+	ALL          field.Asterisk
+	ID           field.Int64
+	Sn           field.String // 站点SN
+	FileRecordID field.Int64  // 文件记录表的id
+	LogTime      field.Time   // 日志记录时间(UTC时间)
+	JSONData     field.String // json数据(二进制)
+	ZoneInfo     field.String // 时区信息
+
+	fieldMap map[string]field.Expr
+}
+
+func (s siteAlarmSnapshotData) Table(newTableName string) *siteAlarmSnapshotData {
+	s.siteAlarmSnapshotDataDo.UseTable(newTableName)
+	return s.updateTableName(newTableName)
+}
+
+func (s siteAlarmSnapshotData) As(alias string) *siteAlarmSnapshotData {
+	s.siteAlarmSnapshotDataDo.DO = *(s.siteAlarmSnapshotDataDo.As(alias).(*gen.DO))
+	return s.updateTableName(alias)
+}
+
+func (s *siteAlarmSnapshotData) updateTableName(table string) *siteAlarmSnapshotData {
+	s.ALL = field.NewAsterisk(table)
+	s.ID = field.NewInt64(table, "id")
+	s.Sn = field.NewString(table, "sn")
+	s.FileRecordID = field.NewInt64(table, "file_record_id")
+	s.LogTime = field.NewTime(table, "log_time")
+	s.JSONData = field.NewString(table, "json_data")
+	s.ZoneInfo = field.NewString(table, "zone_info")
+
+	s.fillFieldMap()
+
+	return s
+}
+
+func (s *siteAlarmSnapshotData) WithContext(ctx context.Context) ISiteAlarmSnapshotDataDo {
+	return s.siteAlarmSnapshotDataDo.WithContext(ctx)
+}
+
+func (s siteAlarmSnapshotData) TableName() string { return s.siteAlarmSnapshotDataDo.TableName() }
+
+func (s siteAlarmSnapshotData) Alias() string { return s.siteAlarmSnapshotDataDo.Alias() }
+
+func (s siteAlarmSnapshotData) Columns(cols ...field.Expr) gen.Columns {
+	return s.siteAlarmSnapshotDataDo.Columns(cols...)
+}
+
+func (s *siteAlarmSnapshotData) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := s.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (s *siteAlarmSnapshotData) fillFieldMap() {
+	s.fieldMap = make(map[string]field.Expr, 6)
+	s.fieldMap["id"] = s.ID
+	s.fieldMap["sn"] = s.Sn
+	s.fieldMap["file_record_id"] = s.FileRecordID
+	s.fieldMap["log_time"] = s.LogTime
+	s.fieldMap["json_data"] = s.JSONData
+	s.fieldMap["zone_info"] = s.ZoneInfo
+}
+
+func (s siteAlarmSnapshotData) clone(db *gorm.DB) siteAlarmSnapshotData {
+	s.siteAlarmSnapshotDataDo.ReplaceConnPool(db.Statement.ConnPool)
+	return s
+}
+
+func (s siteAlarmSnapshotData) replaceDB(db *gorm.DB) siteAlarmSnapshotData {
+	s.siteAlarmSnapshotDataDo.ReplaceDB(db)
+	return s
+}
+
+type siteAlarmSnapshotDataDo struct{ gen.DO }
+
+type ISiteAlarmSnapshotDataDo interface {
+	gen.SubQuery
+	Debug() ISiteAlarmSnapshotDataDo
+	WithContext(ctx context.Context) ISiteAlarmSnapshotDataDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ISiteAlarmSnapshotDataDo
+	WriteDB() ISiteAlarmSnapshotDataDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ISiteAlarmSnapshotDataDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ISiteAlarmSnapshotDataDo
+	Not(conds ...gen.Condition) ISiteAlarmSnapshotDataDo
+	Or(conds ...gen.Condition) ISiteAlarmSnapshotDataDo
+	Select(conds ...field.Expr) ISiteAlarmSnapshotDataDo
+	Where(conds ...gen.Condition) ISiteAlarmSnapshotDataDo
+	Order(conds ...field.Expr) ISiteAlarmSnapshotDataDo
+	Distinct(cols ...field.Expr) ISiteAlarmSnapshotDataDo
+	Omit(cols ...field.Expr) ISiteAlarmSnapshotDataDo
+	Join(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotDataDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotDataDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotDataDo
+	Group(cols ...field.Expr) ISiteAlarmSnapshotDataDo
+	Having(conds ...gen.Condition) ISiteAlarmSnapshotDataDo
+	Limit(limit int) ISiteAlarmSnapshotDataDo
+	Offset(offset int) ISiteAlarmSnapshotDataDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ISiteAlarmSnapshotDataDo
+	Unscoped() ISiteAlarmSnapshotDataDo
+	Create(values ...*model_alarm_snapshot.SiteAlarmSnapshotData) error
+	CreateInBatches(values []*model_alarm_snapshot.SiteAlarmSnapshotData, batchSize int) error
+	Save(values ...*model_alarm_snapshot.SiteAlarmSnapshotData) error
+	First() (*model_alarm_snapshot.SiteAlarmSnapshotData, error)
+	Take() (*model_alarm_snapshot.SiteAlarmSnapshotData, error)
+	Last() (*model_alarm_snapshot.SiteAlarmSnapshotData, error)
+	Find() ([]*model_alarm_snapshot.SiteAlarmSnapshotData, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model_alarm_snapshot.SiteAlarmSnapshotData, err error)
+	FindInBatches(result *[]*model_alarm_snapshot.SiteAlarmSnapshotData, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model_alarm_snapshot.SiteAlarmSnapshotData) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ISiteAlarmSnapshotDataDo
+	Assign(attrs ...field.AssignExpr) ISiteAlarmSnapshotDataDo
+	Joins(fields ...field.RelationField) ISiteAlarmSnapshotDataDo
+	Preload(fields ...field.RelationField) ISiteAlarmSnapshotDataDo
+	FirstOrInit() (*model_alarm_snapshot.SiteAlarmSnapshotData, error)
+	FirstOrCreate() (*model_alarm_snapshot.SiteAlarmSnapshotData, error)
+	FindByPage(offset int, limit int) (result []*model_alarm_snapshot.SiteAlarmSnapshotData, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Rows() (*sql.Rows, error)
+	Row() *sql.Row
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ISiteAlarmSnapshotDataDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+
+	FilterByTimeRange(start string, end string) (result []model_alarm_snapshot.SiteAlarmSnapshotData, err error)
+}
+
+// SELECT * FROM @@table
+// WHERE log_time BETWEEN @start AND @end
+func (s siteAlarmSnapshotDataDo) FilterByTimeRange(start string, end string) (result []model_alarm_snapshot.SiteAlarmSnapshotData, err error) {
+	var params []interface{}
+
+	var generateSQL strings.Builder
+	params = append(params, start)
+	params = append(params, end)
+	generateSQL.WriteString("SELECT * FROM alarm_snapshot.site_alarm_snapshot_data WHERE log_time BETWEEN ? AND ? ")
+
+	var executeSQL *gorm.DB
+	executeSQL = s.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert
+	err = executeSQL.Error
+
+	return
+}
+
+func (s siteAlarmSnapshotDataDo) Debug() ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Debug())
+}
+
+func (s siteAlarmSnapshotDataDo) WithContext(ctx context.Context) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.WithContext(ctx))
+}
+
+func (s siteAlarmSnapshotDataDo) ReadDB() ISiteAlarmSnapshotDataDo {
+	return s.Clauses(dbresolver.Read)
+}
+
+func (s siteAlarmSnapshotDataDo) WriteDB() ISiteAlarmSnapshotDataDo {
+	return s.Clauses(dbresolver.Write)
+}
+
+func (s siteAlarmSnapshotDataDo) Session(config *gorm.Session) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Session(config))
+}
+
+func (s siteAlarmSnapshotDataDo) Clauses(conds ...clause.Expression) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Clauses(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Returning(value interface{}, columns ...string) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Returning(value, columns...))
+}
+
+func (s siteAlarmSnapshotDataDo) Not(conds ...gen.Condition) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Not(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Or(conds ...gen.Condition) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Or(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Select(conds ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Select(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Where(conds ...gen.Condition) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Where(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Order(conds ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Order(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Distinct(cols ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Distinct(cols...))
+}
+
+func (s siteAlarmSnapshotDataDo) Omit(cols ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Omit(cols...))
+}
+
+func (s siteAlarmSnapshotDataDo) Join(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Join(table, on...))
+}
+
+func (s siteAlarmSnapshotDataDo) LeftJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.LeftJoin(table, on...))
+}
+
+func (s siteAlarmSnapshotDataDo) RightJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.RightJoin(table, on...))
+}
+
+func (s siteAlarmSnapshotDataDo) Group(cols ...field.Expr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Group(cols...))
+}
+
+func (s siteAlarmSnapshotDataDo) Having(conds ...gen.Condition) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Having(conds...))
+}
+
+func (s siteAlarmSnapshotDataDo) Limit(limit int) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Limit(limit))
+}
+
+func (s siteAlarmSnapshotDataDo) Offset(offset int) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Offset(offset))
+}
+
+func (s siteAlarmSnapshotDataDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Scopes(funcs...))
+}
+
+func (s siteAlarmSnapshotDataDo) Unscoped() ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Unscoped())
+}
+
+func (s siteAlarmSnapshotDataDo) Create(values ...*model_alarm_snapshot.SiteAlarmSnapshotData) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Create(values)
+}
+
+func (s siteAlarmSnapshotDataDo) CreateInBatches(values []*model_alarm_snapshot.SiteAlarmSnapshotData, batchSize int) error {
+	return s.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (s siteAlarmSnapshotDataDo) Save(values ...*model_alarm_snapshot.SiteAlarmSnapshotData) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Save(values)
+}
+
+func (s siteAlarmSnapshotDataDo) First() (*model_alarm_snapshot.SiteAlarmSnapshotData, error) {
+	if result, err := s.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotData), nil
+	}
+}
+
+func (s siteAlarmSnapshotDataDo) Take() (*model_alarm_snapshot.SiteAlarmSnapshotData, error) {
+	if result, err := s.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotData), nil
+	}
+}
+
+func (s siteAlarmSnapshotDataDo) Last() (*model_alarm_snapshot.SiteAlarmSnapshotData, error) {
+	if result, err := s.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotData), nil
+	}
+}
+
+func (s siteAlarmSnapshotDataDo) Find() ([]*model_alarm_snapshot.SiteAlarmSnapshotData, error) {
+	result, err := s.DO.Find()
+	return result.([]*model_alarm_snapshot.SiteAlarmSnapshotData), err
+}
+
+func (s siteAlarmSnapshotDataDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model_alarm_snapshot.SiteAlarmSnapshotData, err error) {
+	buf := make([]*model_alarm_snapshot.SiteAlarmSnapshotData, 0, batchSize)
+	err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (s siteAlarmSnapshotDataDo) FindInBatches(result *[]*model_alarm_snapshot.SiteAlarmSnapshotData, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return s.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (s siteAlarmSnapshotDataDo) Attrs(attrs ...field.AssignExpr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Attrs(attrs...))
+}
+
+func (s siteAlarmSnapshotDataDo) Assign(attrs ...field.AssignExpr) ISiteAlarmSnapshotDataDo {
+	return s.withDO(s.DO.Assign(attrs...))
+}
+
+func (s siteAlarmSnapshotDataDo) Joins(fields ...field.RelationField) ISiteAlarmSnapshotDataDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Joins(_f))
+	}
+	return &s
+}
+
+func (s siteAlarmSnapshotDataDo) Preload(fields ...field.RelationField) ISiteAlarmSnapshotDataDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Preload(_f))
+	}
+	return &s
+}
+
+func (s siteAlarmSnapshotDataDo) FirstOrInit() (*model_alarm_snapshot.SiteAlarmSnapshotData, error) {
+	if result, err := s.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotData), nil
+	}
+}
+
+func (s siteAlarmSnapshotDataDo) FirstOrCreate() (*model_alarm_snapshot.SiteAlarmSnapshotData, error) {
+	if result, err := s.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotData), nil
+	}
+}
+
+func (s siteAlarmSnapshotDataDo) FindByPage(offset int, limit int) (result []*model_alarm_snapshot.SiteAlarmSnapshotData, count int64, err error) {
+	result, err = s.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = s.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (s siteAlarmSnapshotDataDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = s.Count()
+	if err != nil {
+		return
+	}
+
+	err = s.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (s siteAlarmSnapshotDataDo) Scan(result interface{}) (err error) {
+	return s.DO.Scan(result)
+}
+
+func (s siteAlarmSnapshotDataDo) Delete(models ...*model_alarm_snapshot.SiteAlarmSnapshotData) (result gen.ResultInfo, err error) {
+	return s.DO.Delete(models)
+}
+
+func (s *siteAlarmSnapshotDataDo) withDO(do gen.Dao) *siteAlarmSnapshotDataDo {
+	s.DO = *do.(*gen.DO)
+	return s
+}

+ 452 - 0
service/models/model_pgsql/query_alarm_snapshot/alarm_snapshot.site_alarm_snapshot_file_record.gen.go

@@ -0,0 +1,452 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query_alarm_snapshot
+
+import (
+	"context"
+	"database/sql"
+	"strings"
+
+	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
+	"gorm.io/gorm/schema"
+
+	"gorm.io/gen"
+	"gorm.io/gen/field"
+
+	"gorm.io/plugin/dbresolver"
+
+	"fwh-toolbox-server/models/model_pgsql/model_alarm_snapshot"
+)
+
+func newSiteAlarmSnapshotFileRecord(db *gorm.DB, opts ...gen.DOOption) siteAlarmSnapshotFileRecord {
+	_siteAlarmSnapshotFileRecord := siteAlarmSnapshotFileRecord{}
+
+	_siteAlarmSnapshotFileRecord.siteAlarmSnapshotFileRecordDo.UseDB(db, opts...)
+	_siteAlarmSnapshotFileRecord.siteAlarmSnapshotFileRecordDo.UseModel(&model_alarm_snapshot.SiteAlarmSnapshotFileRecord{})
+
+	tableName := _siteAlarmSnapshotFileRecord.siteAlarmSnapshotFileRecordDo.TableName()
+	_siteAlarmSnapshotFileRecord.ALL = field.NewAsterisk(tableName)
+	_siteAlarmSnapshotFileRecord.ID = field.NewInt64(tableName, "id")
+	_siteAlarmSnapshotFileRecord.CodeType = field.NewInt32(tableName, "code_type")
+	_siteAlarmSnapshotFileRecord.FileName = field.NewString(tableName, "file_name")
+	_siteAlarmSnapshotFileRecord.FileURL = field.NewString(tableName, "file_url")
+	_siteAlarmSnapshotFileRecord.Sn = field.NewString(tableName, "sn")
+	_siteAlarmSnapshotFileRecord.LogTime = field.NewTime(tableName, "log_time")
+	_siteAlarmSnapshotFileRecord.StartTime = field.NewTime(tableName, "start_time")
+	_siteAlarmSnapshotFileRecord.EndTime = field.NewTime(tableName, "end_time")
+	_siteAlarmSnapshotFileRecord.CompleteTime = field.NewTime(tableName, "complete_time")
+	_siteAlarmSnapshotFileRecord.State = field.NewInt16(tableName, "state")
+
+	_siteAlarmSnapshotFileRecord.fillFieldMap()
+
+	return _siteAlarmSnapshotFileRecord
+}
+
+type siteAlarmSnapshotFileRecord struct {
+	siteAlarmSnapshotFileRecordDo siteAlarmSnapshotFileRecordDo
+
+	ALL          field.Asterisk
+	ID           field.Int64
+	CodeType     field.Int32
+	FileName     field.String
+	FileURL      field.String
+	Sn           field.String // site SN
+	LogTime      field.Time   // 日志记录日期(format YYYY-MM-DD)
+	StartTime    field.Time   // 记录开始时间(format YYYY-MM-DD HH:mm:SS)
+	EndTime      field.Time   // 记录结束时间(format YYYY-MM-DD HH:mm:SS)
+	CompleteTime field.Time   // 记录上传完成时间(format YYYY-MM-DD HH:mm:SS)
+	State        field.Int16  // 文件分析状态(0-分析中;1-完成;-1-失败)
+
+	fieldMap map[string]field.Expr
+}
+
+func (s siteAlarmSnapshotFileRecord) Table(newTableName string) *siteAlarmSnapshotFileRecord {
+	s.siteAlarmSnapshotFileRecordDo.UseTable(newTableName)
+	return s.updateTableName(newTableName)
+}
+
+func (s siteAlarmSnapshotFileRecord) As(alias string) *siteAlarmSnapshotFileRecord {
+	s.siteAlarmSnapshotFileRecordDo.DO = *(s.siteAlarmSnapshotFileRecordDo.As(alias).(*gen.DO))
+	return s.updateTableName(alias)
+}
+
+func (s *siteAlarmSnapshotFileRecord) updateTableName(table string) *siteAlarmSnapshotFileRecord {
+	s.ALL = field.NewAsterisk(table)
+	s.ID = field.NewInt64(table, "id")
+	s.CodeType = field.NewInt32(table, "code_type")
+	s.FileName = field.NewString(table, "file_name")
+	s.FileURL = field.NewString(table, "file_url")
+	s.Sn = field.NewString(table, "sn")
+	s.LogTime = field.NewTime(table, "log_time")
+	s.StartTime = field.NewTime(table, "start_time")
+	s.EndTime = field.NewTime(table, "end_time")
+	s.CompleteTime = field.NewTime(table, "complete_time")
+	s.State = field.NewInt16(table, "state")
+
+	s.fillFieldMap()
+
+	return s
+}
+
+func (s *siteAlarmSnapshotFileRecord) WithContext(ctx context.Context) ISiteAlarmSnapshotFileRecordDo {
+	return s.siteAlarmSnapshotFileRecordDo.WithContext(ctx)
+}
+
+func (s siteAlarmSnapshotFileRecord) TableName() string {
+	return s.siteAlarmSnapshotFileRecordDo.TableName()
+}
+
+func (s siteAlarmSnapshotFileRecord) Alias() string { return s.siteAlarmSnapshotFileRecordDo.Alias() }
+
+func (s siteAlarmSnapshotFileRecord) Columns(cols ...field.Expr) gen.Columns {
+	return s.siteAlarmSnapshotFileRecordDo.Columns(cols...)
+}
+
+func (s *siteAlarmSnapshotFileRecord) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+	_f, ok := s.fieldMap[fieldName]
+	if !ok || _f == nil {
+		return nil, false
+	}
+	_oe, ok := _f.(field.OrderExpr)
+	return _oe, ok
+}
+
+func (s *siteAlarmSnapshotFileRecord) fillFieldMap() {
+	s.fieldMap = make(map[string]field.Expr, 10)
+	s.fieldMap["id"] = s.ID
+	s.fieldMap["code_type"] = s.CodeType
+	s.fieldMap["file_name"] = s.FileName
+	s.fieldMap["file_url"] = s.FileURL
+	s.fieldMap["sn"] = s.Sn
+	s.fieldMap["log_time"] = s.LogTime
+	s.fieldMap["start_time"] = s.StartTime
+	s.fieldMap["end_time"] = s.EndTime
+	s.fieldMap["complete_time"] = s.CompleteTime
+	s.fieldMap["state"] = s.State
+}
+
+func (s siteAlarmSnapshotFileRecord) clone(db *gorm.DB) siteAlarmSnapshotFileRecord {
+	s.siteAlarmSnapshotFileRecordDo.ReplaceConnPool(db.Statement.ConnPool)
+	return s
+}
+
+func (s siteAlarmSnapshotFileRecord) replaceDB(db *gorm.DB) siteAlarmSnapshotFileRecord {
+	s.siteAlarmSnapshotFileRecordDo.ReplaceDB(db)
+	return s
+}
+
+type siteAlarmSnapshotFileRecordDo struct{ gen.DO }
+
+type ISiteAlarmSnapshotFileRecordDo interface {
+	gen.SubQuery
+	Debug() ISiteAlarmSnapshotFileRecordDo
+	WithContext(ctx context.Context) ISiteAlarmSnapshotFileRecordDo
+	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
+	ReplaceDB(db *gorm.DB)
+	ReadDB() ISiteAlarmSnapshotFileRecordDo
+	WriteDB() ISiteAlarmSnapshotFileRecordDo
+	As(alias string) gen.Dao
+	Session(config *gorm.Session) ISiteAlarmSnapshotFileRecordDo
+	Columns(cols ...field.Expr) gen.Columns
+	Clauses(conds ...clause.Expression) ISiteAlarmSnapshotFileRecordDo
+	Not(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo
+	Or(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo
+	Select(conds ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	Where(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo
+	Order(conds ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	Distinct(cols ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	Omit(cols ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	Join(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	LeftJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	RightJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	Group(cols ...field.Expr) ISiteAlarmSnapshotFileRecordDo
+	Having(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo
+	Limit(limit int) ISiteAlarmSnapshotFileRecordDo
+	Offset(offset int) ISiteAlarmSnapshotFileRecordDo
+	Count() (count int64, err error)
+	Scopes(funcs ...func(gen.Dao) gen.Dao) ISiteAlarmSnapshotFileRecordDo
+	Unscoped() ISiteAlarmSnapshotFileRecordDo
+	Create(values ...*model_alarm_snapshot.SiteAlarmSnapshotFileRecord) error
+	CreateInBatches(values []*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, batchSize int) error
+	Save(values ...*model_alarm_snapshot.SiteAlarmSnapshotFileRecord) error
+	First() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error)
+	Take() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error)
+	Last() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error)
+	Find() ([]*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error)
+	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, err error)
+	FindInBatches(result *[]*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error
+	Pluck(column field.Expr, dest interface{}) error
+	Delete(...*model_alarm_snapshot.SiteAlarmSnapshotFileRecord) (info gen.ResultInfo, err error)
+	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	Updates(value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
+	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
+	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
+	UpdateFrom(q gen.SubQuery) gen.Dao
+	Attrs(attrs ...field.AssignExpr) ISiteAlarmSnapshotFileRecordDo
+	Assign(attrs ...field.AssignExpr) ISiteAlarmSnapshotFileRecordDo
+	Joins(fields ...field.RelationField) ISiteAlarmSnapshotFileRecordDo
+	Preload(fields ...field.RelationField) ISiteAlarmSnapshotFileRecordDo
+	FirstOrInit() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error)
+	FirstOrCreate() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error)
+	FindByPage(offset int, limit int) (result []*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, count int64, err error)
+	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
+	Rows() (*sql.Rows, error)
+	Row() *sql.Row
+	Scan(result interface{}) (err error)
+	Returning(value interface{}, columns ...string) ISiteAlarmSnapshotFileRecordDo
+	UnderlyingDB() *gorm.DB
+	schema.Tabler
+
+	QueryState(id int64) (result map[string]interface{}, err error)
+}
+
+// SELECT state FROM @@table WHERE id = @id LIMIT 1
+func (s siteAlarmSnapshotFileRecordDo) QueryState(id int64) (result map[string]interface{}, err error) {
+	var params []interface{}
+
+	var generateSQL strings.Builder
+	params = append(params, id)
+	generateSQL.WriteString("SELECT state FROM alarm_snapshot.site_alarm_snapshot_file_record WHERE id = ? LIMIT 1 ")
+
+	result = make(map[string]interface{})
+	var executeSQL *gorm.DB
+	executeSQL = s.UnderlyingDB().Raw(generateSQL.String(), params...).Take(result) // ignore_security_alert
+	err = executeSQL.Error
+
+	return
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Debug() ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Debug())
+}
+
+func (s siteAlarmSnapshotFileRecordDo) WithContext(ctx context.Context) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.WithContext(ctx))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) ReadDB() ISiteAlarmSnapshotFileRecordDo {
+	return s.Clauses(dbresolver.Read)
+}
+
+func (s siteAlarmSnapshotFileRecordDo) WriteDB() ISiteAlarmSnapshotFileRecordDo {
+	return s.Clauses(dbresolver.Write)
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Session(config *gorm.Session) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Session(config))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Clauses(conds ...clause.Expression) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Clauses(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Returning(value interface{}, columns ...string) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Returning(value, columns...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Not(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Not(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Or(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Or(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Select(conds ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Select(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Where(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Where(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Order(conds ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Order(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Distinct(cols ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Distinct(cols...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Omit(cols ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Omit(cols...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Join(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Join(table, on...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) LeftJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.LeftJoin(table, on...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) RightJoin(table schema.Tabler, on ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.RightJoin(table, on...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Group(cols ...field.Expr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Group(cols...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Having(conds ...gen.Condition) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Having(conds...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Limit(limit int) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Limit(limit))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Offset(offset int) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Offset(offset))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Scopes(funcs...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Unscoped() ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Unscoped())
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Create(values ...*model_alarm_snapshot.SiteAlarmSnapshotFileRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Create(values)
+}
+
+func (s siteAlarmSnapshotFileRecordDo) CreateInBatches(values []*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, batchSize int) error {
+	return s.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (s siteAlarmSnapshotFileRecordDo) Save(values ...*model_alarm_snapshot.SiteAlarmSnapshotFileRecord) error {
+	if len(values) == 0 {
+		return nil
+	}
+	return s.DO.Save(values)
+}
+
+func (s siteAlarmSnapshotFileRecordDo) First() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error) {
+	if result, err := s.DO.First(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotFileRecord), nil
+	}
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Take() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error) {
+	if result, err := s.DO.Take(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotFileRecord), nil
+	}
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Last() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error) {
+	if result, err := s.DO.Last(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotFileRecord), nil
+	}
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Find() ([]*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error) {
+	result, err := s.DO.Find()
+	return result.([]*model_alarm_snapshot.SiteAlarmSnapshotFileRecord), err
+}
+
+func (s siteAlarmSnapshotFileRecordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, err error) {
+	buf := make([]*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, 0, batchSize)
+	err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+		defer func() { results = append(results, buf...) }()
+		return fc(tx, batch)
+	})
+	return results, err
+}
+
+func (s siteAlarmSnapshotFileRecordDo) FindInBatches(result *[]*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+	return s.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Attrs(attrs ...field.AssignExpr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Attrs(attrs...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Assign(attrs ...field.AssignExpr) ISiteAlarmSnapshotFileRecordDo {
+	return s.withDO(s.DO.Assign(attrs...))
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Joins(fields ...field.RelationField) ISiteAlarmSnapshotFileRecordDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Joins(_f))
+	}
+	return &s
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Preload(fields ...field.RelationField) ISiteAlarmSnapshotFileRecordDo {
+	for _, _f := range fields {
+		s = *s.withDO(s.DO.Preload(_f))
+	}
+	return &s
+}
+
+func (s siteAlarmSnapshotFileRecordDo) FirstOrInit() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error) {
+	if result, err := s.DO.FirstOrInit(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotFileRecord), nil
+	}
+}
+
+func (s siteAlarmSnapshotFileRecordDo) FirstOrCreate() (*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, error) {
+	if result, err := s.DO.FirstOrCreate(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model_alarm_snapshot.SiteAlarmSnapshotFileRecord), nil
+	}
+}
+
+func (s siteAlarmSnapshotFileRecordDo) FindByPage(offset int, limit int) (result []*model_alarm_snapshot.SiteAlarmSnapshotFileRecord, count int64, err error) {
+	result, err = s.Offset(offset).Limit(limit).Find()
+	if err != nil {
+		return
+	}
+
+	if size := len(result); 0 < limit && 0 < size && size < limit {
+		count = int64(size + offset)
+		return
+	}
+
+	count, err = s.Offset(-1).Limit(-1).Count()
+	return
+}
+
+func (s siteAlarmSnapshotFileRecordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+	count, err = s.Count()
+	if err != nil {
+		return
+	}
+
+	err = s.Offset(offset).Limit(limit).Scan(result)
+	return
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Scan(result interface{}) (err error) {
+	return s.DO.Scan(result)
+}
+
+func (s siteAlarmSnapshotFileRecordDo) Delete(models ...*model_alarm_snapshot.SiteAlarmSnapshotFileRecord) (result gen.ResultInfo, err error) {
+	return s.DO.Delete(models)
+}
+
+func (s *siteAlarmSnapshotFileRecordDo) withDO(do gen.Dao) *siteAlarmSnapshotFileRecordDo {
+	s.DO = *do.(*gen.DO)
+	return s
+}

+ 111 - 0
service/models/model_pgsql/query_alarm_snapshot/gen.go

@@ -0,0 +1,111 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query_alarm_snapshot
+
+import (
+	"context"
+	"database/sql"
+
+	"gorm.io/gorm"
+
+	"gorm.io/gen"
+
+	"gorm.io/plugin/dbresolver"
+)
+
+var (
+	Q                           = new(Query)
+	SiteAlarmSnapshotData       *siteAlarmSnapshotData
+	SiteAlarmSnapshotFileRecord *siteAlarmSnapshotFileRecord
+)
+
+func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
+	*Q = *Use(db, opts...)
+	SiteAlarmSnapshotData = &Q.SiteAlarmSnapshotData
+	SiteAlarmSnapshotFileRecord = &Q.SiteAlarmSnapshotFileRecord
+}
+
+func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
+	return &Query{
+		db:                          db,
+		SiteAlarmSnapshotData:       newSiteAlarmSnapshotData(db, opts...),
+		SiteAlarmSnapshotFileRecord: newSiteAlarmSnapshotFileRecord(db, opts...),
+	}
+}
+
+type Query struct {
+	db *gorm.DB
+
+	SiteAlarmSnapshotData       siteAlarmSnapshotData
+	SiteAlarmSnapshotFileRecord siteAlarmSnapshotFileRecord
+}
+
+func (q *Query) Available() bool { return q.db != nil }
+
+func (q *Query) clone(db *gorm.DB) *Query {
+	return &Query{
+		db:                          db,
+		SiteAlarmSnapshotData:       q.SiteAlarmSnapshotData.clone(db),
+		SiteAlarmSnapshotFileRecord: q.SiteAlarmSnapshotFileRecord.clone(db),
+	}
+}
+
+func (q *Query) ReadDB() *Query {
+	return q.ReplaceDB(q.db.Clauses(dbresolver.Read))
+}
+
+func (q *Query) WriteDB() *Query {
+	return q.ReplaceDB(q.db.Clauses(dbresolver.Write))
+}
+
+func (q *Query) ReplaceDB(db *gorm.DB) *Query {
+	return &Query{
+		db:                          db,
+		SiteAlarmSnapshotData:       q.SiteAlarmSnapshotData.replaceDB(db),
+		SiteAlarmSnapshotFileRecord: q.SiteAlarmSnapshotFileRecord.replaceDB(db),
+	}
+}
+
+type queryCtx struct {
+	SiteAlarmSnapshotData       ISiteAlarmSnapshotDataDo
+	SiteAlarmSnapshotFileRecord ISiteAlarmSnapshotFileRecordDo
+}
+
+func (q *Query) WithContext(ctx context.Context) *queryCtx {
+	return &queryCtx{
+		SiteAlarmSnapshotData:       q.SiteAlarmSnapshotData.WithContext(ctx),
+		SiteAlarmSnapshotFileRecord: q.SiteAlarmSnapshotFileRecord.WithContext(ctx),
+	}
+}
+
+func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error {
+	return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...)
+}
+
+func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx {
+	tx := q.db.Begin(opts...)
+	return &QueryTx{Query: q.clone(tx), Error: tx.Error}
+}
+
+type QueryTx struct {
+	*Query
+	Error error
+}
+
+func (q *QueryTx) Commit() error {
+	return q.db.Commit().Error
+}
+
+func (q *QueryTx) Rollback() error {
+	return q.db.Rollback().Error
+}
+
+func (q *QueryTx) SavePoint(name string) error {
+	return q.db.SavePoint(name).Error
+}
+
+func (q *QueryTx) RollbackTo(name string) error {
+	return q.db.RollbackTo(name).Error
+}

+ 1 - 1
service/models/model_pgsql/siteAlarmSnapshot.go

@@ -11,7 +11,7 @@ var db = database.PgSQL
 
 // 保存快照文件数据
 type SiteAlarmSnapshotModel struct {
-	ID           int64          `gorm:"primaryKey;autoIncrement"` // 自增ID
+	ID           int64          `gorm:"primaryKey;autoIncrement;comment:"` // 自增ID
 	SN           string         `gorm:"size:64;not null;uniqueIndex:idx_type_sn_time"`
 	FileRecordID int64          `gorm:"not null"`
 	LogTime      time.Time      `gorm:"type:timestamp;not null;uniqueIndex:idx_type_sn_time"` // TIMESTAMP WITHOUT TIME ZONE