Browse Source

update:修改自动填写排序

zoie 1 month ago
parent
commit
bd67e8a250
5 changed files with 521 additions and 657 deletions
  1. 139 250
      controllers/TaskData.go
  2. 227 389
      controllers/TaskHandle.go
  3. 24 12
      models/Device/DeviceClassList.go
  4. 131 6
      models/Task/TaskData.go
  5. BIN
      自动填写逻辑.xlsx

+ 139 - 250
controllers/TaskData.go

@@ -2875,18 +2875,27 @@ func (c *TaskDataController) ListJson() {
 		//"柜内所有测点",
 		"均匀性布点",
 		"产品存放区域测点",
+		"作业出入口总测点",
+		"风机布点总测点",
+		"库内除风机出风口、回风口外总测点",
+		"库内除风机出风口、回风口、特殊位置布点、作业口外总测点",
+		"车内除风机出风口、回风口外总测点",
+		"报告编号",
+		"数据分析时间",
+		"实施计划月份",
+		"计划验证实施时间",
+		"监测终端01",
+		"监测终端安装编号01",
+		"监测终端02",
+		"监测终端安装编号02",
+		"培训讲师",
+		"培训时间",
 		"冷藏柜内部最高温",
 		"冷藏柜内部最低温",
-		"外部环境分割线最高温",
-		"外部环境分割线最低温",
 		"冷藏柜外部环境测点最高温",
 		"冷藏柜外部环境测点最低温",
 		"内部环境分割线最低温",
 		"内部环境分割线最高温",
-		"冰排释冷开始时间",
-		"冰排释冷结束时间",
-		"冰排释冷分割线最高温",
-		"冰排释冷分割线最低温",
 		"静态第一次开箱注释",
 		"静态第二次开箱注释",
 		"静态第三次开箱注释",
@@ -2900,40 +2909,8 @@ func (c *TaskDataController) ListJson() {
 		"风机温度设定值",
 		"保温箱准备开始时间",
 		"冰排预冷保温箱准备结束时间",
-		"温度自动监测设备放置位置开始时间",
-		"温度自动监测设备放置位置结束时间",
-		"温度分布特性开始时间",
-		"温度分布特性结束时间",
-		"最长保温时限开始时间",
-		"最长保温时限结束时间",
-		"温度分布特性的测试与分析(满载)开始时间",
-		"温度分布特性的测试与分析(空载)开始时间",
-		"温度分布特性的测试与分析(满载)结束时间",
-		"温度分布特性的测试与分析(空载)结束时间",
-		"温控设备运行参数及使用状况测试(满载)开始时间",
-		"温控设备运行参数及使用状况测试(空载)开始时间",
-		"温控设备运行参数及使用状况测试(满载)结束时间",
-		"温控设备运行参数及使用状况测试(空载)结束时间",
-		"(满载)温度偏差均匀度波动度分析时间区间",
-		"(空载)温度偏差均匀度波动度分析时间区间",
-		"运行确认及偏差处理(满载)开始时间",
-		"运行确认及偏差处理(空载)开始时间",
-		"运行确认及偏差处理(满载)结束时间",
-		"运行确认及偏差处理(空载)结束时间",
-		"满载风机启动时间点注释",
-		"满载风机停止时间点注释",
-		"满载测试结束风机停止时间注释",
-		"空载风机启动时间点注释",
-		"空载风机停止时间点注释",
-		"空载测试结束风机停止时间注释",
 		"第一次开门开始时间",
 		"第一次开门结束时间",
-		"满载风机启动时间点",
-		"空载风机启动时间点",
-		"满载风机停止时间点",
-		"空载风机停止时间点",
-		"满载测试结束风机停止时间",
-		"空载测试结束风机停止时间",
 		"满载第一次关门温度恢复时间",
 		"空载第一次关门温度恢复时间",
 		"满载第二次关门温度恢复时间",
@@ -2954,27 +2931,50 @@ func (c *TaskDataController) ListJson() {
 		"冷藏车内部最低温",
 		"验证测试期间当地天气情况曲线图",
 		"当地历史气温数据查询曲线图",
-		"报告编号",
-		"数据分析时间",
-		"实施计划月份",
-		"计划验证实施时间",
-		"监测终端01",
-		"监测终端安装编号01",
-		"监测终端02",
-		"监测终端安装编号02",
+		"预冷开始时间",
+		"预冷结束时间",
+		"运行确认及偏差处理(满载)开始时间",
+		"运行确认及偏差处理(空载)开始时间",
+		"运行确认及偏差处理(满载)结束时间",
+		"运行确认及偏差处理(空载)结束时间",
+		"温度自动监测设备放置位置开始时间",
+		"温度自动监测设备放置位置结束时间",
+		"冰排释冷开始时间",
+		"冰排释冷结束时间",
+		"最长保温时限开始时间",
+		"最长保温时限结束时间",
+		"温度分布特性开始时间",
+		"温度分布特性结束时间",
+		"冰排释冷分割线最高温",
+		"冰排释冷分割线最低温",
+		"外部环境分割线最高温",
+		"外部环境分割线最低温",
 		"监测系统配置的测点终端参数及安装位置确认(满载)开始时间",
 		"监测系统配置的测点终端参数及安装位置确认(满载)结束时间",
 		"监测系统配置的测点终端参数及安装位置确认(空载)开始时间",
 		"监测系统配置的测点终端参数及安装位置确认(空载)结束时间",
-		"培训讲师",
-		"培训时间",
-		"作业出入口总测点",
-		"风机布点总测点",
-		"库内除风机出风口、回风口外总测点",
-		"库内除风机出风口、回风口、特殊位置布点、作业口外总测点",
-		"车内除风机出风口、回风口外总测点",
-		"预冷开始时间",
-		"预冷结束时间",
+		"满载测试结束风机停止时间",
+		"空载测试结束风机停止时间",
+		"满载风机启动时间点",
+		"空载风机启动时间点",
+		"满载风机停止时间点",
+		"空载风机停止时间点",
+		"满载风机启动时间点注释",
+		"满载风机停止时间点注释",
+		"满载测试结束风机停止时间注释",
+		"空载风机启动时间点注释",
+		"空载风机停止时间点注释",
+		"空载测试结束风机停止时间注释",
+		"温控设备运行参数及使用状况测试(满载)开始时间",
+		"温控设备运行参数及使用状况测试(空载)开始时间",
+		"温控设备运行参数及使用状况测试(满载)结束时间",
+		"温控设备运行参数及使用状况测试(空载)结束时间",
+		"(满载)温度偏差均匀度波动度分析时间区间",
+		"(空载)温度偏差均匀度波动度分析时间区间",
+		"温度分布特性的测试与分析(满载)开始时间",
+		"温度分布特性的测试与分析(空载)开始时间",
+		"温度分布特性的测试与分析(满载)结束时间",
+		"温度分布特性的测试与分析(空载)结束时间",
 	}
 
 	c.Data["json"] = mySlice
@@ -3091,14 +3091,12 @@ func (c *TaskDataController) A空载测试结束风机停止时间() {
 	list := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 开始时间, 结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list)
 
-	if len(CalculateHumps_list) < 7 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到连续5个循环 !"})
-		return
+	var end Task.TaskData_AVG
+	if len(CalculateHumps_list) == 5 {
+		end = CalculateHumps_list[4].End
+	} else {
+		end = CalculateHumps_list[5].End // 驼峰结束
 	}
-	//start := CalculateHumps_list[6].Start // 驼峰开始
-	//peak := CalculateHumps_list[0]["peak"].(Task.TaskData) // 驼峰最高
-	end := CalculateHumps_list[4].End // 驼峰结束// 驼峰结束
-	// .Format("2006-01-02 15:04:05")
 
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: end.T_time})
 
@@ -3650,23 +3648,21 @@ func (c *TaskDataController) A运行确认及偏差处理空载开始时间() {
 		groupMap[r.T_id] = append(groupMap[r.T_id], r)
 	}
 
-	var earliest *Task.TaskData_
+	var latest *Task.TaskData_
 
-	// Step 2: 对每个组调用 FindFirstDecreasingToNumber
 	for _, group := range groupMap {
-		candidate := Task.FindFirstDecreasingToNumber(group, 温度控制范围最高值)
+		candidate := Task.FindFirstDecreasingTendency(group, 温度控制范围最高值-0.1)
 		if candidate != nil {
-			if earliest == nil || lib.ParseTime(candidate.T_time).Before(lib.ParseTime(earliest.T_time)) {
-				earliest = candidate
+			if latest == nil || lib.ParseTime(candidate.T_time).After(lib.ParseTime(latest.T_time)) {
+				latest = candidate
 			}
 		}
 	}
-	if earliest == nil {
+	if latest == nil {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 温度下降至“温度控制范围最高值”以下 数据!"})
 		return
 	}
-
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: earliest.T_time})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: latest.T_time})
 	// Close the connection
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
@@ -3733,29 +3729,28 @@ func (c *TaskDataController) A运行确认及偏差处理满载开始时间() {
 		return
 	}
 
-	// 情况2 现场测试开开始时间温度高于温度控制范围最高值,取温度下降至“温度控制范围最高值”以下的一个终端,该终端下降至最低点,并出现上升0.2℃的时间点
+	// 情况2 现场测试开开始时间温度高于温度控制范围最高值,取温度下降至“温度控制范围最高值”以下的最后一个终端,该终端下降至最低点,并出现上升0.2℃的时间点
 	groupMap := make(map[string][]Task.TaskData_)
 	for _, r := range list {
 		groupMap[r.T_id] = append(groupMap[r.T_id], r)
 	}
 
-	var earliest *Task.TaskData_
+	var latest *Task.TaskData_
 
-	// Step 2: 对每个组调用 FindFirstDecreasingToNumber
 	for _, group := range groupMap {
-		candidate := Task.FindFirstDecreasingToNumber(group, 温度控制范围最高值)
+		candidate := Task.FindFirstDecreasingTendency(group, 温度控制范围最高值-0.1)
 		if candidate != nil {
-			if earliest == nil || lib.ParseTime(candidate.T_time).Before(lib.ParseTime(earliest.T_time)) {
-				earliest = candidate
+			if latest == nil || lib.ParseTime(candidate.T_time).After(lib.ParseTime(latest.T_time)) {
+				latest = candidate
 			}
 		}
 	}
-	if earliest == nil {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 温度下降至“温度控制范围最高值”以下的第一个终端,该终端下降至最低点,并出现上升0.2℃的时间点 数据!"})
+	if latest == nil {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 温度下降至“温度控制范围最高值”以下 数据!"})
 		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: earliest.T_time})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: latest.T_time})
 	// Close the connection
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
@@ -3773,79 +3768,35 @@ func (c *TaskDataController) A运行确认及偏差处理空载结束时间() {
 		return
 	}
 
-	柜内所有测点 := c.GetString("柜内所有测点") //  v26nplogbwt1
-	if len(柜内所有测点) == 0 {
-		柜内所有测点 = c.GetString("库内所有测点")
+	所有测点 := c.GetString("柜内所有测点") //  v26nplogbwt1
+	if len(所有测点) == 0 {
+		所有测点 = c.GetString("库内所有测点")
 	}
-	if len(柜内所有测点) == 0 {
-		柜内所有测点 = c.GetString("车内所有测点")
+	if len(所有测点) == 0 {
+		所有测点 = c.GetString("车内所有测点")
 	}
-	if len(柜内所有测点) == 0 {
+	if len(所有测点) == 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 柜/库/车内所有测点 失败!"})
 		return
 	}
-	温度控制范围最高值_ := c.GetString("温度控制范围最高值") //  v26nplogbwt1
-	if len(温度控制范围最高值_) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度控制范围最高值 失败!"})
-		return
-	}
-	温度控制范围最高值 := lib.To_float32(温度控制范围最高值_)
 
-	现场测试开始时间 := c.GetString("现场测试开始时间") //  v26nplogbwt1
-	if len(现场测试开始时间) == 0 || 现场测试开始时间 == "null" {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 现场测试开始时间 失败!"})
-		return
-	}
 	现场测试结束时间 := c.GetString("现场测试结束时间") //  v26nplogbwt1
 	if len(现场测试结束时间) == 0 || 现场测试结束时间 == "null" {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 现场测试结束时间 失败!"})
 		return
 	}
 
-	list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 柜内所有测点, "", 现场测试开始时间, 现场测试结束时间, 0, 9999)
-	if len(list) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 柜内所有测点|现场测试开始时间-现场测试结束时间 当前 温度数据 失败!"})
+	运行确认及偏差处理空载开始时间 := c.GetString("运行确认及偏差处理(空载)开始时间")
+	if len(运行确认及偏差处理空载开始时间) == 0 || 运行确认及偏差处理空载开始时间 == "null" {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 运行确认及偏差处理(空载)开始时间 失败!"})
 		return
 	}
-	var startTimeData *Task.TaskData_
-	//情况1 现场测试开始时间的温度低于温度控制范围最高值,直接取现场测试开始时间
-	firstTimeData := Task.GetFirstTimeData(list)
-	超过温度控制范围最高值 := false
-	for _, v := range firstTimeData {
-		if v.T_t > 温度控制范围最高值 {
-			超过温度控制范围最高值 = true
-		}
-	}
-	if !超过温度控制范围最高值 {
-		startTimeData = &firstTimeData[0]
-	} else {
-		// 情况2 现场测试开开始时间温度高于温度控制范围最高值,取温度下降至“温度控制范围最高值”以下的第一个终端,该终端下降至最低点,并出现上升0.2℃的时间点
-
-		groupMap := make(map[string][]Task.TaskData_)
-		for _, r := range list {
-			groupMap[r.T_id] = append(groupMap[r.T_id], r)
-		}
-
-		var earliest *Task.TaskData_
-
-		// Step 2: 对每个组调用 FindFirstDecreasingToNumber
-		for _, group := range groupMap {
-			candidate := Task.FindFirstDecreasingToNumber(group, 温度控制范围最高值)
-			if candidate != nil {
-				if earliest == nil || lib.ParseTime(candidate.T_time).Before(lib.ParseTime(earliest.T_time)) {
-					earliest = candidate
-				}
-			}
-		}
-		startTimeData = earliest
-	}
 
-	if startTimeData == nil {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 运行确认及偏差处理空载开始时间 数据!"})
-		return
-	}
+	// 获取数据波动最大的三条
+	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 所有测点, "", 运行确认及偏差处理空载开始时间, 现场测试结束时间, 0, 9999)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
 
-	list2 := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, startTimeData.T_sn, startTimeData.T_time, 现场测试结束时间)
+	list2 := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 运行确认及偏差处理空载开始时间, 现场测试结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list2)
 
 	if len(CalculateHumps_list) < 4 {
@@ -3885,79 +3836,34 @@ func (c *TaskDataController) A运行确认及偏差处理满载结束时间() {
 		return
 	}
 
-	柜内所有测点 := c.GetString("柜内所有测点") //  v26nplogbwt1
-	if len(柜内所有测点) == 0 {
-		柜内所有测点 = c.GetString("库内所有测点")
+	所有测点 := c.GetString("柜内所有测点") //  v26nplogbwt1
+	if len(所有测点) == 0 {
+		所有测点 = c.GetString("库内所有测点")
 	}
-	if len(柜内所有测点) == 0 {
-		柜内所有测点 = c.GetString("车内所有测点")
+	if len(所有测点) == 0 {
+		所有测点 = c.GetString("车内所有测点")
 	}
-	if len(柜内所有测点) == 0 {
+	if len(所有测点) == 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 柜/库/车内所有测点 失败!"})
 		return
 	}
-	温度控制范围最高值_ := c.GetString("温度控制范围最高值") //  v26nplogbwt1
-	if len(温度控制范围最高值_) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 温度控制范围最高值 失败!"})
-		return
-	}
-	温度控制范围最高值 := lib.To_float32(温度控制范围最高值_)
 
-	现场测试开始时间 := c.GetString("现场测试开始时间") //  v26nplogbwt1
-	if len(现场测试开始时间) == 0 || 现场测试开始时间 == "null" {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 现场测试开始时间 失败!"})
-		return
-	}
 	现场测试结束时间 := c.GetString("现场测试结束时间") //  v26nplogbwt1
 	if len(现场测试结束时间) == 0 || 现场测试结束时间 == "null" {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 现场测试结束时间 失败!"})
 		return
 	}
 
-	list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 柜内所有测点, "", 现场测试开始时间, 现场测试结束时间, 0, 9999)
-	if len(list) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 柜内所有测点|现场测试开始时间-现场测试结束时间 温度数据列表 失败!"})
-		return
-	}
-	var startTimeData *Task.TaskData_
-	//情况1 现场测试开始时间的温度低于温度控制范围最高值,直接取现场测试开始时间
-	firstTimeData := Task.GetFirstTimeData(list)
-	超过温度控制范围最高值 := false
-	for _, v := range firstTimeData {
-		if v.T_t > 温度控制范围最高值 {
-			超过温度控制范围最高值 = true
-		}
-	}
-	if !超过温度控制范围最高值 {
-		startTimeData = &firstTimeData[0]
-	} else {
-		// 情况2 现场测试开开始时间温度高于温度控制范围最高值,取温度下降至“温度控制范围最高值”以下的第一个终端,该终端下降至最低点,并出现上升0.2℃的时间点
-
-		groupMap := make(map[string][]Task.TaskData_)
-		for _, r := range list {
-			groupMap[r.T_id] = append(groupMap[r.T_id], r)
-		}
-
-		var earliest *Task.TaskData_
-
-		// Step 2: 对每个组调用 FindFirstDecreasingToNumber
-		for _, group := range groupMap {
-			candidate := Task.FindFirstDecreasingToNumber(group, 温度控制范围最高值)
-			if candidate != nil {
-				if earliest == nil || lib.ParseTime(candidate.T_time).Before(lib.ParseTime(earliest.T_time)) {
-					earliest = candidate
-				}
-			}
-		}
-		startTimeData = earliest
-	}
-
-	if startTimeData == nil {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 运行确认及偏差处理空载开始时间 数据!"})
+	运行确认及偏差处理满载开始时间 := c.GetString("运行确认及偏差处理(满载)开始时间")
+	if len(运行确认及偏差处理满载开始时间) == 0 || 运行确认及偏差处理满载开始时间 == "null" {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 运行确认及偏差处理(满载)开始时间 失败!"})
 		return
 	}
 
-	list2 := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, startTimeData.T_sn, startTimeData.T_time, 现场测试结束时间)
+	// 获取数据波动最大的三条
+	initialData, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 所有测点, "", 运行确认及偏差处理满载开始时间, 现场测试结束时间, 0, 9999)
+	snList := Task.GetTheGreatestFluctuations(initialData, 3)
+	list2 := Task.Read_TaskData_ById_AVG(Task_r.T_task_id, snList, 运行确认及偏差处理满载开始时间, 现场测试结束时间)
 	CalculateHumps_list := Task.CalculateHumps(list2)
 
 	if len(CalculateHumps_list) < 4 {
@@ -3979,7 +3885,7 @@ func (c *TaskDataController) A运行确认及偏差处理满载结束时间() {
 			return
 		}
 	}
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到 开始时间过后出现第二个循环温度再次上升0.2℃的拐点时间点  数据!"})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没找到 运行确认及偏差处理(满载)开始时间过后出现第二个循环温度再次上升0.2℃的拐点时间点  数据!"})
 	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 
 }
@@ -5206,7 +5112,7 @@ func (c *TaskDataController) A空载第一次关门温度恢复时间() {
 				// 情况1:开门有超标的情况:
 				// 柜内所有测点中任意一条数据出现超温度控制范围最高值后所有验证工具下降至温度控制范围最高值减0.5℃此时的时间
 				for _, group := range maps_Time_Min_Max_GROUP {
-					if group.T_max < 温度控制范围最高值-0.5 {
+					if group.T_max <= 温度控制范围最高值-0.5 {
 						lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: group.T_times})
 						return
 					}
@@ -6118,7 +6024,7 @@ func (c *TaskDataController) A监测终端01() {
 	}
 
 	监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
-	if len(监测终端_list) > 1 {
+	if len(监测终端_list) > 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 监测终端_list[0].T_sn})
 
 		// Close the connection
@@ -6145,15 +6051,15 @@ func (c *TaskDataController) A监测终端安装编号01() {
 	}
 
 	监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
-	if len(监测终端_list) > 1 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 监测终端_list[0].T_sn})
+	if len(监测终端_list) > 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 监测终端_list[0].T_id})
 
 		// Close the connection
 		c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 SN-1 终端!"})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 监测终端 1 终端!"})
 	return
 }
 func (c *TaskDataController) A监测终端02() {
@@ -6170,18 +6076,16 @@ func (c *TaskDataController) A监测终端02() {
 		return
 	}
 
-	DeviceClassList_r := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	for _, v := range DeviceClassList_r {
-		if strings.Contains(v.T_sn, "-2") {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: v.T_sn})
+	监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
+	if len(监测终端_list) > 2 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 监测终端_list[1].T_sn})
 
-			// Close the connection
-			c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
-			return
-		}
+		// Close the connection
+		c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
+		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 SN-2 终端!"})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 监测终端 2 终端!"})
 	return
 
 }
@@ -6199,18 +6103,16 @@ func (c *TaskDataController) A监测终端安装编号02() {
 		return
 	}
 
-	DeviceClassList_r := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	for _, v := range DeviceClassList_r {
-		if strings.Contains(v.T_sn, "-2") {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: v.T_sn})
+	监测终端_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, true)
+	if len(监测终端_list) > 1 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: 监测终端_list[1].T_id})
 
-			// Close the connection
-			c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
-			return
-		}
+		// Close the connection
+		c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
+		return
 	}
 
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 SN-2 终端!"})
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "没有找到 监测终端 2 终端!"})
 	return
 }
 
@@ -6253,19 +6155,13 @@ func (c *TaskDataController) A监测系统配置的测点终端参数及安装
 		return
 	}
 
-	DeviceClassList_r := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	var T_sn string
-	for _, v := range DeviceClassList_r {
-		if strings.Contains(v.T_sn, "-") {
-			T_sn = v.T_sn
-			break
-		}
-	}
-	if len(T_sn) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 终端 失败!"})
+	监测终端01 := c.GetString("监测终端01") //  v26nplogbwt1
+	if len(监测终端01) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 监测终端01 失败!"})
 		return
 	}
-	list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, T_sn, "", "", 开满开, 0, 9999)
+
+	list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 监测终端01, "", "", 开满开, 0, 9999)
 
 	if len(list) == 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 终端数据 失败!"})
@@ -6303,9 +6199,9 @@ func (c *TaskDataController) A监测系统配置的测点终端参数及安装
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	开满开 := c.GetString("开满开")
-	if len(开开) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 开开 失败!"})
+	开空开 := c.GetString("开空开")
+	if len(开开) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 开开 失败!"})
 		return
 	}
 
@@ -6315,19 +6211,12 @@ func (c *TaskDataController) A监测系统配置的测点终端参数及安装
 		return
 	}
 
-	DeviceClassList_r := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	var T_sn string
-	for _, v := range DeviceClassList_r {
-		if strings.Contains(v.T_sn, "-") {
-			T_sn = v.T_sn
-			break
-		}
-	}
-	if len(T_sn) == 0 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 终端 失败!"})
+	监测终端01 := c.GetString("监测终端01") //  v26nplogbwt1
+	if len(监测终端01) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 监测终端01 失败!"})
 		return
 	}
-	list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, T_sn, "", "", 开满开, 0, 9999)
+	list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, 监测终端01, "", "", 开空开, 0, 9999)
 
 	if len(list) == 0 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "获取 终端数据 失败!"})
@@ -6419,8 +6308,8 @@ func (c *TaskDataController) A风机布点总测点() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	一号风机测点 := c.GetString("1号风机测点")   //  v26nplogbwt1
-	二号风机测点 := c.GetString("2号风机测点")   //  v26nplogbwt1
+	一号风机测点 := c.GetString("1号风机测点")     //  v26nplogbwt1
+	二号风机测点 := c.GetString("2号风机测点")     //  v26nplogbwt1
 	一号风机回风口 := c.GetString("1号风机回风口") //  v26nplogbwt1
 	二号风机回风口 := c.GetString("2号风机回风口") //  v26nplogbwt1
 
@@ -6448,7 +6337,7 @@ func (c *TaskDataController) A库内除风机出风口回风口外总测点() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	库内所有测点 := c.GetString("库内所有测点")   //  v26nplogbwt1
+	库内所有测点 := c.GetString("库内所有测点")     //  v26nplogbwt1
 	风机布点总测点 := c.GetString("风机布点总测点") //  v26nplogbwt1
 
 	parts1 := strings.Split(库内所有测点, "|")
@@ -6479,9 +6368,9 @@ func (c *TaskDataController) A库内除风机出风口回风口特殊位置布
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	库内所有测点 := c.GetString("库内所有测点")                       //  v26nplogbwt1
-	风机布点总测点 := c.GetString("风机布点总测点")                     //  v26nplogbwt1
-	作业出入口总测点 := c.GetString("作业出入口总测点")                   //  v26nplogbwt1
+	库内所有测点 := c.GetString("库内所有测点")                                           //  v26nplogbwt1
+	风机布点总测点 := c.GetString("风机布点总测点")                                       //  v26nplogbwt1
+	作业出入口总测点 := c.GetString("作业出入口总测点")                                   //  v26nplogbwt1
 	照明灯除湿机风幕机等特殊区域测点 := c.GetString("照明灯、除湿机、风幕机等特殊区域测点") //  v26nplogbwt1
 
 	parts1 := strings.Split(strings.Trim(库内所有测点, "|"), "|")
@@ -6520,7 +6409,7 @@ func (c *TaskDataController) A车内除风机出风口回风口外总测点() {
 	c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
 	c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
 
-	车内所有测点 := c.GetString("车内所有测点")   //  v26nplogbwt1
+	车内所有测点 := c.GetString("车内所有测点")     //  v26nplogbwt1
 	风机布点总测点 := c.GetString("风机布点总测点") //  v26nplogbwt1
 
 	parts1 := strings.Split(车内所有测点, "|")

+ 227 - 389
controllers/TaskHandle.go

@@ -8,7 +8,6 @@ import (
 	"ColdVerify_local/models/VerifyTemplate"
 	"fmt"
 	beego "github.com/beego/beego/v2/server/web"
-	"github.com/beego/beego/v2/server/web/context"
 	"math"
 	"net/http"
 	"sort"
@@ -46,114 +45,18 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_terminal() {
 	for _, class_ := range DeviceClassList_r {
 		_, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, class_.T_sn, class_.T_id, "", "", 0, 1)
 		if cnt == 0 {
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + class_.T_id + class_.T_remark + " 自检探头"})
-			// 获取 备注 下面关联设备,数量
-			var DeviceClassListT_remark_r_list_MAX int64
-			DeviceClassListT_remark_r_list_MAX = 0 //最大值
-			DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(class_.T_class, class_.T_remark)
-			for _, DeviceClassListT_remark_r_list := range DeviceClassListT_remark_r {
-				_, cnt = Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "", "", 0, 9999)
-				logs.Println(DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "数量:", cnt)
-				if DeviceClassListT_remark_r_list_MAX < cnt {
-					DeviceClassListT_remark_r_list_MAX = cnt
-				}
-			}
-			// 筛选 符合的数量 终端
-			SN_List_sn := 9
-			SN_List_s := "" // 2023282551724643,003|2023282534778895,004|
-			SN_List_xn := 9
-			SN_List_x := "" // 2023282551724643,003|2023282534778895,004|
-			SN_List := ""
-			//SN_List_num := 0 // 数量  只能两个
-			CopyTime := ""  //复制的起点 2025-01-07 15:18:00
-			StartTime := "" // 2025-01-07 15:18:00
-			EndTime := ""   //2025-01-07 21:17:00
-			for _, DeviceClassListT_remark_r_list := range DeviceClassListT_remark_r {
-				List_data, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "", "", 0, 9999)
-				if len(List_data) == 0 {
-					//lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: DeviceClassListT_remark_r_list.T_id+"没有找到对应数据!"})
-					continue
-				}
-				if DeviceClassListT_remark_r_list_MAX == cnt {
-					logs.Println(DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "数量:", cnt)
-					CopyTime = List_data[len(List_data)-1].T_time
-					StartTime = List_data[len(List_data)-1].T_time
-					EndTime = List_data[0].T_time
-
-					absc := int(math.Abs(float64(lib.To_int(DeviceClassListT_remark_r_list.T_id) - lib.To_int(class_.T_id))))
-
-					if absc < SN_List_sn {
-						SN_List_s = DeviceClassListT_remark_r_list.T_sn + "," + DeviceClassListT_remark_r_list.T_id + "|"
-						SN_List_sn = absc
-						continue
-					}
-					if absc < SN_List_xn {
-						SN_List_x = DeviceClassListT_remark_r_list.T_sn + "," + DeviceClassListT_remark_r_list.T_id + "|"
-						SN_List_xn = absc
-						continue
-					}
-
-					//SN_List_num++
-					//if SN_List_num >= 2 {
-					//	break // 数量  只能两个
-					//}
-				}
-			}
-			logs.Println("复制参数:", SN_List, CopyTime, StartTime, EndTime)
-			if len(SN_List_x) == 0 || len(SN_List_s) == 0 {
-				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + class_.T_remark + "]中没有找到 至少2条 完整可用数据"})
-				return
-			}
-
-			SN_List = SN_List_s + SN_List_x
-
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: class_.T_sn + "|" + class_.T_id + "开始平均复制到" + SN_List})
-
-			// 开始平均复制到
-			CopySN := class_.T_sn
-			CopyID := class_.T_id
-
-			copyTime, _ := lib.TimeStrToTime(CopyTime)
-			endTime, _ := lib.TimeStrToTime(EndTime)
-			startTime, _ := lib.TimeStrToTime(StartTime)
-			// 时间间隔 s
-			T_saveT := 60
-			CopyEndTime := copyTime.Add(endTime.Sub(startTime)).Format("2006-01-02 15:04:05")
-
-			SN_List_Split := strings.Split(strings.Trim(SN_List, "|"), "|")
-			sn_id1 := strings.Split(SN_List_Split[0], ",")
-
-			sn1, id_str1 := sn_id1[0], sn_id1[1]
-			sn_id2 := strings.Split(SN_List_Split[1], ",")
-
-			sn2, id_str2 := sn_id2[0], sn_id2[1]
-			List1, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999)
-			List2, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999)
-			num := len(List1)
-			if len(List2) < len(List1) {
-				num = len(List2)
-			}
-			ct := copyTime
-			var valueStrings []string
-			for i := 0; i < num; i++ {
-				if List1[i].T_time != List2[i].T_time {
-					lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[i].T_id, List1[i].T_time, List2[i].T_id, List2[i].T_time)})
-					return
-				}
-				T_t := (List1[i].T_t + List2[i].T_t) / 2
-				T_rh := (List1[i].T_rh + List2[i].T_rh) / 2
-
-				valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", CopySN, CopyID, T_t, T_rh, ct.Format("2006-01-02 15:04:05")))
-
-				ct = ct.Add(time.Second * time.Duration(T_saveT))
-			}
-			Task.DeleteTaskDataByTimeRange(Task_r.T_task_id, CopySN, CopyID, CopyTime, CopyEndTime)
-
-			err = Task.Batch_Adds_TaskData(T_task_id, valueStrings)
-			if err == nil {
-				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))})
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + class_.T_id + " " + class_.T_remark + " 自检探头"})
+
+			// -----------开始平均复制到
+			device := Device.DeviceClassList{
+				T_class:  class_.T_class,
+				T_id:     class_.T_id,
+				T_sn:     class_.T_sn,
+				T_remark: class_.T_remark,
 			}
 
+			c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
+			// -----------开始平均复制到结束
 		}
 
 	}
@@ -182,106 +85,103 @@ func (c *TaskDataHandleController) SSE_Automatically_add_missing_data() {
 	// 时间间隔 s
 	T_saveT := 60
 
-	// 获取 备注 下面关联设备,数量
-	var Devicedata_list_MAX int64
-	Devicedata_list_MAX = 0 //最大值
 	DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
-	for _, DeviceClassListT_remark_r_list := range DeviceClassList_list {
-		_, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "", "", 0, 9999)
 
-		if Devicedata_list_MAX < cnt {
-			Devicedata_list_MAX = cnt
-		}
+	// 分组统计每个sn的数据数量
+	snList := Device.JoinDeviceClassListSnToString(DeviceClassList_list)
+	TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(Task_r.T_task_id, snList, "", "")
+	if len(TaskData_Total_GroupBySnId) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "暂无测点需要自检!"})
+	}
+	Devicedata_list_MAX := TaskData_Total_GroupBySnId[0].Total
 
+	TaskData_Total_GroupBySnId_Map := make(map[string]int64)
+	for _, v := range TaskData_Total_GroupBySnId {
+		TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
 	}
+
+	startTime, endTime := Task.Read_TaskData_T_time_T_Min_Max(Task_r.T_task_id, TaskData_Total_GroupBySnId[0].T_sn, TaskData_Total_GroupBySnId[0].T_id, "", "")
+
 	logs.Println("数据标准数量:", Devicedata_list_MAX)
 	// 选择 数据缺失的终端
 	for _, DeviceClassList_r := range DeviceClassList_list {
+
+		total, ok := TaskData_Total_GroupBySnId_Map[DeviceClassList_r.T_sn]
+		if !ok {
+			// 测点自检事再处理
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 , 测点缺失,跳过"})
+			continue
+		}
+		if Devicedata_list_MAX == total {
+			continue
+		}
+
 		list, cnt := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
-		if Devicedata_list_MAX != cnt {
-
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 ,自检:" + lib.To_string(Devicedata_list_MAX-cnt) + " "})
-			for i := 0; i < len(list)-1; i++ {
-				current := list[i].T_time
-				next := list[i+1].T_time
-				ct, _ := time.Parse("2006-01-02 15:04:05", current)
-				nt, _ := time.Parse("2006-01-02 15:04:05", next)
-				interval := nt.Unix() - ct.Unix()
-				//logs.Debug("时间间隔:", interval, "保存时间:", saveTime)
-				//fmt.Println("当前:", current, "下一个:", next)
-				// 缺一个时间点 补漏
-				if int(interval) == 2*T_saveT {
-					lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到自检点 " + current + " ~ " + next + " 开始自检"})
-
-					t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04:05") //时间临时变量
-					ttt := (list[i].T_t + list[i+1].T_t) / 2
-					trht := (list[i].T_rh + list[i+1].T_rh) / 2
-					Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
-						T_sn:   list[i].T_sn,
-						T_id:   list[i].T_id,
-						T_t:    ttt,
-						T_rh:   trht,
-						T_time: t,
-					})
-					continue
-				}
-				// 缺的数据大于一个时间点,执行平均复制到
-				if int(interval) > T_saveT {
-					lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到自检点 " + current + " ~ " + next + " 开始自检"})
-
-					// -------------------- 开始 平均复制到  --------------------
-
-					// 获取 备注 下面关联设备,数量
-					var DeviceClassListT_remark_r_list_MAX int64
-					DeviceClassListT_remark_r_list_MAX = 0 //最大值
-					DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(DeviceClassList_r.T_class, DeviceClassList_r.T_remark)
-					for _, DeviceClassListT_remark_r_list := range DeviceClassListT_remark_r {
-						_, cnt = Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "", "", 0, 9999)
-						logs.Println(DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "数量:", cnt)
-						if DeviceClassListT_remark_r_list_MAX < cnt {
-							DeviceClassListT_remark_r_list_MAX = cnt
-						}
-					}
-					// 筛选 符合的数量 终端
-					//SN_List_sn := 9
-					//SN_List_s := "" // 2023282551724643,003|2023282534778895,004|
-					//SN_List_xn := 9
-					//SN_List_x := "" // 2023282551724643,003|2023282534778895,004|
-					SN_List := "" // 2023282551724643,003|2023282534778895,004|
-					//SN_List_num := 0     // 数量  只能两个
-					CopyTime := current  //复制的起点 2025-01-07 15:18:00
-					StartTime := current // 2025-01-07 15:18:00
-					EndTime := next      //2025-01-07 21:17:00
-					var completeDataDeviceClassList []Device.DeviceClassList
-					for _, DeviceClassList := range DeviceClassListT_remark_r {
-						List_data, count := Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassList.T_sn, DeviceClassList.T_id, "", "", 0, 9999)
-						if DeviceClassListT_remark_r_list_MAX == count {
-							logs.Println(DeviceClassList.T_sn, DeviceClassList.T_id, "数量:", cnt)
-							EndTime = List_data[0].T_time
-							completeDataDeviceClassList = append(completeDataDeviceClassList, DeviceClassList)
-						}
-					}
-
-					logs.Println("复制参数:", SN_List, CopyTime, StartTime, EndTime)
-					if len(completeDataDeviceClassList) < 2 {
-						lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + DeviceClassList_r.T_remark + "] 中没有找到 至少2条 完整可用数据,【请手动处理!】"})
-						return
-					}
-
-					// -----------开始平均复制到
-					device := Device.DeviceClassList{
-						T_id: DeviceClassList_r.T_id,
-						T_sn: DeviceClassList_r.T_sn,
-					}
-
-					c.SetAdjacentDeviceAVGTaskData(T_task_id, device, completeDataDeviceClassList, StartTime, EndTime)
-
-					// -----------开始平均复制到结束
 
-				}
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: DeviceClassList_r.T_id + " 终端自检数据 ,数据差值:" + lib.To_string(Devicedata_list_MAX-cnt) + " "})
+
+		// 开始结束时间不同,直接执行平均复制到
+		if startTime != list[0].T_time || endTime != list[len(list)-1].T_time {
+			// -----------开始平均复制到
+			device := Device.DeviceClassList{
+				T_class:  DeviceClassList_r.T_class,
+				T_id:     DeviceClassList_r.T_id,
+				T_sn:     DeviceClassList_r.T_sn,
+				T_remark: DeviceClassList_r.T_remark,
+			}
+
+			c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
+
+			// -----------开始平均复制到结束
+			continue
+		}
+
+		for i := 0; i < len(list)-1; i++ {
+
+			current := list[i].T_time
+			next := list[i+1].T_time
+
+			ct, _ := time.Parse("2006-01-02 15:04:05", current)
+			nt, _ := time.Parse("2006-01-02 15:04:05", next)
+			interval := nt.Unix() - ct.Unix()
+			//logs.Debug("时间间隔:", interval, "保存时间:", saveTime)
+			//fmt.Println("当前:", current, "下一个:", next)
+			// 缺一个时间点 补漏
+			if int(interval) == 2*T_saveT {
+				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到自检时间点 " + current + " ~ " + next + " 开始自检"})
+
+				t := ct.Add(time.Second * time.Duration(T_saveT)).Format("2006-01-02 15:04") //时间临时变量
+				ttt := (list[i].T_t + list[i+1].T_t) / 2
+				trht := (list[i].T_rh + list[i+1].T_rh) / 2
+				Task.InsertTaskData(Task_r.T_task_id, Task.TaskData_{
+					T_sn:   list[i].T_sn,
+					T_id:   list[i].T_id,
+					T_t:    ttt,
+					T_rh:   trht,
+					T_time: t,
+				})
+				continue
 			}
+			// 缺的数据大于一个时间点,执行平均复制到
+			if int(interval) > T_saveT {
+				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到自检时间点 " + current + " ~ " + next + " 开始自检"})
+
+				// -----------开始平均复制到
+				device := Device.DeviceClassList{
+					T_class:  DeviceClassList_r.T_class,
+					T_id:     DeviceClassList_r.T_id,
+					T_sn:     DeviceClassList_r.T_sn,
+					T_remark: DeviceClassList_r.T_remark,
+				}
+				c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
+				// -----------开始平均复制到结束
+
+				// 平均复制结束,跳出循环
+				break
 
+			}
 		}
+
 	}
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
 
@@ -308,150 +208,49 @@ func (c *TaskDataHandleController) SSE_Continuously_unchanged_data() {
 	}
 
 	// 获取 备注 下面关联设备,数量
-	var Devicedata_list_MAX int64
-	Devicedata_list_MAX = 0 //最大值
-	DeviceClassList_list := Device.Read_DeviceClassList_List_id(Task_r.T_class)
-	for _, DeviceClassListT_remark_r_list := range DeviceClassList_list {
-		_, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "", "", 0, 9999)
-
-		if Devicedata_list_MAX < cnt {
-			Devicedata_list_MAX = cnt
-		}
-	}
-	logs.Println("数据标准数量:", Devicedata_list_MAX)
+	DeviceClassList_list := Device.Read_DeviceClassList_List_id_By_Terminal(Task_r.T_class, false)
+
 	// 选择 数据缺失的终端
+	var DeleteDeviceClassList []Device.DeviceClassList
 	for _, DeviceClassList_r := range DeviceClassList_list {
 		TaskData_list, _ := Task.Read_TaskData_ById_List_AES(Task_r.T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "", 0, 9999)
 
-		var t_data float32
-		t_data = 0
-		t_data_num := 0
-
-		current := ""
-		next := ""
-		for i := 0; i < len(TaskData_list)-1; i++ {
-			if t_data == TaskData_list[i].T_t {
-				if t_data_num == 0 {
-					current = TaskData_list[i].T_time
-
-				}
-				t_data_num += 1
-				continue
-
-			} else {
-				if t_data_num > T_timeout {
-					next = TaskData_list[i].T_time
-
-					CopyFromPositionAverage(c.Ctx.ResponseWriter, Task_r.T_task_id, DeviceClassList_r.T_class, DeviceClassList_r.T_remark, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, current, next)
-				}
-				// 清空标致
-				t_data = TaskData_list[i].T_t
-				t_data_num = 0
-				continue
-			}
-
+		if len(TaskData_list) == 0 {
+			continue
 		}
 
-	}
-	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
-
-	// Close the connection
-	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
-}
+		maxCount, start, end := Task.FindUnchangedInterval(TaskData_list)
+		if maxCount > T_timeout {
 
-// 平均复制到
-func CopyFromPositionAverage(c *context.Response, T_task_id string, T_class int, T_remark, T_sn, T_id, current, next string) {
-	fmt.Println("平均复制到 CopyFromPositionAverage:", T_task_id, T_class, T_remark, T_sn, T_id, current, next)
+			Task.DeleteTaskDataByTimeRange(T_task_id, DeviceClassList_r.T_sn, DeviceClassList_r.T_id, "", "")
+			DeleteDeviceClassList = append(DeleteDeviceClassList, DeviceClassList_r)
 
-	lib.SseWriteJSON(c, lib.JSONSSE{State: 0, Msg: "找到 " + T_id + " 无数据变化, 时间 " + current + " ~ " + next})
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "找到" + DeviceClassList_r.T_id + "  探头, " +
+				"最多连续 " + lib.To_string(maxCount) + " 分钟没有变化," +
+				"开始时间:" + start + " 结束时间:" + end + "," +
+				"开始自检"})
 
-	// -------------------- 开始 平均复制到  --------------------
-	// 时间间隔 s
-	T_saveT := 60
-	// 获取 备注 下面关联设备,数量
-	var DeviceClassListT_remark_r_list_MAX int64
-	DeviceClassListT_remark_r_list_MAX = 0 //最大值
-	DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(T_class, T_remark)
-	for _, DeviceClassListT_remark_r_list := range DeviceClassListT_remark_r {
-		_, cnt := Task.Read_TaskData_ById_List(T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, current, next, 0, 9999)
-		logs.Println(DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "数量:", cnt)
-		if DeviceClassListT_remark_r_list_MAX < cnt {
-			DeviceClassListT_remark_r_list_MAX = cnt
-		}
-	}
-	// 筛选 符合的数量 终端
-	SN_List := ""        // 2023282551724643,003|2023282534778895,004|
-	SN_List_num := 0     // 数量  只能两个
-	CopyTime := current  //复制的起点 2025-01-07 15:18:00
-	StartTime := current // 2025-01-07 15:18:00
-	EndTime := next      //2025-01-07 21:17:00
-	for _, DeviceClassListT_remark_r_list := range DeviceClassListT_remark_r {
-		_, cnt := Task.Read_TaskData_ById_List(T_task_id, DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, current, next, 0, 9999)
-		if DeviceClassListT_remark_r_list_MAX == cnt {
-			logs.Println(DeviceClassListT_remark_r_list.T_sn, DeviceClassListT_remark_r_list.T_id, "数量:", cnt)
-			SN_List += DeviceClassListT_remark_r_list.T_sn + "," + DeviceClassListT_remark_r_list.T_id + "|"
-			//CopyTime = List_data[len(List_data)-1].T_time
-			//StartTime = List_data[len(List_data)-1].T_time
-			//EndTime = List_data[0].T_time
-			SN_List_num++
-			if SN_List_num >= 2 {
-				break // 数量  只能两个
-			}
 		}
-	}
-	logs.Println("复制参数:", SN_List, CopyTime, StartTime, EndTime)
-	if SN_List_num != 2 {
-		lib.SseWriteJSON(c, lib.JSONSSE{State: 2, Msg: "[" + T_remark + "] 中没有找到 至少2条 完整可用数据"})
-		return
-	}
-	lib.SseWriteJSON(c, lib.JSONSSE{State: 0, Msg: T_sn + "|" + T_id + "开始平均复制到" + SN_List})
-
-	// 开始平均复制到
-	CopySN := T_sn
-	CopyID := T_id
-
-	copyTime, _ := lib.TimeStrToTime(CopyTime)
-	endTime, _ := lib.TimeStrToTime(EndTime)
-	startTime, _ := lib.TimeStrToTime(StartTime)
-
-	CopyEndTime := copyTime.Add(endTime.Sub(startTime)).Format("2006-01-02 15:04:05")
-
-	SN_List_Split := strings.Split(strings.Trim(SN_List, "|"), "|")
-	sn_id1 := strings.Split(SN_List_Split[0], ",")
-
-	sn1, id_str1 := sn_id1[0], sn_id1[1]
-	sn_id2 := strings.Split(SN_List_Split[1], ",")
 
-	sn2, id_str2 := sn_id2[0], sn_id2[1]
-	List1, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn1, id_str1, StartTime, EndTime, 0, 9999)
-	List2, _ := Task.Read_TaskData_ById_List_AES(T_task_id, sn2, id_str2, StartTime, EndTime, 0, 9999)
-	num := len(List1)
-	if len(List2) < len(List1) {
-		num = len(List2)
 	}
 
-	fmt.Println("num:", num)
-	ct := copyTime
-	var valueStrings []string
-
-	for TaskData_i := 0; TaskData_i < num; TaskData_i++ {
-		if List1[TaskData_i].T_time != List2[TaskData_i].T_time {
-			lib.SseWriteJSON(c, lib.JSONSSE{State: 2, Msg: fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[TaskData_i].T_id, List1[TaskData_i].T_time, List2[TaskData_i].T_id, List2[TaskData_i].T_time)})
-			return
+	for _, class_ := range DeleteDeviceClassList {
+		// -----------开始平均复制到
+		device := Device.DeviceClassList{
+			T_class:  class_.T_class,
+			T_id:     class_.T_id,
+			T_sn:     class_.T_sn,
+			T_remark: class_.T_remark,
 		}
-		T_t := (List1[TaskData_i].T_t + List2[TaskData_i].T_t) / 2
-		T_rh := (List1[TaskData_i].T_rh + List2[TaskData_i].T_rh) / 2
-		valueStrings = append(valueStrings, fmt.Sprintf("('%s','%s',%v,%v,'%s')", CopySN, CopyID, T_t, T_rh, ct.Format("2006-01-02 15:04:05")))
 
-		ct = ct.Add(time.Second * time.Duration(T_saveT))
-	}
-	Task.DeleteTaskDataByTimeRange(T_task_id, CopySN, CopyID, CopyTime, CopyEndTime)
+		c.SetAdjacentDeviceAVGTaskData(T_task_id, device, "", "")
+		// -----------开始平均复制到结束
 
-	err := Task.Batch_Adds_TaskData(T_task_id, valueStrings)
-	if err == nil {
-		lib.SseWriteJSON(c, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("%d/%d", len(valueStrings), len(valueStrings))})
 	}
+	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "完成!"})
 
+	// Close the connection
+	c.Ctx.ResponseWriter.WriteHeader(http.StatusOK)
 }
 
 // 绑定点与终端比对  (绑定点数据自检) 终端数据为参照物,绑定点数据在终端偏差±1℃,保温箱为±0.5℃
@@ -487,6 +286,7 @@ func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_ter
 	// 均匀性布点   产品存放区域测点
 	部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
 	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
+	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "作业出入口总测点")...)
 	部点终端_list = Device.DeduplicateById(部点终端_list)
 	if len(部点终端_list) <= 2 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
@@ -553,6 +353,11 @@ func (c *TaskDataHandleController) SSE_Comparison_between_binding_points_and_ter
 			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点" + lib.To_string(i+1) + " 中找到 " + lib.To_string(len(温湿度绑定点_list)) + "条,只允许 一条数据!"})
 		}
 
+		TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(Task_r.T_task_id, 温湿度绑定点_list[0].T_sn, "", "")
+		if len(TaskData_Total_GroupBySnId) == 0 {
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点" + lib.To_string(i+1) + " 无数据!请先处理数据!"})
+		}
+
 		fmt.Println("温湿度绑定点"+lib.To_string(i+1)+"数据准备:", 温湿度绑定点_list[0].T_id, 监测终端.T_id, 开始时间, 结束时间)
 
 		var 温湿度绑定点vga, 监测终端vga, vgaca float64
@@ -630,6 +435,7 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 	// 均匀性布点   产品存放区域测点
 	部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
 	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
+	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "作业出入口总测点")...)
 	部点终端_list = Device.DeduplicateById(部点终端_list)
 	开始时间 := ""
 	// 开始时间 获取温度下降到第二个低点时间
@@ -701,7 +507,7 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 	// -------  温湿度绑定点
 	温湿度绑定点1_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "温湿度绑定点1")
 	if len(温湿度绑定点1_list) != 1 {
-		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点1 中找到 " + lib.To_string(len(温湿度绑定点1_list)) + "条,布点终端异常!"})
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 1, Msg: "温湿度绑定点1 中找到 " + lib.To_string(len(温湿度绑定点1_list)) + "条,布点终端异常!"})
 		return
 	}
 	温湿度绑定点2_list_is := true
@@ -711,6 +517,20 @@ func (c *TaskDataHandleController) SSE_Compare_binding_points_with_cold_and_hot_
 		温湿度绑定点2_list = 温湿度绑定点1_list
 		温湿度绑定点2_list_is = false
 	}
+
+	TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, fmt.Sprintf("%s|%s", 温湿度绑定点1_list[0].T_sn, 温湿度绑定点2_list[0].T_sn), 开始时间, 结束时间)
+
+	if len(TaskData_Total_GroupBySnId) == 0 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点 无数据"})
+		return
+	}
+	for _, v := range TaskData_Total_GroupBySnId {
+		if v.Total == 0 {
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "温湿度绑定点[" + v.T_id + "] 无数据"})
+			return
+		}
+	}
+
 	温湿度绑定点1vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点1_list[0].T_sn, 温湿度绑定点1_list[0].T_id, 开始时间, 结束时间)
 	温湿度绑定点2vga := Task.Read_TaskData_AVG(T_task_id, 温湿度绑定点2_list[0].T_sn, 温湿度绑定点2_list[0].T_id, 开始时间, 结束时间)
 
@@ -895,6 +715,7 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 	// 均匀性布点   产品存放区域测点
 	部点终端_list := Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "均匀性布点")
 	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "产品存放区域测点")...)
+	部点终端_list = append(部点终端_list, Device.Read_DeviceClassList_List_id_T_remark(Task_r.T_class, "作业出入口总测点")...)
 	部点终端_list = Device.DeduplicateById(部点终端_list)
 	if len(部点终端_list) <= 2 {
 		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "均匀性布点,产品存放区域测点 太少了,至少两条以上!"})
@@ -940,13 +761,6 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 		T_min  float64
 		T_diff float64 // 最大最小值差异
 	}
-	var AVGClassList_r []AVGClassList
-	for _, i2 := range 部点终端_list {
-		T_max := Task.Read_TaskData_max(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)
-		T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)
-		AVGClassList_r = append(AVGClassList_r, AVGClassList{T_sn: i2.T_sn, T_id: i2.T_id, T_max: T_max, T_min: T_min, T_diff: T_max - T_min})
-	}
-	fmt.Println("AVGClassList_r:", AVGClassList_r)
 
 	fmt.Println("数据准备:", 开始时间, 结束时间, 温度控制范围最小值, 温度控制范围最高值)
 
@@ -954,50 +768,44 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "--- 进行处理 数据!---"})
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: fmt.Sprintf("开始时间:%s 结束时间:%s", 开始时间, 结束时间)})
 
-	for _, AVGClassList_i := range AVGClassList_r {
-		var vgaca float64
-		if AVGClassList_i.T_max > 温度控制范围最高值 && AVGClassList_i.T_min < 温度控制范围最小值 {
+	var AVGClassList_r []AVGClassList
+	for _, i2 := range 部点终端_list {
+		T_max := Task.Read_TaskData_max(T_task_id, i2.T_sn, i2.T_id, 开始时间, 结束时间)
+		T_min := Task.Read_TaskData_min(T_task_id, i2.T_sn, i2.T_id, "", "")
+		AVGClassList_r = append(AVGClassList_r, AVGClassList{T_sn: i2.T_sn, T_id: i2.T_id, T_max: T_max, T_min: T_min, T_diff: T_max - T_min})
+	}
 
-			// 压缩
-			diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
-			// 获取压缩度
-			compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.4)/diff, 2)
-			// 压缩
-			Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
-			// 向上偏移
-			vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress, 1)
+	for _, AVGClassList_i := range AVGClassList_r {
+		if AVGClassList_i.T_max < 温度控制范围最高值 && AVGClassList_i.T_min > 温度控制范围最小值 {
+			continue
+		}
 
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
-				" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
-				" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
-				" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
-				" 压缩:" + lib.To_string(compress) +
-				" 向上偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+		var vgaca float64
 
-			Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", RoundToDecimal(vgaca+0.1, 1), 0)
-		}
-		if (AVGClassList_i.T_max - AVGClassList_i.T_min) > (温度控制范围最高值 - 温度控制范围最小值 - 0.2) {
+		if (AVGClassList_i.T_max - AVGClassList_i.T_min) > (温度控制范围最高值 - 温度控制范围最小值 - 0.4) {
 
 			// 压缩
 			diff := RoundToDecimal(AVGClassList_i.T_max-AVGClassList_i.T_min, 1)
 			// 获取压缩度
-			compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.4)/diff, 2)
+			compress := RoundToDecimal((温度控制范围最高值-温度控制范围最小值-0.6)/diff, 2)
 			// 压缩
 			Task.UpdateTaskDataTemperatureAndHumidityByGeometric(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", compress, 1)
 
+			T_max_compress := RoundToDecimal(AVGClassList_i.T_max*compress, 1)
+			T_min_compress := RoundToDecimal(AVGClassList_i.T_min*compress, 1)
 			// 判断压缩后是否在 温度控制范围最小值-温度控制范围最高值范围内 不做处理
-			if AVGClassList_i.T_max*compress > 温度控制范围最高值 && AVGClassList_i.T_min*compress < 温度控制范围最小值 {
+			if T_max_compress <= RoundToDecimal(温度控制范围最高值-0.1, 1) && T_min_compress >= RoundToDecimal(温度控制范围最小值+0.1, 1) {
 				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
 					" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
 					" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
-					" 压缩:" + lib.To_string(fmt.Sprintf("%.2f", compress)) +
-					" 压缩后最大值:" + lib.To_string(fmt.Sprintf("%.2f", AVGClassList_i.T_max*compress)) + "℃  " +
-					" 压缩后最小值:" + lib.To_string(fmt.Sprintf("%.2f", AVGClassList_i.T_min*compress)) + "℃  "})
+					" 压缩:" + lib.To_string(compress) +
+					" 压缩后最大值:" + lib.To_string(T_max_compress) + "℃  " +
+					" 压缩后最小值:" + lib.To_string(T_min_compress) + "℃  "})
 				continue
 			}
 			// 压缩后仍高于 温度控制范围最高值,向下偏移
-			if AVGClassList_i.T_max*compress > 温度控制范围最高值 {
-				vgaca = RoundToDecimal(AVGClassList_i.T_max*compress-温度控制范围最高值, 1)
+			if T_max_compress >= 温度控制范围最高值 {
+				vgaca = RoundToDecimal(T_max_compress-温度控制范围最高值+0.1, 1)
 				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
 					" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
 					" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
@@ -1005,15 +813,15 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 					" 压缩后最大值:" + lib.To_string(AVGClassList_i.T_max*compress) + "℃  " +
 					" 压缩后最小值:" + lib.To_string(AVGClassList_i.T_min*compress) + "℃  " +
 					" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
-					" 向下偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+					" 向下偏移:" + lib.To_string(vgaca) + "℃ "})
 
-				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -RoundToDecimal(vgaca+0.1, 1), 0)
+				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
 				continue
 			}
 			// 压缩后仍低于 温度控制范围最小值,向上偏移
-			if AVGClassList_i.T_min*compress < 温度控制范围最小值 {
+			if T_min_compress <= 温度控制范围最小值 {
 				// 向上偏移
-				vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress, 1)
+				vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min*compress+0.1, 1)
 
 				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
 					" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
@@ -1022,33 +830,34 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 					" 压缩后最大值:" + lib.To_string(AVGClassList_i.T_max*compress) + "℃  " +
 					" 压缩后最小值:" + lib.To_string(AVGClassList_i.T_min*compress) + "℃  " +
 					" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
-					" 向上偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
+					" 向上偏移:" + lib.To_string(vgaca) + "℃ "})
 
-				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", RoundToDecimal(vgaca+0.1, 1), 0)
+				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
 
 			}
 			continue
-		}
-		// 向下偏移
-		if AVGClassList_i.T_max > 温度控制范围最高值 {
-			vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值, 1)
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
-				" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
-				" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
-				" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
-				" 向下偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
-			// 偏移
-			Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -RoundToDecimal(vgaca+0.1, 1), 0)
-			continue
-		}
-		if AVGClassList_i.T_min < 温度控制范围最小值 {
-			vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min, 1)
-			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
-				" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
-				" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
-				" 数据偏差: " + lib.To_string(vgaca) + "℃ " +
-				" 向上偏移:" + lib.To_string(RoundToDecimal(vgaca+0.1, 1)) + "℃ "})
-			Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", RoundToDecimal(vgaca+0.1, 1), 0)
+		} else {
+			// 向下偏移
+			if AVGClassList_i.T_max >= 温度控制范围最高值 {
+				vgaca = RoundToDecimal(AVGClassList_i.T_max-温度控制范围最高值+0.1, 1)
+				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
+					" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
+					" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
+					" 数据偏差:" + lib.To_string(vgaca) + "℃ " +
+					" 向下偏移:" + lib.To_string(vgaca) + "℃ "})
+				// 偏移
+				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", -vgaca, 0)
+				continue
+			}
+			if AVGClassList_i.T_min <= 温度控制范围最小值 {
+				vgaca = RoundToDecimal(温度控制范围最小值-AVGClassList_i.T_min+0.1, 1)
+				lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: "进行处理 数据!" + lib.To_string(AVGClassList_i.T_id) +
+					" 最大值:" + lib.To_string(AVGClassList_i.T_max) + "℃  " +
+					" 最小值:" + lib.To_string(AVGClassList_i.T_min) + "℃  " +
+					" 数据偏差: " + lib.To_string(vgaca) + "℃ " +
+					" 向上偏移:" + lib.To_string(vgaca) + "℃ "})
+				Task.UpdateTaskDataTemperatureAndHumidity(Task_r.T_task_id, AVGClassList_i.T_sn, AVGClassList_i.T_id, "", "", vgaca, 0)
+			}
 		}
 
 	}
@@ -1060,9 +869,40 @@ func (c *TaskDataHandleController) SSE_Interval_data_correction() {
 }
 
 // 获取相邻2个终端值平均复制到
-func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, data []Device.DeviceClassList, StartTime, EndTime string) {
+func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string, device Device.DeviceClassList, StartTime, EndTime string) {
+
+	DeviceClassListT_remark_r := Device.Read_DeviceClassList_List_id_T_remark(device.T_class, device.T_remark)
+	// 分组统计每个sn的数据数量
+	snList := Device.JoinDeviceClassListSnToString(DeviceClassListT_remark_r)
+	TaskData_Total_GroupBySnId := Task.Read_TaskData_Total_GroupBySnId(T_task_id, snList, StartTime, EndTime)
+
+	if len(TaskData_Total_GroupBySnId) < 2 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 可用数据"})
+		return
+	}
 
-	twoDevice := getBeforeAndAfter(device.T_id, data)
+	// 获取 备注 下面关联设备,数量
+	DeviceClassListT_remark_r_list_MAX := TaskData_Total_GroupBySnId[0].Total
+
+	TaskData_Total_GroupBySnId_Map := make(map[string]int64)
+	for _, v := range TaskData_Total_GroupBySnId {
+		TaskData_Total_GroupBySnId_Map[v.T_sn] = v.Total
+	}
+
+	var completeDataDeviceClassList []Device.DeviceClassList
+
+	for _, v := range DeviceClassListT_remark_r {
+		if TaskData_Total_GroupBySnId_Map[v.T_sn] == DeviceClassListT_remark_r_list_MAX || v.T_sn == device.T_sn {
+			completeDataDeviceClassList = append(completeDataDeviceClassList, v)
+		}
+	}
+
+	if len(completeDataDeviceClassList) < 3 {
+		lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: "[" + device.T_remark + "]中没有找到 至少2条 完整可用数据"})
+		return
+	}
+
+	twoDevice := getBeforeAndAfter(device.T_id, completeDataDeviceClassList)
 	sn1, id_str1 := twoDevice[0].T_sn, twoDevice[0].T_id
 	sn2, id_str2 := twoDevice[1].T_sn, twoDevice[1].T_id
 	lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 0, Msg: device.T_sn + "|" + device.T_id + "开始平均复制到" +
@@ -1083,11 +923,9 @@ func (c *TaskDataHandleController) SetAdjacentDeviceAVGTaskData(T_task_id string
 	var valueStrings []string
 	for i := 0; i < num; i++ {
 		if List1[i].T_time != List2[i].T_time {
-			c.Data["json"] = lib.JSONS{202, fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[i].T_id, List1[i].T_time, List2[i].T_id, List2[i].T_time), nil}
-			c.ServeJSON()
+			lib.SseWriteJSON(c.Ctx.ResponseWriter, lib.JSONSSE{State: 2, Msg: fmt.Sprintf("%s【%s】、%s【%s】时间不一致", List1[i].T_id, List1[i].T_time, List2[i].T_id, List2[i].T_time)})
 			return
-			//ct = ct.Add(time.Second * time.Duration(T_saveT))
-			//continue
+
 		}
 		T_t := (List1[i].T_t + List2[i].T_t) / 2
 		T_rh := (List1[i].T_rh + List2[i].T_rh) / 2

+ 24 - 12
models/Device/DeviceClassList.go

@@ -327,25 +327,26 @@ func Read_DeviceClassList_List_id_By_Terminal(T_class_Id int, T_Terminal bool) (
 func Read_DeviceClassList_List_id_T_remark(T_class_Id int, T_remark string) (r []DeviceClassList) {
 
 	o := orm.NewOrm()
-	// 也可以直接使用 Model 结构体作为表名
 
-	qs := o.QueryTable(new(DeviceClassList))
 	T_remark_s := strings.Split(T_remark, "|")
-	cond := orm.NewCondition()
-	cond1 := orm.NewCondition()
-
-	for _, v := range T_remark_s {
-		if len(T_remark_s) > 0 {
-			cond1 = cond1.Or("T_remark__icontains", v) // .AndNot("status__in", 1).Or("profile__age__gt", 2000)
 
-		}
+	sqlWhere := "t_class = " + strconv.Itoa(T_class_Id) + " AND t__state = 1 AND t_terminal <= 1"
 
+	var conditions []string
+	for _, v := range T_remark_s {
+		conditions = append(conditions, fmt.Sprintf("t_remark LIKE '%%%s%%'", v))
+	}
+	if len(conditions) > 0 {
+		sqlWhere += " AND (" + strings.Join(conditions, " OR ") + ")"
 	}
-	cond = cond.And("T_class", T_class_Id).And("T_State", 1).AndCond(cond1)
 
-	qs.SetCond((*orm2.Condition)(cond)).All(&r)
+	sql := "SELECT *  FROM device_class_list WHERE " + sqlWhere + " ORDER BY t_id+0 "
 
-	//qs.Filter("T_class", T_class_Id).Filter("T_remark", T_remark).Filter("T_State", 1).All(&r)
+	logs.Println(sql)
+	_, err := o.Raw(sql).QueryRows(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
 
 	return r
 }
@@ -401,3 +402,14 @@ func DeduplicateById(devices []DeviceClassList) []DeviceClassList {
 	}
 	return result
 }
+
+func JoinDeviceClassListSnToString(devices []DeviceClassList) string {
+	var builder strings.Builder
+
+	for _, device := range devices {
+		builder.WriteString(device.T_sn)
+		builder.WriteString("|")
+	}
+
+	return builder.String()
+}

+ 131 - 6
models/Task/TaskData.go

@@ -174,6 +174,12 @@ type TaskData_AVG struct {
 	T_time string  `orm:"column(t_times);null;"`     // 采集时间
 }
 
+type TaskData_Total struct {
+	T_sn  string
+	T_id  string
+	Total int64
+}
+
 func Read_TaskData_ById_List(T_task_id string, SN string, T_id string, Time_start_ string, Time_end_ string, page int, page_z int) ([]TaskData_, int64) {
 	o := orm.NewOrm()
 	var maps []TaskData_
@@ -830,6 +836,55 @@ func Read_TaskData_Num(T_task_id string) int {
 	return key
 }
 
+func Read_TaskData_Total_GroupBySnId(T_task_id string, SN string, Time_start_ string, Time_end_ string) []TaskData_Total {
+	o := orm.NewOrm()
+
+	var maps []TaskData_Total
+	sql_condition := ""
+	if len(Time_start_) > 1 {
+		sql_condition += " AND t_time >= '" + Time_start_ + "'"
+	}
+
+	if len(Time_end_) > 1 {
+		sql_condition += " AND t_time <= '" + Time_end_ + "'"
+	}
+
+	if len(SN) > 0 {
+		if strings.Contains(SN, "|") {
+			// 将字符串按 | 分割
+			ids := strings.Split(strings.TrimSuffix(SN, "|"), "|")
+
+			// 构建 SQL 查询
+			query := " AND t_sn IN ("
+			// 动态添加每个 id
+			for i, id := range ids {
+				query += "'" + id + "'"
+				if i < len(ids)-1 {
+					query += ", " // 添加逗号分隔
+				}
+			}
+			query += ") " // 结束 SQL 查询
+			sql_condition += query
+
+		} else {
+			sql_condition += " AND t_sn = '" + SN + "'"
+		}
+	}
+	if len(sql_condition) > 0 {
+		sql_condition = " WHERE " + strings.TrimLeft(sql_condition, " AND ")
+	}
+
+	sql := "SELECT t_sn,t_id, count(*) AS total FROM z_task_data_" + T_task_id + sql_condition + " GROUP BY T_sn,T_id ORDER BY total DESC"
+	fmt.Println(sql)
+	_, err := o.Raw(sql).QueryRows(&maps)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return maps
+	}
+
+	return maps
+}
+
 func Dump_TaskData(T_task_id, root, password, url_port, database, sql_file string) (string, error) {
 	// url_port 127.0.0.1:3306
 	// mysql8.0 以上加 --column-statistics=0
@@ -1088,7 +1143,41 @@ func Read_TaskData_T_Min_Max(T_task_id string, SN string, T_id string, Time_star
 		sql_condition = " WHERE " + strings.TrimLeft(sql_condition, " AND ")
 	}
 	//fmt.Println("maps_z;",maps_z[0][0])
-	sql := "SELECT MIN(t_t) AS min_t, MAX(t_t) AS max_t FROM z_task_data_" + T_task_id + sql_condition
+	sql := "SELECT MIN(t_t)AS min_t, MAX(t_t)AS max_t FROM z_task_data_" + T_task_id + sql_condition
+
+	fmt.Println(sql)
+	err := o.Raw(sql).QueryRow(&minT, &maxT)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+
+}
+
+// 查询时间最小值 最大值
+func Read_TaskData_T_time_T_Min_Max(T_task_id string, SN string, T_id string, Time_start_ string, Time_end_ string) (minT, maxT string) {
+	o := orm.NewOrm()
+
+	sql_condition := ""
+	if len(Time_start_) > 1 {
+		sql_condition += " AND t_time >= '" + Time_start_ + "'"
+	}
+
+	if len(Time_end_) > 1 {
+		sql_condition += " AND t_time <= '" + Time_end_ + "'"
+	}
+
+	if len(T_id) > 0 {
+		sql_condition += " AND t_id = '" + T_id + "'"
+	}
+	if len(SN) > 0 {
+		sql_condition += " AND t_sn = '" + SN + "'"
+	}
+	if len(sql_condition) > 0 {
+		sql_condition = " WHERE " + strings.TrimLeft(sql_condition, " AND ")
+	}
+	//fmt.Println("maps_z;",maps_z[0][0])
+	sql := "SELECT DATE_FORMAT(MIN(t_time), '%Y-%m-%d %H:%i:%s') AS min_t, DATE_FORMAT(MAX(t_time), '%Y-%m-%d %H:%i:%s') AS max_t FROM z_task_data_" + T_task_id + sql_condition
 
 	fmt.Println(sql)
 	err := o.Raw(sql).QueryRow(&minT, &maxT)
@@ -1329,7 +1418,7 @@ func Read_TaskData_T_Min_Max_Time_Min_Max_ListGROUP(T_task_id string, SN string,
 		}
 		maps_Time_Min_Max_GROUP = append(maps_Time_Min_Max_GROUP, maps_Time_Min_Max_GROUP_)
 
-		时间_a = 时间_a.Add(time.Minute * 10)
+		时间_a = 时间_a.Add(time.Minute * 1)
 
 	}
 
@@ -1427,8 +1516,10 @@ func Read_TaskData_AVG(T_task_id, T_sn, T_id, startTime, endTime string) float64
 func Read_TaskData_max(T_task_id, T_sn, T_id, startTime, endTime string) float64 {
 	o := orm.NewOrm()
 	var v float64
-	sql := fmt.Sprintf("select MAX(t_t) FROM z_task_data_%s where t_id = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, T_id, startTime, endTime)
-
+	sql := fmt.Sprintf("select MAX(t_t) FROM z_task_data_%s where t_id = '%s' ", T_task_id, T_id)
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sql += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
+	}
 	err := o.Raw(sql).QueryRow(&v)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
@@ -1442,8 +1533,10 @@ func Read_TaskData_max(T_task_id, T_sn, T_id, startTime, endTime string) float64
 func Read_TaskData_min(T_task_id, T_sn, T_id, startTime, endTime string) float64 {
 	o := orm.NewOrm()
 	var v float64
-	sql := fmt.Sprintf("select MIN(t_t) FROM z_task_data_%s where t_id = '%s' and t_time BETWEEN '%s' and '%s'", T_task_id, T_id, startTime, endTime)
-
+	sql := fmt.Sprintf("select MIN(t_t) FROM z_task_data_%s where t_id = '%s' ", T_task_id, T_id)
+	if len(startTime) > 0 && len(endTime) > 0 {
+		sql += " AND t_time BETWEEN '" + startTime + "' AND '" + endTime + "'"
+	}
 	err := o.Raw(sql).QueryRow(&v)
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
@@ -1957,3 +2050,35 @@ func standardDeviation(data []float64) float64 {
 	}
 	return math.Sqrt(sumSquares / float64(len(data)))
 }
+
+func FindUnchangedInterval(data []TaskData_) (int, string, string) {
+	if len(data) == 0 {
+		return 0, "", ""
+	}
+
+	maxLen := 1       // 最大连续长度
+	currentLen := 1   // 当前连续长度
+	startIndex := 0   // 最大连续段的起始索引
+	currentStart := 0 // 当前连续段的起始索引
+
+	for i := 1; i < len(data); i++ {
+		if data[i].T_t == data[i-1].T_t {
+			currentLen++
+			// 发现更长的连续段时更新记录
+			if currentLen > maxLen {
+				maxLen = currentLen
+				startIndex = currentStart
+			}
+		} else {
+			currentLen = 1
+			currentStart = i
+		}
+	}
+
+	// 计算时间区间
+	endIndex := startIndex + maxLen - 1
+	startTime := data[startIndex].T_time
+	endTime := data[endIndex].T_time
+
+	return maxLen, startTime, endTime
+}

BIN
自动填写逻辑.xlsx