waybill.go 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138
  1. package controller
  2. import (
  3. "bufio"
  4. "cold-delivery/app/admin/model"
  5. "cold-delivery/app/admin/service"
  6. "cold-delivery/app/admin/service/dto"
  7. "cold-delivery/common/actions"
  8. "cold-delivery/common/lib"
  9. "cold-delivery/common/nats/nats_server"
  10. "errors"
  11. "fmt"
  12. "github.com/beego/beego/v2/core/logs"
  13. "github.com/gin-gonic/gin"
  14. "github.com/gin-gonic/gin/binding"
  15. "github.com/golang/freetype/truetype"
  16. "github.com/pborman/uuid"
  17. "github.com/signintech/gopdf"
  18. "github.com/wcharczuk/go-chart/v2"
  19. "github.com/wcharczuk/go-chart/v2/drawing"
  20. "github.com/xuri/excelize/v2"
  21. "gogs.baozhida.cn/zoie/OAuth-core/api"
  22. "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
  23. _ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
  24. "gonum.org/v1/plot"
  25. "gonum.org/v1/plot/plotter"
  26. "gonum.org/v1/plot/vg"
  27. "gonum.org/v1/plot/vg/draw"
  28. "image/color"
  29. "log"
  30. "math"
  31. "net/url"
  32. "os"
  33. "path"
  34. "sort"
  35. "sync"
  36. "time"
  37. )
  38. type WaybillController struct {
  39. api.Api
  40. }
  41. // GetPage 获取运单列表
  42. // @Summary 获取运单列表
  43. // @Description 获取运单列表
  44. // @Tags 运单
  45. // @Param waybillNo query string false "运单号"
  46. // @Param orderNo query string false "订单号"
  47. // @Param status query int false "状态"
  48. // @Param orderStartTime query string false "下单开始时间"
  49. // @Param orderEndTime query string false "下单结束时间"
  50. // @Param pageSize query int false "页条数"
  51. // @Param page query int false "页码"
  52. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  53. // @Router /api/waybill [get]
  54. // @Security Bearer
  55. func (e WaybillController) GetPage(c *gin.Context) {
  56. s := service.Waybill{}
  57. userSvc := service.SysUser{}
  58. req := dto.WaybillGetPageReq{}
  59. err := e.MakeContext(c).
  60. MakeOrm().
  61. Bind(&req, binding.Query).
  62. MakeService(&s.Service).
  63. MakeService(&userSvc.Service).
  64. Errors
  65. if err != nil {
  66. e.Logger.Error(err)
  67. e.Error(500, err, err.Error())
  68. return
  69. }
  70. //数据权限检查
  71. p := actions.GetPermissionFromContext(c)
  72. var userObj model.SysUser
  73. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  74. if err != nil {
  75. e.Error(500, err, err.Error())
  76. return
  77. }
  78. list := make([]model.Waybill, 0)
  79. var count int64
  80. if userObj.Type == model.SysUserTypeSys {
  81. err = s.GetPage(&req, &list, &count, p)
  82. } else {
  83. err = s.GetUserPage(&req, &list, &count, p)
  84. }
  85. if err != nil {
  86. e.Error(500, err, err.Error())
  87. return
  88. }
  89. e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
  90. }
  91. // Export 导出运单列表
  92. // @Summary 导出运单列表
  93. // @Description 导出运单列表
  94. // @Tags 运单
  95. // @Param waybillNo query string false "运单号"
  96. // @Param pageSize query int false "页条数"
  97. // @Param page query int false "页码"
  98. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  99. // @Router /api/waybill/export [get]
  100. // @Security Bearer
  101. func (e WaybillController) Export(c *gin.Context) {
  102. s := service.Waybill{}
  103. req := dto.WaybillGetPageReq{}
  104. err := e.MakeContext(c).
  105. MakeOrm().
  106. Bind(&req, binding.Query).
  107. MakeService(&s.Service).
  108. Errors
  109. if err != nil {
  110. e.Logger.Error(err)
  111. e.Error(500, err, err.Error())
  112. return
  113. }
  114. //数据权限检查
  115. p := actions.GetPermissionFromContext(c)
  116. list := make([]model.Waybill, 0)
  117. var count int64
  118. req.PageSize = 9999
  119. err = s.GetPage(&req, &list, &count, p)
  120. if err != nil {
  121. e.Error(500, err, err.Error())
  122. return
  123. }
  124. f := excelize.NewFile() // 设置单元格的值
  125. // 这里设置表头ÒÒ
  126. f.SetCellValue("Sheet1", "A1", "序号")
  127. f.SetCellValue("Sheet1", "B1", "状态")
  128. f.SetCellValue("Sheet1", "C1", "寄件人名称")
  129. f.SetCellValue("Sheet1", "D1", "寄件人电话")
  130. f.SetCellValue("Sheet1", "E1", "寄件人地址")
  131. f.SetCellValue("Sheet1", "F1", "收件人名称")
  132. f.SetCellValue("Sheet1", "G1", "收件人电话")
  133. f.SetCellValue("Sheet1", "H1", "收件人地址")
  134. f.SetCellValue("Sheet1", "I1", "防拆标签码")
  135. f.SetCellValue("Sheet1", "J1", "运输备注")
  136. // 设置列宽
  137. f.SetColWidth("Sheet1", "A", "A", 6)
  138. f.SetColWidth("Sheet1", "B", "B", 8)
  139. f.SetColWidth("Sheet1", "C", "C", 14)
  140. f.SetColWidth("Sheet1", "D", "D", 14)
  141. f.SetColWidth("Sheet1", "E", "E", 30)
  142. f.SetColWidth("Sheet1", "F", "F", 14)
  143. f.SetColWidth("Sheet1", "G", "G", 14)
  144. f.SetColWidth("Sheet1", "H", "H", 30)
  145. f.SetColWidth("Sheet1", "I", "J", 15)
  146. f.SetColWidth("Sheet1", "K", "K", 30)
  147. line := 1
  148. // 循环写入数据
  149. for i, v := range list {
  150. line++
  151. f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), i+1)
  152. f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), model.WaybillStatusMap[v.Status])
  153. f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), v.SenderAddressName)
  154. f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.SenderAddressPhone)
  155. f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.SenderAddressDetails)
  156. f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.ConsigneeAddressName)
  157. f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v.ConsigneeAddressPhone)
  158. f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.ConsigneeAddressDetails)
  159. f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v.DeliveryName)
  160. f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v.DeliveryPhone)
  161. f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v.Remark)
  162. }
  163. timeStr := time.Now().Format("20060102150405")
  164. filePath := "ofile/" + "运单" + timeStr + ".xlsx"
  165. // 保存文件
  166. if err = f.SaveAs(filePath); err != nil {
  167. logs.Error("保存运单失败:", err)
  168. }
  169. defer func() {
  170. os.Remove(filePath)
  171. }()
  172. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  173. // PathEscape 函数对中文做处理
  174. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape("运单"+timeStr+".xlsx"))
  175. c.Header("Content-Transfer-Encoding", "binary")
  176. c.File(filePath)
  177. }
  178. // Home 首页统计
  179. // @Summary 首页统计
  180. // @Description 首页统计
  181. // @Tags 运单
  182. // @Param data body dto.WaybillStatsReq true "data"
  183. // @Param date query string true "日期"
  184. // @Param type query string true "类型 month-月 year-年"
  185. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  186. // @Router /api/waybill/home [get]
  187. // @Security Bearer
  188. func (e WaybillController) Home(c *gin.Context) {
  189. s := service.Waybill{}
  190. userSvc := service.SysUser{}
  191. req := dto.WaybillStatsReq{}
  192. err := e.MakeContext(c).
  193. MakeOrm().
  194. Bind(&req, binding.Query).
  195. MakeService(&s.Service).
  196. MakeService(&userSvc.Service).
  197. Errors
  198. if err != nil {
  199. e.Logger.Error(err)
  200. e.Error(500, err, err.Error())
  201. return
  202. }
  203. //数据权限检查
  204. p := actions.GetPermissionFromContext(c)
  205. var userObj model.SysUser
  206. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  207. if err != nil {
  208. e.Error(500, err, err.Error())
  209. return
  210. }
  211. var res dto.WaybillStatsRes
  212. if userObj.Type == model.SysUserTypeSys {
  213. res = s.GetBasicsStats(&req, p)
  214. } else {
  215. res = s.GetUserBasicsStats(&req, p, service.GetUserBasicsStatsScopes(p.UserId))
  216. }
  217. e.OK(res, "查询成功")
  218. }
  219. // UserStats 用户运单数量统计
  220. // @Summary 首页统计
  221. // @Description 首页统计
  222. // @Tags 运单
  223. // @Param data body dto.WaybillUserStatsReq true "data"
  224. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  225. // @Router /api/waybill/user-stats [post]
  226. // @Security Bearer
  227. func (e WaybillController) UserStats(c *gin.Context) {
  228. s := service.Waybill{}
  229. userSvc := service.SysUser{}
  230. req := dto.WaybillUserStatsReq{}
  231. err := e.MakeContext(c).
  232. MakeOrm().
  233. Bind(&req, binding.JSON).
  234. MakeService(&s.Service).
  235. MakeService(&userSvc.Service).
  236. Errors
  237. if err != nil {
  238. e.Logger.Error(err)
  239. e.Error(500, err, err.Error())
  240. return
  241. }
  242. //数据权限检查
  243. p := actions.GetPermissionFromContext(c)
  244. var userObj model.SysUser
  245. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  246. if err != nil {
  247. e.Error(500, err, err.Error())
  248. return
  249. }
  250. var res []dto.WaybillUserStats
  251. if req.UserType == "delivery" {
  252. if userObj.Type == model.SysUserTypeSys {
  253. res = s.GetDeliveryStats(&req, p)
  254. } else {
  255. req.UserIds = []int{p.UserId}
  256. res = s.GetDeliveryStats(&req, p)
  257. }
  258. }
  259. if req.UserType == "reCheck" {
  260. if userObj.Type == model.SysUserTypeSys {
  261. res = s.GetReCheckStats(&req, p)
  262. } else {
  263. req.UserIds = []int{p.UserId}
  264. res = s.GetReCheckStats(&req, p)
  265. }
  266. }
  267. e.OK(res, "查询成功")
  268. }
  269. // GetAppletPage 获取运单列表
  270. // @Summary 获取运单列表
  271. // @Description 获取运单列表
  272. // @Tags 运单
  273. // @Param waybillNo query string false "运单号"
  274. // @Param status query int false "状态"
  275. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  276. // @Router /api/waybill/applet [get]
  277. // @Security Bearer
  278. func (e WaybillController) GetAppletPage(c *gin.Context) {
  279. s := service.Waybill{}
  280. req := dto.WaybillGetAppletPageReq{}
  281. err := e.MakeContext(c).
  282. MakeOrm().
  283. Bind(&req, binding.Query).
  284. MakeService(&s.Service).
  285. Errors
  286. if err != nil {
  287. e.Logger.Error(err)
  288. e.Error(500, err, err.Error())
  289. return
  290. }
  291. //数据权限检查
  292. p := actions.GetPermissionFromContext(c)
  293. list := make([]model.Waybill, 0)
  294. var count int64
  295. err = s.GetAppletPage(&req, &list, &count, p)
  296. if err != nil {
  297. e.Error(500, err, err.Error())
  298. return
  299. }
  300. e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
  301. }
  302. // GetAppletCount 获取app运单统计数量
  303. // @Summary 获取app运单统计数量
  304. // @Description 获取app运单统计数量
  305. // @Tags 运单
  306. // @Param waybillNo query string false "运单号"
  307. // @Param status query int false "状态"
  308. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  309. // @Router /api/waybill/applet-count [get]
  310. // @Security Bearer
  311. func (e WaybillController) GetAppletCount(c *gin.Context) {
  312. s := service.Waybill{}
  313. userSvc := service.SysUser{}
  314. req := dto.WaybillGetAppletPageReq{}
  315. err := e.MakeContext(c).
  316. MakeOrm().
  317. Bind(&req, binding.Query).
  318. MakeService(&s.Service).
  319. MakeService(&userSvc.Service).
  320. Errors
  321. if err != nil {
  322. e.Logger.Error(err)
  323. e.Error(500, err, err.Error())
  324. return
  325. }
  326. //数据权限检查
  327. p := actions.GetPermissionFromContext(c)
  328. var userObj model.SysUser
  329. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  330. if err != nil {
  331. e.Error(500, err, err.Error())
  332. return
  333. }
  334. list := make([]model.Waybill, 0)
  335. var count int64
  336. if userObj.UserType == "customer" {
  337. r := dto.WaybillGetCustomerPageReq{}
  338. r.PageSize = 9999
  339. r.CustomerId = p.UserId
  340. err = s.GetCustomerPage(&r, &list, &count, p)
  341. var statusCount = make(map[int]int)
  342. statusCount[0] = int(count)
  343. for _, waybill := range list {
  344. if _, ok := statusCount[waybill.Status]; ok {
  345. statusCount[waybill.Status] += 1
  346. } else {
  347. statusCount[waybill.Status] = 1
  348. }
  349. }
  350. e.OK(statusCount, "查询成功")
  351. return
  352. }
  353. err = s.GetAppletCount(&list, &count, p)
  354. if err != nil {
  355. e.Error(500, err, err.Error())
  356. return
  357. }
  358. var statusCount = make(map[int]int)
  359. statusCount[0] = int(count)
  360. for _, waybill := range list {
  361. if _, ok := statusCount[waybill.Status]; ok {
  362. statusCount[waybill.Status] += 1
  363. } else {
  364. statusCount[waybill.Status] = 1
  365. }
  366. }
  367. e.OK(statusCount, "查询成功")
  368. }
  369. // Get 通过id获取运单
  370. // @Summary 通过id获取运单
  371. // @Description 通过id获取运单
  372. // @Tags 运单
  373. // @Param id path string true "运单id"
  374. // @Success 200 {object} response.Response{data=model.Waybill} "{"code": 200, "data": [...]}"
  375. // @Router /api/waybill/{id} [get]
  376. // @Security Bearer
  377. func (e WaybillController) Get(c *gin.Context) {
  378. s := service.Waybill{}
  379. req := dto.WaybillGetReq{}
  380. err := e.MakeContext(c).
  381. MakeOrm().
  382. Bind(&req, nil).
  383. MakeService(&s.Service).
  384. Errors
  385. if err != nil {
  386. e.Logger.Error(err)
  387. e.Error(500, err, err.Error())
  388. return
  389. }
  390. var object model.Waybill
  391. p := actions.GetPermissionFromContext(c)
  392. //数据权限检查
  393. err = s.Get(&req, &object, p)
  394. if err != nil {
  395. e.Error(500, err, err.Error())
  396. return
  397. }
  398. e.OK(object, "查询成功")
  399. }
  400. // GetByWaybillNo 通过id获取运单
  401. // @Summary 通过id获取运单
  402. // @Description 通过id获取运单
  403. // @Tags 运单
  404. // @Param waybillNo path string true "运单编号-必填"
  405. // @Success 200 {object} response.Response{data=model.Waybill} "{"code": 200, "data": [...]}"
  406. // @Router /api/waybill/no [get]
  407. // @Security Bearer
  408. func (e WaybillController) GetByWaybillNo(c *gin.Context) {
  409. s := service.Waybill{}
  410. req := dto.WaybillGetByWaybillPdfReq{}
  411. err := e.MakeContext(c).
  412. MakeOrm().
  413. Bind(&req, binding.Query).
  414. MakeService(&s.Service).
  415. Errors
  416. if err != nil {
  417. e.Logger.Error(err)
  418. e.Error(500, err, err.Error())
  419. return
  420. }
  421. var object model.Waybill
  422. //数据权限检查
  423. err = s.GetByWaybillNo(&req, &object, nil)
  424. if err != nil {
  425. e.Error(500, err, err.Error())
  426. return
  427. }
  428. e.OK(object, "查询成功")
  429. }
  430. // Insert 添加运单
  431. // @Summary 添加运单
  432. // @Description 添加运单
  433. // @Tags 运单
  434. // @Accept application/json
  435. // @Product application/json
  436. // @Param data body dto.WaybillInsertReq true "data"
  437. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  438. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  439. // @Router /api/waybill [post]
  440. // @Security Bearer
  441. func (e WaybillController) Insert(c *gin.Context) {
  442. s := service.Waybill{}
  443. req := dto.WaybillInsertReq{}
  444. err := e.MakeContext(c).
  445. MakeOrm().
  446. Bind(&req, binding.JSON).
  447. MakeService(&s.Service).
  448. Errors
  449. if err != nil {
  450. e.Logger.Error(err)
  451. e.Error(500, err, err.Error())
  452. return
  453. }
  454. p := actions.GetPermissionFromContext(c)
  455. // 设置创建人
  456. req.SetCreateBy(user.GetUserId(c))
  457. req.SetDeptId(p.DeptId)
  458. err = s.Insert(&req)
  459. if err != nil {
  460. e.Error(500, err, err.Error())
  461. return
  462. }
  463. e.OK(req.GetId(), "添加成功")
  464. }
  465. // UpdateStatus 修改运单状态
  466. // @Summary 修改运单状态
  467. // @Description 修改运单状态
  468. // @Tags 运单
  469. // @Accept application/json
  470. // @Product application/json
  471. // @Param data body dto.WaybillUpdateStatusReq true "body"
  472. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  473. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  474. // @Router /api/waybill/update-status [put]
  475. // @Security Bearer
  476. func (e WaybillController) UpdateStatus(c *gin.Context) {
  477. s := service.Waybill{}
  478. req := dto.WaybillUpdateStatusReq{}
  479. err := e.MakeContext(c).
  480. MakeOrm().
  481. Bind(&req).
  482. MakeService(&s.Service).
  483. Errors
  484. if err != nil {
  485. e.Logger.Error(err)
  486. e.Error(500, err, err.Error())
  487. return
  488. }
  489. p := actions.GetPermissionFromContext(c)
  490. req.SetUpdateBy(user.GetUserId(c))
  491. err = s.UpdateStatus(&req, p)
  492. if err != nil {
  493. e.Error(500, err, err.Error())
  494. return
  495. }
  496. e.OK(req.GetId(), "修改成功")
  497. }
  498. // Update 修改运单
  499. // @Summary 修改运单
  500. // @Description 修改运单
  501. // @Tags 运单
  502. // @Accept application/json
  503. // @Product application/json
  504. // @Param data body dto.WaybillUpdateReq true "body"
  505. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  506. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  507. // @Router /api/waybill [put]
  508. // @Security Bearer
  509. func (e WaybillController) Update(c *gin.Context) {
  510. s := service.Waybill{}
  511. req := dto.WaybillUpdateReq{}
  512. err := e.MakeContext(c).
  513. MakeOrm().
  514. Bind(&req).
  515. MakeService(&s.Service).
  516. Errors
  517. if err != nil {
  518. e.Logger.Error(err)
  519. e.Error(500, err, err.Error())
  520. return
  521. }
  522. p := actions.GetPermissionFromContext(c)
  523. req.SetUpdateBy(user.GetUserId(c))
  524. err = s.Update(&req, p)
  525. if err != nil {
  526. e.Error(500, err, err.Error())
  527. return
  528. }
  529. e.OK(req.GetId(), "修改成功")
  530. }
  531. // Delivery 派单
  532. // @Summary 派单
  533. // @Description 派单
  534. // @Tags 运单
  535. // @Accept application/json
  536. // @Product application/json
  537. // @Param data body dto.WaybillDeliveryReq true "body"
  538. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  539. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  540. // @Router /api/waybill/delivery [put]
  541. // @Security Bearer
  542. func (e WaybillController) Delivery(c *gin.Context) {
  543. s := service.Waybill{}
  544. IceRaftSvc := service.IceRaft{}
  545. req := dto.WaybillDeliveryReq{}
  546. err := e.MakeContext(c).
  547. MakeOrm().
  548. Bind(&req).
  549. MakeService(&s.Service).
  550. MakeService(&IceRaftSvc.Service).
  551. Errors
  552. if err != nil {
  553. e.Logger.Error(err)
  554. e.Error(500, err, err.Error())
  555. return
  556. }
  557. p := actions.GetPermissionFromContext(c)
  558. oldIceRaftCode := make([]string, 0)
  559. missingIceRaftCode := make([]string, 0)
  560. err = IceRaftSvc.GetPageByCoolerBoxId(req.CoolerBoxId, &oldIceRaftCode, p)
  561. if err != nil {
  562. e.Error(500, err, err.Error())
  563. return
  564. }
  565. req.SetUpdateBy(user.GetUserId(c))
  566. req.OldIceRaftCode = oldIceRaftCode
  567. err = s.Delivery(&req, p)
  568. if err != nil {
  569. e.Error(500, err, err.Error())
  570. return
  571. }
  572. missingIceRaftCode = lib.FindStrListMissingData(oldIceRaftCode, req.IceRaftCode)
  573. if len(missingIceRaftCode) > 0 {
  574. c.JSON(200, map[string]interface{}{
  575. "requestId": uuid.NewUUID(),
  576. "code": 2000,
  577. "msg": "派单成功",
  578. "status": "success",
  579. "data": missingIceRaftCode,
  580. })
  581. return
  582. }
  583. e.OK(req.GetId(), "派单成功")
  584. }
  585. // Delete 删除运单
  586. // @Summary 删除运单
  587. // @Description 删除运单
  588. // @Tags 运单
  589. // @Accept application/json
  590. // @Product application/json
  591. // @Param data body dto.WaybillDeleteReq true "body"
  592. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  593. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  594. // @Router /api/waybill [delete]
  595. // @Security Bearer
  596. func (e WaybillController) Delete(c *gin.Context) {
  597. s := service.Waybill{}
  598. req := dto.WaybillDeleteReq{}
  599. userSvc := service.SysUser{}
  600. err := e.MakeContext(c).
  601. MakeOrm().
  602. Bind(&req, binding.JSON, nil).
  603. MakeService(&s.Service).
  604. MakeService(&userSvc.Service).
  605. Errors
  606. if err != nil {
  607. e.Logger.Error(err)
  608. e.Error(500, err, err.Error())
  609. return
  610. }
  611. //数据权限检查
  612. p := actions.GetPermissionFromContext(c)
  613. err = s.Remove(&req, p)
  614. if err != nil {
  615. e.Error(500, err, err.Error())
  616. return
  617. }
  618. e.OK(req.GetId(), "删除成功")
  619. }
  620. // Receipt 签收
  621. // @Summary 签收
  622. // @Description 签收
  623. // @Tags 运单
  624. // @Accept application/json
  625. // @Product application/json
  626. // @Param data body dto.WaybillInOutReq true "body"
  627. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  628. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  629. // @Router /api/waybill/receipt [post]
  630. // @Security Bearer
  631. func (e WaybillController) Receipt(c *gin.Context) {
  632. s := service.Waybill{}
  633. req := dto.WaybillReceiptReq{}
  634. err := e.MakeContext(c).
  635. MakeOrm().
  636. Bind(&req, binding.JSON, nil).
  637. MakeService(&s.Service).
  638. Errors
  639. if err != nil {
  640. e.Logger.Error(err)
  641. e.Error(500, err, err.Error())
  642. return
  643. }
  644. //数据权限检查
  645. p := actions.GetPermissionFromContext(c)
  646. err = s.Receipt(&req, p)
  647. if err != nil {
  648. e.Error(500, err, err.Error())
  649. return
  650. }
  651. e.OK(req.WaybillNo, "签收成功")
  652. }
  653. // CustomerReceipt 客户签收
  654. // @Summary 客户签收
  655. // @Description 客户签收
  656. // @Tags 运单
  657. // @Accept application/json
  658. // @Product application/json
  659. // @Param data body dto.WaybillReceiptReq true "body"
  660. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  661. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  662. // @Router /api/waybill/customer/receipt [post]
  663. // @Security Bearer
  664. func (e WaybillController) CustomerReceipt(c *gin.Context) {
  665. s := service.Waybill{}
  666. req := dto.WaybillReceiptReq{}
  667. err := e.MakeContext(c).
  668. MakeOrm().
  669. Bind(&req, binding.JSON, nil).
  670. MakeService(&s.Service).
  671. Errors
  672. if err != nil {
  673. e.Logger.Error(err)
  674. e.Error(500, err, err.Error())
  675. return
  676. }
  677. //req.WaybillNo = lib.AesDecryptCBC(req.WaybillNo, lib.AesKey)
  678. //数据权限检查
  679. err = s.Receipt(&req, nil)
  680. if err != nil {
  681. e.Error(500, err, err.Error())
  682. return
  683. }
  684. e.OK(req.WaybillNo, "签收成功")
  685. }
  686. // GetCustomerPage 获取客户运单列表
  687. // @Summary 获取客户运单列表
  688. // @Description 获取客户运单列表
  689. // @Tags 运单
  690. // @Param waybillNo query string false "运单号"
  691. // @Param orderNo query string false "订单号"
  692. // @Param status query int false "状态"
  693. // @Param orderStartTime query string false "下单开始时间"
  694. // @Param orderEndTime query string false "下单结束时间"
  695. // @Param pageSize query int false "页条数"
  696. // @Param page query int false "页码"
  697. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  698. // @Router /api/waybill/customer [get]
  699. // @Security Bearer
  700. func (e WaybillController) GetCustomerPage(c *gin.Context) {
  701. s := service.Waybill{}
  702. req := dto.WaybillGetCustomerPageReq{}
  703. err := e.MakeContext(c).
  704. MakeOrm().
  705. Bind(&req, binding.Query).
  706. MakeService(&s.Service).
  707. Errors
  708. if err != nil {
  709. e.Logger.Error(err)
  710. e.Error(500, err, err.Error())
  711. return
  712. }
  713. //数据权限检查
  714. p := actions.GetPermissionFromContext(c)
  715. list := make([]model.Waybill, 0)
  716. var count int64
  717. req.CustomerId = p.UserId
  718. err = s.GetCustomerPage(&req, &list, &count, p)
  719. if err != nil {
  720. e.Error(500, err, err.Error())
  721. return
  722. }
  723. e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
  724. }
  725. // CustomerExport 导出客户运单列表
  726. // @Summary 导出客户运单列表
  727. // @Description 导出客户运单列表
  728. // @Tags 运单
  729. // @Param waybillNo query string false "运单号"
  730. // @Param orderNo query string false "订单号"
  731. // @Param status query int false "状态"
  732. // @Param orderStartTime query string false "下单开始时间"
  733. // @Param orderEndTime query string false "下单结束时间"
  734. // @Param pageSize query int false "页条数"
  735. // @Param page query int false "页码"
  736. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  737. // @Router /api/waybill/customer/export [get]
  738. // @Security Bearer
  739. func (e WaybillController) CustomerExport(c *gin.Context) {
  740. s := service.Waybill{}
  741. req := dto.WaybillGetCustomerPageReq{}
  742. err := e.MakeContext(c).
  743. MakeOrm().
  744. Bind(&req, binding.Query).
  745. MakeService(&s.Service).
  746. Errors
  747. if err != nil {
  748. e.Logger.Error(err)
  749. e.Error(500, err, err.Error())
  750. return
  751. }
  752. //数据权限检查
  753. p := actions.GetPermissionFromContext(c)
  754. list := make([]model.Waybill, 0)
  755. var count int64
  756. req.CustomerId = p.UserId
  757. req.PageSize = 9999
  758. err = s.GetCustomerPage(&req, &list, &count, p)
  759. if err != nil {
  760. e.Error(500, err, err.Error())
  761. return
  762. }
  763. f := excelize.NewFile() // 设置单元格的值
  764. // 这里设置表头ÒÒ
  765. f.SetCellValue("Sheet1", "A1", "序号")
  766. f.SetCellValue("Sheet1", "B1", "状态")
  767. f.SetCellValue("Sheet1", "C1", "寄件人名称")
  768. f.SetCellValue("Sheet1", "D1", "寄件人电话")
  769. f.SetCellValue("Sheet1", "E1", "寄件人地址")
  770. f.SetCellValue("Sheet1", "F1", "收件人名称")
  771. f.SetCellValue("Sheet1", "G1", "收件人电话")
  772. f.SetCellValue("Sheet1", "H1", "收件人地址")
  773. f.SetCellValue("Sheet1", "I1", "配送人姓名")
  774. f.SetCellValue("Sheet1", "J1", "配送人电话")
  775. f.SetCellValue("Sheet1", "K1", "运输备注")
  776. // 设置列宽
  777. f.SetColWidth("Sheet1", "A", "A", 6)
  778. f.SetColWidth("Sheet1", "B", "B", 8)
  779. f.SetColWidth("Sheet1", "C", "C", 14)
  780. f.SetColWidth("Sheet1", "D", "D", 14)
  781. f.SetColWidth("Sheet1", "E", "E", 30)
  782. f.SetColWidth("Sheet1", "F", "F", 14)
  783. f.SetColWidth("Sheet1", "G", "G", 14)
  784. f.SetColWidth("Sheet1", "H", "H", 30)
  785. f.SetColWidth("Sheet1", "I", "I", 15)
  786. f.SetColWidth("Sheet1", "J", "J", 15)
  787. f.SetColWidth("Sheet1", "K", "K", 15)
  788. line := 1
  789. // 循环写入数据
  790. for i, v := range list {
  791. line++
  792. f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), i+1)
  793. f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), model.WaybillStatusMap[v.Status])
  794. f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), v.SenderAddressName)
  795. f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.SenderAddressPhone)
  796. f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.SenderAddressDetails)
  797. f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.ConsigneeAddressName)
  798. f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v.ConsigneeAddressPhone)
  799. f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.ConsigneeAddressDetails)
  800. f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v.DeliveryName)
  801. f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v.DeliveryPhone)
  802. f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v.Remark)
  803. }
  804. timeStr := time.Now().Format("20060102150405")
  805. filePath := "ofile/" + "运单" + timeStr + ".xlsx"
  806. defer func() {
  807. os.Remove(filePath)
  808. }()
  809. // 保存文件
  810. if err = f.SaveAs(filePath); err != nil {
  811. logs.Error("保存运单失败:", err)
  812. }
  813. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  814. // PathEscape 函数对中文做处理
  815. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape("运单"+timeStr+".xlsx"))
  816. c.Header("Content-Transfer-Encoding", "binary")
  817. c.File(filePath)
  818. }
  819. // CustomerInsert 客户添加运单
  820. // @Summary 客户添加运单
  821. // @Description 客户添加运单
  822. // @Tags 运单
  823. // @Accept application/json
  824. // @Product application/json
  825. // @Param data body dto.WaybillInsertReq true "data"
  826. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  827. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  828. // @Router /api/waybill/customer [post]
  829. // @Security Bearer
  830. func (e WaybillController) CustomerInsert(c *gin.Context) {
  831. s := service.Waybill{}
  832. userSvc := service.SysUser{}
  833. req := dto.WaybillInsertReq{}
  834. err := e.MakeContext(c).
  835. MakeOrm().
  836. Bind(&req, binding.JSON).
  837. MakeService(&s.Service).
  838. MakeService(&userSvc.Service).
  839. Errors
  840. if err != nil {
  841. e.Logger.Error(err)
  842. e.Error(500, err, err.Error())
  843. return
  844. }
  845. p := actions.GetPermissionFromContext(c)
  846. var userObj model.SysUser
  847. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  848. if err != nil {
  849. e.Error(500, err, "获取用户信息失败")
  850. return
  851. }
  852. if p.DeptId == 0 && req.DeptId == 0 {
  853. e.Error(500, err, "请先选择运输公司")
  854. return
  855. }
  856. // 设置创建人
  857. req.SetCreateBy(user.GetUserId(c))
  858. if p.DeptId > 0 {
  859. req.SetDeptId(p.DeptId)
  860. }
  861. err = s.Insert(&req)
  862. if err != nil {
  863. e.Error(500, err, err.Error())
  864. return
  865. }
  866. e.OK(req.GetId(), "添加成功")
  867. }
  868. // Import 导入运单
  869. // @Summary 导入运单
  870. // @Description 导入运单
  871. // @Tags 运单
  872. // @Accept application/json
  873. // @Product application/json
  874. // @Param data body dto.WaybillImportReq true "data"
  875. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  876. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  877. // @Router /api/waybill/import [post]
  878. // @Security Bearer
  879. func (e WaybillController) Import(c *gin.Context) {
  880. s := service.Waybill{}
  881. userSvc := service.SysUser{}
  882. req := dto.WaybillImportReq{}
  883. err := e.MakeContext(c).
  884. MakeOrm().
  885. Bind(&req, binding.Form).
  886. MakeService(&s.Service).
  887. MakeService(&userSvc.Service).
  888. Errors
  889. if err != nil {
  890. e.Logger.Error(err)
  891. e.Error(500, err, err.Error())
  892. return
  893. }
  894. //读取第一fileName的文件
  895. fileHeader, err := c.FormFile("file")
  896. if err != nil {
  897. err = errors.New("文件格式错误" + err.Error())
  898. e.Logger.Error(err)
  899. e.Error(500, err, err.Error())
  900. return
  901. }
  902. if fileHeader.Size > 1024*1024*2 {
  903. err = errors.New("文件大小超过2M")
  904. e.Logger.Error(err)
  905. e.Error(500, err, err.Error())
  906. return
  907. }
  908. file, err := fileHeader.Open()
  909. if err != nil {
  910. err = errors.New("文件格式错误" + err.Error())
  911. e.Logger.Error(err)
  912. e.Error(500, err, err.Error())
  913. return
  914. }
  915. defer file.Close()
  916. xlsx, err := excelize.OpenReader(bufio.NewReader(file))
  917. if err != nil {
  918. err = errors.New("文件格式错误" + err.Error())
  919. e.Logger.Error(err)
  920. e.Error(500, err, err.Error())
  921. return
  922. }
  923. p := actions.GetPermissionFromContext(c)
  924. if p.DeptId == 0 {
  925. e.Error(500, err, "获取用户信息失败")
  926. return
  927. }
  928. var userObj model.SysUser
  929. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  930. if err != nil {
  931. e.Error(500, err, "获取用户信息失败")
  932. return
  933. }
  934. rows, _ := xlsx.GetRows("Sheet1")
  935. for indexRow, row := range rows {
  936. if indexRow == 0 {
  937. continue
  938. }
  939. if len(row) < 10 {
  940. for i := 0; i < 10-len(row); i++ {
  941. row = append(row, "")
  942. }
  943. }
  944. for i, colCell := range row {
  945. fmt.Println(i, ":", colCell)
  946. }
  947. //quantity, _ := strconv.Atoi(row[8])
  948. obj := dto.WaybillInsertReq{
  949. Status: 1,
  950. ConsigneeAddressName: row[0],
  951. ConsigneeAddressPhone: row[1],
  952. ConsigneeAddressDetails: row[2],
  953. TamperProofLabel: row[3], // 防拆标签
  954. Remark: row[4],
  955. ReCheckId: p.UserId,
  956. DeliveryId: p.UserId,
  957. }
  958. obj.SetDeptId(p.DeptId)
  959. obj.SetCreateBy(user.GetUserId(c))
  960. err = s.Insert(&obj)
  961. if err != nil {
  962. e.Error(500, err, err.Error())
  963. return
  964. }
  965. }
  966. e.OK(len(rows)-1, "导入成功")
  967. }
  968. // ExportTemplate 导出运单模板
  969. // @Summary 导出运单模板
  970. // @Description 导出运单模板
  971. // @Tags 运单
  972. // @Accept application/json
  973. // @Product application/json
  974. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  975. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  976. // @Router /api/waybill/export-template [get]
  977. // @Security Bearer
  978. func (e WaybillController) ExportTemplate(c *gin.Context) {
  979. s := service.Waybill{}
  980. err := e.MakeContext(c).
  981. MakeOrm().
  982. MakeService(&s.Service).
  983. Errors
  984. if err != nil {
  985. e.Logger.Error(err)
  986. e.Error(500, err, err.Error())
  987. return
  988. }
  989. filePath := "./ofile/运单导入模板.xlsx"
  990. //打开文件
  991. fileTmp, errByOpenFile := os.Open(filePath)
  992. defer fileTmp.Close()
  993. //获取文件的名称
  994. fileName := path.Base(filePath)
  995. if errByOpenFile != nil {
  996. e.Logger.Error(err)
  997. e.Error(500, err, err.Error())
  998. return
  999. }
  1000. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  1001. // PathEscape 函数对中文做处理
  1002. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(fileName))
  1003. c.Header("Content-Transfer-Encoding", "binary")
  1004. c.File(filePath)
  1005. }
  1006. // TemperaturePDF 导出温度记录
  1007. // @Summary 导出温度记录
  1008. // @Description 导出温度记录
  1009. // @Tags 运单
  1010. // @Accept application/json
  1011. // @Product application/json
  1012. // @Param data body dto.WaybillGetByWaybillPdfReq true "data"
  1013. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  1014. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  1015. // @Router /api/waybill/temperature-pdf [get]
  1016. // @Security Bearer
  1017. func (e WaybillController) TemperaturePDF(c *gin.Context) {
  1018. s := service.Waybill{}
  1019. req := dto.WaybillGetByWaybillPdfReq{}
  1020. err := e.MakeContext(c).
  1021. MakeOrm().
  1022. Bind(&req, binding.Query).
  1023. MakeService(&s.Service).
  1024. Errors
  1025. if err != nil {
  1026. e.Logger.Error(err)
  1027. e.Error(500, err, err.Error())
  1028. return
  1029. }
  1030. var waybill model.Waybill
  1031. //p := actions.GetPermissionFromContext(c)
  1032. //err = s.GetByWaybillNo(&req, &waybill, p)
  1033. err = s.GetByWaybillNo(&req, &waybill, nil)
  1034. if err != nil {
  1035. e.Error(500, err, err.Error())
  1036. return
  1037. }
  1038. DeviceSensor_data, waybillPDF, err := s.GetAllData(&dto.WaybillGetByWaybillNoReq{WaybillNo: req.WaybillNo})
  1039. // 最高温度、最低温度、最高湿度、最低湿度
  1040. var maxTemp, minTemp, maxHumidity, minHumidity float32
  1041. // 最高温度时间、最低温度时间、最高湿度时间、最低湿度时间
  1042. var maxTempTime, minTempTime, maxHumidityTime, minHumidityTime string
  1043. // 总温度 总湿度
  1044. var totalTemp, totalHumidity float32
  1045. // 平均温度 平均湿度
  1046. var avgTemp, avgHumidity float32
  1047. // 温度阈值,湿度阈值
  1048. var tempThreshold, humidityThreshold string
  1049. // 记录开始时间,记录结束时间
  1050. var s_time, e_time string
  1051. var lastTime string
  1052. var isFirst, isSecond = true, false
  1053. var first_column, second_column []nats_server.DeviceData_R
  1054. if len(DeviceSensor_data) > 0 {
  1055. tempThreshold = fmt.Sprintf("%.1f-%.1f", DeviceSensor_data[0].T_tl, DeviceSensor_data[0].T_tu)
  1056. humidityThreshold = fmt.Sprintf("%.1f-%.1f", DeviceSensor_data[0].T_rhl, DeviceSensor_data[0].T_rhu)
  1057. s_time = DeviceSensor_data[0].T_time
  1058. e_time = DeviceSensor_data[len(DeviceSensor_data)-1].T_time
  1059. // 最高温度及时刻
  1060. maxTemp = DeviceSensor_data[0].T_t
  1061. maxTempTime = DeviceSensor_data[0].T_time
  1062. // 最低温度及时刻
  1063. minTemp = DeviceSensor_data[0].T_t
  1064. minTempTime = DeviceSensor_data[0].T_time
  1065. // 最高湿度及时刻
  1066. maxHumidity = DeviceSensor_data[0].T_rh
  1067. maxHumidityTime = DeviceSensor_data[0].T_time
  1068. // 获取最低湿度及时刻
  1069. minHumidity = DeviceSensor_data[0].T_rh
  1070. minHumidityTime = DeviceSensor_data[0].T_time
  1071. for i := 0; i < len(DeviceSensor_data); i++ {
  1072. data := DeviceSensor_data[i]
  1073. if data.T_t > maxTemp {
  1074. maxTemp = data.T_t
  1075. maxTempTime = data.T_time
  1076. }
  1077. if data.T_t < minTemp {
  1078. minTemp = data.T_t
  1079. minTempTime = data.T_time
  1080. }
  1081. totalTemp += data.T_t
  1082. if data.T_rh > maxHumidity {
  1083. maxHumidity = data.T_rh
  1084. maxHumidityTime = data.T_time
  1085. }
  1086. if data.T_rh < minHumidity {
  1087. minHumidity = data.T_rh
  1088. minHumidityTime = data.T_time
  1089. }
  1090. totalHumidity += data.T_rh
  1091. }
  1092. var sn string
  1093. for _, w := range waybillPDF {
  1094. for _, data := range w.Data {
  1095. if len(lastTime) > 0 {
  1096. if lastTime != data.T_time && isFirst == true {
  1097. isFirst = false
  1098. isSecond = true
  1099. } else if lastTime != data.T_time && isSecond == true {
  1100. isFirst = true
  1101. isSecond = false
  1102. }
  1103. }
  1104. if len(sn) > 0 && sn != data.T_sn && len(first_column)%2 == 1 {
  1105. isFirst, isSecond = isSecond, isFirst
  1106. }
  1107. if isFirst {
  1108. first_column = append(first_column, data)
  1109. lastTime = data.T_time
  1110. sn = data.T_sn
  1111. }
  1112. if isSecond {
  1113. second_column = append(second_column, data)
  1114. lastTime = data.T_time
  1115. sn = data.T_sn
  1116. }
  1117. }
  1118. }
  1119. // 平均温度
  1120. avgTemp = totalTemp / float32(len(DeviceSensor_data))
  1121. // 平均湿度
  1122. avgHumidity = totalHumidity / float32(len(DeviceSensor_data))
  1123. }
  1124. // -------------------获取最高温湿度、温蒂温湿度、平均温湿度结束
  1125. pdf := &gopdf.GoPdf{}
  1126. pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
  1127. err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
  1128. if err != nil {
  1129. return
  1130. }
  1131. err = pdf.SetFont("wts", "", 20)
  1132. if err != nil {
  1133. return
  1134. }
  1135. pdf.SetGrayFill(0.5)
  1136. pdf.SetMargins(0, 20, 0, 20)
  1137. pdf.AddPage()
  1138. title := "运单" + req.WaybillNo + "温度记录"
  1139. if req.HumidityShow {
  1140. title = "运单" + req.WaybillNo + "温湿度记录"
  1141. }
  1142. var y float64 = 40
  1143. textw, _ := pdf.MeasureTextWidth(title)
  1144. pdf.SetX((595 / 2) - (textw / 2))
  1145. pdf.SetY(y)
  1146. pdf.Text(title)
  1147. //y += 30
  1148. //pdf.SetFont("wts", "", 16)
  1149. //pdf.SetXY(10, y)
  1150. //pdf.Text("实施设备信息")
  1151. //// 线
  1152. //y += 10
  1153. //pdf.SetLineWidth(0.5)
  1154. //pdf.SetStrokeColor(169, 169, 169)
  1155. //pdf.Line(10, y, 585, y)
  1156. //pdf.SetFont("wts", "", 10)
  1157. //y += 20
  1158. //pdf.SetXY(10, y)
  1159. //pdf.Text(fmt.Sprintf("主机名称:%s", device.T_devName))
  1160. //pdf.SetXY(300, y)
  1161. //pdf.Text(fmt.Sprintf("主机编号:%s", device.T_sn))
  1162. y += 25
  1163. pdf.SetFont("wts", "", 16)
  1164. pdf.SetXY(10, y)
  1165. pdf.Text("记录概要信息")
  1166. // 线
  1167. y += 10
  1168. pdf.SetLineWidth(0.5)
  1169. pdf.SetStrokeColor(169, 169, 169)
  1170. pdf.Line(10, y, 585, y)
  1171. y += 20
  1172. pdf.SetFont("wts", "", 10)
  1173. pdf.SetXY(10, y)
  1174. pdf.Text(fmt.Sprintf("记录开始时间:%s", s_time))
  1175. pdf.SetXY(240, y)
  1176. pdf.Text(fmt.Sprintf("记录结束时间:%s", e_time))
  1177. sTime, _ := lib.TimeStrToTime(s_time)
  1178. eTime, _ := lib.TimeStrToTime(e_time)
  1179. pdf.SetXY(470, y)
  1180. minutes := int(eTime.Sub(sTime).Minutes())
  1181. hours := minutes / 60
  1182. remainingMinutes := minutes % 60
  1183. pdf.Text(fmt.Sprintf("记录总时间:%dh%dmin", hours, remainingMinutes))
  1184. // -------------最高温/湿度 最低温/湿度 平均温/湿度
  1185. y += 15
  1186. pdf.SetXY(10, y)
  1187. pdf.Text(fmt.Sprintf("最高温度:%.1f℃,%s", lib.RoundToDecimal(float64(maxTemp), 1), maxTempTime))
  1188. pdf.SetXY(240, y)
  1189. pdf.Text(fmt.Sprintf("最低温度:%.1f℃,%s", lib.RoundToDecimal(float64(minTemp), 1), minTempTime))
  1190. pdf.SetXY(470, y)
  1191. pdf.Text(fmt.Sprintf("平均温度:%.1f℃", lib.RoundToDecimal(float64(avgTemp), 1)))
  1192. if req.HumidityShow {
  1193. y += 15
  1194. pdf.SetXY(10, y)
  1195. pdf.Text(fmt.Sprintf("最高湿度:%.1f%%RH,%s", lib.RoundToDecimal(float64(maxHumidity), 1), maxHumidityTime))
  1196. pdf.SetXY(240, y)
  1197. pdf.Text(fmt.Sprintf("最低湿度:%.1f%%RH,%s", lib.RoundToDecimal(float64(minHumidity), 1), minHumidityTime))
  1198. pdf.SetXY(470, y)
  1199. pdf.Text(fmt.Sprintf("平均湿度:%.1f%%RH", lib.RoundToDecimal(float64(avgHumidity), 1)))
  1200. }
  1201. // -------------温/湿度阈值
  1202. y += 15
  1203. pdf.SetXY(10, y)
  1204. pdf.Text(fmt.Sprintf("温度阈值:%s℃", tempThreshold))
  1205. if req.HumidityShow {
  1206. pdf.SetXY(240, y)
  1207. pdf.Text(fmt.Sprintf("温度阈值:%s%%", humidityThreshold))
  1208. }
  1209. //-------------发货单位,收货单位,备注
  1210. y += 15
  1211. pdf.SetXY(10, y)
  1212. T_forwarding_unit_temp := []rune(waybill.SenderAddressName)
  1213. if len(T_forwarding_unit_temp) > 17 {
  1214. pdf.Text(fmt.Sprintf("发货人:%s", string(T_forwarding_unit_temp[0:17])))
  1215. pdf.SetXY(60, y+15)
  1216. pdf.Text(fmt.Sprintf("%s", string(T_forwarding_unit_temp[17:])))
  1217. } else {
  1218. pdf.Text(fmt.Sprintf("发货人:%s", string(T_forwarding_unit_temp)))
  1219. }
  1220. pdf.SetXY(240, y)
  1221. T_consignee_unit_temp := []rune(waybill.ConsigneeAddressName)
  1222. if len(T_consignee_unit_temp) > 17 {
  1223. pdf.Text(fmt.Sprintf("收货人:%s", string(T_consignee_unit_temp[0:17])))
  1224. pdf.SetXY(290, y+15)
  1225. pdf.Text(fmt.Sprintf("%s", string(T_consignee_unit_temp[17:])))
  1226. } else {
  1227. pdf.Text(fmt.Sprintf("收货人:%s", string(T_consignee_unit_temp)))
  1228. }
  1229. // 承运方
  1230. y += 15
  1231. pdf.SetXY(10, y)
  1232. company_name := []rune(waybill.Dept.Name)
  1233. pdf.Text(fmt.Sprintf("承运方:%s", string(company_name)))
  1234. y += 15
  1235. pdf.SetXY(10, y)
  1236. T_remark_temp := []rune(waybill.Remark)
  1237. if len(waybill.Remark) > 35 {
  1238. pdf.Text(fmt.Sprintf("备注:%s", string(T_remark_temp[0:35])))
  1239. pdf.SetXY(10, y+15)
  1240. pdf.Text(fmt.Sprintf("%s", string(T_remark_temp[35:])))
  1241. } else {
  1242. pdf.Text(fmt.Sprintf("备注: %s", string(T_remark_temp)))
  1243. }
  1244. y += 15
  1245. //pdf.SetFont("wts", "", 16)
  1246. //pdf.SetXY(10, y)
  1247. //pdf.Text("记录曲线信息")
  1248. //// 线
  1249. //y += 10
  1250. //pdf.SetLineWidth(0.5)
  1251. //pdf.SetStrokeColor(169, 169, 169)
  1252. //pdf.Line(10, y, 585, y)
  1253. //y += 1
  1254. //
  1255. //var tempFilepath string
  1256. //tempFilepath, err = DeviceDataTemperatureJPG2(s_time, e_time, waybillPDF)
  1257. //if err == nil {
  1258. // imgH, _ := gopdf.ImageHolderByPath(tempFilepath)
  1259. // pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 315})
  1260. // y += 315
  1261. //}
  1262. //
  1263. //var humidityFilepath string
  1264. //if req.HumidityShow {
  1265. // humidityFilepath, err = DeviceDataHumidityJPG2(s_time, e_time, waybillPDF)
  1266. // if err == nil {
  1267. // imgH, _ := gopdf.ImageHolderByPath(humidityFilepath)
  1268. // pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 315})
  1269. // y += 315
  1270. // }
  1271. //}
  1272. if y > 841.89 {
  1273. // 图片结束直接分页
  1274. pdf.AddPage()
  1275. y = 20
  1276. }
  1277. y += 20
  1278. pdf.SetFont("wts", "", 16)
  1279. pdf.SetXY(10, y)
  1280. pdf.Text("记录数据信息")
  1281. // 线
  1282. y += 10
  1283. pdf.SetLineWidth(0.5)
  1284. pdf.SetStrokeColor(169, 169, 169)
  1285. pdf.Line(10, y, 585, y)
  1286. y += 10
  1287. pdf.SetFont("wts", "", 10)
  1288. var x float64 = 10
  1289. var w float64 = 112
  1290. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1291. x = x + w
  1292. w = 101
  1293. lib.RectFillColor(pdf, "名称", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1294. if req.HumidityShow {
  1295. x = x + w
  1296. w = 37
  1297. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1298. x = x + w
  1299. w = 37
  1300. lib.RectFillColor(pdf, "湿度%", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1301. } else {
  1302. x = x + w
  1303. w = 37 * 2
  1304. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1305. }
  1306. x = x + w
  1307. w = 112
  1308. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1309. x = x + w
  1310. w = 101
  1311. lib.RectFillColor(pdf, "名称", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1312. if req.HumidityShow {
  1313. x = x + w
  1314. w = 37
  1315. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1316. x = x + w
  1317. w = 37
  1318. lib.RectFillColor(pdf, "湿度%", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1319. } else {
  1320. x = x + w
  1321. w = 37 * 2
  1322. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1323. }
  1324. y += 20
  1325. var textH float64 = 25 // if text height is 25px.
  1326. for i, v := range first_column {
  1327. pdf.SetNewY(y, textH)
  1328. y = pdf.GetY()
  1329. x, w = 10, 112
  1330. lib.RectFillColor(pdf, v.T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1331. x = x + w
  1332. w = 101
  1333. lib.RectFillColor(pdf, v.T_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1334. // 显示温湿度
  1335. if req.HumidityShow {
  1336. x = x + w
  1337. w = 37
  1338. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", v.T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1339. x = x + w
  1340. w = 37
  1341. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", v.T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1342. } else {
  1343. x = x + w
  1344. w = 37 * 2
  1345. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", v.T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1346. }
  1347. if i < len(second_column) {
  1348. x = x + w
  1349. w = 112
  1350. lib.RectFillColor(pdf, second_column[i].T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1351. x = x + w
  1352. w = 101
  1353. lib.RectFillColor(pdf, second_column[i].T_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1354. if req.HumidityShow {
  1355. x = x + w
  1356. w = 37
  1357. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1358. x = x + w
  1359. w = 37
  1360. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1361. } else {
  1362. x = x + w
  1363. w = 37 * 2
  1364. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1365. }
  1366. }
  1367. y += 20
  1368. }
  1369. if len(second_column) > len(first_column) {
  1370. for i := len(first_column); i < len(second_column); i++ {
  1371. pdf.SetNewY(y, textH)
  1372. y = pdf.GetY()
  1373. x, w = 297, 112
  1374. lib.RectFillColor(pdf, second_column[i].T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1375. x = x + w
  1376. w = 101
  1377. lib.RectFillColor(pdf, second_column[i].T_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1378. if req.HumidityShow {
  1379. x = x + w
  1380. w = 37
  1381. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1382. x = x + w
  1383. w = 37
  1384. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1385. } else {
  1386. x = x + w
  1387. w = 37 * 2
  1388. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1389. }
  1390. y += 20
  1391. }
  1392. }
  1393. filename := "运单" + req.WaybillNo + "温湿度记录" + time.Now().Format("20060102150405") + ".pdf"
  1394. filePath := "ofile/" + filename
  1395. err = pdf.WritePdf(filePath)
  1396. if err != nil {
  1397. return
  1398. }
  1399. defer func() {
  1400. //os.Remove(tempFilepath)
  1401. //os.Remove(humidityFilepath)
  1402. os.Remove(filePath)
  1403. }()
  1404. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(filename))
  1405. c.Header("Content-Transfer-Encoding", "binary")
  1406. c.File(filePath)
  1407. }
  1408. // 获取温度图片
  1409. func DeviceDataTemperatureJPG(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  1410. if len(waybillPDF) == 0 {
  1411. return "", errors.New("暂无数据可生成图片")
  1412. }
  1413. // 创建一个新的绘图
  1414. p := plot.New()
  1415. // 设置绘图标题和标签
  1416. p.Title.Text = "temperature"
  1417. //p.Legend.ThumbnailWidth = 20
  1418. deviceSensorList := []nats_server.DeviceSensor_R{}
  1419. dataList := []nats_server.DeviceData_R{}
  1420. for _, w := range waybillPDF {
  1421. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  1422. dataList = append(dataList, w.Data...)
  1423. }
  1424. TemperatureMin := deviceSensorList[0].T_DeviceSensorParameter.T_Tlower
  1425. TemperatureMax := deviceSensorList[0].T_DeviceSensorParameter.T_Tupper
  1426. var ymin, ymax float32
  1427. for i, r := range dataList {
  1428. if i == 0 {
  1429. ymin = r.T_t
  1430. ymax = r.T_t
  1431. }
  1432. if ymin > r.T_t {
  1433. ymin = r.T_t
  1434. }
  1435. if ymax < r.T_t {
  1436. ymax = r.T_t
  1437. }
  1438. }
  1439. var chData = make(chan int, 10)
  1440. var jobGroup sync.WaitGroup
  1441. // 创建温度线
  1442. for i := 0; i < len(deviceSensorList); i++ {
  1443. chData <- 1
  1444. jobGroup.Add(1)
  1445. go func(index int) {
  1446. defer func() {
  1447. <-chData // 完成时chan取出1个
  1448. jobGroup.Done() // 完成时将等待组值减1
  1449. }()
  1450. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  1451. r_maps := []nats_server.DeviceData_R{}
  1452. for _, data := range dataList {
  1453. if data.T_sn == sn && data.T_id == id {
  1454. r_maps = append(r_maps, data)
  1455. }
  1456. }
  1457. fmt.Println(r_maps)
  1458. if len(r_maps) == 0 {
  1459. return
  1460. }
  1461. sort.Slice(r_maps, func(i, j int) bool {
  1462. return r_maps[i].T_time < r_maps[j].T_time
  1463. })
  1464. pts := make(plotter.XYs, len(r_maps))
  1465. for j, d := range r_maps {
  1466. t, _ := lib.TimeStrToTime(d.T_time)
  1467. pts[j].X = float64(t.Unix())
  1468. pts[j].Y = float64(d.T_t)
  1469. }
  1470. line, err := plotter.NewLine(pts)
  1471. if err != nil {
  1472. return
  1473. }
  1474. line.Color = randomColor(index)
  1475. p.Add(line)
  1476. }(i)
  1477. }
  1478. jobGroup.Wait()
  1479. st, _ := lib.TimeStrToTime(startTime)
  1480. et, _ := lib.TimeStrToTime(endTime)
  1481. xmin, xmax := float64(st.Unix()), float64(et.Unix())
  1482. // 添加最高,最低标准线 用红色虚线标识
  1483. p.Add(horizontalLine(xmin, xmax, float64(TemperatureMin)))
  1484. p.Add(horizontalLine(xmin, xmax, float64(TemperatureMax)))
  1485. if ymax < TemperatureMax {
  1486. ymax = TemperatureMax
  1487. }
  1488. if ymin > 0 {
  1489. ymin = 0
  1490. }
  1491. p.Y.Min, p.Y.Max = float64(ymin), float64(ymax)
  1492. p.X.Min, p.X.Max = xmin, xmax
  1493. p.Y.Tick.Marker = commaTicks{}
  1494. p.X.Tick.Marker = timeTicks{}
  1495. p.X.Tick.Label.Rotation = math.Pi / 5
  1496. p.X.Tick.Label.YAlign = draw.YCenter
  1497. p.X.Tick.Label.XAlign = draw.XRight
  1498. filepath := "ofile/" + "temperature" + deviceSensorList[0].T_sn + ".jpg"
  1499. // 保存文件
  1500. if err := p.Save(10*vg.Inch, 4*vg.Inch, filepath); err != nil {
  1501. logs.Error(lib.FuncName(), "生成图片失败", err)
  1502. return "", err
  1503. }
  1504. return filepath, nil
  1505. }
  1506. func DeviceDataTemperatureJPG2(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  1507. if len(waybillPDF) == 0 {
  1508. return "", errors.New("暂无数据可生成图片")
  1509. }
  1510. deviceSensorList := []nats_server.DeviceSensor_R{}
  1511. dataList := []nats_server.DeviceData_R{}
  1512. for _, w := range waybillPDF {
  1513. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  1514. dataList = append(dataList, w.Data...)
  1515. }
  1516. TemperatureMin := deviceSensorList[0].T_DeviceSensorParameter.T_Tlower
  1517. TemperatureMax := deviceSensorList[0].T_DeviceSensorParameter.T_Tupper
  1518. var ymin, ymax float32
  1519. for i, r := range dataList {
  1520. if i == 0 {
  1521. ymin = r.T_t
  1522. ymax = r.T_t
  1523. }
  1524. if ymin > r.T_t {
  1525. ymin = r.T_t
  1526. }
  1527. if ymax < r.T_t {
  1528. ymax = r.T_t
  1529. }
  1530. }
  1531. series := make([]chart.Series, 0)
  1532. var chData = make(chan int, 10)
  1533. var jobGroup sync.WaitGroup
  1534. // 创建温度线
  1535. for i := 0; i < len(deviceSensorList); i++ {
  1536. chData <- 1
  1537. jobGroup.Add(1)
  1538. go func(index int) {
  1539. defer func() {
  1540. <-chData // 完成时chan取出1个
  1541. jobGroup.Done() // 完成时将等待组值减1
  1542. }()
  1543. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  1544. r_maps := []nats_server.DeviceData_R{}
  1545. for _, data := range dataList {
  1546. if data.T_sn == sn && data.T_id == id {
  1547. r_maps = append(r_maps, data)
  1548. }
  1549. }
  1550. fmt.Println(r_maps)
  1551. if len(r_maps) == 0 {
  1552. return
  1553. }
  1554. sort.Slice(r_maps, func(i, j int) bool {
  1555. return r_maps[i].T_time < r_maps[j].T_time
  1556. })
  1557. xValues := make([]time.Time, len(r_maps))
  1558. yValues := make([]float64, len(r_maps))
  1559. for j := 0; j < len(r_maps); j++ {
  1560. t, _ := lib.TimeStrToTime(r_maps[j].T_time)
  1561. xValues[j] = t
  1562. yValues[j] = float64(r_maps[j].T_t)
  1563. }
  1564. series = append(series, chart.TimeSeries{
  1565. Name: fmt.Sprintf("%s-%d", sn, id),
  1566. XValues: xValues,
  1567. YValues: yValues,
  1568. })
  1569. }(i)
  1570. }
  1571. jobGroup.Wait()
  1572. if ymax < TemperatureMax {
  1573. ymax = TemperatureMax
  1574. }
  1575. if ymin > 0 {
  1576. ymin = 0
  1577. }
  1578. if ymin > TemperatureMin {
  1579. ymin = TemperatureMin
  1580. }
  1581. st, _ := lib.TimeStrToTime(startTime)
  1582. et, _ := lib.TimeStrToTime(endTime)
  1583. series = append(series, chart.TimeSeries{
  1584. Style: chart.Style{
  1585. StrokeColor: drawing.ColorRed,
  1586. StrokeDashArray: []float64{5.0, 5.0},
  1587. },
  1588. XValues: []time.Time{st, et},
  1589. YValues: []float64{float64(TemperatureMin), float64(TemperatureMin)},
  1590. })
  1591. series = append(series, chart.TimeSeries{
  1592. Style: chart.Style{
  1593. StrokeColor: drawing.ColorRed,
  1594. StrokeDashArray: []float64{5.0, 5.0},
  1595. },
  1596. XValues: []time.Time{st, et},
  1597. YValues: []float64{float64(TemperatureMax), float64(TemperatureMax)},
  1598. })
  1599. font := getZWFont()
  1600. graph := chart.Chart{
  1601. Title: "温度记录",
  1602. TitleStyle: chart.Style{
  1603. FontSize: 15,
  1604. },
  1605. Background: chart.Style{
  1606. Padding: chart.Box{
  1607. Top: 20,
  1608. },
  1609. },
  1610. Font: font,
  1611. XAxis: chart.XAxis{
  1612. Name: "时间",
  1613. ValueFormatter: chart.TimeValueFormatterWithFormat("2006-01-02 15:04"),
  1614. },
  1615. YAxis: chart.YAxis{
  1616. Name: "温度",
  1617. Range: &chart.ContinuousRange{
  1618. Min: float64(ymin),
  1619. Max: float64(ymax + 2),
  1620. },
  1621. },
  1622. Series: series,
  1623. }
  1624. //graph.Elements = []chart.Renderable{
  1625. // chart.Legend(&graph),
  1626. //}
  1627. filepath := "ofile/" + "temperature" + deviceSensorList[0].T_sn + ".jpg"
  1628. f, _ := os.Create(filepath)
  1629. defer f.Close()
  1630. graph.Render(chart.PNG, f)
  1631. return filepath, nil
  1632. }
  1633. // 获取湿度图片
  1634. func DeviceDataHumidityJPG(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  1635. if len(waybillPDF) == 0 {
  1636. return "", errors.New("暂无数据可生成图片")
  1637. }
  1638. // 创建一个新的绘图
  1639. p := plot.New()
  1640. // 设置绘图标题和标签
  1641. p.Title.Text = "humidity"
  1642. deviceSensorList := []nats_server.DeviceSensor_R{}
  1643. dataList := []nats_server.DeviceData_R{}
  1644. for _, w := range waybillPDF {
  1645. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  1646. dataList = append(dataList, w.Data...)
  1647. }
  1648. humidityMin := deviceSensorList[0].T_DeviceSensorParameter.T_RHlower
  1649. humidityMax := deviceSensorList[0].T_DeviceSensorParameter.T_RHupper
  1650. var ymin, ymax float32
  1651. for i, r := range dataList {
  1652. if i == 0 {
  1653. ymin = r.T_rh
  1654. ymax = r.T_rh
  1655. }
  1656. if ymin > r.T_rh {
  1657. ymin = r.T_rh
  1658. }
  1659. if ymax < r.T_rh {
  1660. ymax = r.T_rh
  1661. }
  1662. }
  1663. var chData = make(chan int, 10)
  1664. var jobGroup sync.WaitGroup
  1665. // 创建温度线
  1666. for i := 0; i < len(deviceSensorList); i++ {
  1667. chData <- 1
  1668. jobGroup.Add(1)
  1669. go func(index int) {
  1670. defer func() {
  1671. <-chData // 完成时chan取出1个
  1672. jobGroup.Done() // 完成时将等待组值减1
  1673. }()
  1674. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  1675. r_maps := []nats_server.DeviceData_R{}
  1676. for _, data := range dataList {
  1677. if data.T_sn == sn && data.T_id == id {
  1678. r_maps = append(r_maps, data)
  1679. }
  1680. }
  1681. if len(r_maps) == 0 {
  1682. return
  1683. }
  1684. sort.Slice(r_maps, func(i, j int) bool {
  1685. return r_maps[i].T_time < r_maps[j].T_time
  1686. })
  1687. pts := make(plotter.XYs, len(r_maps))
  1688. for j, d := range r_maps {
  1689. t, _ := lib.TimeStrToTime(d.T_time)
  1690. pts[j].X = float64(t.Unix())
  1691. pts[j].Y = float64(d.T_rh)
  1692. }
  1693. line, err := plotter.NewLine(pts)
  1694. if err != nil {
  1695. return
  1696. }
  1697. line.Color = randomColor(index)
  1698. p.Add(line)
  1699. }(i)
  1700. }
  1701. jobGroup.Wait()
  1702. st, _ := lib.TimeStrToTime(startTime)
  1703. et, _ := lib.TimeStrToTime(endTime)
  1704. xmin, xmax := float64(st.Unix()), float64(et.Unix())
  1705. // 添加最高,最低标准线 用红色虚线标识
  1706. p.Add(horizontalLine(xmin, xmax, float64(humidityMin)))
  1707. p.Add(horizontalLine(xmin, xmax, float64(humidityMax)))
  1708. if ymax < humidityMax {
  1709. ymax = humidityMax
  1710. }
  1711. if ymin > 0 {
  1712. ymin = 0
  1713. }
  1714. p.Y.Min, p.Y.Max = float64(ymin), float64(ymax)
  1715. p.X.Min, p.X.Max = xmin, xmax
  1716. p.Y.Tick.Marker = commaTicks{}
  1717. //p.X.Tick.Marker = plot.TimeTicks{Format: "2006-01-02 15:04:05"}
  1718. p.X.Tick.Marker = timeTicks{}
  1719. p.X.Tick.Label.Rotation = math.Pi / 5
  1720. p.X.Tick.Label.YAlign = draw.YCenter
  1721. p.X.Tick.Label.XAlign = draw.XRight
  1722. filepath := "ofile/" + "humidity" + deviceSensorList[0].T_sn + ".jpg"
  1723. // 保存文件
  1724. if err := p.Save(10*vg.Inch, 4*vg.Inch, filepath); err != nil {
  1725. logs.Error(lib.FuncName(), "生成图片失败", err)
  1726. return "", err
  1727. }
  1728. return filepath, nil
  1729. }
  1730. func DeviceDataHumidityJPG2(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  1731. if len(waybillPDF) == 0 {
  1732. return "", errors.New("暂无数据可生成图片")
  1733. }
  1734. deviceSensorList := []nats_server.DeviceSensor_R{}
  1735. dataList := []nats_server.DeviceData_R{}
  1736. for _, w := range waybillPDF {
  1737. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  1738. dataList = append(dataList, w.Data...)
  1739. }
  1740. humidityMin := deviceSensorList[0].T_DeviceSensorParameter.T_RHlower
  1741. humidityMax := deviceSensorList[0].T_DeviceSensorParameter.T_RHupper
  1742. var ymin, ymax float32
  1743. for i, r := range dataList {
  1744. if i == 0 {
  1745. ymin = r.T_t
  1746. ymax = r.T_t
  1747. }
  1748. if ymin > r.T_t {
  1749. ymin = r.T_t
  1750. }
  1751. if ymax < r.T_t {
  1752. ymax = r.T_t
  1753. }
  1754. }
  1755. series := make([]chart.Series, 0)
  1756. var chData = make(chan int, 10)
  1757. var jobGroup sync.WaitGroup
  1758. // 创建温度线
  1759. for i := 0; i < len(deviceSensorList); i++ {
  1760. chData <- 1
  1761. jobGroup.Add(1)
  1762. go func(index int) {
  1763. defer func() {
  1764. <-chData // 完成时chan取出1个
  1765. jobGroup.Done() // 完成时将等待组值减1
  1766. }()
  1767. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  1768. r_maps := []nats_server.DeviceData_R{}
  1769. for _, data := range dataList {
  1770. if data.T_sn == sn && data.T_id == id {
  1771. r_maps = append(r_maps, data)
  1772. }
  1773. }
  1774. if len(r_maps) == 0 {
  1775. return
  1776. }
  1777. sort.Slice(r_maps, func(i, j int) bool {
  1778. return r_maps[i].T_time < r_maps[j].T_time
  1779. })
  1780. xValues := make([]time.Time, len(r_maps))
  1781. yValues := make([]float64, len(r_maps))
  1782. for j := 0; j < len(r_maps); j++ {
  1783. t, _ := lib.TimeStrToTime(r_maps[j].T_time)
  1784. xValues[j] = t
  1785. yValues[j] = float64(r_maps[j].T_rh)
  1786. }
  1787. series = append(series, chart.TimeSeries{
  1788. Name: fmt.Sprintf("%s-%d", sn, id),
  1789. XValues: xValues,
  1790. YValues: yValues,
  1791. })
  1792. }(i)
  1793. }
  1794. jobGroup.Wait()
  1795. if ymax < humidityMax {
  1796. ymax = humidityMax
  1797. }
  1798. if ymin > 0 {
  1799. ymin = 0
  1800. }
  1801. if ymin > humidityMin {
  1802. ymin = humidityMin
  1803. }
  1804. st, _ := lib.TimeStrToTime(startTime)
  1805. et, _ := lib.TimeStrToTime(endTime)
  1806. series = append(series, chart.TimeSeries{
  1807. Style: chart.Style{
  1808. StrokeColor: drawing.ColorRed,
  1809. StrokeDashArray: []float64{5.0, 5.0},
  1810. },
  1811. XValues: []time.Time{st, et},
  1812. YValues: []float64{float64(humidityMin), float64(humidityMin)},
  1813. })
  1814. series = append(series, chart.TimeSeries{
  1815. Style: chart.Style{
  1816. StrokeColor: drawing.ColorRed,
  1817. StrokeDashArray: []float64{5.0, 5.0},
  1818. },
  1819. XValues: []time.Time{st, et},
  1820. YValues: []float64{float64(humidityMax), float64(humidityMax)},
  1821. })
  1822. font := getZWFont()
  1823. graph := chart.Chart{
  1824. Title: "湿度记录",
  1825. TitleStyle: chart.Style{
  1826. FontSize: 15,
  1827. },
  1828. Background: chart.Style{
  1829. Padding: chart.Box{
  1830. Top: 20,
  1831. },
  1832. },
  1833. Font: font,
  1834. XAxis: chart.XAxis{
  1835. Name: "时间",
  1836. ValueFormatter: chart.TimeValueFormatterWithFormat("2006-01-02 15:04"),
  1837. },
  1838. YAxis: chart.YAxis{
  1839. Name: "湿度",
  1840. Range: &chart.ContinuousRange{
  1841. Min: float64(ymin),
  1842. Max: float64(ymax + 2),
  1843. },
  1844. },
  1845. Series: series,
  1846. }
  1847. //graph.Elements = []chart.Renderable{
  1848. // chart.Legend(&graph),
  1849. //}
  1850. filepath := "ofile/" + "humidity" + deviceSensorList[0].T_sn + ".jpg"
  1851. f, _ := os.Create(filepath)
  1852. defer f.Close()
  1853. graph.Render(chart.PNG, f)
  1854. return filepath, nil
  1855. }
  1856. func horizontalLine(xmin, xmax, y float64) *plotter.Line {
  1857. pts := make(plotter.XYs, 2)
  1858. pts[0].X = xmin
  1859. pts[0].Y = y
  1860. pts[1].X = xmax
  1861. pts[1].Y = y
  1862. line, err := plotter.NewLine(pts)
  1863. if err != nil {
  1864. panic(err)
  1865. }
  1866. line.LineStyle.Dashes = []vg.Length{vg.Points(8), vg.Points(5), vg.Points(1), vg.Points(5)}
  1867. line.Color = color.RGBA{R: 255, A: 255}
  1868. return line
  1869. }
  1870. type timeTicks struct{}
  1871. func (timeTicks) Ticks(min, max float64) []plot.Tick {
  1872. tks := plot.TimeTicks{}.Ticks(min, max)
  1873. for i, t := range tks {
  1874. //if t.Label == "" { // Skip minor ticks, they are fine.
  1875. // continue
  1876. //}
  1877. tks[i].Label = time.Unix(int64(t.Value), 0).Format("2006-01-02 15:04:05")
  1878. }
  1879. return tks
  1880. }
  1881. type commaTicks struct{}
  1882. // Ticks computes the default tick marks, but inserts commas
  1883. // into the labels for the major tick marks.
  1884. func (commaTicks) Ticks(min, max float64) []plot.Tick {
  1885. tks := plot.DefaultTicks{}.Ticks(min, max)
  1886. for i, t := range tks {
  1887. //if t.Label == "" { // Skip minor ticks, they are fine.
  1888. // continue
  1889. //}
  1890. tks[i].Label = fmt.Sprintf("%.0f", t.Value)
  1891. }
  1892. return tks
  1893. }
  1894. // 生成随机颜色的辅助函数
  1895. func randomColor(i int) color.RGBA {
  1896. var colors []color.RGBA
  1897. colors = append(colors,
  1898. color.RGBA{R: 52, G: 152, B: 219, A: 255},
  1899. color.RGBA{R: 230, G: 126, B: 34, A: 255},
  1900. color.RGBA{R: 142, G: 68, B: 173, A: 255},
  1901. color.RGBA{R: 211, G: 84, B: 0, A: 255},
  1902. color.RGBA{R: 231, G: 76, B: 60, A: 255},
  1903. color.RGBA{R: 26, G: 188, B: 156, A: 255},
  1904. color.RGBA{R: 243, G: 156, B: 18, A: 255},
  1905. color.RGBA{R: 22, G: 160, B: 133, A: 255},
  1906. color.RGBA{R: 46, G: 204, B: 113, A: 255},
  1907. color.RGBA{R: 39, G: 174, B: 96, A: 255},
  1908. color.RGBA{R: 41, G: 128, B: 185, A: 255},
  1909. color.RGBA{R: 155, G: 89, B: 182, A: 255},
  1910. color.RGBA{R: 192, G: 57, B: 43, A: 255},
  1911. color.RGBA{R: 241, G: 196, B: 15, A: 255},
  1912. )
  1913. return colors[i%len(colors)]
  1914. }
  1915. func randomColor2(i int) drawing.Color {
  1916. var colors []drawing.Color
  1917. colors = append(colors,
  1918. drawing.Color{R: 52, G: 152, B: 219, A: 255},
  1919. drawing.Color{R: 230, G: 126, B: 34, A: 255},
  1920. drawing.Color{R: 142, G: 68, B: 173, A: 255},
  1921. drawing.Color{R: 211, G: 84, B: 0, A: 255},
  1922. drawing.Color{R: 231, G: 76, B: 60, A: 255},
  1923. drawing.Color{R: 26, G: 188, B: 156, A: 255},
  1924. drawing.Color{R: 243, G: 156, B: 18, A: 255},
  1925. drawing.Color{R: 22, G: 160, B: 133, A: 255},
  1926. drawing.Color{R: 46, G: 204, B: 113, A: 255},
  1927. drawing.Color{R: 39, G: 174, B: 96, A: 255},
  1928. drawing.Color{R: 41, G: 128, B: 185, A: 255},
  1929. drawing.Color{R: 155, G: 89, B: 182, A: 255},
  1930. drawing.Color{R: 192, G: 57, B: 43, A: 255},
  1931. drawing.Color{R: 241, G: 196, B: 15, A: 255},
  1932. )
  1933. return colors[i%len(colors)]
  1934. }
  1935. // getZWFont 加载字体
  1936. func getZWFont() *truetype.Font {
  1937. fontFile := "./static/fonts/MiSans-Medium.ttf"
  1938. fontBytes, err := os.ReadFile(fontFile)
  1939. if err != nil {
  1940. log.Println(err)
  1941. return nil
  1942. }
  1943. font, err := truetype.Parse(fontBytes)
  1944. if err != nil {
  1945. log.Println(err)
  1946. return nil
  1947. }
  1948. return font
  1949. }