diff --git a/controllers/kv.go b/controllers/kv.go index 8071b8878..cd4cfe617 100644 --- a/controllers/kv.go +++ b/controllers/kv.go @@ -481,6 +481,7 @@ func (c *KvController) GetStatisticDataByKey() { } return } + var TSKVService services.TSKVService var data []map[string]interface{} // 继续进行参数校验,如果是不聚合,仅校验时间范围是否是3小时内 @@ -516,6 +517,24 @@ func (c *KvController) GetStatisticDataByKey() { } } + // 导出Excel + if StatisticDataValidate.ExportExcel { + addr, err := TSKVService.KVDataExportExcel( + StatisticDataValidate.StartTime, + StatisticDataValidate.EndTime, + StatisticDataValidate.Key, + StatisticDataValidate.AggregateWindow, + StatisticDataValidate.AggregateFunction, + data) + if err != nil { + response.SuccessWithMessage(400, err.Error(), (*context2.Context)(c.Ctx)) + return + } else { + response.SuccessWithDetailed(200, "success", addr, map[string]string{}, (*context2.Context)(c.Ctx)) + return + } + } + rData := make(map[string]interface{}) rData["time_series"] = data rData["duration"] = StatisticDataValidate.EndTime - StatisticDataValidate.StartTime @@ -527,5 +546,3 @@ func (c *KvController) GetStatisticDataByKey() { // 继续组装 response.SuccessWithDetailed(200, "success", rData, map[string]string{}, (*context2.Context)(c.Ctx)) } - -// 暂时先放在这里,后序优化 diff --git a/services/tskv_service.go b/services/tskv_service.go index a2290da54..fa9b7350a 100644 --- a/services/tskv_service.go +++ b/services/tskv_service.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "log" + "os" "strconv" "strings" "time" @@ -17,7 +18,9 @@ import ( "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" "github.com/bitly/go-simplejson" + "github.com/mintance/go-uniqid" "github.com/spf13/viper" + "github.com/xuri/excelize/v2" //"github.com/zenghouchao/timeHelper" tptodb "ThingsPanel-Go/grpc/tptodb_client" @@ -1575,3 +1578,100 @@ func (*TSKVService) GetKVDataWithAggregate(deviceId, key string, sTime, eTime, a } return data, nil } + +func (*TSKVService) KVDataExportExcel(s, e int64, key, aggregateWindow, aggregateFunc string, data []map[string]interface{}) (string, error) { + + var addr string + var err error + file := excelize.NewFile() + // 合并 A1 到 B2 的单元格 + err = file.MergeCell("Sheet1", "A1", "B1") + if err != nil { + return addr, err + } + + sStr := time.Unix(s/1e6, 0).Format("2006-01-02 15:04:05") + eStr := time.Unix(e/1e6, 0).Format("2006-01-02 15:04:05") + + var aggfunc string + if aggregateFunc == "avg" { + aggfunc = "平均数" + } else { + aggfunc = "最大值" + } + + text := "数据列表(" + sStr + "-" + eStr + ")\n" + aggregateWindow + " " + key + " " + aggfunc + + // 创建换行文本样式 + style, err := file.NewStyle(`{"alignment": {"wrap_text": true}}`) + if err != nil { + return addr, err + } + + // 设置单元格的值和样式 + file.SetCellValue("Sheet1", "A1", text) + file.SetCellStyle("Sheet1", "A1", "A1", style) + + file.SetCellValue("Sheet1", "A2", "时间") + file.SetCellValue("Sheet1", "B2", "数值") + + err = file.SetColWidth("Sheet1", "A", "B", 30) + if err != nil { + return addr, err + } + + i := 3 + for _, v := range data { + var timeStr string + if x, ok := v["x"].(int64); !ok { + return addr, err + } else { + timeStr = time.Unix(x/1e6, 0).Format("2006-01-02 15:04:05") + } + file.SetCellValue("Sheet1", "A"+strconv.Itoa(i), timeStr) + file.SetCellValue("Sheet1", "B"+strconv.Itoa(i), v["y"]) + err = file.SetRowHeight("Sheet1", i, 23) + if err != nil { + return addr, err + } + i++ + } + + // 单元格美化操作 + style, err = file.NewStyle(`{ + "alignment": { + "horizontal": "center", + "vertical": "center" + } + }`) + if err != nil { + return addr, err + + } + // 全文水平垂直居中 + file.SetCellStyle("Sheet1", "A1", "B"+strconv.Itoa(i), style) + + // 行高 + err = file.SetRowHeight("Sheet1", 1, 50) + if err != nil { + return addr, err + } + + err = file.SetRowHeight("Sheet1", 2, 30) + if err != nil { + return addr, err + } + + uploadDir := "./files/excel/" + errs := os.MkdirAll(uploadDir, os.ModePerm) + if errs != nil { + return addr, err + } + // 根据指定路径保存文件 + uniqid_str := uniqid.New(uniqid.Params{Prefix: "excel", MoreEntropy: true}) + addr = "files/excel/数据列表" + uniqid_str + ".xlsx" + if err := file.SaveAs(addr); err != nil { + return addr, err + } + return addr, err +} diff --git a/validate/kv_validate.go b/validate/kv_validate.go index f038277a6..5ece7eae8 100644 --- a/validate/kv_validate.go +++ b/validate/kv_validate.go @@ -84,6 +84,7 @@ type StatisticDataValidate struct { TimeRange string `json:"time_range" alias:"时间范围"` AggregateWindow string `json:"aggregate_window" alias:"聚合间隔"` AggregateFunction string `json:"aggregate_function" alias:"聚合方法"` + ExportExcel bool `json:"export_excel" alias:"聚合方法"` } // 支持的间隔之间