7 Commits eaf1ded530 ... bb87a22be4

Author SHA1 Message Date
  zoie bb87a22be4 add:服务启动命令 1 month ago
  zoie 352aa52ef2 update:查询任务信息frpc切换为直连 2 months ago
  zoie 90a6e35b99 add:添加部署文档 2 months ago
  zoie 954558a554 add:导入数据前修改auto_increment的初始值,适配恢复数据 3 months ago
  zoie a8e7ed1048 update:本地数据导出到线上,本地表不存在提示错误 3 months ago
  zoie d969e253d1 update:优化排版 3 months ago
  zoie 07b284c9b3 update:优化导出温湿度pdf 3 months ago
10 changed files with 584 additions and 279 deletions
  1. 24 12
      Nats/Nats.go
  2. 13 3
      Nats/NatsServer/NatsServer.go
  3. 21 1
      README.md
  4. 3 4
      conf/app.conf
  5. 295 251
      controllers/TaskData.go
  6. 26 0
      lib/libString.go
  7. 80 3
      models/Task/Task.go
  8. 1 1
      models/Task/TaskCopy.go
  9. 50 2
      models/Task/TaskData.go
  10. 71 2
      run.sh

+ 24 - 12
Nats/Nats.go

@@ -46,15 +46,15 @@ func ReconnectNATS() {
 	var err error
 	for {
 		time.Sleep(1 * time.Minute)
-		//time.Sleep(1 * time.Minute)
 
 		if (lib.Nats != nil && !lib.Nats.IsConnected()) || lib.Nats == nil {
 			lib.Nats, err = nats.Connect("nats://" + conf.NatsServer_Url)
 			if err != nil {
 				logs.Println("无法重新连接到 NATS:", err)
 				continue
+			} else {
+				logs.Println("成功重新连接到 NATS...")
 			}
-			logs.Println("成功重新连接到 NATS...")
 		}
 	}
 
@@ -85,7 +85,7 @@ func NatsInit() {
 		}
 		T_uuid, T_task_id := t_r.T_uuid, t_r.T_task_id
 
-		Task_r, err := NatsServer.Read_Task(T_task_id)
+		Task_r, err := Task.Read_Task(T_task_id)
 		if err != nil {
 			logs.Error(lib.FuncName(), err)
 			return
@@ -200,17 +200,27 @@ func NatsInit() {
 			logs.Println("创建sql临时文件失败")
 		}
 		sql_file := fmt.Sprintf("%sz_task_data_%s.sql", conf.Sql_Temp_Dir, T_task_id)
-		org, err := Task.Dump_TaskData(T_task_id, conf.MysqlServer_Username, conf.MysqlServer_Password, conf.MysqlServer_UrlPort, conf.MysqlServer_Database, sql_file)
-		if err != nil {
-			logs.Error(lib.FuncName(), "导出本地数据失败")
-			return
+
+		var org string
+
+		//导出线上数据
+		logs.Info("--------开始导出本地数据---------")
+		i := 0
+		for i < 10 {
+			org, err = Task.Dump_TaskData(T_task_id, conf.MysqlServer_Username, conf.MysqlServer_Password, conf.MysqlServer_UrlPort, conf.MysqlServer_Database, sql_file)
+			if err != nil {
+				logs.Error(lib.FuncName(), "导出本地数据失败", err)
+			} else {
+				System.Add_UserLogs_T(T_uuid, "任务数据-导出本地数据失败", "z_task_data_"+T_task_id, org)
+				break
+			}
+			i++
 		}
-		System.Add_UserLogs_T(T_uuid, "任务数据-更新线上数据", "z_task_data_"+T_task_id, org)
 
 		logs.Info("--------开始导入数据到【线上】---------")
-		i := 0
+		j := 0
 		flag := false
-		for i < 10 {
+		for j < 10 {
 			Task.Truncate_TaskData(conf.Server_AliasName, T_task_id)
 			time.Sleep(2 * time.Second)
 			org, err = Task.Insert_TaskData(conf.MysqlServer2_Username, conf.MysqlServer2_Password, conf.MysqlServer2_UrlPort, conf.MysqlServer2_Database, sql_file)
@@ -223,7 +233,7 @@ func NatsInit() {
 					break
 				}
 			}
-			i++
+			j++
 		}
 		// 重试10次后仍然没有成功导入数据
 		if !flag {
@@ -248,6 +258,8 @@ func NatsInit() {
 		if err != nil {
 			logs.Error(lib.FuncName(), err)
 		}
+		// 删除绑定数据区间外的数据
+		NatsServer.Del_TaskData_ByT_BindDeviceDataTime(T_task_id)
 
 		System.Add_UserLogs_T(T_uuid, "任务数据-更新线上数据", "z_task_data_"+T_task_id, "成功")
 		logs.Info("--------导入数据到【线上】成功!---------")
@@ -270,7 +282,7 @@ func NatsInit() {
 		T_uuid := "9b6b9f9d-f8f2-46fb-82c8-101d4a309c34"
 		T_task_id := string(m.Data)
 
-		Task_r, err := NatsServer.Read_Task(T_task_id)
+		Task_r, err := Task.Read_Task(T_task_id)
 		if err != nil {
 			logs.Error(lib.FuncName(), err)
 			return

+ 13 - 3
Nats/NatsServer/NatsServer.go

@@ -46,14 +46,16 @@ func Update_Task(v Task.Task) error {
 }
 
 func Read_Task(T_task_id string) (task Task.Task, err error) {
-	logs.Println("Nats =>", lib.FuncName(), T_task_id)
+	//logs.Println("Nats =>", lib.FuncName(), T_task_id)
 
 	if lib.Nats == nil || !lib.Nats.IsConnected() {
+
 		lib.Nats, err = nats.Connect("nats://" + conf.NatsServer_Url)
 		if err != nil {
 			logs.Println("无法重新连接到 NATS:", err)
+		} else {
+			logs.Println("成功重新连接到 NATS...")
 		}
-		logs.Println("成功重新连接到 NATS...")
 	}
 
 	msg, err := lib.Nats.Request("ColdVerify_Server_Read_Task", []byte(T_task_id), 3*time.Second)
@@ -114,7 +116,7 @@ func Read_User(T_uuid string) (user Account.User, err error) {
 
 }
 func Device_Class_List(T_task_id string) (list []Device.DeviceClassList, err error) {
-	logs.Println("Nats =>", lib.FuncName(), T_task_id)
+	//logs.Println("Nats =>", lib.FuncName(), T_task_id)
 
 	if !lib.Nats.IsConnected() {
 		lib.Nats, err = nats.Connect("nats://" + conf.NatsServer_Url)
@@ -233,3 +235,11 @@ func Edit_DeviceClassList(T_task_id, T_sn, T_id string) (err error) {
 	return nil
 
 }
+func Del_TaskData_ByT_BindDeviceDataTime(T_task_id string) {
+	logs.Debug("Nats =>", lib.FuncName(), T_task_id)
+	err := lib.Nats.Publish("ColdVerify_Server_Del_TaskData_ByT_BindDeviceDataTime", []byte(T_task_id))
+	if err != nil {
+		logs.Error("Nats =>", lib.FuncName(), err)
+	}
+
+}

+ 21 - 1
README.md

@@ -9,4 +9,24 @@
  - 原sql文件是mysql(8.0版本),高级往低级(5.6版本)导入时出现版本不兼容的情况。
  - 2个数据库排序规则不同 utf8mb4_general_ci utf8mb4_0900_ai_ci
 
-mysqldump 命令参数大全 https://blog.csdn.net/piaoranyuji/article/details/116193100
+mysqldump 命令参数大全 https://blog.csdn.net/piaoranyuji/article/details/116193100
+
+
+## 项目部署
+
+### 1、修改配置文件
+conf/app.conf
+
+### 2、打包linux二进制包
+make build-linux
+
+### 3、启动服务
+./run.sh start
+
+## 服务器
+sudo systemctl start   ColdVerify_local.service   # 启动服务
+sudo systemctl stop    ColdVerify_local.service   # 停止服务
+sudo systemctl restart ColdVerify_local.service   # 重启服务
+sudo systemctl status  ColdVerify_local.service   # 检查服务状态
+
+journalctl -u ColdVerify_local.service -f 查看日志

+ 3 - 4
conf/app.conf

@@ -19,10 +19,9 @@ Redis_dbNum = "2"
 # Mysql 本地
 Local_AliasName = "default"
 MysqlServer_UrlPort = "192.168.11.23:3306"
-# MysqlServer_UrlPort = "111.85.177.202:13306"
-MysqlServer_Database = "coldverify_local"
-MysqlServer_Username = "coldverify_local"
-MysqlServer_Password = "hmZbXNWdpXKB3K8x"
+MysqlServer_Database = "coldverify"
+MysqlServer_Username = "coldverify"
+MysqlServer_Password = "Bd3d34yJ7aibiEi!"
 MysqlServer_MaxIdleConnections = 100
 MysqlServer_MaxOpenConnections = 200
 

+ 295 - 251
controllers/TaskData.go

@@ -52,9 +52,9 @@ func (c *TaskDataController) TaskData_List() {
 	T_id := c.GetString("T_id")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -96,44 +96,110 @@ func (c *TaskDataController) TaskData_Temperature_Pdf() {
 	Time_start := c.GetString("Time_start")
 	Time_end := c.GetString("Time_end")
 	T_snid := c.GetString("T_snid")
-
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+
+	err := c.TaskData_Pdf(Time_start, Time_end, T_task_id, T_snid, Task.Temperature)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
 		c.ServeJSON()
 		return
 	}
-	if Task_r.T_collection_state == 2 {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中,请稍后!"}
+}
+func (c *TaskDataController) TaskData_Humidity_Pdf() {
+
+	Time_start := c.GetString("Time_start")
+	Time_end := c.GetString("Time_end")
+	T_snid := c.GetString("T_snid")
+	T_task_id := c.GetString("T_task_id")
+	err := c.TaskData_Pdf(Time_start, Time_end, T_task_id, T_snid, Task.Humidity)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
 		c.ServeJSON()
 		return
 	}
+
+}
+func (c *TaskDataController) TaskData_Pdf(Time_start, Time_end, T_task_id, T_snid, T_type string) (err error) {
+
+	Time_start_b := Time_start
+	Time_end_b := Time_end
+
+	Task_r, err := Task.Read_Task(T_task_id)
+	if err != nil {
+		return errors.New("获取任务信息失败!")
+	}
+	if Task_r.T_collection_state == 2 {
+		return errors.New("数据采集中,请稍后!")
+	}
 	user, err := NatsServer.Read_User(Task_r.T_uuid)
 	var T_snid_list []string
 	if len(T_snid) > 0 {
 		T_snid_list = strings.Split(strings.Trim(T_snid, "|"), "|")
 	}
 
+	pdf := &gopdf.GoPdf{}
+	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
+
+	err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
+	if err != nil {
+		return
+	}
+	err = pdf.SetFont("wts", "", 10)
+	if err != nil {
+		return
+	}
+
 	dataMap := make(map[string]string)
 	timeMap := make(map[string]bool)
-	//classList := Task.Read_TaskData_ById_ClassList(Task_r.T_task_id)
-	//for _, i2 := range classList {
-	//	T_snid_list = append(T_snid_list, fmt.Sprintf("%s,%s", i2.T_sn, i2.T_id))
-	//}
+	idWidthMap := make(map[string]float64)
+	dataListMap := make(map[string][]Task.TaskData_)
+	T_snid_list1 := []string{}
+	T_snid_list2 := []string{}
+
 	for _, v := range T_snid_list {
 		sn_id := strings.Split(v, ",")
 		if len(sn_id) == 2 {
 			List, _ := Task.Read_TaskData_ById_List(Task_r.T_task_id, sn_id[0], sn_id[1], Time_start, Time_end, 0, 9999)
-
+			if len(List) == 0 {
+				continue
+			}
+			idw, _ := pdf.MeasureTextWidth(sn_id[1])
+			if !lib.IsNumeric(sn_id[1]) {
+				//IsNotNumeric = true
+				T_snid_list1 = append(T_snid_list1, v)
+				if len(Task_r.T_BindDeviceDataStartTime) > 0 {
+					Time_start = Task_r.T_BindDeviceDataStartTime
+				}
+				if len(Task_r.T_BindDeviceDataEndTime) > 0 {
+					Time_end = Task_r.T_BindDeviceDataEndTime
+				}
+			} else {
+				T_snid_list2 = append(T_snid_list2, v)
+			}
+			if idw > 20 {
+				idWidthMap[sn_id[1]] = idw + 12
+			} else {
+				idWidthMap[sn_id[1]] = 30.3
+			}
+			sort.Slice(List, func(i, j int) bool {
+				return List[i].T_time < List[j].T_time
+			})
+			dataListMap[sn_id[1]] = List
 			for _, data := range List {
 				k := fmt.Sprintf("%s,%s", data.T_time, data.T_id)
-				dataMap[k] = fmt.Sprintf("%.1f", data.T_t)
+				if T_type == Task.Temperature {
+					dataMap[k] = fmt.Sprintf("%.1f", data.T_t)
+				}
+				if T_type == Task.Humidity {
+					dataMap[k] = fmt.Sprintf("%.1f", data.T_rh)
+				}
 				if _, ok := timeMap[data.T_time]; !ok {
 					timeMap[data.T_time] = true
 				}
 			}
 		}
+		Time_start = Time_start_b
+		Time_end = Time_end_b
 	}
 
 	var timeList []string
@@ -144,13 +210,6 @@ func (c *TaskDataController) TaskData_Temperature_Pdf() {
 		return timeList[i] < timeList[j]
 	})
 
-	pdf := &gopdf.GoPdf{}
-	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
-
-	err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
-	if err != nil {
-		return
-	}
 	err = pdf.SetFont("wts", "", 15)
 	if err != nil {
 		return
@@ -171,12 +230,23 @@ func (c *TaskDataController) TaskData_Temperature_Pdf() {
 	pdf.Text(name)
 
 	y += 20
-	title := Task_r.T_name + "温度验证数据"
+	T_type_name := ""
+	if T_type == Task.Temperature {
+		T_type_name = "温度"
+	}
+	if T_type == Task.Humidity {
+		T_type_name = "湿度"
+	}
+	title := Task_r.T_name + T_type_name + "验证数据"
 	textw, _ = pdf.MeasureTextWidth(title)
 	pdf.SetX((595 / 2) - (textw / 2))
 	pdf.SetY(y)
 	pdf.Text(title)
 
+	err = pdf.SetFont("wts", "", 12)
+	if err != nil {
+		return
+	}
 	if len(timeList) > 0 {
 		y += 20
 		timeStr := fmt.Sprintf("%s - %s", timeList[0], timeList[len(timeList)-1])
@@ -194,189 +264,116 @@ func (c *TaskDataController) TaskData_Temperature_Pdf() {
 	y += 20
 	var x float64 = 10
 	var w float64 = 120
+	sort.Slice(T_snid_list1, func(i, j int) bool {
+		return extractSecondElement(T_snid_list1[i]) < extractSecondElement(T_snid_list1[j])
+	})
+	for _, v := range T_snid_list1 {
+		sn_id := strings.Split(v, ",")
+		id := sn_id[1]
+		dataList2, _ := dataListMap[id]
 
-	chunks := chunkBy(T_snid_list, 15)
-	for _, list := range chunks {
-		x = 10
-		w = 120
-		lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-		x += w
-		w = 30
-		for _, v2 := range list {
-			sn_id2 := strings.Split(v2, ",")
-			id2 := sn_id2[1]
-			lib.RectFillColor(pdf, id2, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-			x += w
+		err = pdf.SetFont("wts", "", 15)
+		if err != nil {
+			return
 		}
+		var textH float64 = 20 // if text height is 25px.
 		y += 20
+		pdf.SetNewY(y, textH)
+		y = pdf.GetY()
+		if y > 790 {
+			pdf.AddPage()
+			y = 20
+		}
 
-		for _, t := range timeList {
+		textw, _ = pdf.MeasureTextWidth(id)
+		pdf.SetX((595 / 2) - (textw / 2))
+		pdf.SetY(y)
+		pdf.Text(id)
+		y += 10
+
+		err = pdf.SetFont("wts", "", 10)
+		if err != nil {
+			return
+		}
+		pdf.SetNewY(y, textH)
+		y = pdf.GetY()
+		if y < 790 {
 			x = 10
-			var textH float64 = 20 // if text height is 25px.
-			pdf.SetNewY(y, textH)
-			y = pdf.GetY()
-			if y == 20 {
-				w = 120
+			for i := 0; i < 4; i++ {
+				w = 113.8
 				lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 				x += w
 				w = 30
-				for _, v2 := range list {
-					sn_id2 := strings.Split(v2, ",")
-					id2 := sn_id2[1]
-					lib.RectFillColor(pdf, id2, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-					x += w
-				}
-				y += 20
-				x = 10
+				lib.RectFillColor(pdf, T_type_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+				x += w
 			}
-			w = 120
-			lib.RectFillColor(pdf, t, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-			x += w
-			w = 30
-			for _, v := range list {
-				sn_id := strings.Split(v, ",")
-				id := sn_id[1]
-				t_t := dataMap[fmt.Sprintf("%s,%s", t, id)]
-				lib.RectFillColor(pdf, t_t, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			y += 20
+		} else {
+			pdf.AddPage()
+			y = 20
+			x = 10
+			for i := 0; i < 4; i++ {
+				w = 113.8
+				lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+				x += w
+				w = 30
+				lib.RectFillColor(pdf, T_type_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 				x += w
 			}
 			y += 20
-
 		}
-		y += 20
-	}
-	filename := time.Now().Format("20060102150405") + ".pdf"
-	timeStr := "ofile/温度" + filename
-
-	err = pdf.WritePdf(timeStr)
-	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-		c.ServeJSON()
-		return
-	}
-
-	defer func() {
-		//删除目录
-		os.Remove(timeStr)
-	}()
+		for i := 0; i < len(dataList2); i++ {
+			temp := i % 4
+			x = 10 + 143.8*float64(temp)
+			w = 113.8
 
-	c.Ctx.Output.Download(timeStr)
-
-}
-func (c *TaskDataController) TaskData_Humidity_Pdf() {
-
-	Time_start := c.GetString("Time_start")
-	Time_end := c.GetString("Time_end")
-	T_snid := c.GetString("T_snid")
-
-	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
-	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
-		c.ServeJSON()
-		return
-	}
-	if Task_r.T_collection_state == 2 {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中,请稍后!"}
-		c.ServeJSON()
-		return
-	}
-	user, err := NatsServer.Read_User(Task_r.T_uuid)
-	var T_snid_list []string
-	if len(T_snid) > 0 {
-		T_snid_list = strings.Split(strings.Trim(T_snid, "|"), "|")
-	}
-
-	dataMap := make(map[string]string)
-	timeMap := make(map[string]bool)
-	//classList := Task.Read_TaskData_ById_ClassList(Task_r.T_task_id)
-	//for _, i2 := range classList {
-	//	T_snid_list = append(T_snid_list, fmt.Sprintf("%s,%s", i2.T_sn, i2.T_id))
-	//}
-	for _, v := range T_snid_list {
-		sn_id := strings.Split(v, ",")
-		if len(sn_id) == 2 {
-			List, _ := Task.Read_TaskData_ById_List(Task_r.T_task_id, sn_id[0], sn_id[1], Time_start, Time_end, 0, 9999)
-
-			for _, data := range List {
-				k := fmt.Sprintf("%s,%s", data.T_time, data.T_id)
-				dataMap[k] = fmt.Sprintf("%.1f", data.T_rh)
-				if _, ok := timeMap[data.T_time]; !ok {
-					timeMap[data.T_time] = true
+			lib.RectFillColor(pdf, dataList2[i].T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			x += w
+			w = 30
+			if T_type == Task.Temperature {
+				lib.RectFillColor(pdf, fmt.Sprintf("%.1f", dataList2[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			}
+			if T_type == Task.Humidity {
+				lib.RectFillColor(pdf, fmt.Sprintf("%.1f", dataList2[i].T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+			}
+			if temp == 3 {
+				y += 20
+				pdf.SetNewY(y, textH)
+				y = pdf.GetY()
+				// 每页添加表头
+				if y == 20 {
+					x = 10
+					for k := 0; k < 4; k++ {
+						w = 113.8
+						lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+						x += w
+						w = 30
+						lib.RectFillColor(pdf, T_type_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+						x += w
+					}
+					y += 20
 				}
 			}
 		}
-	}
+		y += 25
 
-	var timeList []string
-	for k, _ := range timeMap {
-		timeList = append(timeList, k)
-	}
-	sort.Slice(timeList, func(i, j int) bool {
-		return timeList[i] < timeList[j]
-	})
-
-	pdf := &gopdf.GoPdf{}
-	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
-
-	err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
-	if err != nil {
-		return
-	}
-	err = pdf.SetFont("wts", "", 15)
-	if err != nil {
-		return
-	}
-
-	pdf.SetGrayFill(0.5)
-
-	pdf.SetMargins(0, 20, 0, 20)
-	pdf.AddPage()
-	imgH, _ := gopdf.ImageHolderByPath("./ofile/logo.jpg")
-	err = pdf.ImageByHolder(imgH, 10, 10, &gopdf.Rect{W: 93, H: 32})
-	name := user.T_name
-
-	var y float64 = 40
-	textw, _ := pdf.MeasureTextWidth(name)
-	pdf.SetX((595 / 2) - (textw / 2))
-	pdf.SetY(y)
-	pdf.Text(name)
-
-	y += 20
-	title := Task_r.T_name + "湿度验证数据"
-	textw, _ = pdf.MeasureTextWidth(title)
-	pdf.SetX((595 / 2) - (textw / 2))
-	pdf.SetY(y)
-	pdf.Text(title)
-
-	if len(timeList) > 0 {
-		y += 20
-		timeStr := fmt.Sprintf("%s - %s", timeList[0], timeList[len(timeList)-1])
-		textw, _ = pdf.MeasureTextWidth(timeStr)
-		pdf.SetX((595 / 2) - (textw / 2))
-		pdf.SetY(y)
-		pdf.Text(timeStr)
-	}
-
-	err = pdf.SetFont("wts", "", 10)
-	if err != nil {
-		return
 	}
 
 	y += 20
-	var x float64 = 10
-	var w float64 = 120
-
-	chunks := chunkBy(T_snid_list, 15)
+	sort.Slice(T_snid_list2, func(i, j int) bool {
+		return extractSecondElement(T_snid_list2[i]) < extractSecondElement(T_snid_list2[j])
+	})
+	chunks := splitData(T_snid_list2, 454.5, idWidthMap)
 	for _, list := range chunks {
 		x = 10
-		w = 120
+		w = 120.7
 		lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 		x += w
-		w = 30
+		w = 30.3
 		for _, v2 := range list {
 			sn_id2 := strings.Split(v2, ",")
 			id2 := sn_id2[1]
+			w = idWidthMap[id2]
 			lib.RectFillColor(pdf, id2, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 			x += w
 		}
@@ -388,28 +385,30 @@ func (c *TaskDataController) TaskData_Humidity_Pdf() {
 			pdf.SetNewY(y, textH)
 			y = pdf.GetY()
 			if y == 20 {
-				w = 120
+				w = 120.7
 				lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 				x += w
-				w = 30
+				w = 30.3
 				for _, v2 := range list {
 					sn_id2 := strings.Split(v2, ",")
 					id2 := sn_id2[1]
+					w = idWidthMap[id2]
 					lib.RectFillColor(pdf, id2, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 					x += w
 				}
 				y += 20
 				x = 10
 			}
-			w = 120
+			w = 120.7
 			lib.RectFillColor(pdf, t, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 			x += w
-			w = 30
+			w = 30.3
 			for _, v := range list {
 				sn_id := strings.Split(v, ",")
 				id := sn_id[1]
-				t_t := dataMap[fmt.Sprintf("%s,%s", t, id)]
-				lib.RectFillColor(pdf, t_t, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
+				data := dataMap[fmt.Sprintf("%s,%s", t, id)]
+				w = idWidthMap[id]
+				lib.RectFillColor(pdf, data, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
 				x += w
 			}
 			y += 20
@@ -418,12 +417,10 @@ func (c *TaskDataController) TaskData_Humidity_Pdf() {
 		y += 20
 	}
 	filename := time.Now().Format("20060102150405") + ".pdf"
-	timeStr := "ofile/湿度" + filename
+	timeStr := "ofile/" + T_type_name + filename
 
 	err = pdf.WritePdf(timeStr)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-		c.ServeJSON()
 		return
 	}
 
@@ -433,9 +430,17 @@ func (c *TaskDataController) TaskData_Humidity_Pdf() {
 	}()
 
 	c.Ctx.Output.Download(timeStr)
-
+	return nil
 }
 
+// Function to extract the second element after splitting by comma
+func extractSecondElement(s string) string {
+	parts := strings.Split(s, ",")
+	if len(parts) >= 2 {
+		return parts[1]
+	}
+	return s // return original string if splitting doesn't give expected parts
+}
 func chunkBy[T any](list []T, size int) [][]T {
 	var chunks [][]T
 	for size < len(list) {
@@ -443,6 +448,34 @@ func chunkBy[T any](list []T, size int) [][]T {
 	}
 	return append(chunks, list)
 }
+func splitData(data []string, threshold float64, idWidthMap map[string]float64) [][]string {
+	var result [][]string
+	var currentBatch []string
+	var currentSum float64
+
+	for _, item := range data {
+		sn_id := strings.Split(item, ",")
+		if len(sn_id) == 2 {
+			wd := idWidthMap[sn_id[1]]
+			if currentSum+wd > threshold+0.1 {
+				// 当前批次超过阈值,切分
+				result = append(result, currentBatch)
+				// 重置当前批次和当前总和
+				currentBatch = []string{}
+				currentSum = 0
+			}
+			currentBatch = append(currentBatch, item)
+			currentSum += wd
+		}
+	}
+
+	// 添加最后一批
+	if len(currentBatch) > 0 {
+		result = append(result, currentBatch)
+	}
+
+	return result
+}
 
 // 列表 -
 func (c *TaskDataController) TaskDataClass_List() {
@@ -455,9 +488,9 @@ func (c *TaskDataController) TaskDataClass_List() {
 		page_z = conf.Page_size
 	}
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -480,9 +513,9 @@ func (c *TaskDataController) TaskDataClass_Edit() {
 	T_task_id := c.GetString("T_task_id")
 	T_sn := c.GetString("T_sn")
 	T_id := c.GetString("T_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -511,7 +544,7 @@ func (c *TaskDataController) TaskDataClass_Edit() {
 		return
 	}
 
-	System.Add_UserLogs_T(T_uuid, "本地版-任务分", "修改分类数据"+Task_r.T_name, Task_r.T_task_id+"|"+T_sn+"|"+T_id)
+	System.Add_UserLogs_T(T_uuid, "本地版-任务分", "修改分类数据"+Task_r.T_name, Task_r.T_task_id+"|"+T_sn+"|"+T_id)
 
 	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
 	c.ServeJSON()
@@ -523,9 +556,9 @@ func (c *TaskDataController) TaskDataClass_Del() {
 
 	T_task_id := c.GetString("T_task_id")
 	T_sn := c.GetString("T_sn")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -550,9 +583,9 @@ func (c *TaskDataController) TaskData_AddS() {
 	T_uuid, _ := lib.GetAdminT_Uuid(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -570,6 +603,8 @@ func (c *TaskDataController) TaskData_AddS() {
 	println(len(T_Data_list), "len(T_Data_list)")
 	var T_Data_list_x = 0
 
+	Task.UpdateAUTO_INCREMENT(conf.Local_AliasName, Task_r.T_task_id)
+
 	snMaps := make(map[string]string)
 
 	for _, v := range T_Data_list {
@@ -649,12 +684,13 @@ func (c *TaskDataController) TaskData_AddS_Excel() {
 	T_uuid, _ := lib.GetAdminT_Uuid(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
+	Task.UpdateAUTO_INCREMENT(conf.Local_AliasName, Task_r.T_task_id)
 
 	// 获取上传的文件
 	file, _, err := c.GetFile("file")
@@ -808,12 +844,13 @@ func (c *TaskDataController) TaskData_Add() {
 	}
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
+	Task.UpdateAUTO_INCREMENT(conf.Local_AliasName, Task_r.T_task_id)
 
 	sn, err := Task.Read_TaskData_ByT_id(Task_r.T_task_id, T_id)
 	if err != nil && !errors.Is(err, orm.ErrNoRows) {
@@ -886,9 +923,9 @@ func (c *TaskDataController) TaskData_Up() {
 	T_time := c.GetString("T_time")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -920,9 +957,9 @@ func (c *TaskDataController) TaskData_Del() {
 	}
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -948,9 +985,9 @@ func (c *TaskDataController) TaskData_Del_t_id() {
 	Id := c.GetString("Id")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -981,9 +1018,9 @@ func (c *TaskDataController) Export_Data_Excel() {
 	//}
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1055,14 +1092,14 @@ func (c *TaskDataController) Export_Data_Excel() {
 
 func (c *TaskDataController) Check() {
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if Task_r.T_collection_state == 2 {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中,请稍后!"}
 		c.ServeJSON()
 		return
 	}
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1147,14 +1184,14 @@ func (c *TaskDataController) Check() {
 
 func (c *TaskDataController) Check_Asyn() {
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if Task_r.T_collection_state == 2 {
 		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中,请稍后!"}
 		c.ServeJSON()
 		return
 	}
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1268,9 +1305,9 @@ func (c *TaskDataController) TaskData_Import_TaskData() {
 	T_uuid, _ := lib.GetAdminT_Uuid(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
 
 	T_task_id := c.GetString("T_task_id")
-	_, err := NatsServer.Read_Task(T_task_id)
+	_, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1325,9 +1362,9 @@ func (c *TaskDataController) TaskData_Up_TaskData() {
 
 	T_task_id := c.GetString("T_task_id")
 
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1393,9 +1430,9 @@ func (c *TaskDataController) TaskData_Up_TaskData_Back() {
 
 	T_task_id := c.GetString("T_task_id")
 
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1406,6 +1443,13 @@ func (c *TaskDataController) TaskData_Up_TaskData_Back() {
 		return
 	}
 
+	exist := Task.CheckTableExist(conf.Local_AliasName, T_task_id)
+	if !exist {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "本地数据不存在!"}
+		c.ServeJSON()
+		return
+	}
+
 	// 采集中
 	Task_r.T_delivery_state = 2
 	err = NatsServer.Update_Task(Task_r)
@@ -1464,9 +1508,9 @@ func (c *TaskDataController) CopyFromPosition() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1528,9 +1572,9 @@ func (c *TaskDataController) RepairSensorData() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1618,9 +1662,9 @@ func (c *TaskDataController) DataSensorDataTrend() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1707,9 +1751,9 @@ func (c *TaskDataController) UpdateRand() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1766,9 +1810,9 @@ func (c *TaskDataController) UpdateFix() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1822,9 +1866,9 @@ func (c *TaskDataController) DataSensorDataSmooth() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -1921,9 +1965,9 @@ func (c *TaskDataController) CopyFromPositionAverageSN() {
 		return
 	}
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2031,9 +2075,9 @@ func (c *TaskDataController) CopyFromPositionSN() {
 		return
 	}
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2075,9 +2119,9 @@ func (c *TaskDataController) DataRemoveDuplicates() {
 	T_uuid, _ := lib.GetAdminT_Uuid(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2131,9 +2175,9 @@ func (c *TaskDataController) DataSkewingInterval() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2222,9 +2266,9 @@ func (c *TaskDataController) DataGeometricScale() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2283,9 +2327,9 @@ func (c *TaskDataController) DataBatchDelete() {
 	SN_List := strings.Split(strings.Trim(c.GetString("SN_List"), "|"), "|")
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2325,9 +2369,9 @@ func (c *TaskDataController) TaskDataCopy_List() {
 	}
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2355,9 +2399,9 @@ func (c *TaskDataController) TaskDataCopy_List() {
 func (c *TaskDataController) TaskDataCopy_Add() {
 
 	T_task_id := c.GetString("T_task_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2418,9 +2462,9 @@ func (c *TaskDataController) TaskDataCopy_Del() {
 func (c *TaskDataController) TaskDataCopy_Recover() {
 	T_task_id := c.GetString("T_task_id")
 	T_copy_id := c.GetString("T_copy_id")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2490,9 +2534,9 @@ func (c *TaskDataController) TaskData_JPG() {
 
 	T_task_id := c.GetString("T_task_id")
 	SN_List := c.GetString("SN_List")
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}
@@ -2656,9 +2700,9 @@ func (c *TaskDataController) Certificate_List() {
 	if page_z < 1 {
 		page_z = conf.Page_size
 	}
-	Task_r, err := NatsServer.Read_Task(T_task_id)
+	Task_r, err := Task.Read_Task(T_task_id)
 	if err != nil {
-		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取任务信息失败!"}
 		c.ServeJSON()
 		return
 	}

+ 26 - 0
lib/libString.go

@@ -3,6 +3,7 @@ package lib
 import (
 	"errors"
 	"math/rand"
+	"regexp"
 	"strings"
 	"time"
 )
@@ -67,3 +68,28 @@ func ReplaceSeconds(timeStr string) (string, error) {
 
 	return roundedTimeString, nil
 }
+
+// 判断字符串是否为纯数字
+func IsNumeric(str string) bool {
+	// 定义一个正则表达式来匹配纯数字字符串
+	re := regexp.MustCompile(`^\d+$`)
+	return re.MatchString(str)
+}
+
+func SubtractStringLists(list1, list2 []string) []string {
+	// Create a map to store elements of list2 for fast lookup
+	excludeMap := make(map[string]bool)
+	for _, item := range list2 {
+		excludeMap[item] = true
+	}
+
+	// Initialize the result slice with elements not present in list2
+	var result []string
+	for _, item := range list1 {
+		if !excludeMap[item] {
+			result = append(result, item)
+		}
+	}
+
+	return result
+}

+ 80 - 3
models/Task/Task.go

@@ -1,6 +1,13 @@
 package Task
 
 import (
+	"ColdVerify_local/conf"
+	"ColdVerify_local/lib"
+	"ColdVerify_local/logs"
+	"encoding/json"
+	"fmt"
+	"github.com/astaxie/beego/cache"
+	orm2 "github.com/beego/beego/v2/client/orm"
 	_ "github.com/go-sql-driver/mysql"
 	"time"
 )
@@ -9,6 +16,7 @@ import (
 type Task struct {
 	Id                     int    `orm:"column(ID);size(11);auto;pk"`
 	T_class                int    `orm:"size(200);default(0)"` // 分类id
+	T_InfoCollection_id    string `orm:"size(256);null"`       // 信息采集ID
 	T_task_id              string `orm:"size(256);null"`       // 任务ID
 	T_uuid                 string `orm:"size(256);null"`       // 用户 UUID
 	T_name                 string `orm:"size(256);null"`       // 标题
@@ -23,6 +31,12 @@ type Task struct {
 	T_collection_state     int    `orm:"size(2);default(0)"`   // 数据采集 状态 0 未完成 1 数据来源已完成 2 处理中 3 已采集-无数据 4-数据编辑已完成
 	T_reporting_state      int    `orm:"size(2);default(0)"`   // 报告编写 状态 0 未完成 1 已完成
 	T_delivery_state       int    `orm:"size(2);default(0)"`   // 交付审核 状态 0 未完成 1 已完成 2 处理中
+	T_marking_state        int    `orm:"size(2);default(0)"`   // 验证标识 状态 0 未完成 1 已完成
+
+	T_VerifyDeviceDataStartTime string `orm:"size(256);null"` // 验证设备数据开始时间
+	T_VerifyDeviceDataEndTime   string `orm:"size(256);null"` // 验证设备数据开始时间
+	T_BindDeviceDataStartTime   string `orm:"size(256);null"` // 绑定设备数据开始时间
+	T_BindDeviceDataEndTime     string `orm:"size(256);null"` // 绑定设备数据结束时间
 
 	T_doc1 string `orm:"type(text);null"` // 封面
 	T_pdf1 string `orm:"type(text);null"` // 封面
@@ -30,10 +44,73 @@ type Task struct {
 	T_pdf2 string `orm:"type(text);null"` // 报告
 	T_doc3 string `orm:"type(text);null"` // 证书
 	T_pdf3 string `orm:"type(text);null"` // 证书
+	T_pdf4 string `orm:"type(text);null"` // 验证标识
+
+	T_Show  int `orm:"size(2);default(1)"`   // 0 隐藏   1 公开
+	T_Visit int `orm:"size(200);default(0)"` // 浏览量
+	T_State int `orm:"size(2);default(1)"`   // 0 删除   1 正常
+
+	T_step int `orm:"size(2);default(-1)"` // 验证步骤
+
+	T_sn                        string `orm:"size(256);null"` // sn
+	T_CalibrationExpirationTime string `orm:"size(256);null"` // 校准到期时间
 
-	T_Show     int       `orm:"size(2);default(1)"`                                    // 0 隐藏   1 公开
-	T_Visit    int       `orm:"size(200);default(0)"`                                  // 浏览量
-	T_State    int       `orm:"size(2);default(1)"`                                    // 0 删除   1 正常
 	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 保存时都会对时间自动更新
 }
+
+var redisCache_Task cache.Cache
+
+func init() {
+	orm2.RegisterModel(new(Task))
+	config := fmt.Sprintf(`{"key":"%s","conn":"%s","dbNum":"%s","password":"%s"}`,
+		"redis_"+"Task", conf.Redis_address, conf.Redis_dbNum, conf.Redis_password)
+	logs.Println(config)
+	var err error
+	redisCache_Task, err = cache.NewCache("redis", config)
+	if err != nil || redisCache_Task == nil {
+		errMsg := "failed to init redis"
+		logs.Println(errMsg, err)
+	}
+}
+
+func Redis_Task_Get(key string) (r Task, is bool) {
+	if redisCache_Task.IsExist(key) {
+		logs.Println("找到key:", key)
+		v := redisCache_Task.Get(key)
+		json.Unmarshal(v.([]byte), &r)
+		return r, true
+	}
+	logs.Println("没有 找到key:", key)
+	return Task{}, false
+}
+func Redis_Task_Set(key string, r Task) (err error) {
+	//json序列化
+	str, err := json.Marshal(r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	err = redisCache_Task.Put(key, str, 24*time.Hour)
+	if err != nil {
+		logs.Println("set key:", key, ",value:", str, err)
+	}
+	return
+}
+func Read_Task(T_task_id string) (r Task, err error) {
+	if task, is := Redis_Task_Get(T_task_id); is == true {
+		return task, nil
+	}
+
+	serverOrm := orm2.NewOrmUsingDB(conf.Server_AliasName)
+
+	qs := serverOrm.QueryTable(new(Task))
+	//err := qs.Filter("T_task_id", T_task_id).Filter("T_State", 1).One(&r)
+	err = qs.Filter("T_task_id", T_task_id).Filter("T_State", 1).One(&r)
+	if err != nil {
+		return r, err
+	}
+
+	Redis_Task_Set(T_task_id, r)
+	return r, nil
+}

+ 1 - 1
models/Task/TaskCopy.go

@@ -50,7 +50,7 @@ type TaskCopy struct {
 	UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
 }
 
-func (t *Task) TableName() string {
+func (t *TaskCopy) TableName() string {
 	return "task_copy" // 数据库名称   // ************** 替换 FormulaList **************
 }
 

+ 50 - 2
models/Task/TaskData.go

@@ -10,12 +10,18 @@ import (
 	_ "github.com/astaxie/beego/cache/redis"
 	"github.com/beego/beego/v2/adapter/orm"
 	orm2 "github.com/beego/beego/v2/client/orm"
+	"github.com/go-sql-driver/mysql"
 	_ "github.com/go-sql-driver/mysql"
 	"strconv"
 	"strings"
 	"time"
 )
 
+const (
+	Temperature = "Temperature"
+	Humidity    = "Humidity"
+)
+
 // 模板
 type TaskData struct {
 	Id int `orm:"column(ID);size(11);auto;pk"`
@@ -128,6 +134,11 @@ func Truncate_TaskData(alias_name, T_task_id string) bool {
 	logs.Println(sql)
 	_, err := o.Raw(sql).Exec()
 	if err != nil {
+		// 数据库表不存在,则创建数据库
+		if err.(*mysql.MySQLError).Number == 1146 {
+			CREATE_TaskData(alias_name, T_task_id)
+			return true
+		}
 		logs.Error(lib.FuncName(), err)
 		return false
 	}
@@ -303,6 +314,10 @@ func Read_TaskData_ById_ClassList(T_task_id string) []TaskDataClass_ {
 	_, err := o.Raw(sql).QueryRows(&maps)
 
 	if err != nil {
+		// 数据库表不存在,则创建数据库
+		if err.(*mysql.MySQLError).Number == 1146 {
+			CREATE_TaskData(conf.Local_AliasName, T_task_id)
+		}
 		logs.Error(lib.FuncName(), err)
 		return maps
 	}
@@ -646,7 +661,6 @@ func Dump_TaskData(T_task_id, root, password, url_port, database, sql_file strin
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
 	}
-
 	return org, err
 }
 
@@ -674,7 +688,6 @@ func Dump_TaskData_Verify(T_task_id, root, password, url_port, database, sql_fil
 	if err != nil {
 		logs.Error(lib.FuncName(), err)
 	}
-
 	return org, err
 }
 
@@ -998,3 +1011,38 @@ func DeleteDeduplicate(T_task_id string) (int64, error) {
 	}
 	return cnt, nil
 }
+
+func CheckTableExist(alias_name, T_task_id string) bool {
+	o := orm2.NewOrmUsingDB(alias_name)
+
+	sql := "select count(ID) from z_task_data_" + T_task_id
+	_, err := o.Raw(sql).Exec()
+	if err != nil {
+		// 数据库表不存在,则创建数据库
+		logs.Error(lib.FuncName(), err)
+		if err.(*mysql.MySQLError).Number == 1146 {
+			return false
+		}
+	}
+	return true
+}
+
+// 修改auto_increment的初始值
+func UpdateAUTO_INCREMENT(alias_name, T_task_id string) error {
+	o := orm2.NewOrmUsingDB(alias_name)
+	var max_id int
+	sql := "select max(ID) from z_task_data_" + T_task_id
+	err := o.Raw(sql).QueryRow(&max_id)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return err
+	}
+	// ALTER TABLE z_task_data_lg9v2zpfem7b AUTO_INCREMENT = 39905;
+	sql = "ALTER TABLE z_task_data_" + T_task_id + " AUTO_INCREMENT = " + strconv.Itoa(max_id+1)
+	_, err = o.Raw(sql).Exec()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return err
+	}
+	return nil
+}

+ 71 - 2
run.sh

@@ -1,2 +1,71 @@
-#无日志输出
-nohup ./ColdVerify_local >/dev/null 2>&1 &
+#!/bin/bash
+#这里可替换为你自己的执行程序,其他代码无需更改
+APP_NAME=ColdVerify_local6400
+#使用说明,用来提示输入参数
+usage() {
+  echo "Usage: run.sh [start|stop|restart|status]"
+  exit 1
+}
+#检查程序是否在运行
+is_exist() {
+  pid=$(ps -ef | grep $APP_NAME | grep -v grep | awk '{print $2}')
+  #如果不存在返回1,存在返回0
+  if [ -z "${pid}" ]; then
+    return 1
+  else
+    return 0
+  fi
+}
+#启动方法
+start() {
+  is_exist
+  if [ $? -eq "0" ]; then
+    echo "${APP_NAME} is already running. pid=${pid} ."
+  else
+    mkdir -p logs
+    export GO111MODULE=off
+    nohup ./${APP_NAME} >> ./logs/nohup.out 2>&1 &
+    echo "${APP_NAME} start success"
+  fi
+}
+#停止方法
+stop() {
+  is_exist
+  if [ $? -eq "0" ]; then
+    kill -9 $pid
+  else
+    echo "${APP_NAME} is not running"
+  fi
+}
+#输出运行状态
+status() {
+  is_exist
+  if [ $? -eq "0" ]; then
+    echo "${APP_NAME} is running. Pid is ${pid}"
+  else
+    echo "${APP_NAME} is NOT running."
+  fi
+}
+#重启
+restart() {
+  stop
+  start
+}
+#根据输入参数,选择执行对应方法,不输入则执行使用说明
+case "$1" in
+"start")
+  start
+  ;;
+"stop")
+  stop
+  ;;
+"status")
+  status
+  ;;
+"restart")
+  restart
+  ;;
+*)
+  usage
+  ;;
+esac