waybill.go 57 KB

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