package controllers

import (
	"ColdVerify_server/Nats"
	"ColdVerify_server/conf"
	"ColdVerify_server/lib"
	"ColdVerify_server/logs"
	"ColdVerify_server/models/Account"
	"ColdVerify_server/models/Device"
	"ColdVerify_server/models/System"
	"ColdVerify_server/models/Task"
	"errors"
	"fmt"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/signintech/gopdf"
	"github.com/xuri/excelize/v2"
	"log"
	"math"
	"os"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

type TaskDataController struct {
	beego.Controller
}

// 获取-
func (c *TaskDataController) Extract_TaskData() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}
	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	DeviceClass_List := Device.Read_DeviceClassList_List_id(Task_r.T_class)
	if len(DeviceClass_List) == 0 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_Class_id 分类设备列表 为空!"}
		c.ServeJSON()
		return
	}

	logs.Println("----导入 :", DeviceClass_List)
	// 清空表
	Task.Truncate_TaskData(Task_r.T_task_id)
	// 插入 数据
	for _, v := range DeviceClass_List {
		logs.Println("---- :", v.T_sn, Task_r.T_task_id, Time_start, Time_end)
		Task.Import_TaskData(v.T_sn, v.T_id, Task_r.T_task_id, Time_start, Time_end)
	}

	// 提取数据后 将 当前任务 数据采集 标志 为 1
	Task_r.T_collection_state = 1
	if !Task.Update_Task(Task_r, "T_collection_state") {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
		c.ServeJSON()
		return
	}
	System.Add_UserLogs_T(user_r.T_uuid, "任务", "修改", Task_r)

	System.Add_UserLogs(user_r.T_uuid, "提取数据", "提取数据"+Task_r.T_name, Task_r.T_task_id+"|"+Time_start+"|"+Time_end)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 后台导出数据
func (c *TaskDataController) Extract_TaskData_Back() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}
	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_task_id := c.GetString("T_task_id")

	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		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
	}

	DeviceClass_List := Device.Read_DeviceClassList_List_id(Task_r.T_class)
	if len(DeviceClass_List) == 0 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "设备列表为空，请先添加设备！"}
		c.ServeJSON()
		return
	}

	// 更新状态为采集中
	Task_r.T_collection_state = 2
	if !Task.Update_Task(Task_r, "T_collection_state") {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "导出数据失败!"}
		c.ServeJSON()
		return
	}

	resp := Nats.Extract_TaskData_Back{
		T_uuid:          user_r.T_uuid,
		Time_start:      Time_start,
		Time_end:        Time_end,
		DeviceClassList: DeviceClass_List,
		Task:            Task_r,
	}
	// 后台执行打包数据
	//b, _ := msgpack.Marshal(&data)
	//_ = lib.Nats.Publish("ColdVerify_Server_Extract_TaskData_Back", b)
	go func(resp Nats.Extract_TaskData_Back, Task_r Task.Task) {
		Task_rname := resp.Task
		// 清空表
		Task.Truncate_TaskData(Task_rname.T_task_id)

		//失败重试5次
		DeviceClassList := new(sync.Map)
		var count int
		for _, v := range resp.DeviceClassList {
			if strings.Contains(v.T_sn, "-") || len(v.T_sn) == 0 {
				// 从3.0平台导入
				continue
			}
			DeviceClassList.Store(fmt.Sprintf("%s|%s", v.T_sn, v.T_id), 5)
			//err = Task.Import_TaskData_Back(v.T_sn, v.T_id, resp.Task.T_task_id, resp.Time_start, resp.Time_end)
			//count++
			//time.Sleep(5 * time.Second)
		}
		DeviceClassList.Range(func(k, v interface{}) bool {
			count++
			return true
		})

		for count > 0 {
			DeviceClassList.Range(func(k, v any) bool {
				T_snid := strings.Split(k.(string), "|")
				T_sn := T_snid[0]
				T_id := T_snid[1]
				temp := v.(int)
				temp--
				DeviceClassList.Store(k, temp)

				err := Task.Import_TaskData_Back(T_sn, T_id, resp.Task.T_task_id, resp.Time_start, resp.Time_end)
				if err == nil || strings.Contains(err.Error(), "doesn't exist") {
					DeviceClassList.Delete(k)
					count--
				} else {
					logs.Error("设备数据同步到任务数据失败", err)
					DeviceClassList.Delete(k)
					count--
				}
				return true
			})
		}
		// 提取数据后 将 当前任务 数据采集 标志 为 1
		Task_r.T_collection_state = 1
		if !Task.Update_Task(Task_r, "T_collection_state") {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
			c.ServeJSON()
			return
		}

	}(resp, Task_r)
	System.Add_UserLogs_T(resp.T_uuid, "任务", "修改", Task_r)
	System.Add_UserLogs(resp.T_uuid, "提取数据", "提取数据"+Task_r.T_name, Task_r.T_task_id+"|"+resp.Time_start+"|"+resp.Time_end)
	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 列表 -
func (c *TaskDataController) TaskData_List() {
	// 验证登录 User_is, User_r
	_, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	var r_jsons lib.R_JSONS
	page, _ := c.GetInt("page")
	if page < 1 {
		page = 1
	}
	page_z, _ := c.GetInt("page_z")
	if page_z < 1 {
		page_z = conf.Page_size
	}

	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_sn := c.GetString("T_sn")
	T_id := c.GetString("T_id")
	T_layout_no := c.GetString("T_layout_no") // 替换之前的T_id
	if len(T_layout_no) > 0 {
		T_id = T_layout_no
	}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}
	if Task_r.T_delivery_state == 2 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中，请稍后!"}
		c.ServeJSON()
		return
	}
	// 查询设备列表
	dcList, _ := Device.Read_DeviceClassList_OrderList(Task_r.T_class, T_sn, "", "", page, 9999)
	// 保存布局编号和校准证书对应关系
	var deviceCertificateMap = make(map[string]string) // t_id, T_Certificate_sn
	for _, v := range dcList {
		deviceCertificateMap[v.T_id] = v.T_Certificate_sn
	}

	var cnt int64
	List, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, T_sn, T_id, Time_start, Time_end, page, page_z)
	for i := 0; i < len(List); i++ {
		List[i].T_Certificate_sn = deviceCertificateMap[List[i].T_id]
	}
	page_size := math.Ceil(float64(cnt) / float64(page_z))
	r_jsons.List = List
	r_jsons.Page = page
	r_jsons.Page_size = int(page_size)
	r_jsons.Pages = lib.Func_page(int64(page), int64(page_size))
	r_jsons.Num = int(cnt)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return
}

// 列表 -
func (c *TaskDataController) UserTaskData_List() {
	// 验证登录 User_is, User_r
	User_r, User_is := Account.Verification(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	var r_jsons lib.R_JSONS
	page, _ := c.GetInt("page")
	if page < 1 {
		page = 1
	}
	page_z, _ := c.GetInt("page_z")
	if page_z < 1 {
		page_z = conf.Page_size
	}

	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_sn := c.GetString("T_sn")
	T_id := c.GetString("T_id")
	T_layout_no := c.GetString("T_layout_no") // 替换之前的T_id
	if len(T_layout_no) > 0 {
		T_id = T_layout_no
	}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	if Task_r.T_delivery_state == 2 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中，请稍后!"}
		c.ServeJSON()
		return
	}

	if Task_r.T_uuid != User_r.T_uuid {
		c.Data["json"] = lib.JSONS{Code: 200, Msg: "无权访问！"}
		c.ServeJSON()
		return
	}
	if len(Time_start) == 0 {
		Time_start = Task_r.T_VerifyDeviceDataStartTime
	}
	if len(Time_end) == 0 {
		Time_end = Task_r.T_VerifyDeviceDataEndTime
	}

	// 查询设备列表
	dcList, _ := Device.Read_DeviceClassList_OrderList(Task_r.T_class, T_sn, "", "", page, 9999)
	// 保存布局编号和校准证书对应关系
	var deviceCertificateMap = make(map[string]string) // t_id, T_Certificate_sn
	for _, v := range dcList {
		deviceCertificateMap[v.T_id] = v.T_Certificate_sn
	}

	var cnt int64
	List, cnt := Task.Read_TaskData_ById_List(Task_r.T_task_id, T_sn, T_id, Time_start, Time_end, page, page_z)
	for i := 0; i < len(List); i++ {
		List[i].T_Certificate_sn = deviceCertificateMap[List[i].T_id]
	}
	page_size := math.Ceil(float64(cnt) / float64(page_z))
	r_jsons.List = List
	r_jsons.Page = page
	r_jsons.Page_size = int(page_size)
	r_jsons.Pages = lib.Func_page(int64(page), int64(page_size))
	r_jsons.Num = int(cnt)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return
}

// 列表 -
func (c *TaskDataController) TaskDataClass_List() {
	// 验证登录 User_is, User_r
	_, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}
	if Task_r.T_delivery_state == 2 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "数据采集中，请稍后!"}
		c.ServeJSON()
		return
	}

	List := Task.Read_TaskData_ById_ClassList(Task_r.T_task_id)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: List}
	c.ServeJSON()
	return
}

// 添加-
func (c *TaskDataController) TaskData_AddS() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}
	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	//T_sn|T_id|T_t|T_rh|T_time?

	T_Data := c.GetString("T_Data")
	if len(T_Data) < 5 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "err T_Data!"}
		c.ServeJSON()
		return
	}

	T_Data_list := strings.Split(T_Data, "?")
	println(len(T_Data_list), "len(T_Data_list)")
	var T_Data_list_x = 0
	for _, v := range T_Data_list {
		// 2022-08-09 14:25:00|27.7|55.2
		if len(v) < 5 {
			println(v, "len(v) < 5")
			continue
		}
		v_list := strings.Split(v, "|")
		is = Task.Add_TaskData(Task_r.T_task_id, v_list[0], v_list[1], v_list[2], v_list[3], v_list[4])
		if is {
			T_Data_list_x += 1
		}
	}

	System.Add_UserLogs(user_r.T_uuid, "任务数据", "添加数据"+Task_r.T_name, Task_r.T_task_id+"结果："+string(len(T_Data_list))+"/"+string(T_Data_list_x)+"|=> "+T_Data)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: strconv.Itoa(T_Data_list_x)}
	c.ServeJSON()
	return
}

// 添加-
func (c *TaskDataController) TaskData_Add() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	T_sn := c.GetString("T_sn")
	T_id, _ := c.GetInt("T_id")
	T_t, _ := c.GetFloat("T_t")
	T_rh, _ := c.GetFloat("T_rh")
	T_time := c.GetString("T_time")

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	is = Task.Add_TaskData(Task_r.T_task_id, T_sn, strconv.Itoa(T_id), fmt.Sprintf("%.2f", T_t), fmt.Sprintf("%.2f", T_rh), T_time)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败!"}
		c.ServeJSON()
		return
	}

	System.Add_UserLogs(user_r.T_uuid, "任务数据", "添加数据"+Task_r.T_name, Task_r.T_task_id+"|"+T_sn+"|"+strconv.Itoa(T_id)+"|"+fmt.Sprintf("%.2f", T_t)+"|"+fmt.Sprintf("%.2f", T_rh)+T_time)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 修改-
func (c *TaskDataController) TaskData_Up() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Id, err := c.GetInt("Id")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id 错误!"}
		c.ServeJSON()
		return
	}
	T_t, err := c.GetFloat("T_t")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_t 错误!"}
		c.ServeJSON()
		return
	}
	T_rh, err := c.GetFloat("T_rh")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_rh 错误!"}
		c.ServeJSON()
		return
	}
	T_time := c.GetString("T_time")

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	is = Task.Up_TaskData(Task_r.T_task_id, strconv.Itoa(Id), fmt.Sprintf("%.2f", T_t), fmt.Sprintf("%.2f", T_rh), T_time)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
		c.ServeJSON()
		return
	}

	System.Add_UserLogs(user_r.T_uuid, "任务数据", "修改数据"+Task_r.T_name, Task_r.T_task_id+"|"+strconv.Itoa(Id)+"|"+fmt.Sprintf("%.2f", T_t)+"|"+fmt.Sprintf("%.2f", T_rh)+T_time)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 删除-
func (c *TaskDataController) TaskData_Del() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Id, err := c.GetInt("Id")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id 错误!"}
		c.ServeJSON()
		return
	}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	is = Task.Del_TaskData(Task_r.T_task_id, strconv.Itoa(Id))
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
		c.ServeJSON()
		return
	}
	System.Add_UserLogs(user_r.T_uuid, "任务数据", "删除"+Task_r.T_name, Task_r.T_task_id+"|"+strconv.Itoa(Id))

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 删除-
func (c *TaskDataController) TaskData_Del_t_id() {
	// 验证登录 User_is, User_r
	user_r, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Id, err := c.GetInt("Id")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id 错误!"}
		c.ServeJSON()
		return
	}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	is = Task.Del_TaskData_t_id(Task_r.T_task_id, strconv.Itoa(Id))
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
		c.ServeJSON()
		return
	}
	System.Add_UserLogs(user_r.T_uuid, "任务数据", "删除"+Task_r.T_name, Task_r.T_task_id+"|"+strconv.Itoa(Id))

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 列表 - 接口
func (c *TaskDataController) Export_Data_Excel() {
	// 验证登录 User_is, User_r
	_, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_sn_str := c.GetString("T_sn_list") //865901058809339,865901058815849,865901058818991,865901058810568
	//T_id, err := c.GetInt("T_id")
	//if err != nil {
	//	T_id = -1
	//
	//}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}

	T_sn_list := strings.Split(T_sn_str, ",")
	DeviceSensor_data_list := []Task.TaskData_{}
	for _, v := range T_sn_list {
		DeviceSensor_data, _ := Task.Read_TaskData_ById_List(Task_r.T_task_id, v, "", Time_start, Time_end, 1, 9999)
		DeviceSensor_data_list = append(DeviceSensor_data_list, DeviceSensor_data...)
	}

	f := excelize.NewFile() // 设置单元格的值
	// 这里设置表头
	f.SetCellValue("Sheet1", "A1", "编号")
	f.SetCellValue("Sheet1", "B1", "SN")
	f.SetCellValue("Sheet1", "C1", "温度℃")
	f.SetCellValue("Sheet1", "D1", "湿度%")
	f.SetCellValue("Sheet1", "E1", "记录时间")
	// 设置列宽
	f.SetColWidth("Sheet1", "A", "A", 7)
	f.SetColWidth("Sheet1", "B", "B", 20)
	f.SetColWidth("Sheet1", "C", "C", 10)
	f.SetColWidth("Sheet1", "D", "D", 10)
	f.SetColWidth("Sheet1", "E", "E", 22)

	line := 1

	// 循环写入数据
	for _, v := range DeviceSensor_data_list {
		line++
		f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), v.T_id)
		f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), v.T_sn)
		f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), strconv.FormatFloat(float64(v.T_t), 'f', 1, 64))
		f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), strconv.FormatFloat(float64(v.T_rh), 'f', 1, 64))
		f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.T_time)

	}
	logs.Println("DeviceSensor_data:", len(DeviceSensor_data_list))

	lib.Create_Dir("./ofile")

	timeStr := time.Now().Format("20060102150405")
	// 保存文件
	if err := f.SaveAs("ofile/" + timeStr + ".xlsx"); err != nil {
		logs.Error(lib.FuncName(), err)
	}

	if !lib.Pload_qiniu("ofile/"+timeStr+".xlsx", "ofile/"+timeStr+".xlsx") {
		c.Data["json"] = lib.JSONS{Code: 203, Msg: "oss!"}
		c.ServeJSON()
		return
	}
	//删除目录
	//err = os.Remove("ofile/" + timeStr + ".xlsx")
	//if err != nil {
	//	logs.Error(lib.FuncName(),err)
	//}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: "https://bzdcoldverifyoss.baozhida.cn/" + "ofile/" + timeStr + ".xlsx"}
	c.ServeJSON()
	return
}

// 列表 - 接口
func (c *TaskDataController) Export_Data_PDF() {
	// 验证登录 User_is, User_r
	_, User_is := Account.Verification(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_sn_str := c.GetString("T_sn_list") //865901058809339,865901058815849,865901058818991,865901058810568
	//T_id, err := c.GetInt("T_id")
	//if err != nil {
	//	T_id = -1
	//
	//}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}
	dcList, _ := Device.Read_DeviceClassList_OrderList(Task_r.T_class, "", "", "", 0, 9999)
	// 查询设备列表
	// 保存布局编号和校准证书对应关系
	var deviceCertificateMap = make(map[string]string) // t_id, T_Certificate_sn
	for _, v := range dcList {
		deviceCertificateMap[v.T_id] = v.T_Certificate_sn
	}

	T_sn_list := strings.Split(T_sn_str, ",")
	DeviceSensor_data_list := []Task.TaskData_{}
	for _, v := range T_sn_list {
		DeviceSensor_data, _ := Task.Read_TaskData_ById_List(Task_r.T_task_id, v, "", Time_start, Time_end, 1, 9999)
		DeviceSensor_data_list = append(DeviceSensor_data_list, DeviceSensor_data...)
		for i := 0; i < len(DeviceSensor_data_list); i++ {
			DeviceSensor_data_list[i].T_Certificate_sn = deviceCertificateMap[DeviceSensor_data_list[i].T_id]
		}
	}

	//------

	var err error
	pdf := &gopdf.GoPdf{}
	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
	//err = GetFont(pdf, "LiberationSerif-Regular.ttf")
	//if err != nil {
	//	log.Fatalln(err)
	//}
	//err = pdf.SetFont("Ubuntu-L", "", 14)
	//if err != nil {
	//	log.Fatalln(err)
	//}

	err = pdf.AddTTFFont("simsun", "static/fonts/三极行楷简体-粗.ttf")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 204, Msg: "ok!", Data: err}
		c.ServeJSON()
		return
	}
	err = pdf.SetFont("simsun", "", 24)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 205, Msg: "ok!", Data: err}
		c.ServeJSON()
		return
	}

	pdf.SetGrayFill(0.5)

	pdf.SetMargins(0, 20, 0, 20)
	pdf.AddPage()

	//use path
	//pdf.Image("logo.png", 100, 50, &gopdf.Rect{W: 50, H: 50})

	textw, _ := pdf.MeasureTextWidth(Task_r.T_name)
	pdf.SetX((595 / 2) - (textw / 2))
	pdf.SetY(40)
	pdf.Text(Task_r.T_name)

	// 线
	pdf.SetLineWidth(2)
	pdf.SetLineType("dashed")
	pdf.Line(10, 60, 585, 60)

	err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 206, Msg: "ok!", Data: err}
		c.ServeJSON()
		return
	}
	err = pdf.SetFont("wts", "", 12)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 207, Msg: "ok!", Data: err}
		c.ServeJSON()
		return
	}
	t_ := Time_start + " / " + Time_end
	if len(Time_start) == 0 {
		t_ = "所有数据"
	}
	//fmt.Sprintf(" %.1f ", v.T_t)
	lib.RectFillColor(pdf, "提取数据时间段["+t_+"]", 14, 22, 80, 550, 40, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)

	lib.RectFillColor(pdf, "布局编号", 12, 22, 120, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
	lib.RectFillColor(pdf, "证书编号", 12, 92, 120, 150, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
	lib.RectFillColor(pdf, "温度℃", 12, 242, 120, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
	lib.RectFillColor(pdf, "湿度%", 12, 342, 120, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)

	//lib.RectFillColor(pdf, "温度范围", 12, 272, 120, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
	//lib.RectFillColor(pdf, "湿度范围", 12, 362, 120, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
	lib.RectFillColor(pdf, "记录时间", 12, 442, 120, 130, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)

	var y float64 = 140

	err = pdf.SetFont("wts", "", 10)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 207, Msg: "ok!", Data: err}
		c.ServeJSON()
		return
	}
	for _, v := range DeviceSensor_data_list {
		//text := fmt.Sprintf(" %d ", i+1)
		var textH float64 = 25 // if text height is 25px.
		pdf.SetNewY(y, textH)
		y = pdf.GetY()
		//pdf.SetX(x) // must after pdf.SetNewY() called.
		//err = pdf.Text(text)
		//if err != nil {
		//	log.Fatalln(err)
		//}

		T_t := fmt.Sprintf(" %.1f ", v.T_t)
		T_rh := fmt.Sprintf(" %.1f ", v.T_rh)
		T_time := fmt.Sprintf("%s", v.T_time)

		lib.RectFillColor(pdf, v.T_id, 10, 22, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
		lib.RectFillColor(pdf, v.T_Certificate_sn, 10, 92, y, 150, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
		lib.RectFillColor(pdf, T_t, 10, 242, y, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
		lib.RectFillColor(pdf, T_rh, 10, 342, y, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
		lib.RectFillColor(pdf, T_time, 10, 442, y, 130, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
		y += 20
	}

	timeStr := "ofile/" + time.Now().Format("20060102150405") + ".pdf"

	err = pdf.WritePdf(timeStr)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 207, Msg: "ok!", Data: err}
		c.ServeJSON()
		return
	}

	if !lib.Pload_qiniu(timeStr, timeStr) {
		c.Data["json"] = lib.JSONS{Code: 203, Msg: "oss!"}
		c.ServeJSON()
		return
	}
	//删除目录
	err = os.Remove(timeStr)
	if err != nil {
		logs.Error(lib.FuncName(), err)
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: "https://bzdcoldverifyoss.baozhida.cn/" + timeStr}
	c.ServeJSON()
	return

}

// 列表 - 接口
func (c *TaskDataController) Check() {
	// 验证登录 User_is, User_r
	_, User_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))
	if !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	T_task_id := c.GetString("T_task_id")
	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_task_id 错误!"}
		c.ServeJSON()
		return
	}
	type R_JSONS struct {
		T_sn               string // SN
		T_id               string // 编号
		T_unm              int    // 数据量
		T_time_interval    int64  // 时间间隔
		Time_start         string // 开始
		Time_end           string //  结束
		Result             int    //  200 OK, 201 可以补 , 202 不能补
		Result_str         string //  提示内容
		Result_Time_start  string //  2022-8-05 21:01
		Result_Time_defect int64  //  缺失时间间隔
	}
	var r_jsons []R_JSONS

	List := Task.Read_TaskData_ById_ClassList(Task_r.T_task_id)
	for _, v := range List {
		var r_json R_JSONS
		r_json.T_sn = v.T_sn

		r_json.Result = 200

		DeviceSensor_data := Task.Read_TaskData_ById_List_(Task_r.T_task_id, v.T_sn)
		r_json.T_unm = len(DeviceSensor_data)

		if r_json.T_unm > 2 {
			r_json.T_id = DeviceSensor_data[0].T_id
			r_json.Time_end = DeviceSensor_data[len(DeviceSensor_data)-1].T_time
			r_json.Time_start = DeviceSensor_data[0].T_time

			formatTime_a, _ := time.Parse("2006-1-2 15:04", DeviceSensor_data[0].T_time)
			formatTime_b, _ := time.Parse("2006-1-2 15:04", DeviceSensor_data[1].T_time)
			formatTime_x := formatTime_b.Unix() - formatTime_a.Unix()
			r_json.T_time_interval = formatTime_x
			println("formatTime_x:", v.T_id, v.T_sn, formatTime_x)
			if formatTime_x > 60*30 || formatTime_x < 60 {
				r_json.Result = 202
				r_json.Result_str = "数据异常（数据的第一个时间与第二个时间相差 " + strconv.FormatInt(formatTime_x, 10) + "秒）,必须大于60秒，小于30分钟"
				r_jsons = append(r_jsons, r_json)
				continue
			}
			for data_i := 2; data_i < len(DeviceSensor_data); data_i++ {
				formatTime_a = formatTime_b
				formatTime_b, _ = time.Parse("2006-1-2 15:04", DeviceSensor_data[data_i].T_time)
				formatTime_ := formatTime_b.Unix() - formatTime_a.Unix()
				println("formatTime_x-:", formatTime_)
				if formatTime_ < formatTime_x {
					r_json.Result = 202
					r_json.Result_str = "开始时间：" + DeviceSensor_data[data_i-1].T_time + "  离下一条时间间隔:" + strconv.FormatInt(formatTime_, 10) + "秒，间隔小于时间间隔，不能自动补充"
					break
				}
				if formatTime_x != formatTime_ {
					if formatTime_ > 60*30 {
						r_json.Result = 202
						r_json.Result_str = "开始时间：" + DeviceSensor_data[data_i-1].T_time + "  离下一条时间间隔:" + strconv.FormatInt(formatTime_, 10) + "秒，相差时间大于30分钟，不能自动补充"
						break
					}
					r_json.Result = 201
					r_json.Result_str = "开始时间：" + DeviceSensor_data[data_i-1].T_time + "  离下一条时间间隔:" + strconv.FormatInt(formatTime_, 10) + "秒"
					r_json.Result_Time_start = DeviceSensor_data[data_i-1].T_time
					r_json.Result_Time_defect = formatTime_
					println(r_json.Result_str)
					break
				}

			}
		} else {
			r_json.Result = 202
			r_json.Result_str = "数据量太少 必须大于 2条以上！"
		}

		r_jsons = append(r_jsons, r_json)
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return
}

func (c *TaskDataController) TaskData_Temperature_Pdf() {
	// 验证登录管理员 User_is, User_r
	_, User_Admin_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))

	// 验证登录用户 User_is, User_r
	_, User_is := Account.Verification(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))

	if !User_Admin_is && !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_sn := c.GetString("T_sn")
	T_id := c.GetString("T_id")

	T_task_id := c.GetString("T_task_id")

	err := c.TaskData_Pdf(Time_start, Time_end, T_task_id, T_sn, T_id, Task.Temperature)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
		c.ServeJSON()
		return
	}

}
func (c *TaskDataController) TaskData_Humidity_Pdf() {
	// 验证登录管理员 User_is, User_r
	_, User_Admin_is := Account.Verification_Admin(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))

	// 验证登录用户 User_is, User_r
	_, User_is := Account.Verification(c.Ctx.GetCookie("User_tokey"), c.GetString("User_tokey"))

	if !User_Admin_is && !User_is {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登录!"}
		c.ServeJSON()
		return
	}

	Time_start := c.GetString("Time_start")
	Time_end := c.GetString("Time_end")
	T_sn := c.GetString("T_sn")
	T_id := c.GetString("T_id")

	T_task_id := c.GetString("T_task_id")

	err := c.TaskData_Pdf(Time_start, Time_end, T_task_id, T_sn, T_id, 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_sn, T_id, T_type string) (err error) {

	Task_r, is := Task.Read_Task(T_task_id)
	if !is {
		return errors.New("T_task_id 错误!")
	}
	user, is := Account.Read_User(Task_r.T_uuid)
	if !is {
		return errors.New("Task uuid 错误!")
	}

	if Task_r.T_delivery_state == 2 {
		return errors.New("数据采集中，请稍后!")
	}

	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("./static/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
	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)

	// 查询设备列表
	//dcList, _ := Device.Read_DeviceClassList_OrderList(Task_r.T_class, T_sn, T_id, "", 0, 9999)
	dcList := []Device.DeviceClassList{}
	dataList, _ := Task.Read_TaskData_ById_List(Task_r.T_task_id, T_sn, T_id, Time_start, Time_end, 0, 9999)
	dataListMap := make(map[string][]Task.TaskData_)
	dcListMap := make(map[string]string)
	dataMap := make(map[string]string)
	timeMap := make(map[string]bool)
	for _, data := range dataList {
		dataListMap[data.T_id] = append(dataListMap[data.T_id], data)
		if _, ok := dcListMap[data.T_id]; !ok {
			dcListMap[data.T_id] = data.T_sn
		}
		k := fmt.Sprintf("%s,%s", data.T_time, data.T_id)
		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
		}
	}
	for id, sn := range dcListMap {
		dcList = append(dcList, Device.DeviceClassList{T_id: id, T_sn: sn})
	}
	for id, list := range dataListMap {
		sort.Slice(list, func(i, j int) bool {
			return list[i].T_time < list[j].T_time
		})
		dataListMap[id] = list
	}

	var timeList []string
	for k, _ := range timeMap {
		timeList = append(timeList, k)
	}
	sort.Slice(timeList, func(i, j int) bool {
		return timeList[i] < timeList[j]
	})
	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])
		textw, _ = pdf.MeasureTextWidth(timeStr)
		pdf.SetX((595 / 2) - (textw / 2))
		pdf.SetY(y)
		pdf.Text(timeStr)
	}

	//y += 20
	var x float64 = 10
	var w float64 = 120

	err = pdf.SetFont("wts", "", 10)
	if err != nil {
		return
	}
	idWidthMap := make(map[string]float64)
	dcList1 := make([]Device.DeviceClassList, 0)
	for _, list := range dcList {
		idw, _ := pdf.MeasureTextWidth(list.T_id)
		if !lib.IsNumeric(list.T_id) {
			dcList1 = append(dcList1, list)
		}
		if idw > 20 {
			idWidthMap[list.T_id] = idw + 12
		} else {
			idWidthMap[list.T_id] = 30.3
		}
	}
	sort.Slice(dcList1, func(i, j int) bool {
		return dcList1[i].T_id < dcList1[j].T_id
	})
	dcList2 := listSubtract(dcList, dcList1)
	// 获取探头时间
	var timeList2 []string
	timeMap2 := make(map[string]struct{})
	for _, list := range dcList2 {
		dataList2, ok := dataListMap[list.T_id]
		if ok {
			for _, data := range dataList2 {
				if _, ok = timeMap2[data.T_time]; !ok {
					timeMap2[data.T_time] = struct{}{}
				}
			}
		}
	}
	for k, _ := range timeMap2 {
		timeList2 = append(timeList2, k)
	}
	sort.Slice(timeList2, func(i, j int) bool {
		return timeList2[i] < timeList2[j]
	})
	var temp int
	for index, dc := range dcList1 {

		dataList2, _ := dataListMap[dc.T_id]

		err = pdf.SetFont("wts", "", 15)
		if err != nil {
			return
		}
		y += 30

		var textH float64 = 20 // if text height is 25px.
		if y >= 790 {
			addStampImage(pdf, 455, y-150)
			// AddWatermark(Task_r, pdf)
			pdf.AddPage()
			y = 30
		} else {
			if index > 0 {
				y += 10
			}
		}

		textw, _ = pdf.MeasureTextWidth(dc.T_id)
		pdf.SetX((595 / 2) - (textw / 2))
		pdf.SetY(y)
		pdf.Text(dc.T_id)
		y += 10

		err = pdf.SetFont("wts", "", 10)
		if err != nil {
			return
		}

		if y < 790 {
			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
		} else {
			addStampImage(pdf, 455, y-150)
			// AddWatermark(Task_r, pdf)
			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
		}

		for i := 0; i < len(dataList2); i++ {
			if y > 790 {
				addStampImage(pdf, 455, y-130)
				// AddWatermark(Task_r, pdf)
				pdf.AddPage()
				y = pdf.GetY()
				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
			}

			temp = i % 4
			// 每页添加表头
			if y == 20 && temp == 0 {
				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
			}

			x = 10 + 143.8*float64(temp)
			w = 113.8

			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 y > 760 {
			//	fmt.Println("=====y:", y)
			//}
			//if y > 790 {
			//	addStampImage(pdf, 455, y-130)
			//}
			if temp == 3 {
				y += 20
				pdf.SetNewY(y, textH)
				y = pdf.GetY()
			}

		}

	}

	if len(dcList2) > 0 {
		if temp != 3 {
			y += 20
		}
		y += 40
	}
	sort.Slice(dcList2, func(i, j int) bool {
		return dcList2[i].T_id < dcList2[j].T_id
	})
	chunks := splitData(dcList2, 454.5, idWidthMap)
	for i, list := range chunks {

		if i > 0 {
			y += 40
		}
		if y < 790 {
			x = 10
			w = 120.7
			lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
			x += w
			w = 30.3
			for _, v2 := range list {
				w = idWidthMap[v2.T_id]
				lib.RectFillColor(pdf, v2.T_id, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
				x += w
			}
			y += 20
		} else {
			addStampImage(pdf, 455, y-150)
			// AddWatermark(Task_r, pdf)
			pdf.AddPage()
			y = 20
		}

		StampImageX := x
		for j, t := range timeList2 {
			if j > 0 {
				y += 20
			}

			if y >= 790 {
				addStampImage(pdf, StampImageX-130, y-130)
				// AddWatermark(Task_r, pdf)
				pdf.AddPage()
				y = pdf.GetY()
				x = 10
				w = 120.7
				lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
				x += w
				w = 30.3
				for _, v2 := range list {
					w = idWidthMap[v2.T_id]
					lib.RectFillColor(pdf, v2.T_id, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
					x += w
				}
				y += 20
				x = 10
			}
			x = 10
			if y == 20 {
				w = 120.7
				lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
				x += w
				w = 30.3
				for _, v2 := range list {
					w = idWidthMap[v2.T_id]
					lib.RectFillColor(pdf, v2.T_id, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
					x += w
				}
				y += 20
				x = 10
			}
			w = 120.7
			lib.RectFillColor(pdf, t, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
			x += w
			w = 30.3
			for _, v := range list {
				t_t := dataMap[fmt.Sprintf("%s,%s", t, v.T_id)]
				w = idWidthMap[v.T_id]
				lib.RectFillColor(pdf, t_t, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
				x += w
			}
			StampImageX = x
		}
	}

	if y <= 790 {
		if y < 150 {
			y = 20
		} else {
			y = y - 145
		}
		x = x - 135
		if len(dcList2) == 0 {
			x = 455
		}
		addStampImage(pdf, x, y)
		// AddWatermark(Task_r, pdf)

	} else if y > 790 && len(dcList2) == 0 {
		if y < 150 {
			y = 20
		} else {
			y = y - 145
		}
		addStampImage(pdf, 455, y)

	}
	filename := time.Now().Format("20060102150405") + ".pdf"
	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
	}

	// 上传 OSS
	//url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+timeStr, timeStr)
	//url, is := NatsServer.Qiniu_UploadFile("/Users/zoie/work/bzd_project/ColdVerify_server/"+timeStr, timeStr)
	//if !is {
	//	err = errors.New("oss!")
	//	return
	//}

	defer func() {
		//删除目录
		os.Remove(timeStr)
	}()

	c.Ctx.Output.Download(timeStr)
	//c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
	//c.ServeJSON()
	//return
	return nil

}

// 添加公章图片
func addStampImage(pdf *gopdf.GoPdf, x, y float64) {
	imagePath := "./static/commonSeal.jpg"
	if x < 10 {
		x = 10
	}
	if y < 20 {
		y = 20
	}
	err := pdf.Image(imagePath, x, y, &gopdf.Rect{W: 123, H: 128.6})
	if err != nil {
		log.Print(err.Error())
	}
}
func listSubtract(sliceA, sliceB []Device.DeviceClassList) []Device.DeviceClassList {
	// 创建一个集合用于存储 sliceB 的元素
	elementsToRemove := make(map[string]Device.DeviceClassList)
	for _, item := range sliceB {
		elementsToRemove[item.T_id] = item
	}

	// 构建新切片，包含 sliceA 中不在 elementsToRemove 中的元素
	var result []Device.DeviceClassList
	for _, item := range sliceA {
		if _, found := elementsToRemove[item.T_id]; !found {
			result = append(result, item)
		}
	}

	return result
}

func splitData(data []Device.DeviceClassList, threshold float64, idWidthMap map[string]float64) [][]Device.DeviceClassList {
	var result [][]Device.DeviceClassList
	var currentBatch []Device.DeviceClassList
	var currentSum float64

	for _, item := range data {
		wd := idWidthMap[item.T_id]
		if currentSum+wd > threshold+0.1 {
			// 当前批次超过阈值，切分
			result = append(result, currentBatch)
			// 重置当前批次和当前总和
			currentBatch = []Device.DeviceClassList{}
			currentSum = 0
		}
		currentBatch = append(currentBatch, item)
		currentSum += wd
	}

	// 添加最后一批
	if len(currentBatch) > 0 {
		result = append(result, currentBatch)
	}

	return result
}

func AddWatermark(task Task.Task, pdf *gopdf.GoPdf) {
	// 设置透明度 (通过绘制透明背景实现)
	// 使用浅色字体来模拟透明度
	//originalX := pdf.GetX()
	//originalY := pdf.GetY()
	//grayColor := color.RGBA{R: 200, G: 200, B: 200, A: 255} // 浅灰色，接近透明效果
	//pdf.SetTextColor(grayColor.R, grayColor.G, grayColor.B) // 设置字体颜色
	//pdf.SetFontSize(50)
	//
	//// 设置水印的重复布局
	//text := "水印"
	//xOffset := 180.0 // X 坐标的偏移量
	//yOffset := 180.0 // Y 坐标的偏移量
	//angle := 45.0    // 旋转角度（度）
	//
	//// 循环绘制水印
	//for y := 0.0; y < 780; y += yOffset { // 842 是 A4 页面高度的像素数 (72 DPI)
	//	for x := -100.0; x < 595; x += xOffset { // 595 是 A4 页面宽度的像素数 (72 DPI)
	//		// 保存当前的绘制状态
	//		pdf.SetX(x)
	//		pdf.SetY(y)
	//		pdf.Rotate(angle, x+100, y+50) // 旋转水印
	//		pdf.Cell(nil, text)
	//		pdf.RotateReset() // 恢复旋转状态
	//	}
	//}
	//
	//grayColor2 := color.RGBA{R: 0, G: 0, B: 0, A: 0}           // 浅灰色，接近透明效果
	//pdf.SetTextColor(grayColor2.R, grayColor2.G, grayColor2.B) // 设置字体颜色
	//pdf.SetFontSize(10)
	//pdf.SetX(originalX)
	//pdf.SetY(originalY)
}
