Procházet zdrojové kódy

2023-09-06 用户绑定主机

zoie před 1 rokem
rodič
revize
f0c4cd1973

+ 1 - 2
conf/app.conf

@@ -66,8 +66,7 @@ Panel_url = "http://127.0.0.1:6204/Cold_Panel"
 FilterExcludeURL = /Login_verification,/Data/List,/WxPay/Notify
 # 小程序 冷链验证 /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,/DeviceWarning/DeviceSensor_List,/Device/Applet_Stat_View2,/DeviceSensor/Applet_List_View1,/DeviceSensor/Applet_List_View2,/DeviceSensorType/List,/Device/DeviceTask_Post,/Data/DeviceSensor_Data_Print
-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
+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
 
 
 MqttIds = mqttjxit,mqttlodr,mqttyuht

+ 333 - 4
controllers/Data.go

@@ -7,6 +7,7 @@ import (
 	"Cold_Api/logs"
 	"Cold_Api/models/Account"
 	"Cold_Api/models/Device"
+	"encoding/base64"
 	"fmt"
 	beego "github.com/beego/beego/v2/server/web"
 	"github.com/signintech/gopdf"
@@ -104,7 +105,13 @@ func (c *DataController) Device_Sensor_List() {
 
 	var cnt int64
 	Device.Read_DeviceSensorParameter_All_Map("", 0)
-	r_jsons.DeviceSensor_lite, cnt = Device.Read_DeviceSensor_List_For_Data(c.T_pid, T_name, T_Class_id, T_type, T_RealTime, T_MapShow, page, page_z)
+	bindSN, err := Account.Read_UserDevice_List(c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+	r_jsons.DeviceSensor_lite, cnt = Device.Read_DeviceSensor_List_For_Data(c.Admin_r, bindSN, c.T_pid, T_name, T_Class_id, T_type, T_RealTime, T_MapShow, page, page_z)
 
 	page_size := math.Ceil(float64(cnt) / float64(page_z))
 	r_jsons.Page = page
@@ -117,6 +124,60 @@ func (c *DataController) Device_Sensor_List() {
 	return
 
 }
+func (c *DataController) Company_Device_Sensor_List() {
+	var r_jsons lib.R_JSONS
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+
+	if page_z == 0 {
+		page_z = conf.Page_size
+	}
+
+	T_Class_id, _ := c.GetInt("T_calssid")
+	T_type, T_type_err := c.GetInt("T_type")
+	if T_type_err != nil {
+		T_type = -1
+	}
+	T_name := c.GetString("T_name")
+
+	// 数据展示页面
+	T_RealTime, T_RealTime_err := c.GetInt("T_RealTime")
+	if T_RealTime_err != nil {
+		T_RealTime = 0
+	}
+
+	// 轨迹展示页面
+	T_MapShow, T_MapShow_err := c.GetInt("T_MapShow")
+	if T_MapShow_err != nil {
+		T_MapShow = 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
+	}
+	// 查询公司下面所有子公司id
+	T_pids := Account.ReadCompanyIds_T_path(Company_r.T_path)
+	var cnt int64
+	Device.Read_DeviceSensorParameter_All_Map("", 0)
+	Account.Read_Company_All_Maps()
+	r_jsons.Data, cnt = Device.Read_CompanyDeviceSensor_List_For_Data(&c.Admin_r, T_pids, T_name, T_Class_id, T_type, T_RealTime, T_MapShow, page, page_z)
+
+	page_size := math.Ceil(float64(cnt) / float64(page_z))
+	r_jsons.Page = page
+	r_jsons.Page_size = int(page_size)
+	r_jsons.Num = cnt
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+
+}
 
 // 传感器数据列表
 func (c *DataController) Device_Sensor_Data() {
@@ -571,9 +632,6 @@ func (c *DataController) Device_Sensor_Data_PDF() {
 	pdf.SetMargins(0, 20, 0, 20)
 	pdf.AddPage()
 
-	//use path
-	//pdf.Image("logo.png", 100, 50, &gopdf.Rect{W: 50, H: 50})
-
 	company, _ := Account.Read_Company_ById(c.T_pid)
 
 	textw, _ := pdf.MeasureTextWidth(company.T_name)
@@ -693,6 +751,277 @@ func (c *DataController) Device_Sensor_Data_PDF() {
 
 }
 
+// 图表展示 下载PDF
+func (c *DataController) Device_Sensor_Data_ChartShow_PDF() {
+	T_snid := c.GetString("T_snid")
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	// 获取图片信息
+	//f, _, err := c.GetFile("file")
+	//if err != nil {
+	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "读取文件错误"}
+	//	c.ServeJSON()
+	//	return
+	//}
+	//// 延迟关闭文件
+	//defer f.Close()
+	//var img image.Image
+	//if img, err = png.Decode(f); err != nil {
+	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "读取文件错误"}
+	//	c.ServeJSON()
+	//	return
+	//}
+	base64String := c.GetString("file")
+
+	imageBytes, err := base64.StdEncoding.DecodeString(base64String)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "解析base64失败"}
+		c.ServeJSON()
+		return
+	}
+
+	if len(T_snid) < 10 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_snid Err!"}
+		c.ServeJSON()
+		return
+	}
+	var DeviceSensor_data []Device.DeviceData_R
+
+	DeviceSensor_data, _ = Device.Read_DeviceData_By_T_snid_List(T_snid, Time_start, Time_end, 0, 9999)
+	// 最高温度及时刻
+	maxTemp := DeviceSensor_data[0].T_t
+	maxTempTime := DeviceSensor_data[0].T_time
+	// 最低温度及时刻
+	minTemp := DeviceSensor_data[0].T_t
+	minTempTime := DeviceSensor_data[0].T_time
+	// 总温度
+	var totalTemp float32 = 0
+	// 最高湿度及时刻
+	maxHumidity := DeviceSensor_data[0].T_rh
+	maxHumidityTime := DeviceSensor_data[0].T_time
+	// 获取最低湿度及时刻
+	minHumidity := DeviceSensor_data[0].T_rh
+	minHumidityTime := DeviceSensor_data[0].T_time
+	// 总湿度
+	var totalHumidity float32 = 0
+	for _, data := range DeviceSensor_data {
+		if data.T_t > maxTemp {
+			maxTemp = data.T_t
+			maxTempTime = data.T_time
+		}
+		if data.T_t < minTemp {
+			minTemp = data.T_t
+			minTempTime = data.T_time
+		}
+		totalTemp += data.T_t
+
+		if data.T_rh > maxHumidity {
+			maxHumidity = data.T_rh
+			maxHumidityTime = data.T_time
+		}
+		if data.T_rh < minHumidity {
+			minHumidity = data.T_rh
+			minHumidityTime = data.T_time
+		}
+		totalHumidity += data.T_rh
+	}
+	// 平均温度
+	avgTemp := totalTemp / float32(len(DeviceSensor_data))
+	// 平均湿度
+	avgHumidity := totalHumidity / float32(len(DeviceSensor_data))
+
+	pdf := &gopdf.GoPdf{}
+	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
+	//err = GetFont(pdf, "LiberationSerif-Regular.ttf")
+	//if err != nil {
+	//	log.Fatalln(err)
+	//}
+	//err = pdf.SetFont("Ubuntu-L", "", 14)
+	//if err != nil {
+	//	log.Fatalln(err)
+	//}
+	err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+	err = pdf.SetFont("wts", "", 24)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+
+	pdf.SetGrayFill(0.5)
+
+	pdf.SetMargins(0, 20, 0, 20)
+	pdf.AddPage()
+
+	company, _ := Account.Read_Company_ById(c.T_pid)
+	title := company.T_name + "仓库温湿度报告"
+
+	var y float64 = 40
+	textw, _ := pdf.MeasureTextWidth(title)
+	pdf.SetX((595 / 2) - (textw / 2))
+	pdf.SetY(y)
+	pdf.Text(title)
+
+	y += 40
+	pdf.SetFont("wts", "", 18)
+	pdf.SetXY(10, y)
+	pdf.Text("记录概要信息")
+	// 线
+	y += 10
+	pdf.SetLineWidth(0.5)
+	pdf.SetStrokeColor(169, 169, 169)
+	pdf.Line(10, y, 575, y)
+
+	y += 20
+	var s_time, e_time string
+	if len(DeviceSensor_data) > 0 {
+		e_time = fmt.Sprintf("%s", DeviceSensor_data[0].T_time)
+		s_time = fmt.Sprintf("%s", DeviceSensor_data[len(DeviceSensor_data)-1].T_time)
+	}
+	pdf.SetFont("wts", "", 10)
+	pdf.SetXY(10, y)
+	pdf.Text(fmt.Sprintf("记录开始时间: %s", s_time))
+
+	pdf.SetXY(240, y)
+	pdf.Text(fmt.Sprintf("记录结束时间: %s", e_time))
+
+	sTime, _ := lib.TimeStrToTime(s_time)
+	eTime, _ := lib.TimeStrToTime(e_time)
+	pdf.SetXY(470, y)
+	pdf.Text(fmt.Sprintf("记录总时间: %.2f", eTime.Sub(sTime).Minutes()))
+
+	y += 18
+	pdf.SetXY(10, y)
+	pdf.Text(fmt.Sprintf("最高温度: %.2f℃,%s", maxTemp, maxTempTime))
+
+	pdf.SetXY(240, y)
+	pdf.Text(fmt.Sprintf("最低温度: %.2f℃,%s", minTemp, minTempTime))
+
+	pdf.SetXY(470, y)
+	pdf.Text(fmt.Sprintf("平均温度: %.2f℃", avgTemp))
+
+	y += 18
+	pdf.SetXY(10, y)
+	pdf.Text(fmt.Sprintf("最高湿度: %.2f%%RH,%s", maxHumidity, maxHumidityTime))
+
+	pdf.SetXY(240, y)
+	pdf.Text(fmt.Sprintf("最低湿度: %.2f%%RH,%s", minHumidity, minHumidityTime))
+
+	pdf.SetXY(470, y)
+	pdf.Text(fmt.Sprintf("平均湿度: %.2f%%RH", avgHumidity))
+
+	y += 40
+	pdf.SetFont("wts", "", 18)
+	pdf.SetXY(10, y)
+	pdf.Text("记录曲线信息")
+	// 线
+	y += 10
+	pdf.SetLineWidth(0.5)
+	pdf.SetStrokeColor(169, 169, 169)
+	pdf.Line(10, y, 575, y)
+	y += 10
+	// ----------------绘制图片
+	//pdf.ImageFrom(img, 10, y, &gopdf.Rect{W: 575, H: 630})
+	imgH, err := gopdf.ImageHolderByBytes(imageBytes)
+	pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 630})
+
+	// 图片结束直接分页
+	pdf.AddPage()
+	y = 40
+	pdf.SetFont("wts", "", 18)
+	pdf.SetXY(10, y)
+	pdf.Text("记录数据信息")
+	// 线
+	y += 10
+	pdf.SetLineWidth(0.5)
+	pdf.SetStrokeColor(169, 169, 169)
+	pdf.Line(10, y, 575, y)
+	y += 10
+	pdf.SetFont("wts", "", 10)
+	lib.RectFillColor(pdf, "序号", 12, 22, y, 30, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+	lib.RectFillColor(pdf, "传感器名称", 12, 52, y, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+	lib.RectFillColor(pdf, "温度℃", 12, 152, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+
+	lib.RectFillColor(pdf, "湿度%", 12, 202, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+
+	lib.RectFillColor(pdf, "温度范围", 12, 252, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+	lib.RectFillColor(pdf, "湿度范围", 12, 332, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+	lib.RectFillColor(pdf, "记录时间", 12, 412, y, 120, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+	lib.RectFillColor(pdf, "备注", 12, 532, y, 40, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+
+	y += 20
+	for i, v := range DeviceSensor_data {
+		text := fmt.Sprintf(" %d ", i+1)
+		var textH float64 = 25 // if text height is 25px.
+		pdf.SetNewY(y, textH)
+		y = pdf.GetY()
+		//pdf.SetX(x) // must after pdf.SetNewY() called.
+		//err = pdf.Text(text)
+		//if err != nil {
+		//	log.Fatalln(err)
+		//}
+
+		T_t := fmt.Sprintf(" %.1f ", v.T_t)
+		T_rh := fmt.Sprintf(" %.1f ", v.T_rh)
+		T_Tlu := fmt.Sprintf(" %.1f ~ %.1f ", v.T_tl, v.T_tu)
+		T_Rlu := fmt.Sprintf(" %.1f ~ %.1f ", v.T_rhl, v.T_rhu)
+		T_time := fmt.Sprintf("%s", v.T_time)
+
+		if v.T_ist == 1 {
+			lib.RectFillColor(pdf, T_t, 10, 152, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			lib.RectFillColor(pdf, T_Tlu, 10, 252, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		} else {
+			lib.RectFillColor(pdf, "", 10, 152, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			lib.RectFillColor(pdf, "", 10, 252, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		}
+		if v.T_ish == 1 {
+			lib.RectFillColor(pdf, T_rh, 10, 202, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			lib.RectFillColor(pdf, T_Rlu, 10, 332, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		} else {
+			lib.RectFillColor(pdf, "", 10, 202, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			lib.RectFillColor(pdf, "", 10, 332, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		}
+
+		lib.RectFillColor(pdf, text, 10, 22, y, 30, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		lib.RectFillColor(pdf, v.T_name, 10, 52, y, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+
+		lib.RectFillColor(pdf, T_time, 10, 412, y, 120, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		lib.RectFillColor(pdf, v.T_remark, 10, 532, y, 40, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+		y += 20
+	}
+	timeStr := "ofile/" + time.Now().Format("20060102150405") + ".pdf"
+
+	err = pdf.WritePdf(timeStr)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
+		c.ServeJSON()
+		return
+	}
+
+	// 上传 OSS
+	url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/"+timeStr, timeStr)
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
+		c.ServeJSON()
+		return
+	}
+	//删除目录
+	err = os.Remove(timeStr)
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
+	c.ServeJSON()
+	return
+
+}
+
 // 数据备份
 func (c *DataController) Device_Sensor_Data_BackUp() {
 	page, _ := c.GetInt("page")

+ 126 - 32
controllers/Device.go

@@ -66,8 +66,14 @@ func (c *DeviceController) Device_List() {
 	Name := c.GetString("T_name")
 	T_online := c.GetString("T_online")
 	T_monitor := c.GetString("T_monitor")
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
 
-	r_jsons.Device_lite, r_jsons.Num = Device.Read_Device_List(c.Admin_r, c.T_pid, Name, T_monitor, T_online, page, page_z)
+	r_jsons.Device_lite, r_jsons.Num = Device.Read_Device_List(c.Admin_r, bindSN, c.T_pid, Name, T_monitor, T_online, page, page_z)
 
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
@@ -104,12 +110,13 @@ func (c *DeviceController) Device_Add() {
 	var err error
 	T_sn := c.GetString("T_sn")
 	var_ := Device.Device{
-		T_pid:     c.T_pid,
-		T_sn:      T_sn,
-		T_monitor: 1, // 监控状态 已监控
-		T_State:   1, // 状态 正常
-		T_ist:     1, // 温度   1开启
-		T_ish:     1, // 湿度   1开启
+		T_pid:      c.T_pid,
+		T_sn:       T_sn,
+		T_protocol: 3,
+		T_monitor:  1, // 监控状态 已监控
+		T_State:    1, // 状态 正常
+		T_ist:      1, // 温度   1开启
+		T_ish:      1, // 湿度   1开启
 	}
 	if len(T_sn) < 8 {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "SN 太短 必须8个字符以上"}
@@ -604,6 +611,24 @@ func (c *DeviceController) Device_Parameter_Pu() {
 
 }
 
+// 设备参数同步
+func (c *DeviceController) Device_Parameter_Sync() {
+	T_SN := c.GetString("T_sn")
+	Device_r, err := Device.Read_Device_ByT_sn(T_SN)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_sn Err!"}
+		c.ServeJSON()
+		return
+	}
+	NatsServer.Read_DeviceParameter(T_SN, Device_r.T_mqttid)
+	NatsServer.Read_DeviceSensorParameter(T_SN, Device_r.T_mqttid)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+
+}
+
 // 删除设备 传感器
 // 2023-02-02 弃用
 func (c *DeviceController) Device_Parameter_Del_Device() {
@@ -679,7 +704,13 @@ func (c *DeviceController) DeviceSensor_List() {
 			return
 		}
 	}
-	r_jsons.Data, r_jsons.Num = Device.Read_DeviceSensorList(c.Admin_r, c.T_pid, T_sn, T_name, T_class_id, T_datashow, T_type, T_State, page, page_z)
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+	r_jsons.Data, r_jsons.Num = Device.Read_DeviceSensorList(c.Admin_r, bindSN, c.T_pid, T_sn, T_name, T_class_id, T_datashow, T_type, T_State, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -900,15 +931,19 @@ func (c *DeviceController) DeviceSensor_Parameter_Pu() {
 		temp, _ := decimal.NewFromFloat(v).Round(2).Float64()
 		T_hpreu = float32(temp)
 	}
-
-	T_speed := DeviceSensorParameter.T_speed
-	if v, T_speed_err := c.GetInt("T_speed"); T_speed_err == nil {
-		T_speed = v
-	}
-	T_sense := DeviceSensorParameter.T_sense
-	if v, T_sense_err := c.GetInt("T_sense"); T_sense_err == nil {
-		T_sense = v
+	T_enprelnote := DeviceSensorParameter.T_enprelnote
+	if v, T_enprel_err := c.GetInt("T_enprelnote"); T_enprel_err == nil {
+		T_enprelnote = v
 	}
+
+	//T_speed := DeviceSensorParameter.T_speed
+	//if v, T_speed_err := c.GetInt("T_speed"); T_speed_err == nil {
+	//	T_speed = v
+	//}
+	//T_sense := DeviceSensorParameter.T_sense
+	//if v, T_sense_err := c.GetInt("T_sense"); T_sense_err == nil {
+	//	T_sense = v
+	//}
 	T_en := DeviceSensorParameter.T_en
 	if v, T_en_err := c.GetInt("T_en"); T_en_err == nil {
 		T_en = v
@@ -925,16 +960,17 @@ func (c *DeviceController) DeviceSensor_Parameter_Pu() {
 		T_Tupper:  T_Tupper,
 		T_RHlower: T_RHlower,
 		T_RHupper: T_RHupper,
-		T_speed:   T_speed,
-		T_sense:   T_sense,
-		T_en:      T_en,
-		T_free:    T_free,
-
-		T_enprel: T_enprel,
-		T_tprel:  T_tprel,
-		T_tpreu:  T_tpreu,
-		T_hprel:  T_hprel,
-		T_hpreu:  T_hpreu,
+		//T_speed:   T_speed,
+		//T_sense:   T_sense,
+		T_en:   T_en,
+		T_free: T_free,
+
+		T_enprel:     T_enprel,
+		T_tprel:      T_tprel,
+		T_tpreu:      T_tpreu,
+		T_hprel:      T_hprel,
+		T_hpreu:      T_hpreu,
+		T_enprelnote: T_enprelnote,
 
 		T_uuid:      c.Admin_r.T_uuid,
 		T_SendState: 0,
@@ -1023,7 +1059,14 @@ func (c *DeviceController) DeviceSensor_Manage_List() {
 		T_sort = -1
 	}
 
-	r_jsons.Data, r_jsons.Num = Device.Read_DeviceSensorManageList(c.Admin_r, c.T_pid, T_name, T_calss_id, T_en, T_free, T_datashow, T_sort, page, page_z)
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	r_jsons.Data, r_jsons.Num = Device.Read_DeviceSensorManageList(c.Admin_r, bindSN, c.T_pid, T_name, T_calss_id, T_en, T_free, T_datashow, T_sort, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -1167,6 +1210,29 @@ func (c *DeviceController) CompanyClass_All() {
 	c.ServeJSON()
 	return
 }
+
+// 查询公司及公司下所有子公司的公司分类
+func (c *DeviceController) CompanyClass_All_For_Company() {
+
+	var r_jsons lib.R_JSONS
+
+	T_name := c.GetString("T_name")
+	// 查询公司
+	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
+	}
+	// 查询公司下面所有子公司id
+	T_pids := Account.ReadCompanyIds_T_path(Company_r.T_path)
+	Account.Read_Company_All_Maps()
+	r_jsons.Data = Company.Read_CompanyClass_All_For_Company(T_pids, T_name)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
 func (c *DeviceController) CompanyClass_Get() {
 	id, _ := c.GetInt("T_id")
 	R_DeviceClass, err := Company.Read_CompanyClass_ById(id)
@@ -1801,8 +1867,13 @@ func (c *DeviceController) DeviceSensorType_List_All() {
 func (c *DeviceController) DeviceSensorType_List() {
 
 	var r_jsons lib.R_JSONS
-
-	list, err := Device.Read_DeviceSensor_T_type(c.T_pid)
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+	list, err := Device.Read_DeviceSensor_T_type(c.T_pid, bindSN)
 	if err != nil {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
 		c.ServeJSON()
@@ -1849,7 +1920,14 @@ func (c *DeviceController) Device_Applet_Stat() {
 		return
 	}
 
-	snList, err := Device.Read_DeviceSensor_T_sn_ByT_type(c.T_pid, T_type)
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	snList, err := Device.Read_DeviceSensor_T_sn_ByT_type(c.T_pid, bindSN, T_type)
 	if err != nil {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
 		c.ServeJSON()
@@ -1896,7 +1974,15 @@ func (c *DeviceController) DeviceSensor_Applet_List_View1() {
 	if T_type_err != nil {
 		T_type = -1
 	}
-	r_jsons.Data, r_jsons.Num = Device.Read_DeviceSensor_List_For_Applet(c.T_pid, T_name, "3", 1, T_type, page, page_z)
+
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	r_jsons.Data, r_jsons.Num = Device.Read_DeviceSensor_List_For_Applet(c.Admin_r, bindSN, c.T_pid, T_name, "3", 1, T_type, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -1925,7 +2011,15 @@ func (c *DeviceController) DeviceSensor_Applet_List_View2() {
 	if T_type_err != nil {
 		T_type = -1
 	}
-	dsList, _ := Device.Read_DeviceSensor_List_For_Applet(c.T_pid, T_name, T_online, 1, T_type, page, 9999)
+
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	dsList, _ := Device.Read_DeviceSensor_List_For_Applet(c.Admin_r, bindSN, c.T_pid, T_name, T_online, 1, T_type, page, 9999)
 
 	var deviceMap = make(map[string][]Device.DeviceSensor_Applet)
 	var num int64

+ 317 - 15
controllers/User.go

@@ -7,6 +7,7 @@ import (
 	"Cold_Api/logs"
 	"Cold_Api/models/Account"
 	"Cold_Api/models/Company"
+	"Cold_Api/models/Device"
 	"Cold_Api/models/System"
 	"Cold_Api/models/Warning"
 	"encoding/json"
@@ -406,6 +407,38 @@ func (c *UserController) Company_Entry() {
 	return
 }
 
+// 记账扣费
+func (c *UserController) Company_Charging() {
+
+	Id, Id_err := c.GetInt("Id")
+	if Id_err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	Company_r, err := Account.Read_Company_ById(Id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	T_Charging, _ := c.GetInt("T_Charging")
+	Company_r.T_Charging = T_Charging
+	is := Account.Update_Company(Company_r, "T_Charging")
+	if !is {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	System.Add_UserLogs_T(c.Admin_r.T_uuid, "公司管理", "记账扣费", Company_r)
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+}
+
 // 检查 Tokey 是否过期
 
 // 用户管理
@@ -659,6 +692,28 @@ func (c *UserController) User_Del() {
 
 // 管理员
 func (c *UserController) User_Home() {
+	// 报警标识
+	//设备管理-设备报警 callthepolice
+	//公司管理-设备报警 companyCallthepolice
+	//T_warning_sign := c.GetString("T_warning_sign")
+	power, err := Account.Read_Power_ById(c.Admin_r.T_power)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取菜单失败"}
+		c.ServeJSON()
+		return
+	}
+	ret := Account.Read_Menu_Bind_List(power.Id, power.T_menu, c.T_pid)
+	var T_warning_sign string
+	for _, v := range ret.MenuPermission {
+		if v == Warning.CompanyCallthepolice {
+			T_warning_sign = Warning.CompanyCallthepolice
+			break
+		}
+		if v == Warning.Callthepolice {
+			T_warning_sign = Warning.Callthepolice
+		}
+	}
+
 	// 验证登录
 	admin_r := c.Admin_r
 
@@ -668,23 +723,33 @@ func (c *UserController) User_Home() {
 	}
 
 	type Info struct {
-		T_name                string           // 姓名
-		T_pids                string           // 内部用户绑定的公司id
-		T_pid                 int              // 公司id
-		T_Days                int              // 服务天输
-		Admin                 []Account.Admin_ // 专属管理员
-		WarningNum            int64            // 报警数量
-		UntreatedWarningNum   int64            // 未处理报警数量
-		WorkOrderNum          int64            // 工单数量
-		WarningRate           float32          // 设备报警率
-		UntreatedWorkOrderNum int64            // 未处理工单数量
-		Balance               float32          // 余额
-		NoticeRecord          NoticeRecord     // 通知记录
+		T_name              string           // 姓名
+		T_pids              string           // 内部用户绑定的公司id
+		T_pid               int              // 公司id
+		T_Days              int              // 服务天输
+		Admin               []Account.Admin_ // 专属管理员
+		WarningSign         string           // 报警标识
+		WarningNum          int64            // 报警数量
+		UntreatedWarningNum int64            // 未处理报警数量
+		NewsNum             int64            // 消息数量
+
+		WorkOrderNum          int64        // 工单数量
+		WarningRate           float32      // 设备报警率
+		UntreatedWorkOrderNum int64        // 未处理工单数量
+		Balance               float32      // 余额
+		NoticeRecord          NoticeRecord // 通知记录
 	}
 	var info Info
 	info.T_name = admin_r.T_name
 	info.T_pid = admin_r.T_pid
 	if admin_r.T_pid > 0 {
+		info.WarningSign = T_warning_sign
+		bindSN, err := Account.Read_UserDevice_List(c.Admin_r)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+			c.ServeJSON()
+			return
+		}
 		power, _ := Account.Read_Power_ById(admin_r.T_power)
 		company, _ := Account.Read_Company_ById(admin_r.T_pid)
 		info.T_Days = lib.GetDiffDays(time.Now(), company.CreateTime)
@@ -694,8 +759,28 @@ func (c *UserController) User_Home() {
 			Admin_ = append(Admin_, Account.Admin_RToAdmin_(v))
 		}
 		info.Admin = Admin_
-		info.WarningNum = Warning.Read_Warning_ALL_T_State_Count(admin_r.T_pid, 1, power.T_warning, true)
-		info.UntreatedWarningNum = Warning.Read_Warning_ALL_T_State_Count(admin_r.T_pid, 3, power.T_warning, false)
+
+		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 := []int{}
+		// 拥有公司管理-设备报警权限 统计公司及其所有子公司的今日报警数量、未处理报警数量、我的消息数量
+		if T_warning_sign == Warning.CompanyCallthepolice {
+			T_pids = Account.ReadCompanyIds_T_path(Company_r.T_path)
+			info.WarningNum = Warning.Read_Warning_ALL_T_State_Count(0, T_pids, 1, bindSN, power.T_warning, true)
+			info.UntreatedWarningNum = Warning.Read_Warning_ALL_T_State_Count(0, T_pids, 3, bindSN, power.T_warning, false)
+			info.NewsNum = Warning.Read_Warning_ALL_T_State_Count(0, T_pids, 1, bindSN, "T1003|T1002|", false)
+		}
+		// 拥有设备管理-设备报警权限 统计本公司今日报警数量、未处理报警数量、我的消息数量
+		if T_warning_sign == Warning.Callthepolice {
+			info.WarningNum = Warning.Read_Warning_ALL_T_State_Count(admin_r.T_pid, T_pids, 1, bindSN, power.T_warning, true)
+			info.UntreatedWarningNum = Warning.Read_Warning_ALL_T_State_Count(admin_r.T_pid, T_pids, 3, bindSN, power.T_warning, false)
+			info.NewsNum = Warning.Read_Warning_ALL_T_State_Count(admin_r.T_pid, T_pids, 1, bindSN, "T1003|T1002|", false)
+		}
+
 		info.Balance = company.T_money
 		info.NoticeRecord.Sms = Warning.Get_WarningSandNum_CurrentMonth(admin_r.T_pid, 1)
 		info.NoticeRecord.Phone = Warning.Get_WarningSandNum_CurrentMonth(admin_r.T_pid, 2)
@@ -1325,7 +1410,7 @@ func (c *UserController) User_Menu_List() {
 		c.ServeJSON()
 		return
 	}
-	logs.Println("登录用户 菜单 pid 为:", c.T_pid)
+	//logs.Println("登录用户 菜单 pid 为:", c.T_pid)
 	ret := Account.Read_Menu_Bind_List(power.Id, power.T_menu, c.T_pid)
 	r_jsons.Data = ret.Menu
 	r_jsons.Permission = ret.Permission
@@ -1767,3 +1852,220 @@ func (c *UserController) WxPay_GetOrderState() {
 	c.ServeJSON()
 	return
 }
+
+// 设备分类绑定
+func (c *UserController) UserDeviceBind_List() {
+
+	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_uuid := c.GetString("T_uuid")
+	admin_r, err := Account.Read_Admin_ByUuid(T_uuid)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	bindSN, err := Account.Read_UserDevice_List(admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+	if len(bindSN) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+		c.ServeJSON()
+		return
+	}
+
+	r_jsons.Data, r_jsons.Num = Device.Read_Device_List(&c.Admin_r, bindSN, c.T_pid, T_name, "", "", page, page_z)
+	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 *UserController) UserDeviceUnbind_List() {
+
+	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_uuid := c.GetString("T_uuid")
+	admin_r, err := Account.Read_Admin_ByUuid(T_uuid)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	bindSN, err := Account.Read_UserDevice_List(admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	r_jsons.Data, r_jsons.Num = Device.Read_User_Unbind_Device_List(&c.Admin_r, bindSN, c.T_pid, T_name, page, page_z)
+	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 *UserController) UserDeviceBind_Add() {
+
+	T_sn := c.GetString("T_sn")
+	T_uuid := c.GetString("T_uuid")
+	T_oneHey, _ := c.GetInt("T_oneKey") // 一键绑定
+
+	if T_oneHey == 1 {
+		admin_r, err := Account.Read_Admin_ByUuid(T_uuid)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+			c.ServeJSON()
+			return
+		}
+
+		bindSN, err := Account.Read_UserDevice_List(admin_r)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+			c.ServeJSON()
+			return
+		}
+
+		Unbind_Device_List, _ := Device.Read_User_Unbind_Device_List(&c.Admin_r, bindSN, c.T_pid, "", 0, 9999)
+		var UserDeviceList []Account.UserDevice
+		for _, r := range Unbind_Device_List {
+			UserDeviceList = append(UserDeviceList, Account.UserDevice{T_sn: r.T_sn, T_uuid: T_uuid})
+		}
+		if _, err = Account.Add_UserDevice_Multi(T_uuid, UserDeviceList); err != nil {
+			c.Data["json"] = lib.JSONS{Code: 200, Msg: "绑定失败"}
+			c.ServeJSON()
+			return
+		}
+		System.Add_UserLogs(c.Admin_r.T_uuid, "用户管理", "一键绑定主机操作", T_uuid+"-"+T_sn)
+		c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+		c.ServeJSON()
+		return
+	}
+
+	if len(T_uuid) == 0 || len(T_sn) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_sn T_id T_class_id Err!"}
+		c.ServeJSON()
+		return
+	}
+	if len(T_uuid) < 8 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+		c.ServeJSON()
+		return
+	}
+	device, err := Device.Read_Device_ByT_sn(T_sn)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	admin_r, err := Account.Read_Admin_ByUuid(T_uuid)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+		c.ServeJSON()
+		return
+	}
+	if admin_r.T_pid != device.T_pid {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_pid Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	userdievice, err := Account.Read_UserDevice_ByT_uuid_T_sn(T_uuid, T_sn)
+	if userdievice.Id > 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "重复绑定!"}
+		c.ServeJSON()
+		return
+	}
+
+	if _, err = Account.Add_UserDevice(Account.UserDevice{T_sn: T_sn, T_uuid: T_uuid}); err != nil {
+		c.Data["json"] = lib.JSONS{Code: 200, Msg: "绑定失败"}
+		c.ServeJSON()
+		return
+	}
+	System.Add_UserLogs(c.Admin_r.T_uuid, "用户管理", "绑定主机操作", T_uuid+"-"+T_sn)
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+}
+func (c *UserController) UserDeviceBind_Del() {
+	T_sn := c.GetString("T_sn")
+	T_uuid := c.GetString("T_uuid")
+	if len(T_uuid) == 0 || len(T_sn) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_sn T_id T_class_id Err!"}
+		c.ServeJSON()
+		return
+	}
+	if len(T_uuid) < 8 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+		c.ServeJSON()
+		return
+	}
+	device, err := Device.Read_Device_ByT_sn(T_sn)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_sn Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	admin_r, err := Account.Read_Admin_ByUuid(T_uuid)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	if admin_r.T_pid != device.T_pid {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_pid Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	userdievice, err := Account.Read_UserDevice_ByT_uuid_T_sn(T_uuid, T_sn)
+	if err != nil {
+		if err.Error() == orm.ErrNoRows.Error() {
+			c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+			c.ServeJSON()
+			return
+		}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "解绑失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	if err = Account.Delete_UserDevice(Account.UserDevice{Id: userdievice.Id, T_sn: T_sn, T_uuid: T_uuid}); err != nil {
+		c.Data["json"] = lib.JSONS{Code: 200, Msg: "删除失败"}
+		c.ServeJSON()
+		return
+	}
+	System.Add_UserLogs(c.Admin_r.T_uuid, "用户管理", "解绑主机操作", T_uuid+"-"+T_sn)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+	c.ServeJSON()
+	return
+}

+ 212 - 9
controllers/Warning.go

@@ -54,7 +54,16 @@ func (c *DeviceController) DeviceWarning_List() {
 		tpList = lib.SplitStringIds(T_tp, "T")
 	} else {
 		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
-		tpList = lib.SplitStringIds(power.T_warning, "W")
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
 	}
 
 	var T_year, T_month string
@@ -68,6 +77,7 @@ func (c *DeviceController) DeviceWarning_List() {
 		T_year, T_month = date.Format("2006"), date.Format("01")
 	}
 
+	// 管理员界面
 	if T_admin == 1 {
 		if T_history == 1 {
 			// 获取备份
@@ -81,11 +91,75 @@ func (c *DeviceController) DeviceWarning_List() {
 		return
 	}
 
+	// 公司报警界面
 	if T_history == 1 {
-		r_jsons.Data, r_jsons.Num = Warning.Read_Warning_Backups(c.T_pid, T_year, T_month, tpList, T_name, T_handle, Time_start, Time_end, page, page_z)
+		r_jsons.Data, r_jsons.Num = Warning.Read_Warning_Backups(c.T_pid, bindSN, T_year, T_month, tpList, T_name, T_handle, Time_start, Time_end, page, page_z)
 	} else {
 		// 获取最新
-		r_jsons.Data, r_jsons.Num = Warning.Read_Warning_List(c.T_pid, tpList, T_name, T_handle, Time_start, Time_end, page, page_z)
+		r_jsons.Data, r_jsons.Num = Warning.Read_Warning_List(c.T_pid, bindSN, tpList, T_name, T_handle, Time_start, Time_end, page, page_z)
+	}
+	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) CompanyWarning_List() {
+
+	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")
+
+	T_history, _ := c.GetInt("T_history")
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+
+	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 T_year, T_month string
+	if T_history == 1 {
+		date, err := time.Parse("2006-01-02 15:04:05", Time_start)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式错误"}
+			c.ServeJSON()
+			return
+		}
+		T_year, T_month = date.Format("2006"), date.Format("01")
+	}
+	Account.Read_Company_All_Maps()
+	if T_history == 1 {
+		r_jsons.Data, r_jsons.Num = Warning.Read_Company_Warning_Backups(T_pids, T_year, T_month, tpList, T_name, T_handle, Time_start, Time_end, page, page_z)
+	} else {
+		// 获取最新
+		r_jsons.Data, r_jsons.Num = Warning.Read_Company_Warning_List(T_pids, tpList, T_name, T_handle, Time_start, Time_end, page, page_z)
 	}
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
@@ -241,17 +315,24 @@ func (c *DeviceController) DeviceWarning_Data_Excel() {
 		T_year, T_month = date.Format("2006"), date.Format("01")
 	}
 
+	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_history == 1 {
 		// 获取备份
-		Device_data, _ = Warning.Read_Warning_Backups(c.T_pid, T_year, T_month, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999)
+		Device_data, _ = Warning.Read_Warning_Backups(c.T_pid, bindSN, T_year, T_month, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999)
 	} else {
 		// 获取最新
-		Device_data, _ = Warning.Read_Warning_List(c.T_pid, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999)
+		Device_data, _ = Warning.Read_Warning_List(c.T_pid, bindSN, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999)
 	}
 
 	f := excelize.NewFile() // 设置单元格的值
-	// 这里设置表头
+	// 这里设置表头ÒÒ
 	f.SetCellValue("Sheet1", "A1", "报警类型")
 	f.SetCellValue("Sheet1", "B1", "Sn")
 	f.SetCellValue("Sheet1", "C1", "设备名称")
@@ -277,7 +358,7 @@ func (c *DeviceController) DeviceWarning_Data_Excel() {
 	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.Id))
+		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)
@@ -299,7 +380,116 @@ func (c *DeviceController) DeviceWarning_Data_Excel() {
 		return
 	}
 	//删除文件
-	err := os.Remove("ofile/" + timeStr + ".xlsx")
+	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_Excel() {
+	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_history, _ := c.GetInt("T_history")
+	var tpList []string
+	if len(T_tp) > 0 {
+		tpList = lib.SplitStringIds(T_tp, "T")
+	} else {
+		power, _ := Account.Read_Power_ById(c.Admin_r.T_power)
+		if power.T_warning != "*" {
+			tpList = lib.SplitStringIds(power.T_warning, "W")
+		}
+	}
+	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 T_year, T_month string
+	if T_history == 1 {
+		date, err := time.Parse("2006-01-02 15:04:05", Time_start)
+		if err != nil {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "时间格式错误"}
+			c.ServeJSON()
+			return
+		}
+		T_year, T_month = date.Format("2006"), date.Format("01")
+	}
+
+	var Device_data []Warning.CompanyWarning_R
+	if T_history == 1 {
+		// 获取备份
+		Device_data, _ = Warning.Read_Company_Warning_Backups(T_pids, T_year, T_month, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999)
+	} else {
+		// 获取最新
+		Device_data, _ = Warning.Read_Company_Warning_List(T_pids, tpList, T_name, T_handle, Time_start, Time_end, 0, 9999)
+	}
+
+	f := excelize.NewFile() // 设置单元格的值
+	// 这里设置表头
+	f.SetCellValue("Sheet1", "A1", "报警类型")
+	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", 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("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)
+
+	}
+	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)
 	}
@@ -353,7 +543,14 @@ func (c *DeviceController) Read_Warning_List_By_DS_T_type() {
 	T_type, _ := c.GetInt("T_type")
 	T_name := c.GetString("T_name")
 
-	r_jsons.Data, r_jsons.Num = Warning.Read_Warning_List_By_DS_T_type(c.T_pid, T_type, T_name, page, page_z)
+	bindSN, err := Account.Read_UserDevice_List(*c.Admin_r)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	r_jsons.Data, r_jsons.Num = Warning.Read_Warning_List_By_DS_T_type(c.T_pid, bindSN, T_type, T_name, page, page_z)
 	r_jsons.Page = page
 	r_jsons.Page_size = int(math.Ceil(float64(r_jsons.Num) / float64(page_z)))
 
@@ -438,6 +635,12 @@ func (c *DeviceController) Read_WarningRate_List() {
 	c.ServeJSON()
 	return
 }
+func (c *DeviceController) Read_WarningHandle_List() {
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Warning.Read_WarningHandle_List()}
+	c.ServeJSON()
+	return
+}
 
 func Cron_WarningRate() {
 

+ 20 - 1
controllers/lib/libString.go

@@ -3,6 +3,7 @@ package lib
 import (
 	"crypto/md5"
 	"encoding/hex"
+	"fmt"
 	"math/rand"
 	"strconv"
 	"strings"
@@ -103,8 +104,26 @@ func IntIdsDistinct(Ids []int) (result []int) {
 }
 
 func StringListToDotStr(str []string) (r string) {
+	//for _, v := range str {
+	//	r += v + ","
+	//}
+	//r = strings.TrimRight(r, ",")
+
+	return strings.Join(str, ",")
+}
+
+func IntListToDotStr(list []int) (r string) {
+	for _, v := range list {
+		r += fmt.Sprintf("%d,", v)
+	}
+	r = strings.TrimRight(r, ",")
+	return r
+}
+
+// ["a","b","c"] ==> "'a','b','c'"
+func StringListToQuotesDotStr(str []string) (r string) {
 	for _, v := range str {
-		r += v + ","
+		r += fmt.Sprintf("'%s',", v)
 	}
 	r = strings.TrimRight(r, ",")
 	return r

+ 61 - 27
models/Account/Company.go

@@ -12,6 +12,7 @@ import (
 	orm2 "github.com/beego/beego/v2/client/orm"
 	_ "github.com/go-sql-driver/mysql"
 	"strconv"
+	"sync"
 	"time"
 )
 
@@ -29,6 +30,7 @@ type Company struct {
 	T_money    float32   `orm:"digits(12);decimals(2)"`
 	T_State    int       `orm:"size(200);default(1)"`                                  // 0删除  1正常
 	T_warning  int       `orm:"size(20);default(1)"`                                   // 是否处理报警信息 1处理 2不处理
+	T_Charging int       `orm:"size(11);default(0)"`                                   //  记账扣费 公司ID  默认为:0 (自己)
 	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` // auto_now 每次 model 保存时都会对时间自动更新
 	UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     // auto_now_add 第一次保存时才设置时间
 
@@ -36,15 +38,17 @@ type Company struct {
 }
 
 type Company_R struct {
-	Id        int
-	T_mid     int     // 上一级 ID
-	T_name    string  // 公司名称
-	T_plan    string  // 平面图
-	T_data    string  // 大数据
-	T_v3d     string  // 3D 视图
-	T_money   float32 // 余额
-	T_warning int     // 报警统计
-	Children  []Company_R
+	Id         int
+	T_mid      int     // 上一级 ID
+	T_name     string  // 公司名称
+	T_plan     string  // 平面图
+	T_data     string  // 大数据
+	T_v3d      string  // 3D 视图
+	T_money    float32 // 余额
+	T_warning  int     // 报警统计
+	T_key      string
+	T_Charging int
+	Children   []Company_R
 }
 
 func CompanyToCompany_R(r Company) (v Company_R) {
@@ -56,6 +60,8 @@ func CompanyToCompany_R(r Company) (v Company_R) {
 	v.T_v3d = r.T_v3d
 	v.T_money = r.T_money
 	v.T_warning = r.T_warning
+	v.T_key = r.T_key
+	v.T_Charging = r.T_Charging
 	return v
 }
 
@@ -65,8 +71,11 @@ func (t *Company) TableName() string {
 
 var redisCache_Company cache.Cache
 
+var Company_map *sync.Map // 泛型
 func init() {
 	//注册模型
+	Company_map = new(sync.Map)
+	//注册模型
 	orm.RegisterModel(new(Company))
 
 	config := fmt.Sprintf(`{"key":"%s","conn":"%s","dbNum":"%s","password":"%s"}`,
@@ -265,15 +274,16 @@ func Read_Company_Tree(admin_r Admin, T_name string) (CompanyList []Company_R) {
 				continue
 			}
 			r := Company_R{
-				Id:        maps[i].Id,
-				T_mid:     maps[i].T_mid,
-				T_name:    maps[i].T_name,
-				T_plan:    maps[i].T_plan,
-				T_data:    maps[i].T_data,
-				T_v3d:     maps[i].T_v3d,
-				T_money:   maps[i].T_money,
-				T_warning: maps[i].T_warning,
-				Children:  nil,
+				Id:         maps[i].Id,
+				T_mid:      maps[i].T_mid,
+				T_name:     maps[i].T_name,
+				T_plan:     maps[i].T_plan,
+				T_data:     maps[i].T_data,
+				T_v3d:      maps[i].T_v3d,
+				T_money:    maps[i].T_money,
+				T_warning:  maps[i].T_warning,
+				T_Charging: maps[i].T_Charging,
+				Children:   nil,
 			}
 			info := CompanyCall(maps, r)
 			CompanyList = append(CompanyList, info)
@@ -281,15 +291,16 @@ func Read_Company_Tree(admin_r Admin, T_name string) (CompanyList []Company_R) {
 	} else {
 		for i := 0; i < len(maps); i++ {
 			r := Company_R{
-				Id:        maps[i].Id,
-				T_mid:     maps[i].T_mid,
-				T_name:    maps[i].T_name,
-				T_plan:    maps[i].T_plan,
-				T_data:    maps[i].T_data,
-				T_v3d:     maps[i].T_v3d,
-				T_money:   maps[i].T_money,
-				T_warning: maps[i].T_warning,
-				Children:  nil,
+				Id:         maps[i].Id,
+				T_mid:      maps[i].T_mid,
+				T_name:     maps[i].T_name,
+				T_plan:     maps[i].T_plan,
+				T_data:     maps[i].T_data,
+				T_v3d:      maps[i].T_v3d,
+				T_money:    maps[i].T_money,
+				T_warning:  maps[i].T_warning,
+				T_Charging: maps[i].T_Charging,
+				Children:   nil,
 			}
 			info := CompanyCall(maps, r)
 			CompanyList = append(CompanyList, info)
@@ -557,3 +568,26 @@ func Read_Company_List_ByT_pids(T_pids string) (CompanyList []Company_R) {
 
 	return CompanyList
 }
+
+func Read_Company_All_Maps() {
+	o := orm.NewOrm()
+	var r []Company
+	qs := o.QueryTable(new(Company))
+	_, err := qs.All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+
+	for _, v := range r {
+		Company_map.Store(v.Id, v.T_name)
+	}
+
+}
+func Read_Company_Get(id int) string {
+	v, ok := Company_map.Load(id) /*如果确定是真实的,则存在,否则不存在 */
+	if ok {
+		return v.(string)
+	} else {
+		return "未知公司名称"
+	}
+}

+ 13 - 2
models/Account/Menu.go

@@ -35,8 +35,9 @@ type Menu struct {
 }
 
 type Menu_Permission struct {
-	Menu       []Menu
-	Permission []string
+	Menu           []Menu   // 菜单树形结构
+	Permission     []string // 菜单权限标识
+	MenuPermission []string // 菜单权限标识
 }
 
 func (t *Menu) TableName() string {
@@ -246,6 +247,7 @@ func Read_Menu_Bind_List(Power_Id int, Bind_Menu string, T_pid int) (r Menu_Perm
 		m := Menu_Tree(maps, 0)
 		r.Menu = m
 		r.Permission = Get_Permission(maps)
+		r.MenuPermission = Get_MenuPermission(maps)
 		Redis_Munu_Set(Power_Id, T_pid, r)
 		return r
 	}
@@ -268,6 +270,7 @@ func Read_Menu_Bind_List(Power_Id int, Bind_Menu string, T_pid int) (r Menu_Perm
 
 	r.Menu = m
 	r.Permission = Get_Permission(maps)
+	r.MenuPermission = Get_MenuPermission(maps)
 
 	Redis_Munu_Set(Power_Id, T_pid, r)
 	return r
@@ -281,6 +284,14 @@ func Get_Permission(menu []Menu) (permission []string) {
 	}
 	return
 }
+func Get_MenuPermission(menu []Menu) (menuPermission []string) {
+	for _, v := range menu {
+		if v.T_type == MenuType {
+			menuPermission = append(menuPermission, v.T_permission)
+		}
+	}
+	return
+}
 
 // 获取MenuIds下父id
 func recursiveMenu(T_pid int, MenuIds []int, AllIds *[]int) error {

+ 158 - 0
models/Account/UserDevice.go

@@ -0,0 +1,158 @@
+package Account
+
+import (
+	"Cold_Api/conf"
+	"Cold_Api/controllers/lib"
+	"Cold_Api/logs"
+	"encoding/json"
+	"fmt"
+	"github.com/astaxie/beego/cache"
+	"github.com/beego/beego/v2/adapter/orm"
+	"time"
+)
+
+type UserDevice struct {
+	Id     int    `orm:"column(ID);size(11);auto;pk"`
+	T_sn   string `orm:"size(256);null"`       // 设备序列号
+	T_uuid string `orm:"index;size(256);null"` // Account.Company 绑定用户
+}
+
+var redisCache_UserDevice cache.Cache
+
+func init() {
+	//注册模型
+	orm.RegisterModel(new(UserDevice))
+
+	config := fmt.Sprintf(`{"key":"%s","conn":"%s","dbNum":"%s","password":"%s"}`,
+		"redis_UserDevice", conf.Redis_address, conf.Redis_dbNum, conf.Redis_password)
+	fmt.Println(config)
+	var err error
+	redisCache_UserDevice, err = cache.NewCache("redis", config)
+	if err != nil || redisCache_UserDevice == nil {
+		errMsg := "failed to init redis"
+		logs.Error(errMsg, err)
+		panic(errMsg)
+	}
+}
+
+// ---------------- Redis -------------------
+// Redis_Set(m.T_sn,m) // Redis 更新缓存
+func Redis_UserDevice_Set(T_uuid string, deviceList []string) (err error) {
+	//json序列化
+	str, err := json.Marshal(deviceList)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	err = redisCache_UserDevice.Put(T_uuid, str, 24*time.Hour)
+	if err != nil {
+		logs.Error("Redis_UserDevice_Set", "set key:", T_uuid, ",value:", deviceList, err)
+	}
+	return
+}
+
+// if r,is :=Redis_Get(T_sn);is{
+// return r,nil
+// }
+func Redis_UserDevice_Get(key string) (r []string, is bool) {
+	if redisCache_UserDevice.IsExist(key) {
+		//println("找到key:",key)
+		v := redisCache_UserDevice.Get(key)
+
+		err := json.Unmarshal(v.([]byte), &r)
+		if err != nil {
+			logs.Error(lib.FuncName(), err)
+			return []string{}, false
+		}
+		return r, true
+	}
+	//println("没有 找到key:",key)
+	return []string{}, false
+}
+
+func Redis_UserDevice_DelK(key string) (err error) {
+	err = redisCache_UserDevice.Delete(key)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+}
+
+// ---------------- 特殊方法 -------------------
+
+// 添加
+func Add_UserDevice(m UserDevice) (id int64, err error) {
+	o := orm.NewOrm()
+	id, err = o.Insert(&m)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return id, err
+	}
+	Redis_UserDevice_DelK(m.T_uuid)
+	return id, err
+}
+
+// 批量添加主机
+func Add_UserDevice_Multi(T_uuid string, m []UserDevice) (id int64, err error) {
+	o := orm.NewOrm()
+	id, err = o.InsertMulti(len(m), &m)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return id, err
+	}
+	Redis_UserDevice_DelK(T_uuid)
+	return id, err
+}
+func Delete_UserDevice(v UserDevice) error {
+	o := orm.NewOrm()
+	_, err := o.Delete(&v)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return err
+	}
+	Redis_UserDevice_DelK(v.T_uuid)
+	return nil
+}
+
+func Read_UserDevice_List(admin Admin) (UserDeviceList []string, err error) {
+	if admin.T_pid == 0 {
+		return
+	}
+	T_uuid := admin.T_uuid
+	if r, is := Redis_UserDevice_Get(T_uuid); is {
+		//println("Redis_Get  OK")
+		return r, nil
+	}
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+
+	qs := o.QueryTable(new(UserDevice))
+	var maps []UserDevice
+
+	_, err = qs.Filter("T_uuid", T_uuid).All(&maps)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	deviceList := []string{}
+	for _, device := range maps {
+		deviceList = append(deviceList, device.T_sn)
+	}
+	Redis_UserDevice_Set(T_uuid, deviceList)
+	return deviceList, nil
+}
+
+func Read_UserDevice_ByT_uuid_T_sn(T_uuid, sn string) (r UserDevice, err error) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+
+	qs := o.QueryTable(new(UserDevice))
+
+	err = qs.Filter("T_uuid", T_uuid).Filter("T_sn", sn).One(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	return
+}

+ 44 - 0
models/Company/CompanyClass.go

@@ -4,6 +4,7 @@ import (
 	"Cold_Api/conf"
 	"Cold_Api/controllers/lib"
 	"Cold_Api/logs"
+	"Cold_Api/models/Account"
 	"encoding/json"
 	"fmt"
 	"github.com/astaxie/beego/cache"
@@ -31,6 +32,13 @@ type CompanyClass_R struct {
 	T_name string // 分类
 }
 
+type CompanyClass_Company struct {
+	Id         int
+	T_pid      int    // Account.Company 绑定公司
+	T_pid_name string // Account.Company 绑定公司名称
+	T_name     string // 分类
+}
+
 func (t *CompanyClass) TableName() string {
 	return "company_class" // 数据库名称   // ************** 替换 DesignClass **************
 }
@@ -107,6 +115,14 @@ func CompanyClassToCompanyClass_R(t CompanyClass) (r CompanyClass_R) {
 	return r
 }
 
+func CompanyClassToCompanyClass_Company(t CompanyClass) (r CompanyClass_Company) {
+	r.Id = t.Id
+	r.T_pid = t.T_pid
+	r.T_pid_name = Account.Read_Company_Get(t.T_pid)
+	r.T_name = t.T_name
+	return r
+}
+
 // 获取 ById
 func Read_CompanyClass_ById(id int) (r CompanyClass, err error) {
 	key := strconv.Itoa(id)
@@ -242,3 +258,31 @@ func Read_CompanyClass_All(T_pid int, T_name string) (r []CompanyClass_R) {
 	return r
 
 }
+func Read_CompanyClass_All_For_Company(T_pids []int, T_name string) (r []CompanyClass_Company) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+	var map_r []CompanyClass
+	qs := o.QueryTable(new(CompanyClass))
+
+	cond := orm.NewCondition()
+
+	cond1 := cond.And("T_State", 1).And("T_pid__in", T_pids)
+
+	if len(T_name) > 0 {
+		cond1 = cond1.And("T_name__icontains", T_name)
+	}
+
+	_, err := qs.SetCond((*orm2.Condition)(cond1)).OrderBy("T_pid").All(&map_r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	for _, v := range map_r {
+		r = append(r, CompanyClassToCompanyClass_Company(v))
+	}
+
+	return r
+
+}

+ 93 - 14
models/Device/Device.go

@@ -22,7 +22,7 @@ type Device struct {
 	T_sn              string    `orm:"pk;size(256);null"`    // 设备序列号
 	T_pid             int       `orm:"index;size(256);null"` // Account.Company 绑定公司
 	T_devName         string    `orm:"size(256);null"`       // 设备名称  20字
-	T_protocol        int       `orm:"size(2);default(1)"`   // 冷链通讯协议 1 :1.0协议   2 :2.0协议    3 :3.0协议
+	T_protocol        int       `orm:"size(2);default(3)"`   // 冷链通讯协议 1 :1.0协议   2 :2.0协议    3 :3.0协议
 	T_mqttid          string    `orm:"size(256);null"`       // MQTT 服务ID
 	T_VerifyTime      time.Time `orm:"type(timestamp);null"` // 验证时间
 	T_CalibrationTime time.Time `orm:"type(timestamp);null"` // 校准时间
@@ -30,13 +30,14 @@ type Device struct {
 	T_ist             int       `orm:"size(2);default(1)"`   // 温度   1开启   2关闭
 	T_ish             int       `orm:"size(2);default(1)"`   // 湿度   1开启   2关闭
 
+	T_State int `orm:"index;size(2);default(1)"` // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
+
 	// 设备同步参数
 	T_Dattery  int    `orm:"size(4);null"`             // 电量
 	T_Site     string `orm:"size(200);null"`           // GPS
 	T_monitor  int    `orm:"index;size(2);null"`       // 监控状态 0 未监控 1 监控  停止记录
 	T_online   int    `orm:"index;size(2);default(1)"` // 在线状态 0 未启用  1 在线  2 离线
 	T_online_s int    `orm:"index;size(2);default(0)"` // 在线状态-备用  0 未启用  1 在线  2 离线
-	T_State    int    `orm:"index;size(2);default(1)"` // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
 
 	// 硬件信息
 	T_model string `orm:"size(200);null"` // KF200BG  设备型号
@@ -129,9 +130,9 @@ func DeviceToDevice_R(r Device) (t Device_R) {
 	t.T_monitor = r.T_monitor
 	t.T_online = r.T_online
 	t.T_online_s = r.T_online_s
-	if (r.T_online == 0 || r.T_online == 2) && (r.T_online_s == 0 || r.T_online_s == 2) && r.T_monitor == 1 {
-		t.T_monitor = 2
-	}
+	//if (r.T_online == 0 || r.T_online == 2) && (r.T_online_s == 0 || r.T_online_s == 2) && r.T_monitor == 1 {
+	//	t.T_monitor = 2
+	//}
 	t.T_State = r.T_State
 
 	t.T_model = r.T_model
@@ -248,7 +249,7 @@ func Update_Device(r Device, cols ...string) bool {
 }
 
 // 获取列表
-func Read_Device_List(admin *Account.Admin, T_pid int, T_name string, T_monitor string, T_online string, page int, page_z int) (r []Device_R, cnt int64) {
+func Read_Device_List(admin *Account.Admin, bindSN []string, T_pid int, T_name string, T_monitor string, T_online string, page int, page_z int) (r []Device_R, cnt int64) {
 
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
@@ -263,13 +264,26 @@ func Read_Device_List(admin *Account.Admin, T_pid int, T_name string, T_monitor
 
 	cond := orm.NewCondition()
 	cond1 := cond.And("T_pid", T_pid)
-	// 非内部权限 - 不可查看屏蔽数据
-	if admin.T_pid > 0 {
-		cond1 = cond1.And("T_State", 1)
+
+	if len(bindSN) > 0 {
+		cond1 = cond1.And("T_sn__in", bindSN)
 	}
 
-	if len(T_name) > 0 {
-		cond1 = cond1.AndCond(cond.Or("T_sn__icontains", T_name).Or("T_devName__icontains", T_name))
+	// 非内部权限 - 不可查看屏蔽数据
+	if admin.T_pid > 0 {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_sn__icontains", T_name).Or("T_devName__icontains", T_name)).And("T_State", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1)
+		}
+	} else {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_sn__icontains", T_name).Or("T_devName__icontains", T_name))
+		}
 	}
 
 	// 0 未监控 1 监控  2 未知状态
@@ -277,8 +291,8 @@ func Read_Device_List(admin *Account.Admin, T_pid int, T_name string, T_monitor
 		// 未监控
 		cond1 = cond1.And("T_monitor", 0)
 	} else if T_monitor == "1" {
-		// 在线 - 网络在线并且为监控状态
-		cond1 = cond1.And("T_monitor", 1).AndCond(cond.Or("T_online", 1).Or("T_online_s", 1))
+		// 监控
+		cond1 = cond1.And("T_monitor", 1)
 	} else if T_monitor == "2" {
 		// 未知状态 - 网络为未启用或离线状态 监控状态
 		cond1 = cond1.And("T_monitor", 1).AndCond(cond.And("T_online", 0).Or("T_online", 2)).
@@ -348,7 +362,8 @@ func Read_Device_List_ByT_model(T_model string) (r []Device) {
 	return r
 }
 
-// 数据展示菜单下 传感器参数列表
+// 小程序 T_type = 2 分类管理统计
+// 通过T_monitor判断主机监控状态
 func Read_Device_Count_ByT_online(T_pid int, snList []string, T_online string) (cnt int64) {
 
 	o := orm2.NewOrm()
@@ -373,6 +388,7 @@ func Read_Device_Count_ByT_online(T_pid int, snList []string, T_online string) (
 	//	cond1 = cond1.And("T_online", 0).And("T_online_s", 0)
 	//}
 
+	// 0 未监控 1 监控中 2 无网络 3 全部
 	if T_online == "1" {
 		cond1 = cond1.And("T_monitor", 1)
 	} else if T_online == "2" {
@@ -390,3 +406,66 @@ func Read_Device_Count_ByT_online(T_pid int, snList []string, T_online string) (
 
 	return cnt
 }
+
+func Read_User_Unbind_Device_List(admin *Account.Admin, bindSN []string, T_pid int, T_name string, page int, page_z int) (r []Device_R, cnt int64) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+
+	qs := o.QueryTable(new(Device))
+	var offset int64
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = int64((page - 1) * page_z)
+	}
+
+	cond := orm.NewCondition()
+	cond1 := cond.And("T_pid", T_pid)
+
+	if len(bindSN) > 0 {
+		cond1 = cond1.AndNot("T_sn__in", bindSN)
+	}
+
+	// 非内部权限 - 不可查看屏蔽数据
+	if admin.T_pid > 0 {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_sn__icontains", T_name).Or("T_devName__icontains", T_name)).And("T_State", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1)
+		}
+	} else {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_sn__icontains", T_name).Or("T_devName__icontains", T_name))
+		}
+	}
+
+	var rx []Device
+	var err error
+	if page_z == 9999 {
+		_, err = qs.SetCond((*orm2.Condition)(cond1)).OrderBy("CreateTime").All(&rx)
+	} else {
+		_, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond1)).OrderBy("CreateTime").All(&rx)
+	}
+
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	cnt, err = qs.SetCond((*orm2.Condition)(cond1)).Count()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	for _, v := range rx {
+		r = append(r, DeviceToDevice_R(v))
+	}
+
+	return r, cnt
+}

+ 2 - 2
models/Device/DeviceData.go

@@ -23,8 +23,8 @@ var CREATEsql = " ( " +
 	"`t_id` int(6) NOT NULL," +
 	"`t_sp` int(6) NOT NULL," +
 	"`t_time` datetime NOT NULL," +
-	"`t_t` double(6, 2) NULL DEFAULT NULL," +
-	"`t_rh` double(6, 2) NULL DEFAULT NULL," +
+	"`t_t` double(6, 1) NULL DEFAULT NULL," +
+	"`t_rh` double(6, 1) NULL DEFAULT NULL," +
 	"`t_site` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL," +
 	"`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP," +
 	"PRIMARY KEY (`t_time`, `t_id`) USING BTREE" +

+ 256 - 33
models/Device/DeviceSensor.go

@@ -31,6 +31,8 @@ type DeviceSensor struct {
 	T_sort     int    `orm:"index;size(200);default(1)"` // 排序
 	T_3dview   string `orm:"size(256);null"`             // 3D 视图ID
 	T_type     int    `orm:"index;size(4);null"`         // Device.DeviceSensorType  1库房   2移动
+	T_link     int    `orm:"index;size(4):default(1)"`   // 0:断开/故障 1连接 实时数据
+	T_State    int    `orm:"index;size(2);default(1)"`   // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
 
 	// 设备同步参数
 	T_Dattery  int    `orm:"size(4);null"`             // 电量
@@ -38,7 +40,6 @@ type DeviceSensor struct {
 	T_monitor  int    `orm:"index;size(2);null"`       // 监控状态 0 未监控 1 监控
 	T_online   int    `orm:"index;size(2);default(1)"` // 在线状态 0 未启用  1 在线  2 离线
 	T_online_s int    `orm:"index;size(2);default(0)"` // 在线状态-备用  0 未启用  1 在线  2 离线
-	T_State    int    `orm:"index;size(2);default(1)"` // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
 
 	CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
 	UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
@@ -68,6 +69,8 @@ type DeviceSensor_R struct {
 	T_online_s int    // 在线状态-备用  0 未启用  1 在线  2 离线
 	T_datashow int    // 0 屏蔽数据展示  1 正常数据展示
 	T_type     int    // 类型
+	T_link     int    // 0:断开/故障 1连接 实时数据
+	T_State    int    // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
 
 	T_DeviceSensorData      DeviceData_R            // 传感器最新数据
 	T_DeviceSensorParameter DeviceSensorParameter_R //  设备参数
@@ -88,6 +91,8 @@ type DeviceSensor_Applet struct {
 	T_online_s int    // 在线状态-备用  0 未启用  1 在线  2 离线
 	T_datashow int    // 0 屏蔽数据展示  1 正常数据展示
 	T_type     int    // 1库房   2移动
+	T_link     int    // 0:断开/故障 1连接 实时数据
+	T_State    int    // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
 
 	T_DeviceSensorData      DeviceData_R            // 传感器最新数据
 	T_DeviceSensorParameter DeviceSensorParameter_R //  设备参数
@@ -96,6 +101,32 @@ type DeviceSensor_Applet struct {
 
 }
 
+type DeviceSensor_Company struct {
+	T_sn   string // 设备序列号 KF开头,环境监测主机。 YD开头,温途监测主机
+	T_id   int    // 传感器编号
+	T_name string // 标题
+
+	T_pid      int    // 公司id
+	T_pid_name string // 公司名称
+
+	T_3dview   string // 3D 视图ID
+	T_sort     int    // 排序
+	T_Dattery  int    // 电量
+	T_Site     string // GPS
+	T_monitor  int    // 记录状态
+	T_online   int    // 在线状态 1 在线  0 离线
+	T_online_s int    // 在线状态-备用  0 未启用  1 在线  2 离线
+	T_datashow int    // 0 屏蔽数据展示  1 正常数据展示
+	T_type     int    // 类型
+	T_link     int    // 0:断开/故障 1连接 实时数据
+	T_State    int    // 0 屏蔽   1 正常  (屏蔽后 只有内部管理员才能看到,用户 输入SN\名称 搜索时 也能看到)
+
+	T_DeviceSensorData      DeviceData_R            // 传感器最新数据
+	T_DeviceSensorParameter DeviceSensorParameter_R //  设备参数
+	T_DeviceSensorType      DeviceSensorType_R      //  传感器类型
+
+}
+
 // 传感器管理
 type DeviceSensor_P struct {
 	T_sn   string // 设备序列号 KF开头,环境监测主机。 YD开头,温途监测主机
@@ -206,6 +237,8 @@ func DeviceSensorToDeviceSensor_R(DeviceSensor_ DeviceSensor) (DeviceSensor_r De
 	DeviceSensor_r.T_3dview = DeviceSensor_.T_3dview
 	DeviceSensor_r.T_type = DeviceSensor_.T_type
 	DeviceSensor_r.T_sort = DeviceSensor_.T_sort
+	DeviceSensor_r.T_link = DeviceSensor_.T_link
+	DeviceSensor_r.T_State = DeviceSensor_.T_State
 
 	DeviceSensor_r.T_datashow = DeviceSensor_.T_datashow
 
@@ -213,9 +246,56 @@ func DeviceSensorToDeviceSensor_R(DeviceSensor_ DeviceSensor) (DeviceSensor_r De
 	DeviceSensor_r.T_online = DeviceSensor_.T_online
 	DeviceSensor_r.T_online_s = DeviceSensor_.T_online_s
 	DeviceSensor_r.T_monitor = DeviceSensor_.T_monitor
-	if DeviceSensor_.T_online == 2 && (DeviceSensor_.T_online_s == 0 || DeviceSensor_.T_online_s == 2) && DeviceSensor_.T_monitor == 1 {
-		DeviceSensor_r.T_monitor = 2
-	}
+	//if DeviceSensor_.T_online == 2 && (DeviceSensor_.T_online_s == 0 || DeviceSensor_.T_online_s == 2) && DeviceSensor_.T_monitor == 1 {
+	//	DeviceSensor_r.T_monitor = 2
+	//}
+
+	// 最新系统参数
+	DeviceSensor_r.T_DeviceSensorParameter, _ = Read_DeviceSensorParameter(DeviceSensor_.T_sn, DeviceSensor_.T_id)
+
+	// 最新数据
+	//key_data := DeviceSensor_.T_sn + "|" + strconv.Itoa(DeviceSensor_.T_id)
+	//DeviceSensor_r.T_DeviceSensorData, _ = RedisDeviceData_Get(key_data)
+	DeviceData := Read_DeviceData(DeviceSensor_.T_sn, DeviceSensor_.T_id)
+	//DeviceData, _ := RedisDeviceData_Get(DeviceSensor_.T_sn + "|" + strconv.Itoa(DeviceSensor_.T_id))
+
+	DeviceSensor_r.T_DeviceSensorData = DeviceDataToDeviceData_R2(device, DeviceSensor_r.T_DeviceSensorParameter, DeviceData)
+
+	deviceSensorType := Read_DeviceSensorType_Get(DeviceSensor_.T_type)
+	DeviceSensor_r.T_DeviceSensorType = DeviceSensorTypeToDeviceSensorType_R(deviceSensorType)
+	return
+}
+func DeviceSensorToDeviceSensor_Company(DeviceSensor_ DeviceSensor) (DeviceSensor_r DeviceSensor_Company) {
+
+	device, _ := Read_Device_ByT_sn(DeviceSensor_.T_sn)
+
+	//lib.DeviceRealSnMap[DeviceSensor_.T_sn] = 3 // 连续请求 实时数据
+	lib.DeviceRealSnMap.Store(DeviceSensor_.T_sn+"|"+device.T_mqttid, 0) // 连续请求 实时数据
+
+	DeviceSensor_r.T_sn = DeviceSensor_.T_sn
+	DeviceSensor_r.T_id = DeviceSensor_.T_id
+	DeviceSensor_r.T_name = DeviceSensor_.T_name
+	DeviceSensor_r.T_pid = DeviceSensor_.T_pid
+	DeviceSensor_r.T_pid_name = Account.Read_Company_Get(DeviceSensor_.T_pid)
+
+	DeviceSensor_r.T_Site = DeviceSensor_.T_Site
+	DeviceSensor_r.T_Dattery = DeviceSensor_.T_Dattery
+	DeviceSensor_r.T_monitor = DeviceSensor_.T_monitor
+	DeviceSensor_r.T_3dview = DeviceSensor_.T_3dview
+	DeviceSensor_r.T_type = DeviceSensor_.T_type
+	DeviceSensor_r.T_sort = DeviceSensor_.T_sort
+	DeviceSensor_r.T_link = DeviceSensor_.T_link
+	DeviceSensor_r.T_State = DeviceSensor_.T_State
+
+	DeviceSensor_r.T_datashow = DeviceSensor_.T_datashow
+
+	DeviceSensor_r.T_Dattery = DeviceSensor_.T_Dattery
+	DeviceSensor_r.T_online = DeviceSensor_.T_online
+	DeviceSensor_r.T_online_s = DeviceSensor_.T_online_s
+	DeviceSensor_r.T_monitor = DeviceSensor_.T_monitor
+	//if DeviceSensor_.T_online == 2 && (DeviceSensor_.T_online_s == 0 || DeviceSensor_.T_online_s == 2) && DeviceSensor_.T_monitor == 1 {
+	//	DeviceSensor_r.T_monitor = 2
+	//}
 
 	// 最新系统参数
 	DeviceSensor_r.T_DeviceSensorParameter, _ = Read_DeviceSensorParameter(DeviceSensor_.T_sn, DeviceSensor_.T_id)
@@ -248,6 +328,8 @@ func DeviceSensorToDeviceSensor_Applet(DeviceSensor_ DeviceSensor) (DeviceSensor
 	DeviceSensor_r.T_3dview = DeviceSensor_.T_3dview
 	DeviceSensor_r.T_type = DeviceSensor_.T_type
 	DeviceSensor_r.T_sort = DeviceSensor_.T_sort
+	DeviceSensor_r.T_link = DeviceSensor_.T_link
+	DeviceSensor_r.T_State = DeviceSensor_.T_State
 
 	DeviceSensor_r.T_datashow = DeviceSensor_.T_datashow
 
@@ -255,9 +337,9 @@ func DeviceSensorToDeviceSensor_Applet(DeviceSensor_ DeviceSensor) (DeviceSensor
 	DeviceSensor_r.T_online = DeviceSensor_.T_online
 	DeviceSensor_r.T_online_s = DeviceSensor_.T_online_s
 	DeviceSensor_r.T_monitor = DeviceSensor_.T_monitor
-	if DeviceSensor_.T_online == 2 && (DeviceSensor_.T_online_s == 0 || DeviceSensor_.T_online_s == 2) && DeviceSensor_.T_monitor == 1 {
-		DeviceSensor_r.T_monitor = 2
-	}
+	//if DeviceSensor_.T_online == 2 && (DeviceSensor_.T_online_s == 0 || DeviceSensor_.T_online_s == 2) && DeviceSensor_.T_monitor == 1 {
+	//	DeviceSensor_r.T_monitor = 2
+	//}
 
 	// 最新系统参数
 	DeviceSensor_r.T_DeviceSensorParameter, _ = Read_DeviceSensorParameter(DeviceSensor_.T_sn, DeviceSensor_.T_id)
@@ -296,7 +378,7 @@ func Read_DeviceSensor_Num_ByT_sn(T_sn string) int {
 }
 
 // 获取列表
-func Read_DeviceSensorList(admin_r *Account.Admin, T_pid int, T_sn string, T_name string, T_Class_id, T_datashow int, T_type string, T_State int, page int, page_z int) (DeviceSensor_r []DeviceSensor_R, cnt int64) {
+func Read_DeviceSensorList(admin_r *Account.Admin, bindSN []string, T_pid int, T_sn string, T_name string, T_Class_id, T_datashow int, T_type string, T_State int, page int, page_z int) (DeviceSensor_r []DeviceSensor_R, cnt int64) {
 
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
@@ -319,6 +401,10 @@ func Read_DeviceSensorList(admin_r *Account.Admin, T_pid int, T_sn string, T_nam
 		cond1 = cond1.And("T_Class__icontains", T_Class)
 	}
 
+	if len(bindSN) > 0 {
+		cond1 = cond1.And("T_sn__in", bindSN)
+	}
+
 	if len(T_type) > 0 {
 		list := strings.Split(T_type, ",")
 		cond1 = cond1.And("T_type__in", list)
@@ -326,17 +412,17 @@ func Read_DeviceSensorList(admin_r *Account.Admin, T_pid int, T_sn string, T_nam
 
 	if len(T_sn) > 0 {
 		cond1 = cond1.And("T_sn__icontains", T_sn)
+	} else {
+		// 不是内部权限(T_pid>0),T_State=1 0 屏蔽  1 正常
+		if admin_r.T_pid > 0 || T_State == 1 {
+			cond1 = cond1.And("T_State", 1)
+		}
 	}
 
 	if len(T_name) > 0 {
 		cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name))
 	}
 
-	// 不是内部权限(T_pid>0),T_State=1 0 屏蔽  1 正常
-	if admin_r.T_pid > 0 || T_State == 1 {
-		cond1 = cond1.And("T_State", 1)
-	}
-
 	if T_datashow == 1 { // 0 屏蔽数据展示  1 正常数据展示
 		cond1 = cond1.And("T_datashow", 1)
 	}
@@ -763,7 +849,7 @@ func Update_Device_To_DeviceSensor(r_Device Device) bool {
 }
 
 // 传感器管理列列表 -------------------
-func Read_DeviceSensorManageList(admin_r *Account.Admin, T_pid int, T_name string, T_calss_id, T_en, T_free, T_datashow, T_sort, page, page_z int) (DeviceSensor_p []DeviceSensor_P, cnt int64) {
+func Read_DeviceSensorManageList(admin_r *Account.Admin, bindSN []string, T_pid int, T_name string, T_calss_id, T_en, T_free, T_datashow, T_sort, page, page_z int) (DeviceSensor_p []DeviceSensor_P, cnt int64) {
 	o := orm.NewOrm()
 	var maps []DeviceSensor_P
 	var maps_z []orm2.ParamsList
@@ -777,6 +863,10 @@ func Read_DeviceSensorManageList(admin_r *Account.Admin, T_pid int, T_name strin
 
 	sql_WHERE := "t_pid = " + strconv.Itoa(T_pid)
 
+	if len(bindSN) > 0 {
+		sql_WHERE += fmt.Sprintf(" AND t_sn in (%s)", lib.StringListToQuotesDotStr(bindSN))
+	}
+
 	if admin_r.T_pid > 0 {
 		sql_WHERE += " AND t__state = 1"
 	}
@@ -842,9 +932,9 @@ func Read_DeviceSensorManageList(admin_r *Account.Admin, T_pid int, T_name strin
 }
 
 // 数据展示菜单下 传感器参数列表
-// 实时数据页面 温湿度一场数据往前排
+// 实时数据页面 温湿度异常数据往前排
 // 轨迹展示页面
-func Read_DeviceSensor_List_For_Data(T_pid int, T_name string, T_Class_id, T_type, T_RealTime, T_MapShow int, page int, page_z int) (DeviceSensor_r []DeviceSensor_R, cnt int64) {
+func Read_DeviceSensor_List_For_Data(admin Account.Admin, bindSN []string, T_pid int, T_name string, T_Class_id, T_type, T_RealTime, T_MapShow int, page int, page_z int) (DeviceSensor_r []DeviceSensor_R, cnt int64) {
 
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
@@ -859,7 +949,11 @@ func Read_DeviceSensor_List_For_Data(T_pid int, T_name string, T_Class_id, T_typ
 
 	var r []DeviceSensor
 	cond := orm.NewCondition()
-	cond1 := cond.And("T_pid", T_pid).And("T_State", 1)
+	cond1 := cond.And("T_pid", T_pid)
+
+	if len(bindSN) > 0 {
+		cond1 = cond1.And("T_sn__in", bindSN)
+	}
 
 	if T_Class_id > 0 {
 		T_Class := "C" + strconv.Itoa(T_Class_id) + "|"
@@ -870,13 +964,22 @@ func Read_DeviceSensor_List_For_Data(T_pid int, T_name string, T_Class_id, T_typ
 	if T_type > 0 {
 		cond1 = cond1.And("T_type", T_type)
 	}
-
-	if len(T_name) == 16 {
-		cond1 = cond1.And("T_sn", T_name)
-	} else if len(T_name) > 0 {
-		cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_datashow", 1)
+	if admin.T_pid > 0 {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_State", 1).And("T_datashow", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1).And("T_datashow", 1)
+		}
 	} else {
-		cond1 = cond1.And("T_datashow", 1)
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_State", 1).And("T_datashow", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1).And("T_datashow", 1)
+		}
 	}
 
 	if T_MapShow == 1 {
@@ -929,11 +1032,113 @@ func Read_DeviceSensor_List_For_Data(T_pid int, T_name string, T_Class_id, T_typ
 	return DeviceSensor_r, cnt
 }
 
+// 公司管理 实时数据
+// 查询当前公司及其下面所有子公司的传感器列表
+func Read_CompanyDeviceSensor_List_For_Data(admin *Account.Admin, T_pids []int, T_name string, T_Class_id, T_type, T_RealTime, T_MapShow int, page int, page_z int) (DeviceSensor_r []DeviceSensor_Company, cnt int64) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+
+	qs := o.QueryTable(new(DeviceSensor))
+	var offset int
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = (page - 1) * page_z
+	}
+
+	var r []DeviceSensor
+	cond := orm.NewCondition()
+	cond1 := cond.And("T_pid__in", T_pids)
+
+	if T_Class_id > 0 {
+		T_Class := "C" + strconv.Itoa(T_Class_id) + "|"
+		fmt.Println("T_Class:", T_Class)
+		cond1 = cond1.And("T_Class__icontains", T_Class)
+	}
+
+	if T_type > 0 {
+		cond1 = cond1.And("T_type", T_type)
+	}
+
+	if admin.T_pid > 0 {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_State", 1).And("T_datashow", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1).And("T_datashow", 1)
+		}
+	} else {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_State", 1).And("T_datashow", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1).And("T_datashow", 1)
+		}
+	}
+
+	if T_MapShow == 1 {
+		cond1 = cond1.AndNot("T_Site", "")
+	}
+	cnt, err := qs.SetCond((*orm2.Condition)(cond1)).Count()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	// 实时数据页面,温度或者湿度不在正常区间,排在最前面
+	if T_RealTime == 1 {
+		offset_z := offset + page_z
+		if cnt < int64(offset_z) {
+			offset_z = int(cnt)
+		}
+		if offset > offset_z {
+			offset = offset_z
+		}
+		_, err = qs.SetCond((*orm2.Condition)(cond1)).OrderBy("T_sort", "T_id").All(&r)
+		if err != nil {
+			logs.Error(lib.FuncName(), err)
+			return
+		}
+		var DeviceSensor_unusual []DeviceSensor_Company
+		for _, v := range r {
+			v_r := DeviceSensorToDeviceSensor_Company(v)
+			data := v_r.T_DeviceSensorData
+			// 温度或者湿度不在正常区间,排在最前面
+			if data.T_t > data.T_tu || data.T_t < data.T_tl || data.T_rh > data.T_rhu || data.T_rh < data.T_rhl {
+				DeviceSensor_unusual = append(DeviceSensor_unusual, v_r)
+			} else {
+				DeviceSensor_r = append(DeviceSensor_r, v_r)
+			}
+		}
+		DeviceSensor_unusual = append(DeviceSensor_unusual, DeviceSensor_r...)
+		return DeviceSensor_unusual[offset:offset_z], cnt
+	}
+
+	_, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond1)).OrderBy("T_sort", "T_id").All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	for _, v := range r {
+		DeviceSensor_r = append(DeviceSensor_r, DeviceSensorToDeviceSensor_Company(v))
+	}
+	return DeviceSensor_r, cnt
+}
+
 // 获取列表
-func Read_DeviceSensor_T_type(T_pid int) (lists orm2.ParamsList, err error) {
+func Read_DeviceSensor_T_type(T_pid int, bindSN []string) (lists orm2.ParamsList, err error) {
 	o := orm.NewOrm()
 	var pl_lists orm2.ParamsList
-	_, err = o.Raw("SELECT DISTINCT t_type FROM device_sensor WHERE t_pid=? AND t_datashow=1 AND t__state=1 LIMIT 0,1000", T_pid).ValuesFlat(&pl_lists)
+	sql := "SELECT DISTINCT t_type FROM device_sensor WHERE t_pid=? AND t_datashow=1 AND t__state=1"
+	if len(bindSN) > 0 {
+		sql += fmt.Sprintf(" AND t_sn in (%s)", lib.StringListToQuotesDotStr(bindSN))
+	}
+	sql += " LIMIT 0,1000"
+	_, err = o.Raw(sql, T_pid).ValuesFlat(&pl_lists)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
 		return
@@ -943,7 +1148,7 @@ func Read_DeviceSensor_T_type(T_pid int) (lists orm2.ParamsList, err error) {
 }
 
 // 数据展示菜单下 传感器参数列表
-func Read_DeviceSensor_List_For_Applet(T_pid int, T_name, T_online string, T_RealTime, T_type, page, page_z int) (DeviceSensor_r []DeviceSensor_Applet, cnt int64) {
+func Read_DeviceSensor_List_For_Applet(admin *Account.Admin, bindSN []string, T_pid int, T_name, T_online string, T_RealTime, T_type, page, page_z int) (DeviceSensor_r []DeviceSensor_Applet, cnt int64) {
 
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
@@ -959,18 +1164,32 @@ func Read_DeviceSensor_List_For_Applet(T_pid int, T_name, T_online string, T_Rea
 
 	var r []DeviceSensor
 	cond := orm.NewCondition()
-	cond1 := cond.And("T_pid", T_pid).And("T_State", 1)
+	cond1 := cond.And("T_pid", T_pid)
 
 	if T_type > 0 {
 		cond1 = cond1.And("T_type", T_type)
 	}
 
-	if len(T_name) == 16 {
-		cond1 = cond1.And("T_sn", T_name)
-	} else if len(T_name) > 0 {
-		cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_datashow", 1)
+	if len(bindSN) > 0 {
+		cond1 = cond1.And("T_sn__in", bindSN)
+	}
+
+	if admin.T_pid > 0 {
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_State", 1).And("T_datashow", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1).And("T_datashow", 1)
+		}
 	} else {
-		cond1 = cond1.And("T_datashow", 1)
+		if len(T_name) >= 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else if len(T_name) > 0 && len(T_name) < 16 {
+			cond1 = cond1.AndCond(cond.Or("T_name__icontains", T_name).Or("T_sn__icontains", T_name)).And("T_State", 1).And("T_datashow", 1)
+		} else {
+			cond1 = cond1.And("T_State", 1).And("T_datashow", 1)
+		}
 	}
 
 	// 0 未监控 1 监控中 2 无网络 3 全部
@@ -1008,12 +1227,16 @@ func Read_DeviceSensor_List_For_Applet(T_pid int, T_name, T_online string, T_Rea
 }
 
 // 小程序-传感器类型
-func Read_DeviceSensor_T_sn_ByT_type(T_pid, T_type int) (lists []string, err error) {
+func Read_DeviceSensor_T_sn_ByT_type(T_pid int, bindSN []string, T_type int) (lists []string, err error) {
 
 	o := orm.NewOrm()
 
 	sql := "t_pid=? AND t__state=1 AND t_datashow=1 AND t_type = " + strconv.Itoa(T_type)
 
+	if len(bindSN) > 0 {
+		sql += fmt.Sprintf(" AND t_sn in (%s)", lib.StringListToQuotesDotStr(bindSN))
+	}
+
 	_, err = o.Raw("SELECT DISTINCT T_sn FROM device_sensor WHERE "+sql+" LIMIT 0,1000", T_pid).QueryRows(&lists)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)

+ 31 - 25
models/Device/DeviceSensorParameter.go

@@ -30,16 +30,17 @@ type DeviceSensorParameter struct {
 	T_RHlower float32 `orm:"size(200);null"` //  湿度下限
 	T_RHupper float32 `orm:"size(200);null"` //  湿度上限
 	// 预警
-	T_enprel int     `orm:"size(2);default(1)"` //  是否启用预警 1开启  0 关闭
-	T_tprel  float32 `orm:"size(200);null"`     //  温度预警下限
-	T_tpreu  float32 `orm:"size(200);null"`     //  温度预警上限
-	T_hprel  float32 `orm:"size(200);null"`     //  湿度预警下限
-	T_hpreu  float32 `orm:"size(200);null"`     //  温度预警上限
-
-	T_speed int `orm:"size(5);null"`       // 传感器采样率   s(1~240) 默认:15 *
-	T_sense int `orm:"size(5);"`           // 传感器灵敏度   s(0~10) 默认:5
-	T_en    int `orm:"size(2);default(1)"` // en:是否启用传感器,   0 停用  1 启用
-	T_free  int `orm:"size(2);default(1)"` // free:监测点是否为闲置状态(空库,只监测不报警)    0 正常   1 空库
+	T_enprel     int     `orm:"size(2);default(1)"` //  是否启用预警 1开启  0 关闭
+	T_tprel      float32 `orm:"size(200);null"`     //  温度预警下限
+	T_tpreu      float32 `orm:"size(200);null"`     //  温度预警上限
+	T_hprel      float32 `orm:"size(200);null"`     //  湿度预警下限
+	T_hpreu      float32 `orm:"size(200);null"`     //  温度预警上限
+	T_enprelnote int     `orm:"size(2);default(1)"` // 是否启用预警记录数据
+
+	//T_speed int `orm:"size(5);null"` // 传感器采样率   s(1~240) 默认:15 *
+	//T_sense int `orm:"size(5);"`           // 传感器灵敏度   s(0~10) 默认:5
+	T_en   int `orm:"size(2);default(1)"` // en:是否启用传感器,   0 停用  1 启用
+	T_free int `orm:"size(2);default(1)"` // free:监测点是否为闲置状态(空库,只监测不报警)    0 正常   1 空库
 
 	// 逻辑字段
 	T_uuid      string `orm:"size(256);null"`      // 处理 人员
@@ -59,16 +60,17 @@ type DeviceSensorParameter_R struct {
 	T_RHlower float32 //  湿度下限
 	T_RHupper float32 //  湿度上限
 	// 预警
-	T_enprel int     // 是否启用预警
-	T_tprel  float32 //  温度预警下限
-	T_tpreu  float32 //  温度预警上限
-	T_hprel  float32 //  湿度预警下限
-	T_hpreu  float32 //  温度预警上限
-
-	T_speed int // 传感器采样率   s(1~240) 默认:15 *
-	T_sense int // 传感器灵敏度   s(0~10) 默认:5
-	T_en    int // en:是否启用传感器,
-	T_free  int // free:监测点是否为闲置状态(空库,只监测不报警)
+	T_enprel     int     // 是否启用预警
+	T_tprel      float32 //  温度预警下限
+	T_tpreu      float32 //  温度预警上限
+	T_hprel      float32 //  湿度预警下限
+	T_hpreu      float32 //  温度预警上限
+	T_enprelnote int     // 预警记录数据
+
+	//T_speed int // 传感器采样率   s(1~240) 默认:15 *
+	//T_sense int // 传感器灵敏度   s(0~10) 默认:5
+	T_en   int // en:是否启用传感器,
+	T_free int // free:监测点是否为闲置状态(空库,只监测不报警)
 
 	T_time models.JsonTime
 }
@@ -99,8 +101,10 @@ func DeviceSensorParameterToDeviceSensorParameter_R(r DeviceSensorParameter) (t
 	t.T_tpreu = r.T_tpreu
 	t.T_hprel = r.T_hprel
 	t.T_hpreu = r.T_hpreu
-	t.T_speed = r.T_speed
-	t.T_sense = r.T_sense
+	t.T_enprelnote = r.T_enprelnote
+
+	//t.T_speed = r.T_speed
+	//t.T_sense = r.T_sense
 	t.T_en = r.T_en
 	t.T_free = r.T_free
 	t.T_time.Time = r.CreateTime
@@ -133,14 +137,15 @@ func DeviceSensorParameter_T_text(r DeviceSensorParameter) string {
 	s += fmt.Sprintf(" 湿度下限:%.2f", r.T_RHlower)
 	s += fmt.Sprintf(" 湿度上限:%.2f", r.T_RHupper)
 
-	s += fmt.Sprintf(" 是否启用预警:%.2d", r.T_enprel)
+	s += fmt.Sprintf(" 是否启用预警:%d", r.T_enprel)
 	s += fmt.Sprintf(" 温度预警下限:%.2f", r.T_tprel)
 	s += fmt.Sprintf(" 温度预警上限:%.2f", r.T_tpreu)
 	s += fmt.Sprintf(" 湿度预警下限:%.2f", r.T_hprel)
 	s += fmt.Sprintf(" 湿度预警上限:%.2f", r.T_hpreu)
+	s += fmt.Sprintf(" 是否启用预警记录数据:%d", r.T_enprelnote)
 
-	s += fmt.Sprintf(" 传感器采样率:%d", r.T_speed)
-	s += fmt.Sprintf(" 传感器灵敏度:%d", r.T_sense)
+	//s += fmt.Sprintf(" 传感器采样率:%d", r.T_speed)
+	//s += fmt.Sprintf(" 传感器灵敏度:%d", r.T_sense)
 	s += fmt.Sprintf(" 是否启用传感器:%d", r.T_en)
 	s += fmt.Sprintf(" 监测点是否为闲置状态:%d", r.T_free)
 
@@ -232,6 +237,7 @@ func Read_DeviceSensorParameter(T_sn string, T_id int) (t DeviceSensorParameter_
 	}
 	// 判断是否有数据
 	if len(r) == 0 {
+		Redis_DeviceSensorParameter_Set(key, DeviceSensorParameter{})
 		return t, false
 	}
 

+ 246 - 6
models/Warning/Warning.go

@@ -14,6 +14,11 @@ import (
 	"time"
 )
 
+var (
+	CompanyCallthepolice = "companyCallthepolice" // 公司管理-设备报警
+	Callthepolice        = "callthepolice"        // 公司管理-设备报警
+)
+
 // 模板
 type Warning struct {
 	Id        int64     `orm:"column(ID);size(11);auto;pk"`
@@ -72,6 +77,26 @@ type Warning_R struct {
 	T_history  int      // 0 40天 1 历史数据
 	CreateTime string   // 创建时间
 }
+type CompanyWarning_R struct {
+	Id         int64
+	T_pid      int      // Account.Company 绑定公司
+	T_pid_name string   // Account.Company 公司名称
+	T_tp       int      // 报警类型   ->WarningList
+	T_tp_name  string   // 报警类型名称
+	T_sn       string   // 设备序列号
+	T_D_name   string   // 设备名称
+	T_id       int      // 传感器 ID
+	T_DS_name  string   // 传感器名称
+	T_Remark   string   // 采集内容
+	T_Ut       string   // 采集时间
+	T_fUt      string   // 首次采集时间
+	T_Text     string   // 处理备注
+	T_Log      []string // 处理日志
+	T_Msid     int64    // 消息ID
+	T_State    int      // 0 删除   1 未处理   2 已处理
+	T_history  int      // 0 40天 1 历史数据
+	CreateTime string   // 创建时间
+}
 type Warning_Applet struct {
 	Id             int64
 	T_pid          int      // Account.Company 绑定公司
@@ -128,6 +153,32 @@ func WarningToWarning_R(T_history int, t Warning) (r Warning_R) {
 	r.CreateTime = t.CreateTime.Format("2006-01-02 15:04:05")
 	return r
 }
+func WarningToCompanyWarning_R(T_history int, t Warning) (r CompanyWarning_R) {
+	r.Id = t.Id
+	r.T_pid = t.T_pid
+	r.T_pid_name = Account.Read_Company_Get(t.T_pid)
+	r.T_tp = t.T_tp
+	r.T_tp_name = Read_WarningType_Get(t.T_tp)
+	r.T_sn = t.T_sn
+	r.T_D_name = t.T_D_name
+	r.T_id = t.T_id
+	r.T_DS_name = t.T_DS_name
+	r.T_Remark = t.T_Remark
+	r.T_Ut = t.T_Ut.Format("2006-01-02 15:04:05")
+	if !t.T_fUt.IsZero() {
+		r.T_fUt = t.T_fUt.Format("2006-01-02 15:04:05")
+	}
+	r.T_Text = t.T_Text
+	if len(t.T_Log) > 0 {
+		r.T_Log = strings.Split(strings.TrimRight(t.T_Log, "\n"), "\n")
+	}
+
+	r.T_Msid = t.T_Msid
+	r.T_State = t.T_State
+	r.T_history = T_history
+	r.CreateTime = t.CreateTime.Format("2006-01-02 15:04:05")
+	return r
+}
 
 func WarningToWarning_Applet(t Warning) (r Warning_Applet) {
 	r.Id = t.Id
@@ -232,7 +283,7 @@ func Update_Warning_Backups(r Warning, T_year string, T_month string) bool {
 }
 
 // 获取列表
-func Read_Warning_List(T_pid int, tpList []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int) (r []Warning_R, cnt int64) {
+func 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) (r []Warning_R, cnt int64) {
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
 	var map_r []Warning
@@ -248,6 +299,10 @@ func Read_Warning_List(T_pid int, tpList []string, T_name string, T_handle int,
 
 	cond1 := orm.NewCondition()
 
+	if len(bindSN) > 0 {
+		cond1 = cond1.And("T_sn__in", bindSN)
+	}
+
 	if T_pid > 0 {
 		cond1 = cond1.And("T_pid", T_pid)
 	}
@@ -389,7 +444,7 @@ func Read_Admin_Warning_List(T_pids string, T_tp []string, T_name string, T_hand
 }
 
 // 获取列表备份
-func Read_Warning_Backups(T_pid int, T_year string, T_month string, tpList []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int) (r []Warning_R, cnt int64) {
+func Read_Warning_Backups(T_pid int, bindSN []string, T_year string, T_month string, tpList []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int) (r []Warning_R, cnt int64) {
 
 	o := orm.NewOrm()
 	var maps []Warning
@@ -412,6 +467,10 @@ func Read_Warning_Backups(T_pid int, T_year string, T_month string, tpList []str
 	//cond1 := cond.And("T_State__gt", 0)
 	sql_WHERE += " t__state > 0"
 
+	if len(bindSN) > 0 {
+		sql_WHERE += fmt.Sprintf(" AND t_sn in (%s)", lib.StringListToQuotesDotStr(bindSN))
+	}
+
 	if T_pid > 0 {
 		sql_WHERE += " AND t_pid = " + strconv.Itoa(T_pid)
 	}
@@ -536,7 +595,7 @@ func Read_Admin_Warning_Backups(T_pids string, T_year string, T_month string, T_
 	//1:默认 2:全部记录 3 未处理
 	if T_handle == 1 {
 		//cond1 = cond1.And("T_Text__isnull", true)
-		sql_WHERE += " AND t__tstate > 1"
+		sql_WHERE += " AND t__state > 1"
 	}
 	if T_handle == 3 {
 		//cond1 = cond1.And("T_Text__isnull", false).And("T_State", 2)
@@ -579,11 +638,21 @@ func Read_Admin_Warning_Backups(T_pids string, T_year string, T_month string, T_
 
 }
 
-func Read_Warning_ALL_T_State_Count(T_pid, T_handle int, T_Warning string, Is_Today bool) (cnt int64) {
+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) {
 	o := orm.NewOrm()
 	qs := o.QueryTable(new(Warning))
 	cond := orm.NewCondition()
-	cond1 := cond.And("T_State__gt", 0).And("T_pid", T_pid)
+	cond1 := cond.And("T_State__gt", 0)
+	if T_pid > 0 {
+		cond1 = cond1.And("T_pid", T_pid)
+	}
+	if T_pid == 0 {
+		cond1 = cond1.And("T_pid__in", T_pids)
+	}
+
+	if len(bindSN) > 0 {
+		cond1 = cond1.And("T_sn__in", bindSN)
+	}
 
 	if Is_Today {
 		startTime := time.Now().Format("2006-01-02") + " 00:00:00"
@@ -662,7 +731,7 @@ func Read_DeviceLogs_List(T_sn string, page, page_z int) (r []DeviceLogs, cnt in
 }
 
 // 通过传感器类型获取报警列表
-func Read_Warning_List_By_DS_T_type(T_pid, DS_T_type int, T_name string, page int, page_z int) (r []Warning_Applet, cnt int64) {
+func Read_Warning_List_By_DS_T_type(T_pid int, bindSN []string, DS_T_type int, T_name string, page int, page_z int) (r []Warning_Applet, cnt int64) {
 	o := orm.NewOrm()
 	// 也可以直接使用 Model 结构体作为表名
 	var maps []Warning
@@ -677,6 +746,10 @@ func Read_Warning_List_By_DS_T_type(T_pid, DS_T_type int, T_name string, page in
 	// T_State 0 删除   1 不处理   2 已处理   3 未处理
 	sql_WHERE := " t__state > 1 AND t_pid = " + strconv.Itoa(T_pid)
 
+	if len(bindSN) > 0 {
+		sql_WHERE += fmt.Sprintf(" AND t_sn in (%s)", lib.StringListToQuotesDotStr(bindSN))
+	}
+
 	if DS_T_type > 0 {
 		sql_WHERE += " AND ds.t_type = " + strconv.Itoa(DS_T_type)
 	}
@@ -741,3 +814,170 @@ func Read_WarningCount_byDay(T_pids []int) (cnt int64) {
 	return cnt
 
 }
+
+// 公司管理报警列表
+func 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) (r []CompanyWarning_R, cnt int64) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+	var map_r []Warning
+	qs := o.QueryTable(new(Warning))
+	var offset int64
+	if page_z == 0 {
+		page_z = conf.Page_size
+	}
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = int64((page - 1) * page_z)
+	}
+
+	cond := orm.NewCondition()
+	cond1 := orm.NewCondition()
+	cond1 = cond1.And("T_pid__in", T_pids)
+
+	if len(T_tp) > 0 {
+		cond1 = cond1.And("T_tp__in", T_tp)
+	}
+	if len(T_name) > 0 {
+		if len(T_name) == 16 {
+			cond1 = cond1.And("T_sn", T_name)
+		} else {
+			cond1 = cond1.AndCond(cond.Or("T_sn__icontains", T_name).
+				Or("T_D_name__icontains", T_name).
+				Or("T_id__icontains", T_name).
+				Or("T_DS_name__icontains", T_name))
+		}
+	}
+
+	if len(Time_start_) > 0 {
+		cond1 = cond1.And("T_Ut__gte", Time_start_)
+	}
+	if len(Time_end_) > 0 {
+		cond1 = cond1.And("T_Ut__lte", Time_end_)
+	}
+	//1:默认 2:全部记录 3 未处理
+	if T_handle == 1 {
+		cond1 = cond1.And("T_State__gt", 1)
+	}
+	if T_handle == 2 {
+		cond1 = cond1.And("T_State__gt", 0)
+	}
+	if T_handle == 3 {
+		cond1 = cond1.And("T_State", 3)
+	}
+
+	_, err := qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond1)).OrderBy("-T_Ut").All(&map_r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	cnt, err = qs.SetCond((*orm2.Condition)(cond1)).Count()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	for _, v := range map_r {
+		r = append(r, WarningToCompanyWarning_R(0, v))
+	}
+
+	return r, cnt
+
+}
+
+// 获取公司管理列表备份
+func Read_Company_Warning_Backups(T_pids []int, T_year string, T_month string, T_tp []string, T_name string, T_handle int, Time_start_ string, Time_end_ string, page int, page_z int) (r []CompanyWarning_R, cnt int64) {
+
+	if len(T_pids) == 0 {
+		return r, cnt
+	}
+
+	o := orm.NewOrm()
+	var maps []Warning
+	var maps_z []orm2.ParamsList
+	// 也可以直接使用 Model 结构体作为表名
+	// Warning_2022_07
+	Wtab := "warning_" + T_year + "_" + T_month
+
+	var offset int
+	if page_z == 0 {
+		page_z = conf.Page_size
+	}
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = (page - 1) * page_z
+	}
+
+	sql_WHERE := ""
+
+	sql_WHERE += " t__state > 0"
+
+	if len(T_pids) > 0 {
+		sql_WHERE += fmt.Sprintf(" AND t_pid in (%s)", lib.IntListToDotStr(T_pids))
+	}
+
+	if len(T_tp) > 0 {
+		tp := lib.StringListToDotStr(T_tp)
+		sql_WHERE += fmt.Sprintf(" AND t_tp in (%s)", tp)
+
+	}
+	if len(T_name) > 0 {
+		sql_WHERE += " AND (t_sn like '%" + T_name + "%' OR t__d_name like '%" + T_name + "%' OR t_id like '%" + T_name + "%' OR t__d_s_name like '%" + T_name + "%')"
+	}
+
+	if len(Time_start_) > 0 {
+		//cond1 = cond1.And("T_Ut__gte", Time_start_)
+		Time_start_ = lib.ReplaceSQL(Time_start_)
+		sql_WHERE += fmt.Sprintf(" AND t__ut >= '%s'", Time_start_)
+	}
+	if len(Time_end_) > 0 {
+		//cond1 = cond1.And("T_Ut__lte", Time_end_)
+		Time_end_ = lib.ReplaceSQL(Time_end_)
+		sql_WHERE += fmt.Sprintf(" AND t__ut <= '%s'", Time_end_)
+	}
+	//1:默认 2:全部记录 3 未处理
+	if T_handle == 1 {
+		//cond1 = cond1.And("T_Text__isnull", true)
+		sql_WHERE += " AND t__state > 1"
+	}
+	if T_handle == 3 {
+		//cond1 = cond1.And("T_Text__isnull", false).And("T_State", 2)
+		sql_WHERE += " AND t__state = 3"
+	}
+
+	// -------------
+
+	sql := "SELECT COUNT(ID) FROM " + Wtab + " WHERE" + sql_WHERE
+	fmt.Println(sql)
+	_, err := o.Raw(sql).ValuesList(&maps_z)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return r, 0
+	}
+	if len(maps_z) == 0 {
+		return r, 0
+	}
+	//fmt.Println("maps_z;",maps_z[0][0])
+	sql = "SELECT ID,t_pid,t_tp,t_sn,t__d_name,t_id,t__d_s_name,t__remark,t__ut,t__text,t__log,t__msid,t__state,create_time,update_time " +
+		"FROM " + Wtab + " WHERE" + sql_WHERE + " ORDER BY t__ut DESC"
+	if page_z != 9999 {
+		sql = sql + " LIMIT " + strconv.Itoa(offset) + "," + strconv.Itoa(page_z)
+	}
+
+	fmt.Println(sql)
+	_, err = o.Raw(sql).QueryRows(&maps)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	key, _ := strconv.ParseInt(maps_z[0][0].(string), 10, 64)
+
+	for _, v := range maps {
+		r = append(r, WarningToCompanyWarning_R(1, v))
+	}
+
+	return r, key
+
+}

+ 33 - 0
models/Warning/WarningHandle.go

@@ -0,0 +1,33 @@
+package Warning
+
+import (
+	"Cold_Api/controllers/lib"
+	"Cold_Api/logs"
+	"github.com/beego/beego/v2/adapter/orm"
+)
+
+type WarningHandle struct {
+	Id     int    `orm:"column(ID);size(11);auto;pk"`
+	T_name string `orm:"size(256);null"` // 报警处理备注
+}
+
+func (t *WarningHandle) TableName() string {
+	return "warning_handle"
+}
+
+func init() {
+	//注册模型
+	orm.RegisterModel(new(WarningHandle))
+}
+
+func Read_WarningHandle_List() (maps []WarningHandle) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(WarningHandle))
+
+	_, err := qs.OrderBy("Id").All(&maps)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+
+	return maps
+}

+ 2 - 2
models/Warning/WarningSand.go

@@ -16,9 +16,9 @@ import (
 // 模板
 // 报警发送统计
 type WarningSand struct {
-	Id int `orm:"column(ID);size(11);auto;pk"`
-
+	Id       int    `orm:"column(ID);size(11);auto;pk"`
 	T_pid    int    `orm:"index;size(100);null"` // Account.Company 绑定公司, -1:未知   0:管理员  >0 :绑定公司
+	T_Spid   int    `orm:"index;size(100);"`     // 触发公司 ID
 	T_tp     int    `orm:"index;size(20);null"`  // 报警类型   ->WarningList
 	T_Notice string `orm:"size(256);null"`       // 18888888888
 	T_type   int    `orm:"index;size(4);null"`   // 1 短信   2 电话

+ 7 - 5
routers/Data.go

@@ -13,15 +13,17 @@ func init() {
 			beego.NSRouter("/Device_Sensor", &controllers.DataController{}, "*:Device_Sensor_Get"),                       // 获取传感器
 			beego.NSRouter("/Device_Sensor_Data_Real", &controllers.DataController{}, "*:Device_Sensor_Data_Real"),       // 获取传感器
 			beego.NSRouter("/Device_Sensor_List", &controllers.DataController{}, "*:Device_Sensor_List"),                 // 传感器列表
+			beego.NSRouter("/Company_Device_Sensor_List", &controllers.DataController{}, "*:Company_Device_Sensor_List"), // 传感器列表
 			beego.NSRouter("/Device_Sensor_Data", &controllers.DataController{}, "*:Device_Sensor_Data"),                 // 传感器数据
 			beego.NSRouter("/Device_Sensor_Data_Excel", &controllers.DataController{}, "*:Device_Sensor_Data_Excel"),     // 导出传感器数据
 			beego.NSRouter("/Device_Sensor_Data_Excel_m", &controllers.DataController{}, "*:Device_Sensor_Data_Excel_m"), // 导出传感器数据
 
-			beego.NSRouter("/List", &controllers.DataController{}, "*:Device_Sensor_Data_More"),             // 设备数据列表
-			beego.NSRouter("/Excel", &controllers.DataController{}, "*:Device_Sensor_Data_Excel"),           // 导出设备数据列表excel
-			beego.NSRouter("/PDF", &controllers.DataController{}, "*:Device_Sensor_Data_PDF"),               // 设备数据列表pdf
-			beego.NSRouter("/BackUp", &controllers.DataController{}, "*:Device_Sensor_Data_BackUp"),         // 设备数据备份列表
-			beego.NSRouter("/BackUp_PDF", &controllers.DataController{}, "*:Device_Sensor_Data_BackUp_PDF"), // 设备数据备份列表PDF
+			beego.NSRouter("/List", &controllers.DataController{}, "*:Device_Sensor_Data_More"),                   // 设备数据列表
+			beego.NSRouter("/Excel", &controllers.DataController{}, "*:Device_Sensor_Data_Excel"),                 // 导出设备数据列表excel
+			beego.NSRouter("/PDF", &controllers.DataController{}, "*:Device_Sensor_Data_PDF"),                     // 设备数据列表pdf
+			beego.NSRouter("/ChartShow_PDF", &controllers.DataController{}, "*:Device_Sensor_Data_ChartShow_PDF"), // 图表展示下载pdf
+			beego.NSRouter("/BackUp", &controllers.DataController{}, "*:Device_Sensor_Data_BackUp"),               // 设备数据备份列表
+			beego.NSRouter("/BackUp_PDF", &controllers.DataController{}, "*:Device_Sensor_Data_BackUp_PDF"),       // 设备数据备份列表PDF
 
 			beego.NSRouter("/DeviceSensor_Data_Print", &controllers.DataController{}, "*:DeviceSensor_Data_Print"), // 小程序 打印
 

+ 8 - 6
routers/Device.go

@@ -22,6 +22,7 @@ func init() {
 			beego.NSRouter("/Parameter_Get", &controllers.DeviceController{}, "*:Device_Parameter_Get"),   // 设备参数
 			beego.NSRouter("/Parameter_List", &controllers.DeviceController{}, "*:Device_Parameter_List"), // 设备参数列表
 			beego.NSRouter("/Parameter_Pu", &controllers.DeviceController{}, "*:Device_Parameter_Pu"),     // 修改设备参数
+			beego.NSRouter("/Parameter_Sync", &controllers.DeviceController{}, "*:Device_Parameter_Sync"), // 修改设备参数
 			//beego.NSRouter("/Device_Parameter_Del_Device", &controllers.DeviceController{}, "*:Device_Parameter_Del_Device"), // 删除此设备 - 弃用
 			// 设备日志
 			beego.NSRouter("/Log", &controllers.DeviceController{}, "*:DeviceLogs"), // 日志
@@ -67,12 +68,13 @@ func init() {
 		// 分类
 		beego.NSNamespace("/Class",
 			beego.NSBefore(T_pidFilter),
-			beego.NSRouter("/List", &controllers.DeviceController{}, "*:CompanyClass_List"), // 分类列表
-			beego.NSRouter("/All", &controllers.DeviceController{}, "*:CompanyClass_All"),   // 所有分类列表
-			beego.NSRouter("/Get", &controllers.DeviceController{}, "*:CompanyClass_Get"),   // 获取分类
-			beego.NSRouter("/Add", &controllers.DeviceController{}, "*:CompanyClass_Add"),   // 添加分类
-			beego.NSRouter("/Edit", &controllers.DeviceController{}, "*:CompanyClass_Edit"), // 修改分类
-			beego.NSRouter("/Del", &controllers.DeviceController{}, "*:CompanyClass_Del"),   // 删除分类
+			beego.NSRouter("/List", &controllers.DeviceController{}, "*:CompanyClass_List"),                   // 分类列表
+			beego.NSRouter("/All", &controllers.DeviceController{}, "*:CompanyClass_All"),                     // 所有分类列表
+			beego.NSRouter("/Company_All", &controllers.DeviceController{}, "*:CompanyClass_All_For_Company"), // 所有分类列表
+			beego.NSRouter("/Get", &controllers.DeviceController{}, "*:CompanyClass_Get"),                     // 获取分类
+			beego.NSRouter("/Add", &controllers.DeviceController{}, "*:CompanyClass_Add"),                     // 添加分类
+			beego.NSRouter("/Edit", &controllers.DeviceController{}, "*:CompanyClass_Edit"),                   // 修改分类
+			beego.NSRouter("/Del", &controllers.DeviceController{}, "*:CompanyClass_Del"),                     // 删除分类
 			// 分类绑定
 			beego.NSRouter("/Bind_Add", &controllers.DeviceController{}, "*:ClassBind_Add"), // 添加分类设备绑定
 			beego.NSRouter("/Bind_Del", &controllers.DeviceController{}, "*:ClassBind_Del"), // 删除分类设备绑定

+ 10 - 5
routers/User.go

@@ -18,11 +18,15 @@ func init() {
 
 		beego.NSNamespace("/User",
 			beego.NSBefore(T_pidFilter),
-			beego.NSRouter("/List", &controllers.UserController{}, "*:User_List"), // 用户列表
-			beego.NSRouter("/Get", &controllers.UserController{}, "*:User_Get"),   // 获取用户信息
-			beego.NSRouter("/Add", &controllers.UserController{}, "*:User_Add"),   // 增加用户
-			beego.NSRouter("/Edit", &controllers.UserController{}, "*:User_Edit"), // 编辑用户
-			beego.NSRouter("/Del", &controllers.UserController{}, "*:User_Del"),   // 删除用户
+			beego.NSRouter("/List", &controllers.UserController{}, "*:User_List"),                           // 用户列表
+			beego.NSRouter("/Get", &controllers.UserController{}, "*:User_Get"),                             // 获取用户信息
+			beego.NSRouter("/Add", &controllers.UserController{}, "*:User_Add"),                             // 增加用户
+			beego.NSRouter("/Edit", &controllers.UserController{}, "*:User_Edit"),                           // 编辑用户
+			beego.NSRouter("/Del", &controllers.UserController{}, "*:User_Del"),                             // 删除用户
+			beego.NSRouter("/Bind_Device", &controllers.UserController{}, "*:UserDeviceBind_Add"),           // 绑定主机
+			beego.NSRouter("/Unbind_Device", &controllers.UserController{}, "*:UserDeviceBind_Del"),         // 解绑主机
+			beego.NSRouter("/Bind_Device_List", &controllers.UserController{}, "*:UserDeviceBind_List"),     // 已绑定主机列表
+			beego.NSRouter("/Unbind_Device_List", &controllers.UserController{}, "*:UserDeviceUnbind_List"), // 未绑定主机列表
 		),
 
 		beego.NSRouter("/Admin/List", &controllers.UserController{}, "*:Admin_List"), // 内部用户列表
@@ -60,6 +64,7 @@ func init() {
 		beego.NSRouter("/Company/DigitalTwin", &controllers.UserController{}, "*:Company_DigitalTwin"), // 数字孪生
 		beego.NSRouter("/Company/Pay", &controllers.UserController{}, "*:Company_Pay"),                 // 充值
 		beego.NSRouter("/Company/Warning", &controllers.UserController{}, "*:Company_Warning"),         // 报警统计
+		beego.NSRouter("/Company/Charging", &controllers.UserController{}, "*:Company_Charging"),       // 报警统计
 
 		beego.NSRouter("/WxPay/Get_QRCode", &controllers.UserController{}, "*:WxPay_QRCode"),           // 获取微信支付二维码
 		beego.NSRouter("/WxPay/Notify", &controllers.UserController{}, "*:WxPay_Notify"),               // 获取微信支付二维码

+ 10 - 0
routers/Warning.go

@@ -33,6 +33,16 @@ func init() {
 			beego.NSRouter("/List", &controllers.DeviceController{}, "*:Read_WarningRate_List"),      // 内部用户设备报警率列表
 			beego.NSRouter("/User_List", &controllers.DeviceController{}, "*:Read_WarningRate_List"), // 内部用户设备报警率列表
 		),
+		// 报警处理
+		beego.NSNamespace("/WarningHandle",
+			beego.NSRouter("/List", &controllers.DeviceController{}, "*:Read_WarningHandle_List"), // 内部用户设备报警率列表
+		),
+
+		// 公司管理-设备报警
+		beego.NSNamespace("/CompanyWarning",
+			beego.NSRouter("/List", &controllers.DeviceController{}, "*:CompanyWarning_List"),          // 告警列表
+			beego.NSRouter("/ToExcel", &controllers.DeviceController{}, "*:CompanyWarning_Data_Excel"), // 告警列表
+		),
 	)
 
 	beego.AddNamespace(ns)