waybill.go 50 KB

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