| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451 | package controllersimport (	"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/vmihailenco/msgpack/v5"	"github.com/xuri/excelize/v2"	"log"	"math"	"os"	"sort"	"strconv"	"strings"	"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	}	data := 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)	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 chunkBy1[T any](list []T, size int) [][]T {	var chunks [][]T	for size < len(list) {		list, chunks = list[size:], append(chunks, list[0:size:size])	}	return append(chunks, list)}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)}
 |