|
@@ -0,0 +1,632 @@
|
|
|
|
|
+package jobs
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "bytes"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "fwh-toolbox-server/domain"
|
|
|
|
|
+ "fwh-toolbox-server/dto"
|
|
|
|
|
+ "fwh-toolbox-server/utils/echart"
|
|
|
|
|
+ "fwh-toolbox-server/utils/minio"
|
|
|
|
|
+ "os"
|
|
|
|
|
+ "path/filepath"
|
|
|
|
|
+ "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)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 保存功率流图到文件服务器
|
|
|
|
|
+// 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到文件服务器
|
|
|
|
|
+// 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到文件服务器
|
|
|
|
|
+// 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文件到文件服务器
|
|
|
|
|
+// 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")
|
|
|
|
|
+
|
|
|
|
|
+ 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)
|
|
|
|
|
+ }
|
|
|
|
|
+ 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文件到文件服务器
|
|
|
|
|
+// return objName
|
|
|
|
|
+func SaveBatchDownloadEmsLog(sn string, dataBytes []byte, emsLogFileName string, contentType string) (string, error) {
|
|
|
|
|
+ // 将 []byte 封装成 io.Reader
|
|
|
|
|
+ dataReader := bytes.NewReader(dataBytes)
|
|
|
|
|
+ // 保存到minio
|
|
|
|
|
+ objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subEmsLogsPathName, emsLogFileName)
|
|
|
|
|
+ return objectName, minio.UploadFromReader(dataReader, int64(len(dataBytes)), objectName, contentType)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 保存FaultRecord文件到文件服务器
|
|
|
|
|
+// return objName
|
|
|
|
|
+func SaveBatchDownloadFaultRecord(sn string, dataBytes []byte, faultRecordFileName string, contentType string) (string, error) {
|
|
|
|
|
+ // 将 []byte 封装成 io.Reader
|
|
|
|
|
+ dataReader := bytes.NewReader(dataBytes)
|
|
|
|
|
+ // 保存到minio
|
|
|
|
|
+ objectName := fmt.Sprintf("%s/%s/%s/%s", mainPathName, sn, subFaultRecordPathName, faultRecordFileName)
|
|
|
|
|
+ return objectName, minio.UploadFromReader(dataReader, int64(len(dataBytes)), objectName, contentType)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 保存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) {
|
|
|
|
|
+// }
|