| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873 |
- package jobs
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "fwh-toolbox-server/domain"
- "fwh-toolbox-server/dto"
- function "fwh-toolbox-server/function/SnapFile"
- "fwh-toolbox-server/repositories"
- "fwh-toolbox-server/utils/echart"
- "fwh-toolbox-server/utils/mimetype"
- "fwh-toolbox-server/utils/minio"
- "os"
- "path/filepath"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "time"
- "github.com/go-echarts/go-echarts/v2/opts"
- "github.com/xuri/excelize/v2"
- "go.uber.org/zap"
- )
- /* 文件服务器存储结构
- * BatchDownloadData/
- * └── `SN`/
- * ├── PowerFlow/ 功率流图文件
- * ├── MQTT/ MQTT通讯数据文件
- * ├── EventAlarm/ 事件日志与告警日志文件
- * ├── AlarmSnapshot 告警快照
- * ├── EmsLogs/ EMS日志文件
- * ├── FaultRecord/ 故障录波文件
- * ├── UpdateLog/ 升级日志数据文件
- * └── Settings/ 设置数据文件
- *
- * BatchDownloadPackage/ 任务打包数据
- */
- var (
- mainPathName string = "BatchDownloadData"
- subPowerFlowPathName string = "PowerFlow"
- subMqttPathName string = "MQTT"
- subEventAlarmPathName string = "EventAlarm"
- subAlarmSnapshotPathName string = "AlarmSnapshot"
- subEmsLogsPathName string = "EmsLogs"
- subFaultRecordPathName string = "FaultRecord"
- subUpdateLogPathName string = "UpdateLog"
- subSettingsPathName string = "Settings"
- )
- func stringPtr(s string) *string {
- return &s
- }
- // 创建临时保存路径
- func createTempPath(pathType string) (string, error) {
- // 创建临时目录存储下载和解压数据
- tempDirName := fmt.Sprintf("fwhtb-batchDownload-%s-*", pathType)
- tempDir, err := os.MkdirTemp("", tempDirName)
- if err != nil {
- zap.L().Error("创建临时目录失败", zap.String("pathName", tempDirName), zap.String("err", err.Error()))
- return "", err
- }
- return tempDir, nil
- }
- // Excel 指定行-列写入数据, 行列从1开始
- func excelSetCellValue(f *excelize.File, sheetName string, col int, row int, val interface{}) error {
- colName, err := excelize.ColumnNumberToName(col)
- if err != nil {
- zap.L().Error("Excel 列标转换失败", zap.String("col", strconv.Itoa(col)), zap.String("err", err.Error()))
- return err
- }
- return f.SetCellValue(sheetName, fmt.Sprintf("%s%d", colName, row), val)
- }
- // 判断功率流图文件是否存在
- func ExistsBatchDownloadPowerFlow(sn string, dateStr string) (bool, error) {
- fileName := fmt.Sprintf("PowerFlow_%s.html", strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subPowerFlowPathName, fileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查PowerFlow文件失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取功率流图文件状态信息
- func StatBatchDownloadPowerFlow(sn string, dateStr string) (*minio.ObjectInfo, error) {
- fileName := fmt.Sprintf("PowerFlow_%s.html", strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subPowerFlowPathName, fileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取PowerFlow文件状态失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存功率流图到文件服务器
- // return objName
- func SaveBatchDownloadPowerFlow(sn string, dateStr string, powerFlowData dto.SitePowerFlow) (string, error) {
- // 创建临时保存文件路径
- tempPath, err := createTempPath("powerFlow")
- if err != nil {
- return "", err
- }
- defer os.RemoveAll(tempPath) // 程序结束时清理临时目录
- fileName := fmt.Sprintf("PowerFlow_%s.html", strings.ReplaceAll(dateStr, "-", ""))
- filePath := filepath.Join(tempPath, fileName)
- // 数据结构转换
- pvData := []opts.LineData{}
- genData := []opts.LineData{}
- gridData := []opts.LineData{}
- aPowerData := []opts.LineData{}
- loadData := []opts.LineData{}
- socData := []opts.LineData{}
- for i, t := range powerFlowData.DeviceTimeArray {
- var pvValue []interface{}
- if i < len(powerFlowData.PowerSunArray) {
- pvValue = []interface{}{
- t,
- powerFlowData.PowerSunArray[i],
- }
- } else {
- pvValue = []interface{}{
- t,
- nil,
- }
- }
- pvData = append(pvData, opts.LineData{
- Value: pvValue,
- })
- var genValue []interface{}
- if i < len(powerFlowData.PowerGenArray) {
- genValue = []interface{}{
- t,
- powerFlowData.PowerGenArray[i],
- }
- } else {
- genValue = []interface{}{
- t,
- nil,
- }
- }
- genData = append(genData, opts.LineData{
- Value: genValue,
- })
- var gridValue []interface{}
- if i < len(powerFlowData.PowerUtiArray) {
- gridValue = []interface{}{
- t,
- powerFlowData.PowerUtiArray[i],
- }
- } else {
- gridValue = []interface{}{
- t,
- nil,
- }
- }
- gridData = append(gridData, opts.LineData{
- Value: gridValue,
- })
- var aPowerValue []interface{}
- if i < len(powerFlowData.PowerFhpArray) {
- aPowerValue = []interface{}{
- t,
- powerFlowData.PowerFhpArray[i],
- }
- } else {
- aPowerValue = []interface{}{
- t,
- nil,
- }
- }
- aPowerData = append(aPowerData, opts.LineData{
- Value: aPowerValue,
- })
- var loadValue []interface{}
- if i < len(powerFlowData.PowerLoadArray) {
- loadValue = []interface{}{
- t,
- powerFlowData.PowerLoadArray[i],
- }
- } else {
- loadValue = []interface{}{
- t,
- nil,
- }
- }
- loadData = append(loadData, opts.LineData{
- Value: loadValue,
- })
- // SOC
- var socValue []interface{}
- if i < len(powerFlowData.SocArray) {
- socValue = []interface{}{
- t,
- powerFlowData.SocArray[i],
- }
- } else {
- socValue = []interface{}{
- t,
- nil,
- }
- }
- socData = append(socData, opts.LineData{
- Value: socValue,
- })
- }
- // 生成功率流图
- var pfChartData []echart.PowerFlowChartData = []echart.PowerFlowChartData{}
- pfChartData = append(pfChartData, echart.PowerFlowChartData{
- Legend: "光伏",
- Color: stringPtr("#F1A502"),
- Data: pvData,
- })
- pfChartData = append(pfChartData, echart.PowerFlowChartData{
- Legend: "发电机",
- Color: stringPtr("#5398FF"),
- Data: genData,
- })
- pfChartData = append(pfChartData, echart.PowerFlowChartData{
- Legend: "市电",
- Color: stringPtr("#BB56FD"),
- Data: gridData,
- })
- pfChartData = append(pfChartData, echart.PowerFlowChartData{
- Legend: "aPower",
- Color: stringPtr("#41D187"),
- Data: aPowerData,
- })
- pfChartData = append(pfChartData, echart.PowerFlowChartData{
- Legend: "家庭负载",
- Color: stringPtr("#0BF5FF"),
- Data: loadData,
- })
- var socChartData echart.SocChartData = echart.SocChartData{
- Color: stringPtr("#3E7B4D"),
- Data: socData,
- }
- lineOpt := echart.LineChartOpt{
- Global: echart.ChartOpt{
- Title: "功率流图",
- },
- Smooth: true,
- }
- line := echart.CreatePowerFlowChart(lineOpt, pfChartData, socChartData)
- f, _ := os.Create(filePath)
- defer f.Close()
- line.Render(f)
- // 上传到文件服务器
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subPowerFlowPathName, fileName)
- if err = minio.UploadFile(filePath, objectName); err != nil {
- zap.L().Error("上传PowerFlow文件失败", zap.String("path", filePath), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return "", err
- }
- return objectName, nil
- }
- // 判断MqttLog excel文件是否存在
- func ExistsBatchDownloadMqttLog(sn string, cmdType string, dateStr string) (bool, error) {
- fileName := fmt.Sprintf("MqttLog_%s_%s.xlsx", cmdType, strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subMqttPathName, fileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查MqttLog excel文件失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取MqttLog excel文件状态信息
- func StatBatchDownloadMqttLog(sn string, cmdType string, dateStr string) (*minio.ObjectInfo, error) {
- fileName := fmt.Sprintf("MqttLog_%s_%s.xlsx", cmdType, strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subMqttPathName, fileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取MqttLog excel文件状态失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存MqttLog excel到文件服务器
- // return objName
- func SaveBatchDownloadMqttLog(sn string, cmdType string, dateStr string, data []domain.MqttLogItem) (objectName string, err error) {
- err = nil
- f := excelize.NewFile()
- defer func() {
- closeErr := f.Close()
- if closeErr != nil {
- zap.L().Error("Excel 文件close失败", zap.String("err", err.Error()))
- if err == nil {
- err = closeErr
- }
- }
- }()
- // 写标题行
- f.SetCellValue("Sheet1", "A1", "Type")
- f.SetCellValue("Sheet1", "B1", "Time")
- f.SetCellValue("Sheet1", "C1", "Data")
- // 写入数据
- for i, d := range data {
- f.SetCellValue("Sheet1", "A"+strconv.Itoa(i+2), d.CmdType)
- f.SetCellValue("Sheet1", "B"+strconv.Itoa(i+2), d.LogTime)
- f.SetCellValue("Sheet1", "C"+strconv.Itoa(i+2), d.LogData)
- }
- // 创建临时保存文件路径
- tempPath, err := createTempPath("mqtt_" + cmdType)
- if err != nil {
- return
- }
- defer os.RemoveAll(tempPath) // 程序结束时清理临时目录
- fileName := fmt.Sprintf("MqttLog_%s_%s.xlsx", cmdType, strings.ReplaceAll(dateStr, "-", ""))
- filePath := filepath.Join(tempPath, fileName)
- // 保存到文件
- err = f.SaveAs(filePath)
- if err != nil {
- zap.L().Error("Excel文件save失败", zap.String("path", filePath), zap.String("err", err.Error()))
- return
- }
- // 上传到文件服务器
- objectName = fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subMqttPathName, fileName)
- if err = minio.UploadFile(filePath, objectName); err != nil {
- zap.L().Error("上传Excel文件失败", zap.String("path", filePath), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return
- }
- return
- }
- // 判断EventAlarm excel文件是否存在
- func ExistsBatchDownloadEventAlarm(sn string, dateStr string) (bool, error) {
- fileName := fmt.Sprintf("EventAlarm_%s.xlsx", strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEventAlarmPathName, fileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查EventAlarm excel文件失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取EventAlarm excel文件状态信息
- func StatBatchDownloadEventAlarm(sn string, dateStr string) (*minio.ObjectInfo, error) {
- fileName := fmt.Sprintf("EventAlarm_%s.xlsx", strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEventAlarmPathName, fileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取EventAlarm excel文件状态失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存EventAlarm excel到文件服务器
- // return objName
- func SaveBatchDownloadEventAlarm(sn string, dateStr string, eventAlarmData []domain.EventAlarmItem) (objectName string, err error) {
- err = nil
- f := excelize.NewFile()
- defer func() {
- closeErr := f.Close()
- if closeErr != nil {
- zap.L().Error("Excel 文件close失败", zap.String("err", err.Error()))
- if err == nil {
- err = closeErr
- }
- }
- }()
- // 写标题行
- f.SetCellValue("Sheet1", "A1", "ID")
- f.SetCellValue("Sheet1", "B1", "Time")
- f.SetCellValue("Sheet1", "C1", "Type")
- f.SetCellValue("Sheet1", "D1", "AlarmCode")
- f.SetCellValue("Sheet1", "E1", "Name")
- f.SetCellValue("Sheet1", "F1", "StartTime")
- f.SetCellValue("Sheet1", "G1", "EndTime")
- f.SetCellValue("Sheet1", "H1", "Data")
- for i, data := range eventAlarmData {
- var id string
- if data.ID == nil || *data.ID == "" {
- id = strconv.Itoa(i + 1)
- } else {
- id = *data.ID
- }
- f.SetCellValue("Sheet1", "A"+strconv.Itoa(i+2), id)
- f.SetCellValue("Sheet1", "B"+strconv.Itoa(i+2), data.LogTime)
- f.SetCellValue("Sheet1", "C"+strconv.Itoa(i+2), data.LogType)
- f.SetCellValue("Sheet1", "D"+strconv.Itoa(i+2), data.AlarmCode)
- f.SetCellValue("Sheet1", "E"+strconv.Itoa(i+2), data.LogName)
- f.SetCellValue("Sheet1", "F"+strconv.Itoa(i+2), data.StartTime)
- f.SetCellValue("Sheet1", "G"+strconv.Itoa(i+2), data.EndTime)
- f.SetCellValue("Sheet1", "H"+strconv.Itoa(i+2), data.LogData)
- }
- // 创建临时保存文件路径
- tempPath, err := createTempPath("eventAlarm")
- if err != nil {
- return
- }
- defer os.RemoveAll(tempPath) // 程序结束时清理临时目录
- fileName := fmt.Sprintf("EventAlarm_%s.xlsx", strings.ReplaceAll(dateStr, "-", ""))
- filePath := filepath.Join(tempPath, fileName)
- // 保存到文件
- err = f.SaveAs(filePath)
- if err != nil {
- zap.L().Error("Excel文件save失败", zap.String("path", filePath), zap.String("err", err.Error()))
- return
- }
- // 上传到文件服务器
- objectName = fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEventAlarmPathName, fileName)
- if err = minio.UploadFile(filePath, objectName); err != nil {
- zap.L().Error("上传Excel文件失败", zap.String("path", filePath), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return
- }
- return
- }
- // 判断AlarmSnapshot文件是否存在
- func ExistsBatchDownloadAlarmSnapshot(sn string, dateStr string) (bool, error) {
- fileName := fmt.Sprintf("EventAlarm_%s.xlsx", strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subAlarmSnapshotPathName, fileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查AlarmSnapshot文件失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取AlarmSnapshot文件状态信息
- func StatBatchDownloadAlarmSnapshot(sn string, dateStr string) (*minio.ObjectInfo, error) {
- fileName := fmt.Sprintf("EventAlarm_%s.xlsx", strings.ReplaceAll(dateStr, "-", ""))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subAlarmSnapshotPathName, fileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取AlarmSnapshot文件状态失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存AlarmSnapshot文件到文件服务器
- // return objName
- func SaveBatchDownloadAlarmSnapshot(sn string, dateStr string, alarmSnapshotData []*domain.SiteAlarmSnapshotData) (objectName string, err error) {
- err = nil
- f := excelize.NewFile()
- defer func() {
- closeErr := f.Close()
- if closeErr != nil {
- zap.L().Error("Excel 文件close失败", zap.String("err", err.Error()))
- if err == nil {
- err = closeErr
- }
- }
- }()
- // 写标题行
- f.SetCellValue("Sheet1", "A1", "ID")
- f.SetCellValue("Sheet1", "B1", "Time")
- f.SetCellValue("Sheet1", "C1", "Data")
- // 数据按时间排序
- sort.Slice(alarmSnapshotData[:], func(i, j int) bool { return alarmSnapshotData[i].LogTime.Before(alarmSnapshotData[j].LogTime) })
- for i, data := range alarmSnapshotData {
- var logTime string
- loc, e := time.LoadLocation(data.ZoneInfo)
- if e != nil {
- zap.L().Warn("本地时间加载失败", zap.String("ZoneInfo", data.ZoneInfo), zap.String("err", err.Error()))
- logTime = data.LogTime.Format(time.DateTime)
- } else {
- logTime = data.LogTime.In(loc).Format(time.DateTime)
- }
- // 尝试解析成function.
- var snapJson function.SnapUnmarshalJson
- if err := json.Unmarshal([]byte(data.JSONData), &snapJson); err == nil {
- // 能解析成功,则为new json,需要转换
- for _, xid := range snapJson.SnapInfo.XidList {
- if xid.Type == "VID" {
- macro, desc, err := repositories.GetEmsparaVidInfo(uint(xid.ID))
- if err != nil {
- zap.L().Warn("GetEmsparaVidInfo error", zap.String("err", err.Error()))
- continue
- }
- xid.Macro = ¯o
- xid.Brief = &desc
- } else if xid.Type == "PID" {
- macro, desc, err := repositories.GetEmsparaPidInfo(uint(xid.ID))
- if err != nil {
- zap.L().Warn("GetEmsparaPidInfo error", zap.String("err", err.Error()))
- continue
- }
- xid.Macro = ¯o
- xid.Brief = &desc
- }
- }
- if jsonBytes, err := json.Marshal(snapJson); err != nil {
- zap.L().Error("Marshal snapJson failed", zap.String("err", err.Error()))
- } else {
- data.JSONData = string(jsonBytes)
- }
- }
- f.SetCellValue("Sheet1", "A"+strconv.Itoa(i+2), data.ID)
- f.SetCellValue("Sheet1", "B"+strconv.Itoa(i+2), logTime)
- f.SetCellValue("Sheet1", "C"+strconv.Itoa(i+2), data.JSONData)
- }
- // 创建临时保存文件路径
- tempPath, err := createTempPath("alarmSnapshot")
- if err != nil {
- return
- }
- defer os.RemoveAll(tempPath) // 程序结束时清理临时目录
- fileName := fmt.Sprintf("EventAlarm_%s.xlsx", strings.ReplaceAll(dateStr, "-", ""))
- filePath := filepath.Join(tempPath, fileName)
- // 保存到文件
- err = f.SaveAs(filePath)
- if err != nil {
- zap.L().Error("Excel文件save失败", zap.String("path", filePath), zap.String("err", err.Error()))
- return
- }
- // 上传到文件服务器
- objectName = fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subAlarmSnapshotPathName, fileName)
- if err = minio.UploadFile(filePath, objectName); err != nil {
- zap.L().Error("上传Excel文件失败", zap.String("path", filePath), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return
- }
- return
- }
- // 判断EmsLog文件是否存在
- func ExistsBatchDownloadEmsLog(sn string, originalFileName string, fileSupType string, dateStr string, callTime time.Time) (bool, error) {
- // 使用正则匹配多级后缀,例如 .tar.bz2, .tar.gz, .min.js 等
- re := regexp.MustCompile(`(\.[a-zA-Z0-9]+)+$`)
- matchSuffix := re.FindString(originalFileName)
- fileName := fmt.Sprintf("EmsLog_%s_%s_%s_%s%s", sn, fileSupType, strings.ReplaceAll(dateStr, "-", "_"), strconv.FormatInt(callTime.Unix(), 10), matchSuffix)
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEmsLogsPathName, fileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查EmsLog文件失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取EmsLog文件状态信息
- func StatBatchDownloadEmsLog(sn string, originalFileName string, fileSupType string, dateStr string, callTime time.Time) (*minio.ObjectInfo, error) {
- // 使用正则匹配多级后缀,例如 .tar.bz2, .tar.gz, .min.js 等
- re := regexp.MustCompile(`(\.[a-zA-Z0-9]+)+$`)
- matchSuffix := re.FindString(originalFileName)
- fileName := fmt.Sprintf("EmsLog_%s_%s_%s_%s%s", sn, fileSupType, strings.ReplaceAll(dateStr, "-", "_"), strconv.FormatInt(callTime.Unix(), 10), matchSuffix)
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEmsLogsPathName, fileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取EmsLog文件状态失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存EmsLog文件到文件服务器
- // return objName
- func SaveBatchDownloadEmsLog(sn string, dataBytes []byte, originalFileName string, fileSupType string, dateStr string, callTime time.Time) (string, error) {
- // 将 []byte 封装成 io.Reader
- dataReader := bytes.NewReader(dataBytes)
- // 使用正则匹配多级后缀,例如 .tar.bz2, .tar.gz, .min.js 等
- re := regexp.MustCompile(`(\.[a-zA-Z0-9]+)+$`)
- matchSuffix := re.FindString(originalFileName)
- // 计算Content Type
- contentType := mimetype.GetContentType(originalFileName)
- // 保存到minio
- fileName := fmt.Sprintf("EmsLog_%s_%s_%s_%s%s", sn, fileSupType, strings.ReplaceAll(dateStr, "-", "_"), strconv.FormatInt(callTime.Unix(), 10), matchSuffix)
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEmsLogsPathName, fileName)
- return objectName, minio.UploadFromReader(dataReader, int64(len(dataBytes)), objectName, contentType)
- }
- // 判断FaultRecord文件是否存在
- func ExistsBatchDownloadFaultRecord(sn string, faultRecordFileName string) (bool, error) {
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subFaultRecordPathName, faultRecordFileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查FaultRecord文件失败", zap.String("fileName", faultRecordFileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取FaultRecord文件状态信息
- func StatBatchDownloadFaultRecord(sn string, faultRecordFileName string) (*minio.ObjectInfo, error) {
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subFaultRecordPathName, faultRecordFileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取FaultRecord文件状态失败", zap.String("fileName", faultRecordFileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存FaultRecord文件到文件服务器
- // return objName
- func SaveBatchDownloadFaultRecord(sn string, dataBytes []byte, faultRecordFileName string) (string, error) {
- // 将 []byte 封装成 io.Reader
- dataReader := bytes.NewReader(dataBytes)
- // 计算Content Type
- contentType := mimetype.GetContentType(faultRecordFileName)
- // 保存到minio
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subFaultRecordPathName, faultRecordFileName)
- return objectName, minio.UploadFromReader(dataReader, int64(len(dataBytes)), objectName, contentType)
- }
- // 判断UpdateLog excel文件是否存在
- func ExistsBatchDownloadUpdateLog(sn string, date time.Time) (bool, error) {
- fileName := fmt.Sprintf("UpdateLog_%s_%s.xlsx", sn, strings.ReplaceAll(date.Format(time.DateTime), " ", "_"))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subUpdateLogPathName, fileName)
- exists, err := minio.ExistsObject(objectName)
- if err != nil {
- zap.L().Error("检查UpdateLog excel文件失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return false, err
- }
- return exists, nil
- }
- // 获取UpdateLog excel文件状态信息
- func StatBatchDownloadUpdateLog(sn string, date time.Time) (*minio.ObjectInfo, error) {
- fileName := fmt.Sprintf("UpdateLog_%s_%s.xlsx", sn, strings.ReplaceAll(date.Format(time.DateTime), " ", "_"))
- objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subUpdateLogPathName, fileName)
- status, err := minio.StatObject(objectName)
- if err != nil {
- zap.L().Error("获取UpdateLog excel文件状态失败", zap.String("fileName", fileName), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return nil, err
- }
- return &status, nil
- }
- // 保存UpdateLog excel到文件服务器
- // return objName
- func SaveBatchDownloadUpdateLog(sn string, systemUpdateLogData []domain.BatchDownloadSystemUpdateLogInfo, aHubUpdateLogData []domain.BatchDownloadAHubUpdateLogInfo) (objectName string, err error) {
- err = nil
- f := excelize.NewFile()
- defer func() {
- closeErr := f.Close()
- if closeErr != nil {
- zap.L().Error("Excel 文件close失败", zap.String("err", err.Error()))
- if err == nil {
- err = closeErr
- }
- }
- }()
- systemUpdateSheetName := "SystemUpdate"
- aHubUpdateSheetName := "aHubUpdate"
- err = f.SetSheetName("Sheet1", systemUpdateSheetName)
- if err != nil {
- zap.L().Error("Excel Sheet1更名失败", zap.String("sheetName", systemUpdateSheetName), zap.String("err", err.Error()))
- return
- }
- _, err = f.NewSheet(aHubUpdateSheetName)
- if err != nil {
- zap.L().Error("Excel 新增Sheet失败", zap.String("sheetName", aHubUpdateSheetName), zap.String("err", err.Error()))
- return
- }
- // 样式集
- // 加粗
- // 创建加粗样式
- styleBold, err := f.NewStyle(&excelize.Style{
- Font: &excelize.Font{
- Bold: true,
- },
- })
- if err != nil {
- zap.L().Error("Excel 新增Sheet失败", zap.String("err", err.Error()))
- return
- }
- var rowIndex int = 1
- // 写入系统升级日志
- for _, updateItem := range systemUpdateLogData {
- // 写标题行
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), "OrderNo")
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("B%d", rowIndex), "GateSn")
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("C%d", rowIndex), "TriggerType")
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("D%d", rowIndex), "FileName")
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("E%d", rowIndex), "UpdateTime")
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("F%d", rowIndex), "Result")
- f.SetCellStyle(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), fmt.Sprintf("F%d", rowIndex), styleBold)
- rowIndex++
- // 写入项目信息内容
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), updateItem.OrderNo)
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("B%d", rowIndex), updateItem.GateSn)
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("C%d", rowIndex), updateItem.TriggerType)
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("D%d", rowIndex), updateItem.FileName)
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("E%d", rowIndex), updateItem.UpdateTime)
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("F%d", rowIndex), updateItem.Result)
- rowIndex = rowIndex + 2
- // Gate版本信息
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), "GateVer")
- f.SetCellStyle(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), fmt.Sprintf("A%d", rowIndex), styleBold)
- rowIndex++
- for idx, modeVer := range updateItem.GateVerList {
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+1, rowIndex, "Name")
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+1, rowIndex+1, "OldVer")
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+1, rowIndex+2, "NewVer")
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+2, rowIndex, modeVer.Name)
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+2, rowIndex+1, modeVer.OldVer)
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+2, rowIndex+2, modeVer.NewVer)
- }
- rowIndex = rowIndex + 2
- // SubDev版本信息
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), "SubVer")
- f.SetCellStyle(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), fmt.Sprintf("A%d", rowIndex), styleBold)
- rowIndex++
- for _, subVer := range updateItem.SubDevList {
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("A%d", rowIndex), "SubSn")
- f.SetCellValue(systemUpdateSheetName, fmt.Sprintf("B%d", rowIndex), subVer.DevSn)
- rowIndex++
- for idx, modeVer := range subVer.DevVerList {
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+1, rowIndex, "Name")
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+1, rowIndex+1, "OldVer")
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+1, rowIndex+2, "NewVer")
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+2, rowIndex, modeVer.Name)
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+2, rowIndex+1, modeVer.OldVer)
- excelSetCellValue(f, systemUpdateSheetName, (3*idx)+2, rowIndex+2, modeVer.NewVer)
- }
- rowIndex = rowIndex + 3
- }
- rowIndex++
- }
- rowIndex = 1
- // 写入aHub升级日志
- for _, aHubUpdateItem := range aHubUpdateLogData {
- // 写标题行
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("A%d", rowIndex), "OrderNo")
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("B%d", rowIndex), "GateSn")
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("C%d", rowIndex), "TriggerType")
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("D%d", rowIndex), "AHubSn")
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("E%d", rowIndex), "EndTime")
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("F%d", rowIndex), "Result")
- f.SetCellStyle(aHubUpdateSheetName, fmt.Sprintf("A%d", rowIndex), fmt.Sprintf("F%d", rowIndex), styleBold)
- rowIndex++
- // 写入项目信息内容
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("A%d", rowIndex), aHubUpdateItem.OrderNo)
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("B%d", rowIndex), aHubUpdateItem.GateSn)
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("C%d", rowIndex), aHubUpdateItem.TriggerType)
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("D%d", rowIndex), aHubUpdateItem.AHubSn)
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("E%d", rowIndex), aHubUpdateItem.EndTime)
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("F%d", rowIndex), aHubUpdateItem.Result)
- rowIndex = rowIndex + 2
- // aHub版本信息
- f.SetCellValue(aHubUpdateSheetName, fmt.Sprintf("A%d", rowIndex), "aHubVer")
- f.SetCellStyle(aHubUpdateSheetName, fmt.Sprintf("A%d", rowIndex), fmt.Sprintf("A%d", rowIndex), styleBold)
- rowIndex++
- for idx, modeVer := range aHubUpdateItem.DetailList {
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+1, rowIndex, "FileName")
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+1, rowIndex+1, "FileOrder")
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+1, rowIndex+2, "ResultDesc")
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+1, rowIndex+3, "OldVer")
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+1, rowIndex+4, "NewVer")
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+2, rowIndex, modeVer.FileName)
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+2, rowIndex+1, modeVer.FileOrder)
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+2, rowIndex+2, modeVer.ResultDesc)
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+2, rowIndex+3, modeVer.OldVer)
- excelSetCellValue(f, aHubUpdateSheetName, (3*idx)+2, rowIndex+4, modeVer.NewVer)
- }
- rowIndex = rowIndex + 6
- }
- // 创建临时保存文件路径
- tempPath, err := createTempPath("updateLog")
- if err != nil {
- return
- }
- defer os.RemoveAll(tempPath) // 程序结束时清理临时目录
- fileName := fmt.Sprintf("UpdateLog_%s_%s.xlsx", sn, strings.ReplaceAll(time.Now().Format(time.DateTime), " ", "_"))
- filePath := filepath.Join(tempPath, fileName)
- // 保存到文件
- err = f.SaveAs(filePath)
- if err != nil {
- zap.L().Error("Excel文件save失败", zap.String("path", filePath), zap.String("err", err.Error()))
- return
- }
- // 上传到文件服务器
- objectName = fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subUpdateLogPathName, fileName)
- if err = minio.UploadFile(filePath, objectName); err != nil {
- zap.L().Error("上传Excel文件失败", zap.String("path", filePath), zap.String("objectName", objectName), zap.String("err", err.Error()))
- return
- }
- return
- }
- // 保存Settings excel到文件服务器
- // return objName
- // func SaveBatchDownloadSettings(sn string, dateStr string, settingsData []domain.SiteSettings) (string, error) {
- // }
|