Jelajahi Sumber

ADD:报禁列表、导出报警可以查询6个月

zoie 1 tahun lalu
induk
melakukan
496d945d8a
5 mengubah file dengan 1184 tambahan dan 76 penghapusan
  1. 6 3
      conf/app.conf
  2. 1 0
      conf/config.go
  3. 561 30
      controllers/Warning.go
  4. 609 41
      models/Warning/Warning.go
  5. 7 2
      routers/Warning.go

+ 6 - 3
conf/app.conf

@@ -67,7 +67,7 @@ Panel_url = "http://127.0.0.1:6204/Cold_Panel"
 FilterExcludeURL = /Login_verification,/Data/List,/WxPay/Notify,/Data/Company_key_Device_Sensor_List,/docking/Real_Data,/docking/Note_Data,/Company/Transport/List,/DeviceSensor/List_BySN
 # 小程序 冷链验证 /Data/List
 # 小程序接口 /DeviceWarning/DeviceSensor_List,/Device/Applet_Stat_View2,/DeviceSensor/Applet_List_View1,/DeviceSensor/Applet_List_View2,/DeviceSensorType/List,/Device/DeviceTask_Post
-FilterOnlyLoginCheckURL = /Menu/List,/User/Info,/User/Home,/User/Post,/UpFileToken,/User/WxQRCode,/Company/Get,/DataSource,/Company/Bill_Excel,/WarningSend/List,/WxPay/Get_QRCode,/WxPay/GetOrderState,/WarningHandle/List
+FilterOnlyLoginCheckURL = /Menu/List,/User/Info,/User/Home,/User/Post,/UpFileToken,/User/WxQRCode,/Company/Get,/DataSource,/Company/Bill_Excel,/WarningSend/List,/WxPay/Get_QRCode,/WxPay/GetOrderState,/WarningHandle/List,/DeviceWarning/List_Count
 
 
 MqttIds = mqttjxit,mqttlodr,mqttyuht
@@ -79,7 +79,7 @@ Weixin_Notify = "https://cold.coldbaozhida.com/api/WxPay/Notify"
 
 # 日志配置
 # 0-控制台输出 1-文件输出 2-文件和控制台输出
-adapter_type = 2
+adapter_type = 0
 # 文件最多保存多少天
 maxdays = 7
 # 日志级别 (0-紧急 1-报警 2-严重错误 3-错误 4-警告 5-注意 6-信息 7-调试)
@@ -89,4 +89,7 @@ sqlloglevel = 4
 # 慢SQL阈值(毫秒)。慢SQL会在sqlloglevel大于等于3时输出。
 slow_threshold = 200
 # 每个文件保存的最大行数
-maxlines = 10000
+maxlines = 10000
+
+# 使用新的告警查询方式
+UseNewWarningQuery = false

+ 1 - 0
conf/config.go

@@ -46,3 +46,4 @@ var WarningRateExcludePid, _ = beego.AppConfig.String("WarningRateExcludePid")
 
 var Weixin_PwdKey, _ = beego.AppConfig.String("Weixin_PwdKey")
 var Weixin_Notify, _ = beego.AppConfig.String("Weixin_Notify")
+var UseNewWarningQuery, _ = beego.AppConfig.Bool("UseNewWarningQuery")

+ 561 - 30
controllers/Warning.go

@@ -4,15 +4,18 @@ import (
 	"Cold_Api/Nats/NatsServer"
 	"Cold_Api/conf"
 	"Cold_Api/controllers/lib"
+	db "Cold_Api/initialize"
 	"Cold_Api/models/Account"
 	"Cold_Api/models/Device"
 	"Cold_Api/models/System"
 	"Cold_Api/models/Warning"
+	"encoding/json"
 	"fmt"
 	"github.com/beego/beego/v2/core/logs"
 	"github.com/robfig/cron/v3"
 	"github.com/xuri/excelize/v2"
 	"math"
+	"net/http"
 	"os"
 	"strconv"
 	"time"
@@ -110,6 +113,240 @@ func (c *DeviceController) DeviceWarning_List() {
 	c.ServeJSON()
 	return
 }
+func (c *DeviceController) DeviceWarning_List2() {
+
+	type R_JSONS struct {
+		//必须的大写开头
+		Data      []Warning.Warning_R
+		Num       int64
+		Page      int
+		Page_size int
+	}
+	var r_jsons R_JSONS
+
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+
+	T_name := c.GetString("T_name")
+	T_tp := c.GetString("T_tp")
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	T_handle, _ := c.GetInt("T_handle")
+
+	T_admin, _ := c.GetInt("T_admin")
+	T_history, _ := c.GetInt("T_history")
+	tpCount := Warning.Read_WarningType_Count()
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+		if len(tpList) == int(tpCount) {
+			// 类型全选,替换为空,不进行查询筛选(查询全部)
+			tpList = []string{}
+		}
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+	countRedisKey := fmt.Sprintf("Warning_Count_%d_%s_%s_%s_%s_%d_%d_%d", c.T_pid, T_name, T_tp, Time_start, Time_end, T_handle, T_admin, T_history)
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	// 管理员界面
+	if T_admin == 1 {
+		// 获取最新
+		r_jsons.Data, r_jsons.Num = Warning.Gorm_Read_Admin_Warning_List(*c.Admin_r, tpList, T_name, T_handle, Time_start, Time_end, page, page_z, countRedisKey)
+		c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+		c.ServeJSON()
+		return
+	}
+
+	r_jsons.Data, r_jsons.Num = Warning.Gorm_Read_Warning_List(c.T_pid, bindSN, tpList, T_name, T_handle, Time_start, Time_end, page, page_z, countRedisKey)
+
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
+func (c *DeviceController) DeviceWarning_List_Sse() {
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+	T_name := c.GetString("T_name")
+	T_tp := c.GetString("T_tp")
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	T_handle, _ := c.GetInt("T_handle")
+
+	T_admin, _ := c.GetInt("T_admin")
+	tpCount := Warning.Read_WarningType_Count()
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+		if len(tpList) == int(tpCount) {
+			// 类型全选,替换为空,不进行查询筛选(查询全部)
+			tpList = []string{}
+		}
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+	countRedisKey := fmt.Sprintf("Warning_Count_%d_%s_%s_%s_%s_%d_%d_%d", c.T_pid, T_name, T_tp, Time_start, Time_end, T_handle, T_admin, 0)
+	tableNames := Warning.GenerateWarningTableNames(Time_start, Time_end)
+
+	// 设置响应头
+	c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
+	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
+	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
+	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
+	var cnt int64
+	tableCount := make(map[string]int64)
+	// 管理员界面
+	if T_admin == 1 {
+		gormReadWarningListScopes := Warning.GormReadAdminWarningListScopes(*c.Admin_r, tpList, T_name, T_handle, Time_start, Time_end)
+		cnt, tableCount, err = Warning.Redis_WarningCount_GetOne(c.Admin_r.Id, countRedisKey)
+
+		offset := (page - 1) * page_z
+		remaining := offset
+		var warningsCount int
+		for _, tableName := range tableNames {
+
+			tableDB := db.DB.Table(tableName)
+			var count int64
+			if tableName == fmt.Sprintf("warning_%d_%02d", time.Now().Year(), time.Now().Month()) {
+				if saveTime, ok := tableCount["SaveTime"]; ok {
+					t1 := time.Unix(saveTime, 0)
+					if time.Now().Sub(t1) < 5*time.Minute {
+						if count, ok = tableCount[tableName]; !ok {
+							tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+							tableCount[tableName] = count
+						}
+					} else {
+						tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+						tableCount[tableName] = count
+					}
+				}
+			} else {
+				var ok bool
+				if count, ok = tableCount[tableName]; !ok {
+					tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+					tableCount[tableName] = count
+				}
+			}
+
+			cnt += count
+
+			if remaining >= int(count) {
+				remaining -= int(count)
+				continue
+			}
+			var tableWarning []Warning.Warning
+			if warningsCount < page_z {
+
+				tableDB.Scopes(gormReadWarningListScopes).
+					Order("t__ut desc").Offset(remaining).Limit(page_z - warningsCount).Find(&tableWarning)
+			}
+			warningsCount += len(tableWarning)
+			remaining = 0
+
+			var r_jsons lib.R_JSONS
+			r_jsons.Num = cnt
+			r_jsons.Data = tableWarning
+			json_b, _ := json.Marshal(r_jsons)
+			c.Ctx.ResponseWriter.Write(json_b)
+			c.Ctx.ResponseWriter.Flush()
+			// 可以根据需要调整间隔时间
+			time.Sleep(1 * time.Second)
+		}
+		Warning.Redis_WarningCount_Set(c.Admin_r.Id, countRedisKey, cnt, tableCount)
+		return
+	}
+	//从redis获取报警统计数量
+	gormReadWarningListScopes := Warning.GormReadWarningListScopes(c.T_pid, bindSN, tpList, T_name, T_handle, Time_start, Time_end)
+	cnt, tableCount, err = Warning.Redis_WarningCount_GetOne(c.T_pid, countRedisKey)
+
+	offset := (page - 1) * page_z
+	remaining := offset
+	var warningsCount int
+	for _, tableName := range tableNames {
+
+		tableDB := db.DB.Table(tableName)
+		var count int64
+		if tableName == fmt.Sprintf("warning_%d_%02d", time.Now().Year(), time.Now().Month()) {
+			if saveTime, ok := tableCount["SaveTime"]; ok {
+				t1 := time.Unix(saveTime, 0)
+				if time.Now().Sub(t1) < 5*time.Minute {
+					if count, ok = tableCount[tableName]; !ok {
+						tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+						tableCount[tableName] = count
+					}
+				} else {
+					tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+					tableCount[tableName] = count
+				}
+			}
+
+		} else {
+			var ok bool
+			if count, ok = tableCount[tableName]; !ok {
+				tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+				tableCount[tableName] = count
+			}
+		}
+
+		cnt += count
+
+		if remaining >= int(count) {
+			remaining -= int(count)
+			continue
+		}
+		var tableWarning []Warning.Warning
+		if warningsCount < page_z {
+
+			tableDB.Scopes(gormReadWarningListScopes).
+				Order("t__ut desc").Offset(remaining).Limit(page_z - warningsCount).Find(&tableWarning)
+		}
+		warningsCount += len(tableWarning)
+		remaining = 0
+
+		var r_jsons lib.R_JSONS
+		r_jsons.Num = cnt
+		r_jsons.Data = tableWarning
+		json_b, _ := json.Marshal(r_jsons)
+		c.Ctx.ResponseWriter.Write(json_b)
+		c.Ctx.ResponseWriter.Flush()
+		// 可以根据需要调整间隔时间
+		time.Sleep(1 * time.Second)
+	}
+	Warning.Redis_WarningCount_Set(c.T_pid, countRedisKey, cnt, tableCount)
+
+}
 func (c *DeviceController) CompanyWarning_List() {
 
 	var r_jsons lib.R_JSONS
@@ -179,14 +416,89 @@ func (c *DeviceController) CompanyWarning_List() {
 	c.ServeJSON()
 	return
 }
+func (c *DeviceController) CompanyWarning_List2() {
+
+	var r_jsons lib.R_JSONS
+
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+
+	T_name := c.GetString("T_name")
+	T_tp := c.GetString("T_tp")
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	T_handle, _ := c.GetInt("T_handle")
+
+	tpCount := Warning.Read_WarningType_Count()
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+		if len(tpList) == int(tpCount) {
+			// 类型全选,替换为空,不进行查询筛选(查询全部)
+			tpList = []string{}
+		}
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+	countRedisKey := fmt.Sprintf("Company_Warning_Count_%d_%s_%s_%s_%s_%d_%d", c.T_pid, T_name, T_tp, Time_start, Time_end, T_handle, 0)
+
+	Company_r, err := Account.Read_Company_ById(c.T_pid)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	T_pids := Account.ReadCompanyIds_T_path(Company_r.T_path)
+
+	Account.Read_Company_All_Maps()
+
+	// 获取最新
+	r_jsons.Data, r_jsons.Num = Warning.Gorm_Read_Company_Warning_List(T_pids, tpList, T_name, T_handle, Time_start, Time_end, page, page_z, c.T_pid, countRedisKey)
+
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
 
-// 查询告警
+// 查询告警 暂时没有用到
 func (c *DeviceController) DeviceWarning_Get() {
 	id, _ := c.GetInt("T_id")
-	T_history, _ := c.GetInt("T_history")
-	T := Warning.Read_Warning_ById(int64(id))
-
-	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Warning.WarningToWarning_R(T_history, T)}
+	T_time := c.GetString("T_time")
+	if len(T_time) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式错误"}
+		c.ServeJSON()
+		return
+	}
+	var T_year, T_month string
+	date, err := time.Parse("2006-01-02 15:04:05", T_time)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式错误"}
+		c.ServeJSON()
+		return
+	}
+	T_year, T_month = date.Format("2006"), date.Format("01")
+	Wtab := "warning"
+	Wtab += "_" + T_year + "_" + T_month
+	T, err := Warning.Read_Warning_ById_Backups(id, T_year, T_month)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Warning.WarningToWarning_R(0, T)}
 	c.ServeJSON()
 	return
 }
@@ -196,7 +508,12 @@ func (c *DeviceController) DeviceWarning_Post() {
 	id, _ := c.GetInt("T_id")
 	T_Text := c.GetString("T_Text")
 	T_time := c.GetString("T_time")
-	T_history, _ := c.GetInt("T_history")
+	T_history, _ := c.GetInt("T_history") // TODO 后期废弃
+	if len(T_time) == 0 && conf.UseNewWarningQuery {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式错误"}
+		c.ServeJSON()
+		return
+	}
 
 	var T_year, T_month string
 	var warning Warning.Warning
@@ -218,38 +535,46 @@ func (c *DeviceController) DeviceWarning_Post() {
 		}
 		warning.T_Text = T_Text
 		warning.T_State = 2
+		warning.UpdateTime = time.Now()
 		if is := Warning.Update_Warning_Backups(warning, T_year, T_month); !is {
 			c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 			c.ServeJSON()
 			return
 		}
 
-		warning = Warning.Read_Warning_ById(int64(id))
-		if warning.Id > 0 {
+		if !conf.UseNewWarningQuery {
+			warning = Warning.Read_Warning_ById(int64(id))
+			if warning.Id > 0 {
+				warning.T_Text = T_Text
+				warning.T_State = 2
+				warning.UpdateTime = time.Now()
+				if is := Warning.Update_Warning(warning, "T_Text", "T_State", "UpdateTime"); !is {
+					c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
+					c.ServeJSON()
+					return
+				}
+			}
+		}
+
+	} else {
+		// 使用新的查询方式后 warning表不做更新
+		if !conf.UseNewWarningQuery {
+			warning = Warning.Read_Warning_ById(int64(id))
+			if warning.Id == 0 {
+				c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+				c.ServeJSON()
+				return
+			}
 			warning.T_Text = T_Text
 			warning.T_State = 2
-			if is := Warning.Update_Warning(warning, "T_Text", "T_State"); !is {
-				c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
+			warning.UpdateTime = time.Now()
+			if is := Warning.Update_Warning(warning, "T_Text", "T_State", "UpdateTime"); !is {
+				c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 				c.ServeJSON()
 				return
 			}
 		}
 
-	} else {
-		warning = Warning.Read_Warning_ById(int64(id))
-		if warning.Id == 0 {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
-			c.ServeJSON()
-			return
-		}
-		warning.T_Text = T_Text
-		warning.T_State = 2
-		if is := Warning.Update_Warning(warning, "T_Text", "T_State"); !is {
-			c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
-			c.ServeJSON()
-			return
-		}
-
 		// 同步处理历史数据
 		date := warning.T_Ut
 		T_year, T_month = date.Format("2006"), date.Format("01")
@@ -263,6 +588,7 @@ func (c *DeviceController) DeviceWarning_Post() {
 		if warningBackups.Id > 0 {
 			warningBackups.T_Text = T_Text
 			warningBackups.T_State = 2
+			warningBackups.UpdateTime = time.Now()
 			if is := Warning.Update_Warning_Backups(warningBackups, T_year, T_month); !is {
 				c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 				c.ServeJSON()
@@ -285,8 +611,12 @@ func (c *DeviceController) DeviceWarning_Post() {
 func (c *DeviceController) DeviceWarning_Del() {
 	id, _ := c.GetInt("T_id")
 	T_time := c.GetString("T_time")
-	T_history, _ := c.GetInt("T_history")
-
+	T_history, _ := c.GetInt("T_history") // TODO 后期废弃
+	if len(T_time) == 0 && conf.UseNewWarningQuery {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式错误"}
+		c.ServeJSON()
+		return
+	}
 	var T_year, T_month string
 	var warning Warning.Warning
 	Wtab := "warning"
@@ -307,12 +637,12 @@ func (c *DeviceController) DeviceWarning_Del() {
 			return
 		}
 		warning.T_State = 0
+		warning.UpdateTime = time.Now()
 		if is := Warning.Update_Warning_Backups(warning, T_year, T_month); !is {
 			c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
 			c.ServeJSON()
 			return
 		}
-
 		warning = Warning.Read_Warning_ById(int64(id))
 		if warning.Id > 0 {
 			warning.T_State = 0
@@ -347,6 +677,7 @@ func (c *DeviceController) DeviceWarning_Del() {
 		}
 		if warningBackups.Id > 0 {
 			warningBackups.T_State = 0
+			warningBackups.UpdateTime = time.Now()
 			if is := Warning.Update_Warning_Backups(warningBackups, T_year, T_month); !is {
 				c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
 				c.ServeJSON()
@@ -461,7 +792,109 @@ func (c *DeviceController) DeviceWarning_Data_Excel() {
 		f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.T_Remark)
 		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.T_Ut)
 		f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v.T_Text)
-		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.CreateTime)
+		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.UpdateTime)
+
+	}
+	timeStr := time.Now().Format("20060102150405")
+	// 保存文件
+	if err := f.SaveAs("ofile/" + timeStr + ".xlsx"); err != nil {
+		fmt.Println(err)
+	}
+
+	url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+timeStr+".xlsx", "ofile/"+timeStr+".xlsx")
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
+		c.ServeJSON()
+		return
+	}
+	// 删除文件
+	err = os.Remove("ofile/" + timeStr + ".xlsx")
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
+	c.ServeJSON()
+	return
+}
+func (c *DeviceController) DeviceWarning_Data_Excel2() {
+	T_name := c.GetString("T_name")
+	T_tp := c.GetString("T_tp")
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	T_handle, _ := c.GetInt("T_handle")
+
+	T_admin, _ := c.GetInt("T_admin")
+	tpCount := Warning.Read_WarningType_Count()
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+		if len(tpList) == int(tpCount) {
+			// 类型全选,替换为空,不进行查询筛选(查询全部)
+			tpList = []string{}
+		}
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+	countRedisKey := fmt.Sprintf("Warning_Count_%d_%s_%s_%s_%s_%d_%d", c.T_pid, T_name, T_tp, Time_start, Time_end, T_handle, 0)
+
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	var Device_data []Warning.Warning_R
+
+	// 管理员界面
+	if T_admin == 1 {
+		// 获取最新
+		//Device_data, _ = Warning.Gorm_Read_Admin_Warning_List(*c.Admin_r, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999, countRedisKey)
+		Device_data, _ = Warning.Gorm_Read_Admin_Warning_List_Excel(*c.Admin_r, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999, countRedisKey)
+	} else {
+		// 获取最新
+		//Device_data, _ = Warning.Gorm_Read_Warning_List(c.T_pid, bindSN, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999, countRedisKey)
+		Device_data, _ = Warning.Gorm_Read_Warning_List_Excel(c.T_pid, bindSN, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999, countRedisKey)
+	}
+
+	f := excelize.NewFile() // 设置单元格的值
+	// 这里设置表头ÒÒ
+	f.SetCellValue("Sheet1", "A1", "报警类型")
+	f.SetCellValue("Sheet1", "B1", "Sn")
+	f.SetCellValue("Sheet1", "C1", "设备名称")
+	f.SetCellValue("Sheet1", "D1", "传感器")
+	f.SetCellValue("Sheet1", "E1", "报警内容")
+	f.SetCellValue("Sheet1", "F1", "记录时间")
+	f.SetCellValue("Sheet1", "G1", "处理")
+	f.SetCellValue("Sheet1", "H1", "处理时间")
+
+	// 设置列宽
+	f.SetColWidth("Sheet1", "A", "A", 20)
+	f.SetColWidth("Sheet1", "B", "B", 25)
+	f.SetColWidth("Sheet1", "C", "C", 30)
+	f.SetColWidth("Sheet1", "D", "D", 30)
+	f.SetColWidth("Sheet1", "G", "E", 30)
+	f.SetColWidth("Sheet1", "H", "F", 15)
+	f.SetColWidth("Sheet1", "I", "G", 30)
+	f.SetColWidth("Sheet1", "J", "H", 15)
+
+	line := 1
+
+	// 循环写入数据
+	for _, v := range Device_data {
+		line++
+		f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), Warning.Read_WarningType_Get(v.T_tp))
+		f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), fmt.Sprintf("%s[%d]", v.T_sn, v.T_id))
+		f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), v.T_D_name)
+		f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.T_DS_name)
+		f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.T_Remark)
+		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.T_Ut)
+		f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v.T_Text)
+		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.UpdateTime)
 
 	}
 	timeStr := time.Now().Format("20060102150405")
@@ -577,7 +1010,105 @@ func (c *DeviceController) CompanyWarning_Data_Excel() {
 		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.T_Remark)
 		f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v.T_Ut)
 		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.T_Text)
-		f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v.CreateTime)
+		f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v.UpdateTime)
+
+	}
+	timeStr := time.Now().Format("20060102150405")
+	// 保存文件
+	if err := f.SaveAs("ofile/" + timeStr + ".xlsx"); err != nil {
+		fmt.Println(err)
+	}
+
+	url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+timeStr+".xlsx", "ofile/"+timeStr+".xlsx")
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
+		c.ServeJSON()
+		return
+	}
+	// 删除文件
+	err = os.Remove("ofile/" + timeStr + ".xlsx")
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
+	c.ServeJSON()
+	return
+}
+func (c *DeviceController) CompanyWarning_Data_Excel2() {
+	T_name := c.GetString("T_name")
+	T_tp := c.GetString("T_tp")
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	T_handle, _ := c.GetInt("T_handle")
+	tpCount := Warning.Read_WarningType_Count()
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+		if len(tpList) == int(tpCount) {
+			// 类型全选,替换为空,不进行查询筛选(查询全部)
+			tpList = []string{}
+		}
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+	countRedisKey := fmt.Sprintf("Company_Warning_Count_%d_%s_%s_%s_%s_%d_%d", c.T_pid, T_name, T_tp, Time_start, Time_end, T_handle, 0)
+
+	Account.Read_Company_All_Maps()
+	Company_r, err := Account.Read_Company_ById(c.T_pid)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	T_pids := Account.ReadCompanyIds_T_path(Company_r.T_path)
+
+	var Device_data []Warning.CompanyWarning_R
+
+	// 获取最新
+	Device_data, _ = Warning.Gorm_Read_Company_Warning_List_Excel(T_pids, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999, c.T_pid, countRedisKey)
+
+	f := excelize.NewFile() // 设置单元格的值
+	// 这里设置表头
+	f.SetCellValue("Sheet1", "A1", "报警类型")
+	f.SetCellValue("Sheet1", "B1", "公司名称")
+	f.SetCellValue("Sheet1", "C1", "Sn")
+	f.SetCellValue("Sheet1", "D1", "设备名称")
+	f.SetCellValue("Sheet1", "E1", "传感器")
+	f.SetCellValue("Sheet1", "F1", "报警内容")
+	f.SetCellValue("Sheet1", "G1", "记录时间")
+	f.SetCellValue("Sheet1", "H1", "处理")
+	f.SetCellValue("Sheet1", "I1", "处理时间")
+
+	// 设置列宽
+	f.SetColWidth("Sheet1", "A", "A", 20)
+	f.SetColWidth("Sheet1", "B", "B", 40)
+	f.SetColWidth("Sheet1", "C", "C", 25)
+	f.SetColWidth("Sheet1", "D", "D", 30)
+	f.SetColWidth("Sheet1", "E", "E", 30)
+	f.SetColWidth("Sheet1", "F", "F", 30)
+	f.SetColWidth("Sheet1", "J", "J", 15)
+	f.SetColWidth("Sheet1", "H", "H", 30)
+	f.SetColWidth("Sheet1", "I", "I", 15)
+
+	line := 1
+
+	// 循环写入数据
+	for _, v := range Device_data {
+		line++
+		f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), Warning.Read_WarningType_Get(v.T_tp))
+		f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), fmt.Sprintf("%s", v.T_pid_name))
+		f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), fmt.Sprintf("%s[%d]", v.T_sn, v.T_id))
+		f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.T_D_name)
+		f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.T_DS_name)
+		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.T_Remark)
+		f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v.T_Ut)
+		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.T_Text)
+		f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v.UpdateTime)
 
 	}
 	timeStr := time.Now().Format("20060102150405")

+ 609 - 41
models/Warning/Warning.go

@@ -3,6 +3,7 @@ package Warning
 import (
 	"Cold_Api/conf"
 	"Cold_Api/controllers/lib"
+	db "Cold_Api/initialize"
 	"Cold_Api/models/Account"
 	"encoding/json"
 	"fmt"
@@ -13,8 +14,11 @@ import (
 	"github.com/beego/beego/v2/core/logs"
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/gomodule/redigo/redis"
+	"gorm.io/gorm"
+	"sort"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
@@ -25,20 +29,20 @@ var (
 
 // 模板
 type Warning struct {
-	Id        int64     `orm:"column(ID);size(11);auto;pk"`
-	T_pid     int       `orm:"size(256);null"`        // Account.Company 绑定公司
-	T_tp      int       `orm:"size(200);null"`        // 报警类型   ->WarningList
-	T_sn      string    `orm:"index;size(256);null"`  // 设备序列号
-	T_D_name  string    `orm:"size(256);null"`        // 设备名称
-	T_id      int       `orm:"size(200);null"`        // 传感器 ID
-	T_DS_name string    `orm:"size(256);null"`        // 传感器名称
-	T_Remark  string    `orm:"type(text);null"`       // 采集内容
-	T_Ut      time.Time `orm:"type(timestamp);null;"` // 采集时间
-	T_fUt     time.Time `orm:"type(timestamp);null;"` // 首次采集时间
-
-	T_Text string `orm:"type(text);null"` // 处理备注
-	T_Log  string `orm:"type(text);null"` // 通知日志
-	T_Msid int64  `orm:"size(256);null"`  // 消息ID
+	Id        int64     `orm:"column(ID);size(11);auto;pk" gorm:"column:ID"`
+	T_pid     int       `orm:"size(256);null"  gorm:"column:t_pid"`        // Account.Company 绑定公司
+	T_tp      int       `orm:"size(200);null" gorm:"column:t_tp"`          // 报警类型   ->WarningList
+	T_sn      string    `orm:"index;size(256);null" gorm:"column:t_sn"`    // 设备序列号
+	T_D_name  string    `orm:"size(256);null" gorm:"column:t__d_name"`     // 设备名称
+	T_id      int       `orm:"size(200);null" gorm:"column:t_id"`          // 传感器 ID
+	T_DS_name string    `orm:"size(256);null" gorm:"column:t__d_s_name"`   // 传感器名称
+	T_Remark  string    `orm:"type(text);null" gorm:"column:t__remark"`    // 采集内容
+	T_Ut      time.Time `orm:"type(timestamp);null;" gorm:"column:t__ut"`  // 采集时间
+	T_fUt     time.Time `orm:"type(timestamp);null;" gorm:"column:t_f_ut"` // 首次采集时间
+
+	T_Text string `orm:"type(text);null" gorm:"column:t__text"` // 处理备注
+	T_Log  string `orm:"type(text);null" gorm:"column:t__Log"`  // 通知日志
+	T_Msid int64  `orm:"size(256);null" gorm:"column:t__msid"`  // 消息ID
 
 	T_State    int       `orm:"size(2);default(2)"`                                    // 0 删除   1 不处理   2 已处理   3 未处理
 	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
@@ -80,7 +84,9 @@ type Warning_R struct {
 	T_State    int      // 0 删除   1 未处理   2 已处理
 	T_history  int      // 0 40天 1 历史数据
 	CreateTime string   // 创建时间
+	UpdateTime string   // 更新时间
 }
+
 type CompanyWarning_R struct {
 	Id         int64
 	T_pid      int      // Account.Company 绑定公司
@@ -100,6 +106,7 @@ type CompanyWarning_R struct {
 	T_State    int      // 0 删除   1 未处理   2 已处理
 	T_history  int      // 0 40天 1 历史数据
 	CreateTime string   // 创建时间
+	UpdateTime string   // 更新时间
 }
 type Warning_Applet struct {
 	Id             int64
@@ -122,8 +129,9 @@ type Warning_Applet struct {
 }
 
 type Warning_Count struct {
-	Key   string
-	Count int64
+	Key        string
+	Count      int64
+	TableCount map[string]int64
 }
 
 func (t *Warning) TableName() string {
@@ -148,14 +156,15 @@ func init() {
 	}
 }
 
-func Redis_WarningCount_Set(id int, key string, count int64) (err error) {
+func Redis_WarningCount_Set(id int, key string, count int64, TableCount map[string]int64) (err error) {
 	//json序列化
 	idKey := strconv.Itoa(id)
-
+	TableCount["SaveTime"] = time.Now().Unix()
 	warningCount, err := Redis_WarningCount_Get(idKey)
 	warningCount = append(warningCount, Warning_Count{
-		Key:   key,
-		Count: count,
+		Key:        key,
+		Count:      count,
+		TableCount: TableCount,
 	})
 
 	str, err := json.Marshal(warningCount)
@@ -188,11 +197,12 @@ func Redis_WarningCount_Get(userId string) (count []Warning_Count, err error) {
 	}
 	return count, redis.ErrNil
 }
-func Redis_WarningCount_GetOne(id int, key string) (count int64, err error) {
+func Redis_WarningCount_GetOne(id int, key string) (count int64, tableCount map[string]int64, err error) {
 	countList := []Warning_Count{}
+	tableCount = make(map[string]int64)
 	idKey := strconv.Itoa(id)
 	if !redis_Warning_Count.IsExist(idKey) {
-		return count, redis.ErrNil
+		return count, tableCount, redis.ErrNil
 	}
 	//println("找到key:",key)
 	v := redis_Warning_Count.Get(idKey)
@@ -200,15 +210,15 @@ func Redis_WarningCount_GetOne(id int, key string) (count int64, err error) {
 	err = json.Unmarshal(v.([]byte), &countList)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
-		return count, err
+		return count, tableCount, err
 	}
 
 	for _, c := range countList {
 		if c.Key == key {
-			return c.Count, nil
+			return c.Count, c.TableCount, nil
 		}
 	}
-	return count, redis.ErrNil
+	return count, tableCount, redis.ErrNil
 
 }
 
@@ -246,6 +256,7 @@ func WarningToWarning_R(T_history int, t Warning) (r Warning_R) {
 	r.T_State = t.T_State
 	r.T_history = T_history
 	r.CreateTime = t.CreateTime.Format("2006-01-02 15:04:05")
+	r.UpdateTime = t.UpdateTime.Format("2006-01-02 15:04:05")
 	return r
 }
 func WarningToCompanyWarning_R(T_history int, t Warning) (r CompanyWarning_R) {
@@ -272,6 +283,7 @@ func WarningToCompanyWarning_R(T_history int, t Warning) (r CompanyWarning_R) {
 	r.T_State = t.T_State
 	r.T_history = T_history
 	r.CreateTime = t.CreateTime.Format("2006-01-02 15:04:05")
+	r.UpdateTime = t.UpdateTime.Format("2006-01-02 15:04:05")
 	return r
 }
 
@@ -366,7 +378,7 @@ func Update_Warning_Backups(r Warning, T_year string, T_month string) bool {
 	o := orm.NewOrm()
 	Wtab := "warning_" + T_year + "_" + T_month
 
-	num, err := o.Raw("UPDATE "+Wtab+" SET `t__text` = ?,`t__state` = ? WHERE `ID` = ?", r.T_Text, r.T_State, r.Id).Exec()
+	num, err := o.Raw("UPDATE "+Wtab+" SET `t__text` = ?,`t__state` = ?, `update_time` = ? WHERE `ID` = ?", r.T_Text, r.T_State, r.UpdateTime, r.Id).Exec()
 
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
@@ -436,14 +448,14 @@ func Read_Warning_List(T_pid int, bindSN, tpList []string, T_name string, T_hand
 	var err error
 
 	// 从redis获取报警统计数量
-	cnt, err = Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	cnt, _, err = Redis_WarningCount_GetOne(T_pid, countRedisKey)
 	if err != nil {
 		cnt, err = qs.SetCond((*orm2.Condition)(cond1)).Count()
 		if err != nil {
 			logs.Error(lib.FuncName(), err)
 			return
 		}
-		Redis_WarningCount_Set(T_pid, countRedisKey, cnt)
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, map[string]int64{})
 	}
 	if cnt == 0 {
 		return r, 0
@@ -527,14 +539,14 @@ func Read_Admin_Warning_List(admin Account.Admin, T_tp []string, T_name string,
 	}
 	var err error
 	// 从redis获取报警统计数量
-	cnt, err = Redis_WarningCount_GetOne(admin.Id, countRedisKey)
+	cnt, _, err = Redis_WarningCount_GetOne(admin.Id, countRedisKey)
 	if err != nil {
 		cnt, err = qs.SetCond((*orm2.Condition)(cond1)).Count()
 		if err != nil {
 			logs.Error(lib.FuncName(), err)
 			return
 		}
-		Redis_WarningCount_Set(admin.Id, countRedisKey, cnt)
+		Redis_WarningCount_Set(admin.Id, countRedisKey, cnt, map[string]int64{})
 	}
 	if cnt == 0 {
 		return r, 0
@@ -613,7 +625,7 @@ func Read_Warning_Backups(T_pid int, bindSN []string, T_year string, T_month str
 	sql_WHERE = strings.TrimLeft(sql_WHERE, " AND")
 
 	// 从redis获取报警统计数量
-	cnt, err := Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	cnt, _, err := Redis_WarningCount_GetOne(T_pid, countRedisKey)
 	if err != nil {
 		sql := "SELECT COUNT(*) FROM " + Wtab + " WHERE " + sql_WHERE
 		fmt.Println(sql)
@@ -627,7 +639,7 @@ func Read_Warning_Backups(T_pid int, bindSN []string, T_year string, T_month str
 		}
 		cnt, _ = strconv.ParseInt(maps_z[0][0].(string), 10, 64)
 
-		Redis_WarningCount_Set(T_pid, countRedisKey, cnt)
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, map[string]int64{})
 	}
 	if cnt == 0 {
 		return r, 0
@@ -717,7 +729,7 @@ func Read_Admin_Warning_Backups(admin Account.Admin, T_year string, T_month stri
 	sql_WHERE = strings.TrimLeft(sql_WHERE, " AND")
 
 	// 从redis获取报警统计数量
-	cnt, err := Redis_WarningCount_GetOne(admin.Id, countRedisKey)
+	cnt, _, err := Redis_WarningCount_GetOne(admin.Id, countRedisKey)
 	if err != nil {
 		sql := "SELECT COUNT(*) FROM " + Wtab + " WHERE " + sql_WHERE
 		fmt.Println(sql)
@@ -731,7 +743,7 @@ func Read_Admin_Warning_Backups(admin Account.Admin, T_year string, T_month stri
 		}
 		cnt, _ = strconv.ParseInt(maps_z[0][0].(string), 10, 64)
 
-		Redis_WarningCount_Set(admin.Id, countRedisKey, cnt)
+		Redis_WarningCount_Set(admin.Id, countRedisKey, cnt, map[string]int64{})
 	}
 	if cnt == 0 {
 		return r, 0
@@ -761,7 +773,8 @@ func Read_Admin_Warning_Backups(admin Account.Admin, T_year string, T_month stri
 
 }
 
-func Read_Warning_ALL_T_State_Count(T_pid int, T_pids []int, T_handle int, bindSN []string, T_Warning string, Is_Today bool) (cnt int64) {
+// 用户首页统计
+func Read_Warning_ALL_T_State_Count2(T_pid int, T_pids []int, T_handle int, bindSN []string, T_Warning string, Is_Today bool) (cnt int64) {
 	o := orm.NewOrm()
 	qs := o.QueryTable(new(Warning))
 	cond := orm.NewCondition()
@@ -804,6 +817,53 @@ func Read_Warning_ALL_T_State_Count(T_pid int, T_pids []int, T_handle int, bindS
 	return cnt
 }
 
+// 用户首页统计,使用gorm查询
+func Read_Warning_ALL_T_State_Count(T_pid int, T_pids []int, T_handle int, bindSN []string, T_Warning string, Is_Today bool) (cnt int64) {
+
+	tableName := "warning"
+	if conf.UseNewWarningQuery {
+		tableName = fmt.Sprintf("warning_%s_%s", time.Now().Format("2006"), time.Now().Format("01"))
+	}
+	gormDB := db.DB.Table(tableName)
+	gormDB.Where("t__state > 0 ")
+	if T_pid > 0 {
+		gormDB.Where("t_pid = ?", T_pid)
+	}
+	if T_pid == 0 {
+		gormDB.Where("t_pid in (?)", T_pids)
+	}
+
+	if len(bindSN) > 0 {
+		gormDB.Where("t_sn in (?)", bindSN)
+	}
+
+	if Is_Today {
+		startTime := time.Now().Format("2006-01-02") + " 00:00:00"
+		endTime := time.Now().Format("2006-01-02") + " 23:59:59"
+		gormDB.Where("t__ut between ? and ?", startTime, endTime)
+	}
+
+	if len(T_Warning) > 0 && T_Warning != "*" {
+		list := lib.SplitStringIds(T_Warning, "W")
+		gormDB.Where("t_tp in (?)", list)
+	}
+
+	// T_State 0 删除   1 不处理   2 已处理   3 未处理
+	// T_handle  1:默认 2:全部记录 3 未处理
+	if T_handle == 1 {
+		gormDB.Where("t__state > ?", 1)
+	}
+	if T_handle == 3 {
+		gormDB.Where("t__state = ?", 3)
+	}
+	err := gormDB.Count(&cnt).Error
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+
+	return cnt
+}
+
 // 设备日志
 type DeviceLogs struct {
 	Id         int64
@@ -897,7 +957,7 @@ func Read_Warning_List_By_DS_T_type(admin *Account.Admin, T_pid int, bindSN []st
 		"LEFT JOIN ( SELECT t_sn AS tsn,t_id AS tid,t_type FROM device_sensor) AS ds " +
 		"ON w.t_sn = ds.tsn AND w.t_id = ds.tid " +
 		"WHERE " + sql_WHERE
-	cnt, err := Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	cnt, _, err := Redis_WarningCount_GetOne(T_pid, countRedisKey)
 	if err != nil {
 		fmt.Println(sql)
 		_, err = o.Raw(sql).ValuesList(&maps_z)
@@ -910,7 +970,7 @@ func Read_Warning_List_By_DS_T_type(admin *Account.Admin, T_pid int, bindSN []st
 		}
 		cnt, _ = strconv.ParseInt(maps_z[0][0].(string), 10, 64)
 
-		Redis_WarningCount_Set(T_pid, countRedisKey, cnt)
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, map[string]int64{})
 	}
 
 	if cnt == 0 {
@@ -1019,14 +1079,14 @@ func Read_Company_Warning_List(T_pids []int, T_tp []string, T_name string, T_han
 
 	var err error
 	// 从redis获取报警统计数量
-	cnt, err = Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	cnt, _, err = Redis_WarningCount_GetOne(T_pid, countRedisKey)
 	if err != nil {
 		cnt, err = qs.SetCond((*orm2.Condition)(cond1)).Count()
 		if err != nil {
 			logs.Error(lib.FuncName(), err)
 			return
 		}
-		Redis_WarningCount_Set(T_pid, countRedisKey, cnt)
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, map[string]int64{})
 	}
 	if cnt == 0 {
 		return r, 0
@@ -1106,7 +1166,7 @@ func Read_Company_Warning_Backups(T_pids []int, T_year string, T_month string, T
 	sql_WHERE = strings.TrimLeft(sql_WHERE, " AND")
 
 	// 从redis获取报警统计数量
-	cnt, err := Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	cnt, _, err := Redis_WarningCount_GetOne(T_pid, countRedisKey)
 	if err != nil {
 		sql := "SELECT COUNT(*) FROM " + Wtab + " WHERE " + sql_WHERE
 		fmt.Println(sql)
@@ -1120,7 +1180,7 @@ func Read_Company_Warning_Backups(T_pids []int, T_year string, T_month string, T
 		}
 		cnt, _ = strconv.ParseInt(maps_z[0][0].(string), 10, 64)
 
-		Redis_WarningCount_Set(T_pid, countRedisKey, cnt)
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, map[string]int64{})
 	}
 	if cnt == 0 {
 		return r, 0
@@ -1145,3 +1205,511 @@ func Read_Company_Warning_Backups(T_pids []int, T_year string, T_month string, T
 	return r, cnt
 
 }
+
+func GormReadWarningListScopes(T_pid int, bindSN, tpList []string, T_name string, T_handle int, Time_start_ string, Time_end_ string) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		if len(bindSN) > 0 {
+			db.Where("t_sn in (?)", bindSN)
+		}
+
+		if T_pid > 0 {
+			db.Where("t_pid = ?", T_pid)
+		}
+		if len(tpList) > 0 {
+			min, max, is := checkStringListContinuous(tpList)
+			if is {
+				db.Where("t_tp between ? and ?", min, max)
+			} else {
+				db.Where("t_tp in (?)", tpList)
+			}
+		}
+		if len(T_name) > 0 {
+			if len(T_name) == 16 {
+				db.Where("t_sn = ?", T_name)
+			} else {
+				likeName := "%" + T_name + "%"
+				db.Where("t_sn like ? or t__d_name like ? or t_id like ? or t__d_s_name like ? ", likeName, likeName, likeName, likeName)
+			}
+		}
+
+		if len(Time_start_) > 0 {
+			db.Where("t__ut >= ?", Time_start_)
+		}
+		if len(Time_end_) > 0 {
+			db.Where("t__ut <= ?", Time_end_)
+		}
+		// T_State 0 删除   1 不处理   2 已处理   3 未处理
+		// T_handle  1:默认 2:全部记录 3 未处理
+		if T_handle == 1 {
+			db.Where("t__state > ?", 1)
+		} else if T_handle == 3 {
+			db.Where("t__state = ?", 3)
+		} else {
+			db.Where("t__state > ?", 0)
+		}
+		return db
+	}
+}
+
+// 获取列表
+func Gorm_Read_Warning_List(T_pid int, bindSN, tpList []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int,
+	countRedisKey string) (r []Warning_R, cnt int64) {
+	tableNames := GenerateWarningTableNames(Time_start_, Time_end_)
+	var err error
+	var warnings []Warning
+	tableCount := make(map[string]int64)
+	gormReadWarningListScopes := GormReadWarningListScopes(T_pid, bindSN, tpList, T_name, T_handle, Time_start_, Time_end_)
+	// 从redis获取报警统计数量
+	cnt, tableCount, err = Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	if err != nil {
+		for _, tableName := range tableNames {
+			tableDB := db.DB.Table(tableName)
+			var count int64
+
+			tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+			tableCount[tableName] = count
+			cnt += count
+		}
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, tableCount)
+	}
+
+	if cnt == 0 {
+		return r, 0
+	}
+	if page_z == 9999 {
+		for _, tableName := range tableNames {
+			var tableWarning []Warning
+			tableDB := db.DB.Table(tableName)
+			tableDB.Scopes(gormReadWarningListScopes).
+				Order("t__ut desc").Offset(-1).Limit(-1).Find(&tableWarning)
+			warnings = append(warnings, tableWarning...)
+		}
+		for _, v := range warnings {
+			r = append(r, WarningToWarning_R(0, v))
+		}
+		return r, cnt
+	}
+	offset := (page - 1) * page_z
+	remaining := offset
+	for _, tableName := range tableNames {
+		var tableWarning []Warning
+		tableDB := db.DB.Table(tableName)
+		var count int64
+		if tableName == fmt.Sprintf("warning_%d_%02d", time.Now().Year(), time.Now().Month()) {
+			if saveTime, ok := tableCount["SaveTime"]; ok {
+				t1 := time.Unix(saveTime, 0)
+				if time.Now().Sub(t1) < 5*time.Minute {
+					if count, ok = tableCount[tableName]; !ok {
+						tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+						tableCount[tableName] = count
+					}
+				} else {
+					tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+					tableCount[tableName] = count
+				}
+			}
+		} else {
+			var ok bool
+			if count, ok = tableCount[tableName]; !ok {
+				tableDB.Scopes(gormReadWarningListScopes).Count(&count)
+				tableCount[tableName] = count
+			}
+		}
+
+		if remaining >= int(count) {
+			remaining -= int(count)
+			continue
+		}
+
+		tableDB.Scopes(gormReadWarningListScopes).
+			Order("t__ut desc").Offset(remaining).Limit(page_z - len(warnings)).Find(&tableWarning)
+
+		warnings = append(warnings, tableWarning...)
+		if len(warnings) >= page_z {
+			break
+		}
+		remaining = 0
+	}
+	for _, v := range warnings {
+		r = append(r, WarningToWarning_R(0, v))
+	}
+	return r, cnt
+}
+
+func Gorm_Read_Warning_List_Excel(T_pid int, bindSN, tpList []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int,
+	countRedisKey string) (r []Warning_R, cnt int64) {
+	tableNames := GenerateWarningTableNames(Time_start_, Time_end_)
+	gormReadWarningListScopes := GormReadWarningListScopes(T_pid, bindSN, tpList, T_name, T_handle, Time_start_, Time_end_)
+
+	var warnings []Warning
+	var wg sync.WaitGroup
+
+	for _, tableName := range tableNames {
+		wg.Add(1)
+		go func(table string) {
+			defer wg.Done()
+			offset := 0
+			limit := 10000
+			for {
+				var tableWarning []Warning
+				tableDB := db.DB.Table(table)
+				tableDB.Scopes(gormReadWarningListScopes).
+					Order("t__ut desc").Offset(offset).Limit(limit).Find(&tableWarning)
+				if len(tableWarning) == 0 {
+					break // 如果没有数据则结束循环
+				}
+				offset += limit // 更新偏移量
+				warnings = append(warnings, tableWarning...)
+			}
+		}(tableName)
+	}
+	// 等待所有协程完成
+	wg.Wait()
+	// 倒序
+	sort.Slice(warnings, func(i, j int) bool {
+		if warnings[i].T_Ut.After(warnings[j].T_Ut) {
+			return true
+		}
+		return false
+	})
+	for _, v := range warnings {
+		r = append(r, WarningToWarning_R(0, v))
+	}
+
+	return r, cnt
+
+}
+
+func GormReadAdminWarningListScopes(admin Account.Admin, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		if admin.T_pids != "*" && len(admin.T_pids) > 0 {
+			list := lib.SplitStringIds(admin.T_pids, "P")
+			db.Where("t_pid in (?)", list)
+		}
+		if len(T_tp) > 0 {
+			min, max, is := checkStringListContinuous(T_tp)
+			if is {
+				db.Where("t_tp between ? and ?", min, max)
+			} else {
+				db.Where("t_tp in (?)", T_tp)
+			}
+		}
+
+		if len(T_name) > 0 {
+			if len(T_name) == 16 {
+				db.Where("t_sn = ?", T_name)
+			} else {
+				likeName := "%" + T_name + "%"
+				db.Where("t_sn like ? or t__d_name like ? or t_id like ? or t__d_s_name like ? ", likeName, likeName, likeName, likeName)
+			}
+		}
+
+		if len(Time_start_) > 0 {
+			db.Where("t__ut >= ?", Time_start_)
+		}
+		if len(Time_end_) > 0 {
+			db.Where("t__ut <= ?", Time_end_)
+		}
+		// T_State 0 删除   1 不处理   2 已处理   3 未处理
+		// T_handle  1:默认 2:全部记录 3 未处理
+		if T_handle == 1 {
+			db.Where("t__state > ?", 1)
+		} else if T_handle == 3 {
+			db.Where("t__state = ?", 3)
+		} else {
+			db.Where("t__state > ?", 0)
+		}
+		return db
+	}
+}
+
+// 管理员报警列表
+func Gorm_Read_Admin_Warning_List(admin Account.Admin, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int,
+	countRedisKey string) (r []Warning_R, cnt int64) {
+
+	if len(admin.T_pids) == 0 {
+		return r, cnt
+	}
+	gormReadAdminWarningListScopes := GormReadAdminWarningListScopes(admin, T_tp, T_name, T_handle, Time_start_, Time_end_)
+	tableNames := GenerateWarningTableNames(Time_start_, Time_end_)
+	var err error
+	var warnings []Warning
+	tableCount := make(map[string]int64)
+	// 从redis获取报警统计数量
+	cnt, tableCount, err = Redis_WarningCount_GetOne(admin.Id, countRedisKey)
+	if err != nil {
+		for _, tableName := range tableNames {
+			tableDB := db.DB.Table(tableName)
+			var count int64
+
+			tableDB.Scopes(gormReadAdminWarningListScopes).Count(&count)
+			tableCount[tableName] = count
+			cnt += count
+		}
+		Redis_WarningCount_Set(admin.Id, countRedisKey, cnt, tableCount)
+	}
+
+	if cnt == 0 {
+		return r, 0
+	}
+	// page_z == 9999  获取全部
+	if page_z == 9999 {
+		for _, tableName := range tableNames {
+			var tableWarning []Warning
+			tableDB := db.DB.Table(tableName)
+			tableDB.Scopes(gormReadAdminWarningListScopes).
+				Order("t__ut desc").Offset(-1).Limit(-1).Find(&tableWarning)
+			warnings = append(warnings, tableWarning...)
+		}
+		for _, v := range warnings {
+			r = append(r, WarningToWarning_R(0, v))
+		}
+		return r, cnt
+	}
+
+	offset := (page - 1) * page_z
+	remaining := offset
+	for _, tableName := range tableNames {
+		var tableWarning []Warning
+		tableDB := db.DB.Table(tableName)
+
+		count := tableCount[tableName]
+
+		if remaining >= int(count) {
+			remaining -= int(count)
+			continue
+		}
+
+		tableDB.Scopes(gormReadAdminWarningListScopes).
+			Order("t__ut desc").Offset(remaining).Limit(page_z - len(warnings)).Find(&tableWarning)
+		warnings = append(warnings, tableWarning...)
+		if len(warnings) >= page_z {
+			break
+		}
+		remaining = 0
+	}
+	for _, v := range warnings {
+		r = append(r, WarningToWarning_R(0, v))
+	}
+	return r, cnt
+}
+func Gorm_Read_Admin_Warning_List_Excel(admin Account.Admin, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int,
+	countRedisKey string) (r []Warning_R, cnt int64) {
+
+	if len(admin.T_pids) == 0 {
+		return r, cnt
+	}
+	gormReadAdminWarningListScopes := GormReadAdminWarningListScopes(admin, T_tp, T_name, T_handle, Time_start_, Time_end_)
+	tableNames := GenerateWarningTableNames(Time_start_, Time_end_)
+	var warnings []Warning
+	var wg sync.WaitGroup
+
+	for _, tableName := range tableNames {
+		wg.Add(1)
+		go func(table string) {
+			defer wg.Done()
+			offset := 0
+			limit := 10000
+			for {
+				var tableWarning []Warning
+				tableDB := db.DB.Table(table)
+				tableDB.Scopes(gormReadAdminWarningListScopes).
+					Order("t__ut desc").Offset(offset).Limit(limit).Find(&tableWarning)
+				if len(tableWarning) == 0 {
+					break // 如果没有数据则结束循环
+				}
+				offset += limit // 更新偏移量
+				warnings = append(warnings, tableWarning...)
+			}
+		}(tableName)
+	}
+	// 等待所有协程完成
+	wg.Wait()
+	// 倒序
+	sort.Slice(warnings, func(i, j int) bool {
+		if warnings[i].T_Ut.After(warnings[j].T_Ut) {
+			return true
+		}
+		return false
+	})
+	for _, v := range warnings {
+		r = append(r, WarningToWarning_R(0, v))
+	}
+
+	return r, cnt
+
+}
+func GormReadCompanyWarningListScopes(T_pids []int, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string) func(db *gorm.DB) *gorm.DB {
+	return func(db *gorm.DB) *gorm.DB {
+		if len(T_pids) > 0 {
+			db.Where("t_pid in (?)", T_pids)
+		}
+		if len(T_tp) > 0 {
+			min, max, is := checkStringListContinuous(T_tp)
+			if is {
+				db.Where("t_tp between ? and ?", min, max)
+			} else {
+				db.Where("t_tp in (?)", T_tp)
+			}
+		}
+
+		if len(T_name) > 0 {
+			if len(T_name) == 16 {
+				db.Where("t_sn = ?", T_name)
+			} else {
+				likeName := "%" + T_name + "%"
+				db.Where("t_sn like ? or t__d_name like ? or t_id like ? or t__d_s_name like ?", likeName, likeName, likeName, likeName)
+			}
+		}
+
+		if len(Time_start_) > 0 {
+			db.Where("t__ut >= ?", Time_start_)
+		}
+		if len(Time_end_) > 0 {
+			db.Where("t__ut <= ?", Time_end_)
+		}
+		// T_State 0 删除   1 不处理   2 已处理   3 未处理
+		// T_handle  1:默认 2:全部记录 3 未处理
+		if T_handle == 1 {
+			db.Where("t__state > ?", 1)
+		} else if T_handle == 3 {
+			db.Where("t__state = ?", 3)
+		} else {
+			db.Where("t__state > ?", 0)
+		}
+		return db
+	}
+}
+
+// 公司管理报警列表
+func Gorm_Read_Company_Warning_List(T_pids []int, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int,
+	T_pid int, countRedisKey string) (r []CompanyWarning_R, cnt int64) {
+
+	gormReadCompanyWarningListScopes := GormReadCompanyWarningListScopes(T_pids, T_tp, T_name, T_handle, Time_start_, Time_end_)
+	tableNames := GenerateWarningTableNames(Time_start_, Time_end_)
+	var err error
+	var warnings []Warning
+	tableCount := make(map[string]int64)
+	// 从redis获取报警统计数量
+	cnt, tableCount, err = Redis_WarningCount_GetOne(T_pid, countRedisKey)
+	if err != nil {
+		for _, tableName := range tableNames {
+			tableDB := db.DB.Table(tableName)
+			var count int64
+
+			tableDB.Scopes(gormReadCompanyWarningListScopes).Count(&count)
+			tableCount[tableName] = count
+			cnt += count
+		}
+		Redis_WarningCount_Set(T_pid, countRedisKey, cnt, tableCount)
+	}
+
+	if cnt == 0 {
+		return r, 0
+	}
+
+	offset := (page - 1) * page_z
+	remaining := offset
+	for _, tableName := range tableNames {
+		var tableWarning []Warning
+		tableDB := db.DB.Table(tableName)
+
+		count := tableCount[tableName]
+		if remaining >= int(count) {
+			remaining -= int(count)
+			continue
+		}
+
+		tableDB.Scopes(gormReadCompanyWarningListScopes).
+			Order("t__ut desc").Offset(remaining).Limit(page_z - len(warnings)).Find(&tableWarning)
+		warnings = append(warnings, tableWarning...)
+		if len(warnings) >= page_z {
+			break
+		}
+		remaining = 0
+	}
+	for _, v := range warnings {
+		r = append(r, WarningToCompanyWarning_R(0, v))
+	}
+	return r, cnt
+
+}
+
+func Gorm_Read_Company_Warning_List_Excel(T_pids []int, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int,
+	T_pid int, countRedisKey string) (r []CompanyWarning_R, cnt int64) {
+
+	gormReadCompanyWarningListScopes := GormReadCompanyWarningListScopes(T_pids, T_tp, T_name, T_handle, Time_start_, Time_end_)
+	tableNames := GenerateWarningTableNames(Time_start_, Time_end_)
+	var warnings []Warning
+	var wg sync.WaitGroup
+
+	for _, tableName := range tableNames {
+		wg.Add(1)
+		go func(table string) {
+			defer wg.Done()
+			offset := 0
+			limit := 10000
+			for {
+				var tableWarning []Warning
+				tableDB := db.DB.Table(table)
+				tableDB.Scopes(gormReadCompanyWarningListScopes).
+					Order("t__ut desc").Offset(offset).Limit(limit).Find(&tableWarning)
+				if len(tableWarning) == 0 {
+					break // 如果没有数据则结束循环
+				}
+				offset += limit // 更新偏移量
+				warnings = append(warnings, tableWarning...)
+			}
+		}(tableName)
+	}
+	// 等待所有协程完成
+	wg.Wait()
+	// 倒序
+	sort.Slice(warnings, func(i, j int) bool {
+		if warnings[i].T_Ut.After(warnings[j].T_Ut) {
+			return true
+		}
+		return false
+	})
+	for _, v := range warnings {
+		r = append(r, WarningToCompanyWarning_R(0, v))
+	}
+	return r, cnt
+}
+
+func GenerateWarningTableNames(startDateStr string, endDateStr string) []string {
+	startDate, _ := lib.TimeStrToTime(startDateStr)
+
+	endDate, _ := lib.TimeStrToTime(endDateStr)
+
+	monthsArray := []string{}
+	for startDate.Before(endDate) || startDate.Equal(endDate) {
+		monthsArray = append(monthsArray, fmt.Sprintf("warning_%d_%02d", startDate.Year(), startDate.Month()))
+		startDate = time.Date(startDate.Year(), startDate.Month()+1, 1, 0, 0, 0, 0, time.Local)
+	}
+	sort.Stable(sort.Reverse(sort.StringSlice(monthsArray)))
+	return monthsArray
+}
+
+// 检查数据列表是否连续 返回最小值 最大值
+func checkStringListContinuous(nums []string) (int, int, bool) {
+	intNums := make([]int, len(nums))
+	for i, num := range nums {
+		parsedNum, err := strconv.Atoi(num)
+		if err != nil {
+			fmt.Println("Error converting string to int:", err)
+			return 0, 0, false
+		}
+		intNums[i] = parsedNum
+	}
+
+	sort.Ints(intNums)
+
+	for i := 1; i < len(intNums); i++ {
+		if intNums[i] != intNums[i-1]+1 {
+			return 0, 0, false
+		}
+	}
+
+	return intNums[0], intNums[len(intNums)-1], true
+}

+ 7 - 2
routers/Warning.go

@@ -12,10 +12,13 @@ func init() {
 		// 设备报警
 		beego.NSNamespace("/DeviceWarning",
 			beego.NSRouter("/List", &controllers.DeviceController{}, "*:DeviceWarning_List"),                          // 告警列表
+			beego.NSRouter("/List2", &controllers.DeviceController{}, "*:DeviceWarning_List2"),                        // 告警列表 - 跨月查询
+			beego.NSRouter("/List_sse", &controllers.DeviceController{}, "*:DeviceWarning_List_Sse"),                  // 告警列表 - 跨月查询
 			beego.NSRouter("/Get", &controllers.DeviceController{}, "*:DeviceWarning_Get"),                            // 获取告警
 			beego.NSRouter("/Edit", &controllers.DeviceController{}, "*:DeviceWarning_Post"),                          // 修改告警 报警处理
 			beego.NSRouter("/Del", &controllers.DeviceController{}, "*:DeviceWarning_Del"),                            // 删除告警
 			beego.NSRouter("/ToExcel", &controllers.DeviceController{}, "*:DeviceWarning_Data_Excel"),                 // 导出excel
+			beego.NSRouter("/ToExcel2", &controllers.DeviceController{}, "*:DeviceWarning_Data_Excel2"),               // 导出excel
 			beego.NSRouter("/DeviceSensor_List", &controllers.DeviceController{}, "*:Read_Warning_List_By_DS_T_type"), // 告警列表 - 小程序
 
 		),
@@ -40,8 +43,10 @@ func init() {
 
 		// 公司管理-设备报警
 		beego.NSNamespace("/CompanyWarning",
-			beego.NSRouter("/List", &controllers.DeviceController{}, "*:CompanyWarning_List"),          // 告警列表
-			beego.NSRouter("/ToExcel", &controllers.DeviceController{}, "*:CompanyWarning_Data_Excel"), // 告警列表
+			beego.NSRouter("/List", &controllers.DeviceController{}, "*:CompanyWarning_List"),            // 告警列表
+			beego.NSRouter("/List2", &controllers.DeviceController{}, "*:CompanyWarning_List2"),          // 告警列表
+			beego.NSRouter("/ToExcel", &controllers.DeviceController{}, "*:CompanyWarning_Data_Excel"),   // 告警列表
+			beego.NSRouter("/ToExcel2", &controllers.DeviceController{}, "*:CompanyWarning_Data_Excel2"), // 告警列表
 		),
 	)