waybill.go 85 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131
  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. "cold-logistics/conf"
  11. "errors"
  12. "fmt"
  13. "github.com/beego/beego/v2/core/logs"
  14. "github.com/boombuler/barcode"
  15. "github.com/boombuler/barcode/code128"
  16. "github.com/gin-gonic/gin"
  17. "github.com/gin-gonic/gin/binding"
  18. "github.com/golang/freetype/truetype"
  19. "github.com/jordan-wright/email"
  20. "github.com/ser163/png2j"
  21. "github.com/signintech/gopdf"
  22. "github.com/skip2/go-qrcode"
  23. "github.com/wcharczuk/go-chart/v2"
  24. "github.com/wcharczuk/go-chart/v2/drawing"
  25. "github.com/xuri/excelize/v2"
  26. "gogs.baozhida.cn/zoie/OAuth-core/api"
  27. "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user"
  28. _ "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
  29. "gonum.org/v1/plot"
  30. "gonum.org/v1/plot/plotter"
  31. "gonum.org/v1/plot/vg"
  32. "gonum.org/v1/plot/vg/draw"
  33. "image/color"
  34. "image/jpeg"
  35. "image/png"
  36. "log"
  37. "math"
  38. "net/smtp"
  39. "net/url"
  40. "os"
  41. "path"
  42. "sort"
  43. "strconv"
  44. "strings"
  45. "sync"
  46. "time"
  47. )
  48. type WaybillController struct {
  49. api.Api
  50. }
  51. // GetPage 获取运单列表
  52. // @Summary 获取运单列表
  53. // @Description 获取运单列表
  54. // @Tags 运单
  55. // @Param no query string false "运单号"
  56. // @Param pageSize query int false "页条数"
  57. // @Param page query int false "页码"
  58. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  59. // @Router /api/waybill [get]
  60. // @Security Bearer
  61. func (e WaybillController) GetPage(c *gin.Context) {
  62. s := service.Waybill{}
  63. req := dto.WaybillGetPageReq{}
  64. err := e.MakeContext(c).
  65. MakeOrm().
  66. Bind(&req, binding.Query).
  67. MakeService(&s.Service).
  68. Errors
  69. if err != nil {
  70. e.Logger.Error(err)
  71. e.Error(500, err, err.Error())
  72. return
  73. }
  74. //数据权限检查
  75. p := actions.GetPermissionFromContext(c)
  76. list := make([]model.Waybill, 0)
  77. var count int64
  78. err = s.GetPage(&req, &list, &count, p)
  79. if err != nil {
  80. e.Error(500, err, err.Error())
  81. return
  82. }
  83. e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
  84. }
  85. // Export 导出运单excel
  86. // @Summary 导出运单excel
  87. // @Description 导出运单excel
  88. // @Tags 运单
  89. // @Param no query string false "运单号"
  90. // @Param pageSize query int false "页条数"
  91. // @Param page query int false "页码"
  92. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  93. // @Router /api/waybill [get]
  94. // @Security Bearer
  95. func (e WaybillController) Export(c *gin.Context) {
  96. s := service.Waybill{}
  97. req := dto.WaybillGetPageReq{}
  98. err := e.MakeContext(c).
  99. MakeOrm().
  100. Bind(&req, binding.Query).
  101. MakeService(&s.Service).
  102. Errors
  103. if err != nil {
  104. e.Logger.Error(err)
  105. e.Error(500, err, err.Error())
  106. return
  107. }
  108. //数据权限检查
  109. p := actions.GetPermissionFromContext(c)
  110. list := make([]model.Waybill, 0)
  111. var count int64
  112. req.PageSize = 9999
  113. err = s.GetPage(&req, &list, &count, p)
  114. if err != nil {
  115. e.Error(500, err, err.Error())
  116. return
  117. }
  118. f := excelize.NewFile() // 设置单元格的值
  119. // 这里设置表头ÒÒ
  120. f.SetCellValue("Sheet1", "A1", "序号")
  121. f.SetCellValue("Sheet1", "B1", "状态")
  122. f.SetCellValue("Sheet1", "C1", "寄件人名称")
  123. f.SetCellValue("Sheet1", "D1", "寄件人电话")
  124. f.SetCellValue("Sheet1", "E1", "寄件人地址")
  125. f.SetCellValue("Sheet1", "F1", "收件人名称")
  126. f.SetCellValue("Sheet1", "G1", "收件人电话")
  127. f.SetCellValue("Sheet1", "H1", "收件人地址")
  128. f.SetCellValue("Sheet1", "I1", "温度要求")
  129. f.SetCellValue("Sheet1", "J1", "配送要求")
  130. f.SetCellValue("Sheet1", "K1", "货物类型")
  131. f.SetCellValue("Sheet1", "L1", "运输备注")
  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", "K", 15)
  142. f.SetColWidth("Sheet1", "L", "L", 15)
  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.TemperatureInterval)
  156. f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v.DeliveryCondition)
  157. f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v.CargoType)
  158. f.SetCellValue("Sheet1", fmt.Sprintf("L%d", line), v.Remark)
  159. }
  160. timeStr := time.Now().Format("20060102150405")
  161. filePath := "ofile/" + "运单" + timeStr + ".xlsx"
  162. // 保存文件
  163. if err = f.SaveAs(filePath); err != nil {
  164. logs.Error("保存运单失败:", err)
  165. }
  166. defer func() {
  167. os.Remove(filePath)
  168. }()
  169. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  170. // PathEscape 函数对中文做处理
  171. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape("运单"+timeStr+".xlsx"))
  172. c.Header("Content-Transfer-Encoding", "binary")
  173. c.File(filePath)
  174. }
  175. // Home 首页统计
  176. // @Summary 首页统计
  177. // @Description 首页统计
  178. // @Tags 运单
  179. // @Param no query string false "运单号"
  180. // @Param pageSize query int false "页条数"
  181. // @Param page query int false "页码"
  182. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  183. // @Router /api/waybill [get]
  184. // @Security Bearer
  185. func (e WaybillController) Home(c *gin.Context) {
  186. s := service.Waybill{}
  187. req := dto.WaybillStatsReq{}
  188. err := e.MakeContext(c).
  189. MakeOrm().
  190. Bind(&req, binding.Query).
  191. MakeService(&s.Service).
  192. Errors
  193. if err != nil {
  194. e.Logger.Error(err)
  195. e.Error(500, err, err.Error())
  196. return
  197. }
  198. //数据权限检查
  199. p := actions.GetPermissionFromContext(c)
  200. res := s.GetBasicsStats(&req, p)
  201. e.OK(res, "查询成功")
  202. }
  203. // GetAppletPage 获取运单列表
  204. // @Summary 获取运单列表
  205. // @Description 获取运单列表
  206. // @Tags 运单
  207. // @Param no query string false "运单号"
  208. // @Param pageSize query int false "页条数"
  209. // @Param page query int false "页码"
  210. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  211. // @Router /api/waybill [get]
  212. // @Security Bearer
  213. func (e WaybillController) GetAppletPage(c *gin.Context) {
  214. s := service.Waybill{}
  215. req := dto.WaybillGetAppletPageReq{}
  216. err := e.MakeContext(c).
  217. MakeOrm().
  218. Bind(&req, binding.Query).
  219. MakeService(&s.Service).
  220. Errors
  221. if err != nil {
  222. e.Logger.Error(err)
  223. e.Error(500, err, err.Error())
  224. return
  225. }
  226. //数据权限检查
  227. p := actions.GetPermissionFromContext(c)
  228. list := make([]model.Waybill, 0)
  229. var count int64
  230. err = s.GetAppletPage(&req, &list, &count, p)
  231. if err != nil {
  232. e.Error(500, err, err.Error())
  233. return
  234. }
  235. e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
  236. }
  237. // GetAppletCount 获取app运单统计数量
  238. // @Summary 获取app运单统计数量
  239. // @Description 获取app运单统计数量
  240. // @Tags 运单
  241. // @Param no query string false "运单号"
  242. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  243. // @Router /api/waybill/applet-count [get]
  244. // @Security Bearer
  245. func (e WaybillController) GetAppletCount(c *gin.Context) {
  246. s := service.Waybill{}
  247. userSvc := service.SysUser{}
  248. req := dto.WaybillGetAppletPageReq{}
  249. err := e.MakeContext(c).
  250. MakeOrm().
  251. Bind(&req, binding.Query).
  252. MakeService(&s.Service).
  253. MakeService(&userSvc.Service).
  254. Errors
  255. if err != nil {
  256. e.Logger.Error(err)
  257. e.Error(500, err, err.Error())
  258. return
  259. }
  260. //数据权限检查
  261. p := actions.GetPermissionFromContext(c)
  262. var userObj model.SysUser
  263. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  264. if err != nil {
  265. e.Error(500, err, err.Error())
  266. return
  267. }
  268. list := make([]model.Waybill, 0)
  269. var count int64
  270. if userObj.UserType == "customer" {
  271. r := dto.WaybillGetCustomerPageReq{}
  272. r.PageSize = 9999
  273. r.CustomerId = p.UserId
  274. err = s.GetCustomerPage(&r, &list, &count, p)
  275. var statusCount = make(map[int]int)
  276. statusCount[0] = int(count)
  277. for _, waybill := range list {
  278. if _, ok := statusCount[waybill.Status]; ok {
  279. statusCount[waybill.Status] += 1
  280. } else {
  281. statusCount[waybill.Status] = 1
  282. }
  283. }
  284. e.OK(statusCount, "查询成功")
  285. return
  286. }
  287. err = s.GetAppletCount(&list, &count, p)
  288. if err != nil {
  289. e.Error(500, err, err.Error())
  290. return
  291. }
  292. var statusCount = make(map[int]int)
  293. statusCount[0] = int(count)
  294. for _, waybill := range list {
  295. if _, ok := statusCount[waybill.Status]; ok {
  296. statusCount[waybill.Status] += 1
  297. } else {
  298. statusCount[waybill.Status] = 1
  299. }
  300. }
  301. e.OK(statusCount, "查询成功")
  302. }
  303. // Get 通过id获取运单
  304. // @Summary 通过id获取运单
  305. // @Description 通过id获取运单
  306. // @Tags 运单
  307. // @Param id path string true "运单id"
  308. // @Success 200 {object} response.Response{data=model.Waybill} "{"code": 200, "data": [...]}"
  309. // @Router /api/waybill/{id} [get]
  310. // @Security Bearer
  311. func (e WaybillController) Get(c *gin.Context) {
  312. s := service.Waybill{}
  313. req := dto.WaybillGetReq{}
  314. err := e.MakeContext(c).
  315. MakeOrm().
  316. Bind(&req, nil).
  317. MakeService(&s.Service).
  318. Errors
  319. if err != nil {
  320. e.Logger.Error(err)
  321. e.Error(500, err, err.Error())
  322. return
  323. }
  324. var object model.Waybill
  325. p := actions.GetPermissionFromContext(c)
  326. //数据权限检查
  327. err = s.Get(&req, &object, p)
  328. if err != nil {
  329. e.Error(500, err, err.Error())
  330. return
  331. }
  332. e.OK(object, "查询成功")
  333. }
  334. // Insert 添加运单
  335. // @Summary 添加运单
  336. // @Description 添加运单
  337. // @Tags 运单
  338. // @Accept application/json
  339. // @Product application/json
  340. // @Param data body dto.WaybillInsertReq true "data"
  341. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  342. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  343. // @Router /api/waybill [post]
  344. // @Security Bearer
  345. func (e WaybillController) Insert(c *gin.Context) {
  346. s := service.Waybill{}
  347. req := dto.WaybillInsertReq{}
  348. err := e.MakeContext(c).
  349. MakeOrm().
  350. Bind(&req, binding.JSON).
  351. MakeService(&s.Service).
  352. Errors
  353. if err != nil {
  354. e.Logger.Error(err)
  355. e.Error(500, err, err.Error())
  356. return
  357. }
  358. p := actions.GetPermissionFromContext(c)
  359. // 设置创建人
  360. req.SetCreateBy(user.GetUserId(c))
  361. req.SetDeptId(p.DeptId)
  362. err = s.Insert(&req)
  363. if err != nil {
  364. e.Error(500, err, err.Error())
  365. return
  366. }
  367. e.OK(req.GetId(), "创建成功")
  368. }
  369. // AppletInsert 添加运单app
  370. // @Summary 添加运单app
  371. // @Description 添加运单app
  372. // @Tags 运单
  373. // @Accept application/json
  374. // @Product application/json
  375. // @Param data body dto.WaybillInsertReq true "data"
  376. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  377. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  378. // @Router /api/waybill [post]
  379. // @Security Bearer
  380. func (e WaybillController) AppletInsert(c *gin.Context) {
  381. s := service.Waybill{}
  382. req := dto.WaybillInsertReq{}
  383. err := e.MakeContext(c).
  384. MakeOrm().
  385. Bind(&req, binding.JSON).
  386. MakeService(&s.Service).
  387. Errors
  388. if err != nil {
  389. e.Logger.Error(err)
  390. e.Error(500, err, err.Error())
  391. return
  392. }
  393. p := actions.GetPermissionFromContext(c)
  394. err = s.AppletInsert(&req, p)
  395. if err != nil {
  396. e.Error(500, err, err.Error())
  397. return
  398. }
  399. e.OK(req.GetId(), "添加成功")
  400. }
  401. // Update 修改运单
  402. // @Summary 修改运单
  403. // @Description 修改运单
  404. // @Tags 运单
  405. // @Accept application/json
  406. // @Product application/json
  407. // @Param data body dto.WaybillUpdateReq true "body"
  408. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  409. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  410. // @Router /api/waybill [put]
  411. // @Security Bearer
  412. func (e WaybillController) Update(c *gin.Context) {
  413. s := service.Waybill{}
  414. req := dto.WaybillUpdateReq{}
  415. err := e.MakeContext(c).
  416. MakeOrm().
  417. Bind(&req).
  418. MakeService(&s.Service).
  419. Errors
  420. if err != nil {
  421. e.Logger.Error(err)
  422. e.Error(500, err, err.Error())
  423. return
  424. }
  425. p := actions.GetPermissionFromContext(c)
  426. req.SetUpdateBy(user.GetUserId(c))
  427. err = s.Update(&req, p)
  428. if err != nil {
  429. e.Error(500, err, err.Error())
  430. return
  431. }
  432. e.OK(req.GetId(), "更新成功")
  433. }
  434. // Delivery 派单
  435. // @Summary 派单
  436. // @Description 派单
  437. // @Tags 运单
  438. // @Accept application/json
  439. // @Product application/json
  440. // @Param data body dto.WaybillDeliveryReq true "body"
  441. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  442. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  443. // @Router /api/waybill [put]
  444. // @Security Bearer
  445. func (e WaybillController) Delivery(c *gin.Context) {
  446. s := service.Waybill{}
  447. req := dto.WaybillDeliveryReq{}
  448. err := e.MakeContext(c).
  449. MakeOrm().
  450. Bind(&req).
  451. MakeService(&s.Service).
  452. Errors
  453. if err != nil {
  454. e.Logger.Error(err)
  455. e.Error(500, err, err.Error())
  456. return
  457. }
  458. p := actions.GetPermissionFromContext(c)
  459. req.SetUpdateBy(user.GetUserId(c))
  460. err = s.Delivery(&req, p)
  461. if err != nil {
  462. e.Error(500, err, err.Error())
  463. return
  464. }
  465. e.OK(req.GetId(), "派单成功")
  466. }
  467. // Delete 删除运单
  468. // @Summary 删除运单
  469. // @Description 删除运单
  470. // @Tags 运单
  471. // @Accept application/json
  472. // @Product application/json
  473. // @Param data body dto.WaybillDeleteReq true "body"
  474. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  475. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  476. // @Router /api/waybill [delete]
  477. // @Security Bearer
  478. func (e WaybillController) Delete(c *gin.Context) {
  479. s := service.Waybill{}
  480. req := dto.WaybillDeleteReq{}
  481. userSvc := service.SysUser{}
  482. err := e.MakeContext(c).
  483. MakeOrm().
  484. Bind(&req, binding.JSON, nil).
  485. MakeService(&s.Service).
  486. MakeService(&userSvc.Service).
  487. Errors
  488. if err != nil {
  489. e.Logger.Error(err)
  490. e.Error(500, err, err.Error())
  491. return
  492. }
  493. //数据权限检查
  494. p := actions.GetPermissionFromContext(c)
  495. err = s.Remove(&req, p)
  496. if err != nil {
  497. e.Error(500, err, err.Error())
  498. return
  499. }
  500. e.OK(req.GetId(), "删除成功")
  501. }
  502. // WarehouseIn 入库
  503. // @Summary 入库
  504. // @Description 入库
  505. // @Tags 运单
  506. // @Accept application/json
  507. // @Product application/json
  508. // @Param data body dto.WaybillInOutReq true "body"
  509. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  510. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  511. // @Router /api/waybill/warehouse-in [post]
  512. // @Security Bearer
  513. func (e WaybillController) WarehouseIn(c *gin.Context) {
  514. s := service.Waybill{}
  515. req := dto.WaybillInOutReq{}
  516. err := e.MakeContext(c).
  517. MakeOrm().
  518. Bind(&req, binding.JSON, nil).
  519. MakeService(&s.Service).
  520. Errors
  521. if err != nil {
  522. e.Logger.Error(err)
  523. e.Error(500, err, err.Error())
  524. return
  525. }
  526. //数据权限检查
  527. p := actions.GetPermissionFromContext(c)
  528. err = s.WarehouseIn(&req, p)
  529. if err != nil {
  530. e.Error(500, err, err.Error())
  531. return
  532. }
  533. e.OK(req.WaybillNoList, "入库成功")
  534. }
  535. // WarehouseOut 出库
  536. // @Summary 出库
  537. // @Description 出库
  538. // @Tags 运单
  539. // @Accept application/json
  540. // @Product application/json
  541. // @Param data body dto.WaybillInOutReq true "body"
  542. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  543. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  544. // @Router /api/waybill/warehouse-out [post]
  545. // @Security Bearer
  546. func (e WaybillController) WarehouseOut(c *gin.Context) {
  547. s := service.Waybill{}
  548. req := dto.WaybillInOutReq{}
  549. err := e.MakeContext(c).
  550. MakeOrm().
  551. Bind(&req, binding.JSON, nil).
  552. MakeService(&s.Service).
  553. Errors
  554. if err != nil {
  555. e.Logger.Error(err)
  556. e.Error(500, err, err.Error())
  557. return
  558. }
  559. //数据权限检查
  560. p := actions.GetPermissionFromContext(c)
  561. err = s.WarehouseOut(&req, p)
  562. if err != nil {
  563. e.Error(500, err, err.Error())
  564. return
  565. }
  566. e.OK(req.WaybillNoList, "出库成功")
  567. }
  568. // CarIn 上车
  569. // @Summary 上车
  570. // @Description 上车
  571. // @Tags 运单
  572. // @Accept application/json
  573. // @Product application/json
  574. // @Param data body dto.WaybillInOutReq true "body"
  575. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  576. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  577. // @Router /api/waybill/car-in [post]
  578. // @Security Bearer
  579. func (e WaybillController) CarIn(c *gin.Context) {
  580. s := service.Waybill{}
  581. req := dto.WaybillInOutReq{}
  582. err := e.MakeContext(c).
  583. MakeOrm().
  584. Bind(&req, binding.JSON, nil).
  585. MakeService(&s.Service).
  586. Errors
  587. if err != nil {
  588. e.Logger.Error(err)
  589. e.Error(500, err, err.Error())
  590. return
  591. }
  592. //数据权限检查
  593. p := actions.GetPermissionFromContext(c)
  594. err = s.CarIn(&req, p)
  595. if err != nil {
  596. e.Error(500, err, err.Error())
  597. return
  598. }
  599. e.OK(req.WaybillNoList, "装车成功")
  600. }
  601. // CarOut 下车
  602. // @Summary 下车
  603. // @Description 下车
  604. // @Tags 运单
  605. // @Accept application/json
  606. // @Product application/json
  607. // @Param data body dto.WaybillInOutReq true "body"
  608. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  609. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  610. // @Router /api/waybill/car-out [post]
  611. // @Security Bearer
  612. func (e WaybillController) CarOut(c *gin.Context) {
  613. s := service.Waybill{}
  614. req := dto.WaybillInOutReq{}
  615. err := e.MakeContext(c).
  616. MakeOrm().
  617. Bind(&req, binding.JSON, nil).
  618. MakeService(&s.Service).
  619. Errors
  620. if err != nil {
  621. e.Logger.Error(err)
  622. e.Error(500, err, err.Error())
  623. return
  624. }
  625. //数据权限检查
  626. p := actions.GetPermissionFromContext(c)
  627. err = s.CarOut(&req, p)
  628. if err != nil {
  629. e.Error(500, err, err.Error())
  630. return
  631. }
  632. e.OK(req.WaybillNoList, "下车成功")
  633. }
  634. // CoolerBoxIn 装箱
  635. // @Summary 装箱
  636. // @Description 装箱
  637. // @Tags 运单
  638. // @Accept application/json
  639. // @Product application/json
  640. // @Param data body dto.WaybillInOutReq true "body"
  641. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  642. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  643. // @Router /api/waybill/cooler-box-in [post]
  644. // @Security Bearer
  645. func (e WaybillController) CoolerBoxIn(c *gin.Context) {
  646. s := service.Waybill{}
  647. req := dto.WaybillCoolerBoxInReq{}
  648. err := e.MakeContext(c).
  649. MakeOrm().
  650. Bind(&req, binding.JSON, nil).
  651. MakeService(&s.Service).
  652. Errors
  653. if err != nil {
  654. e.Logger.Error(err)
  655. e.Error(500, err, err.Error())
  656. return
  657. }
  658. //数据权限检查
  659. p := actions.GetPermissionFromContext(c)
  660. err = s.CoolerBoxIn(&req, p)
  661. if err != nil {
  662. e.Error(500, err, err.Error())
  663. return
  664. }
  665. e.OK(req.WaybillNoList, "装箱成功")
  666. }
  667. // Receipt 签收
  668. // @Summary 签收
  669. // @Description 签收
  670. // @Tags 运单
  671. // @Accept application/json
  672. // @Product application/json
  673. // @Param data body dto.WaybillInOutReq true "body"
  674. // @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
  675. // @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
  676. // @Router /api/waybill/car-out [post]
  677. // @Security Bearer
  678. func (e WaybillController) Receipt(c *gin.Context) {
  679. s := service.Waybill{}
  680. req := dto.WaybillReceiptReq{}
  681. err := e.MakeContext(c).
  682. MakeOrm().
  683. Bind(&req, binding.JSON, nil).
  684. MakeService(&s.Service).
  685. Errors
  686. if err != nil {
  687. e.Logger.Error(err)
  688. e.Error(500, err, err.Error())
  689. return
  690. }
  691. //数据权限检查
  692. p := actions.GetPermissionFromContext(c)
  693. err = s.Receipt(&req, p)
  694. if err != nil {
  695. e.Error(500, err, err.Error())
  696. return
  697. }
  698. e.OK(req.WaybillNo, "签收成功")
  699. }
  700. // GetCustomerPage 获取客户运单列表
  701. // @Summary 获取客户运单列表
  702. // @Description 获取客户运单列表
  703. // @Tags 运单
  704. // @Param no query string false "运单号"
  705. // @Param pageSize query int false "页条数"
  706. // @Param page query int false "页码"
  707. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  708. // @Router /api/waybill/customer [get]
  709. // @Security Bearer
  710. func (e WaybillController) GetCustomerPage(c *gin.Context) {
  711. s := service.Waybill{}
  712. req := dto.WaybillGetCustomerPageReq{}
  713. err := e.MakeContext(c).
  714. MakeOrm().
  715. Bind(&req, binding.Query).
  716. MakeService(&s.Service).
  717. Errors
  718. if err != nil {
  719. e.Logger.Error(err)
  720. e.Error(500, err, err.Error())
  721. return
  722. }
  723. //数据权限检查
  724. p := actions.GetPermissionFromContext(c)
  725. list := make([]model.Waybill, 0)
  726. var count int64
  727. req.CustomerId = p.UserId
  728. err = s.GetCustomerPage(&req, &list, &count, p)
  729. if err != nil {
  730. e.Error(500, err, err.Error())
  731. return
  732. }
  733. e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
  734. }
  735. func (e WaybillController) CustomerExport(c *gin.Context) {
  736. s := service.Waybill{}
  737. req := dto.WaybillGetCustomerPageReq{}
  738. err := e.MakeContext(c).
  739. MakeOrm().
  740. Bind(&req, binding.Query).
  741. MakeService(&s.Service).
  742. Errors
  743. if err != nil {
  744. e.Logger.Error(err)
  745. e.Error(500, err, err.Error())
  746. return
  747. }
  748. //数据权限检查
  749. p := actions.GetPermissionFromContext(c)
  750. list := make([]model.Waybill, 0)
  751. var count int64
  752. req.CustomerId = p.UserId
  753. req.PageSize = 9999
  754. err = s.GetCustomerPage(&req, &list, &count, p)
  755. if err != nil {
  756. e.Error(500, err, err.Error())
  757. return
  758. }
  759. f := excelize.NewFile() // 设置单元格的值
  760. // 这里设置表头ÒÒ
  761. f.SetCellValue("Sheet1", "A1", "序号")
  762. f.SetCellValue("Sheet1", "B1", "状态")
  763. f.SetCellValue("Sheet1", "C1", "寄件人名称")
  764. f.SetCellValue("Sheet1", "D1", "寄件人电话")
  765. f.SetCellValue("Sheet1", "E1", "寄件人地址")
  766. f.SetCellValue("Sheet1", "F1", "收件人名称")
  767. f.SetCellValue("Sheet1", "G1", "收件人电话")
  768. f.SetCellValue("Sheet1", "H1", "收件人地址")
  769. f.SetCellValue("Sheet1", "I1", "温度要求")
  770. f.SetCellValue("Sheet1", "J1", "配送要求")
  771. f.SetCellValue("Sheet1", "K1", "货物类型")
  772. f.SetCellValue("Sheet1", "L1", "运输备注")
  773. // 设置列宽
  774. f.SetColWidth("Sheet1", "A", "A", 6)
  775. f.SetColWidth("Sheet1", "B", "B", 8)
  776. f.SetColWidth("Sheet1", "C", "C", 14)
  777. f.SetColWidth("Sheet1", "D", "D", 14)
  778. f.SetColWidth("Sheet1", "E", "E", 30)
  779. f.SetColWidth("Sheet1", "F", "F", 14)
  780. f.SetColWidth("Sheet1", "G", "G", 14)
  781. f.SetColWidth("Sheet1", "H", "H", 30)
  782. f.SetColWidth("Sheet1", "I", "K", 15)
  783. f.SetColWidth("Sheet1", "L", "L", 15)
  784. line := 1
  785. // 循环写入数据
  786. for i, v := range list {
  787. line++
  788. f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), i+1)
  789. f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), model.GetCustomerWaybillStatus(v.Status))
  790. f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), v.SenderAddressName)
  791. f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.SenderAddressPhone)
  792. f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.SenderAddressDetails)
  793. f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.ConsigneeAddressName)
  794. f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v.ConsigneeAddressPhone)
  795. f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v.ConsigneeAddressDetails)
  796. f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v.TemperatureInterval)
  797. f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v.DeliveryCondition)
  798. f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v.CargoType)
  799. f.SetCellValue("Sheet1", fmt.Sprintf("L%d", line), v.Remark)
  800. }
  801. timeStr := time.Now().Format("20060102150405")
  802. filePath := "ofile/" + "运单" + timeStr + ".xlsx"
  803. defer func() {
  804. os.Remove(filePath)
  805. }()
  806. // 保存文件
  807. if err = f.SaveAs(filePath); err != nil {
  808. logs.Error("保存运单失败:", err)
  809. }
  810. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  811. // PathEscape 函数对中文做处理
  812. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape("运单"+timeStr+".xlsx"))
  813. c.Header("Content-Transfer-Encoding", "binary")
  814. c.File(filePath)
  815. }
  816. // CustomerInsert 客户添加运单
  817. // @Summary 客户添加运单
  818. // @Description 客户添加运单
  819. // @Tags 运单
  820. // @Accept application/json
  821. // @Product application/json
  822. // @Param data body dto.WaybillInsertReq true "data"
  823. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  824. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  825. // @Router /api/waybill/customer [post]
  826. // @Security Bearer
  827. func (e WaybillController) CustomerInsert(c *gin.Context) {
  828. s := service.Waybill{}
  829. userSvc := service.SysUser{}
  830. req := dto.WaybillInsertReq{}
  831. err := e.MakeContext(c).
  832. MakeOrm().
  833. Bind(&req, binding.JSON).
  834. MakeService(&s.Service).
  835. MakeService(&userSvc.Service).
  836. Errors
  837. if err != nil {
  838. e.Logger.Error(err)
  839. e.Error(500, err, err.Error())
  840. return
  841. }
  842. p := actions.GetPermissionFromContext(c)
  843. var userObj model.SysUser
  844. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  845. if err != nil {
  846. e.Error(500, err, "获取用户信息失败")
  847. return
  848. }
  849. if p.DeptId == 0 && req.DeptId == 0 {
  850. e.Error(500, err, "请先选择运输公司")
  851. return
  852. }
  853. // 设置创建人
  854. req.SetCreateBy(user.GetUserId(c))
  855. req.CustomerId = p.UserId
  856. req.CustomerName = userObj.NickName
  857. if p.DeptId > 0 {
  858. req.SetDeptId(p.DeptId)
  859. }
  860. err = s.Insert(&req)
  861. if err != nil {
  862. e.Error(500, err, err.Error())
  863. return
  864. }
  865. e.OK(req.GetId(), "创建成功")
  866. }
  867. // Import 导入运单
  868. // @Summary 导入运单
  869. // @Description 导入运单
  870. // @Tags 运单
  871. // @Accept application/json
  872. // @Product application/json
  873. // @Param data body dto.WaybillInsertReq true "data"
  874. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  875. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  876. // @Router /api/waybill/import [post]
  877. // @Security Bearer
  878. func (e WaybillController) Import(c *gin.Context) {
  879. s := service.Waybill{}
  880. userSvc := service.SysUser{}
  881. req := dto.WaybillImportReq{}
  882. err := e.MakeContext(c).
  883. MakeOrm().
  884. Bind(&req, binding.Form).
  885. MakeService(&s.Service).
  886. MakeService(&userSvc.Service).
  887. Errors
  888. if err != nil {
  889. e.Logger.Error(err)
  890. e.Error(500, err, err.Error())
  891. return
  892. }
  893. //读取第一fileName的文件
  894. fileHeader, err := c.FormFile("file")
  895. if err != nil {
  896. err = errors.New("文件格式错误" + err.Error())
  897. e.Logger.Error(err)
  898. e.Error(500, err, err.Error())
  899. return
  900. }
  901. if fileHeader.Size > 1024*1024*2 {
  902. err = errors.New("文件大小超过2M")
  903. e.Logger.Error(err)
  904. e.Error(500, err, err.Error())
  905. return
  906. }
  907. file, err := fileHeader.Open()
  908. if err != nil {
  909. err = errors.New("文件格式错误" + err.Error())
  910. e.Logger.Error(err)
  911. e.Error(500, err, err.Error())
  912. return
  913. }
  914. defer file.Close()
  915. xlsx, err := excelize.OpenReader(bufio.NewReader(file))
  916. if err != nil {
  917. err = errors.New("文件格式错误" + err.Error())
  918. e.Logger.Error(err)
  919. e.Error(500, err, err.Error())
  920. return
  921. }
  922. p := actions.GetPermissionFromContext(c)
  923. if p.DeptId == 0 {
  924. e.Error(500, err, "获取用户信息失败")
  925. return
  926. }
  927. var userObj model.SysUser
  928. err = userSvc.Get(&dto.SysUserGetReq{Id: p.UserId}, nil, &userObj)
  929. if err != nil {
  930. e.Error(500, err, "获取用户信息失败")
  931. return
  932. }
  933. var customerId int
  934. //customerName := req.CustomerName
  935. if userObj.UserType == model.UserTypeCustomer {
  936. customerId = userObj.Id
  937. //customerName = userObj.NickName
  938. }
  939. rows, _ := xlsx.GetRows("Sheet1")
  940. for indexRow, row := range rows {
  941. if indexRow == 0 {
  942. continue
  943. }
  944. if len(row) < 12 {
  945. for i := 0; i < 12-len(row); i++ {
  946. row = append(row, "")
  947. }
  948. }
  949. for i, colCell := range row {
  950. fmt.Println(i, ":", colCell)
  951. }
  952. quantity, _ := strconv.Atoi(row[10])
  953. obj := dto.WaybillInsertReq{
  954. Status: 1,
  955. SenderAddressName: row[0],
  956. SenderAddressPhone: row[1],
  957. SenderAddressDetails: row[2],
  958. CustomerName: row[3],
  959. ConsigneeAddressName: row[4],
  960. ConsigneeAddressPhone: row[5],
  961. ConsigneeAddressDetails: row[6],
  962. TemperatureInterval: row[7],
  963. DeliveryCondition: row[8],
  964. CargoType: row[9],
  965. Quantity: quantity,
  966. Remark: row[11],
  967. CustomerId: customerId,
  968. }
  969. obj.SetDeptId(p.DeptId)
  970. obj.SetCreateBy(user.GetUserId(c))
  971. err = s.Insert(&obj)
  972. if err != nil {
  973. e.Error(500, err, err.Error())
  974. return
  975. }
  976. }
  977. e.OK(len(rows)-1, "导入成功")
  978. }
  979. // ExportTemplate 导出运单模板
  980. // @Summary 导出运单模板
  981. // @Description 导出运单模板
  982. // @Tags 运单
  983. // @Accept application/json
  984. // @Product application/json
  985. // @Param data body dto.WaybillInsertReq true "data"
  986. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  987. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  988. // @Router /api/waybill/export-template [post]
  989. // @Security Bearer
  990. func (e WaybillController) ExportTemplate(c *gin.Context) {
  991. s := service.Waybill{}
  992. err := e.MakeContext(c).
  993. MakeOrm().
  994. MakeService(&s.Service).
  995. Errors
  996. if err != nil {
  997. e.Logger.Error(err)
  998. e.Error(500, err, err.Error())
  999. return
  1000. }
  1001. filePath := "./ofile/运单导入模板.xlsx"
  1002. //打开文件
  1003. fileTmp, errByOpenFile := os.Open(filePath)
  1004. defer fileTmp.Close()
  1005. //获取文件的名称
  1006. fileName := path.Base(filePath)
  1007. if errByOpenFile != nil {
  1008. e.Logger.Error(err)
  1009. e.Error(500, err, err.Error())
  1010. return
  1011. }
  1012. c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
  1013. // PathEscape 函数对中文做处理
  1014. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(fileName))
  1015. c.Header("Content-Transfer-Encoding", "binary")
  1016. c.File(filePath)
  1017. }
  1018. // TemperaturePDF 导出温度记录
  1019. // @Summary 导出温度记录
  1020. // @Description 导出温度记录
  1021. // @Tags 运单
  1022. // @Accept application/json
  1023. // @Product application/json
  1024. // @Param data body dto.WaybillInsertReq true "data"
  1025. // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
  1026. // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
  1027. // @Router /api/waybill/temperature-pdf [post]
  1028. // @Security Bearer
  1029. func (e WaybillController) TemperaturePDF1(c *gin.Context) {
  1030. s := service.Waybill{}
  1031. companySvc := service.Company{}
  1032. req := dto.WaybillGetByWaybillPdfReq{}
  1033. err := e.MakeContext(c).
  1034. MakeOrm().
  1035. Bind(&req, binding.Query).
  1036. MakeService(&s.Service).
  1037. MakeService(&companySvc.Service).
  1038. Errors
  1039. if err != nil {
  1040. e.Logger.Error(err)
  1041. e.Error(500, err, err.Error())
  1042. return
  1043. }
  1044. var waybill model.Waybill
  1045. var company model.SysDept
  1046. //err = s.GetByWaybillNo(&req, &waybill, p)
  1047. err = s.GetByWaybillNo(&req, &waybill, nil)
  1048. if err != nil {
  1049. e.Error(500, err, err.Error())
  1050. return
  1051. }
  1052. err = companySvc.Get(&dto.CompanyGetReq{Id: waybill.DeptId}, &company)
  1053. if err != nil {
  1054. e.Error(500, err, err.Error())
  1055. return
  1056. }
  1057. DeviceSensor_data, waybillPDF, err := s.GetAllData(&dto.WaybillGetByWaybillNoReq{WaybillNo: req.WaybillNo})
  1058. // 最高温度、最低温度、最高湿度、最低湿度
  1059. var maxTemp, minTemp, maxHumidity, minHumidity float32
  1060. // 最高温度时间、最低温度时间、最高湿度时间、最低湿度时间
  1061. var maxTempTime, minTempTime, maxHumidityTime, minHumidityTime string
  1062. // 总温度 总湿度
  1063. var totalTemp, totalHumidity float32
  1064. // 平均温度 平均湿度
  1065. var avgTemp, avgHumidity float32
  1066. // 温度阈值,湿度阈值
  1067. var tempThreshold, humidityThreshold string
  1068. // 记录开始时间,记录结束时间
  1069. var s_time, e_time string
  1070. var lastTime string
  1071. var isFirst, isSecond = true, false
  1072. var first_column, second_column []nats_server.DeviceData_R
  1073. if len(DeviceSensor_data) > 0 {
  1074. tempThreshold = fmt.Sprintf("%.1f-%.1f", DeviceSensor_data[0].T_tl, DeviceSensor_data[0].T_tu)
  1075. humidityThreshold = fmt.Sprintf("%.1f-%.1f", DeviceSensor_data[0].T_rhl, DeviceSensor_data[0].T_rhu)
  1076. s_time = DeviceSensor_data[0].T_time
  1077. e_time = DeviceSensor_data[len(DeviceSensor_data)-1].T_time
  1078. // 最高温度及时刻
  1079. maxTemp = DeviceSensor_data[0].T_t
  1080. maxTempTime = DeviceSensor_data[0].T_time
  1081. // 最低温度及时刻
  1082. minTemp = DeviceSensor_data[0].T_t
  1083. minTempTime = DeviceSensor_data[0].T_time
  1084. // 最高湿度及时刻
  1085. maxHumidity = DeviceSensor_data[0].T_rh
  1086. maxHumidityTime = DeviceSensor_data[0].T_time
  1087. // 获取最低湿度及时刻
  1088. minHumidity = DeviceSensor_data[0].T_rh
  1089. minHumidityTime = DeviceSensor_data[0].T_time
  1090. for i := 0; i < len(DeviceSensor_data); i++ {
  1091. data := DeviceSensor_data[i]
  1092. if data.T_t > maxTemp {
  1093. maxTemp = data.T_t
  1094. maxTempTime = data.T_time
  1095. }
  1096. if data.T_t < minTemp {
  1097. minTemp = data.T_t
  1098. minTempTime = data.T_time
  1099. }
  1100. totalTemp += data.T_t
  1101. if data.T_rh > maxHumidity {
  1102. maxHumidity = data.T_rh
  1103. maxHumidityTime = data.T_time
  1104. }
  1105. if data.T_rh < minHumidity {
  1106. minHumidity = data.T_rh
  1107. minHumidityTime = data.T_time
  1108. }
  1109. totalHumidity += data.T_rh
  1110. }
  1111. var sn string
  1112. for _, w := range waybillPDF {
  1113. for _, data := range w.Data {
  1114. if len(lastTime) > 0 {
  1115. if lastTime != data.T_time && isFirst == true {
  1116. isFirst = false
  1117. isSecond = true
  1118. } else if lastTime != data.T_time && isSecond == true {
  1119. isFirst = true
  1120. isSecond = false
  1121. }
  1122. }
  1123. if len(sn) > 0 && sn != data.T_sn && len(first_column)%2 == 1 {
  1124. isFirst, isSecond = isSecond, isFirst
  1125. }
  1126. if isFirst {
  1127. first_column = append(first_column, data)
  1128. lastTime = data.T_time
  1129. sn = data.T_sn
  1130. }
  1131. if isSecond {
  1132. second_column = append(second_column, data)
  1133. lastTime = data.T_time
  1134. sn = data.T_sn
  1135. }
  1136. }
  1137. }
  1138. // 平均温度
  1139. avgTemp = totalTemp / float32(len(DeviceSensor_data))
  1140. // 平均湿度
  1141. avgHumidity = totalHumidity / float32(len(DeviceSensor_data))
  1142. }
  1143. // -------------------获取最高温湿度、温蒂温湿度、平均温湿度结束
  1144. pdf := &gopdf.GoPdf{}
  1145. pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
  1146. err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
  1147. if err != nil {
  1148. return
  1149. }
  1150. err = pdf.SetFont("wts", "", 20)
  1151. if err != nil {
  1152. return
  1153. }
  1154. pdf.SetGrayFill(0.5)
  1155. pdf.SetMargins(0, 20, 0, 20)
  1156. pdf.AddPage()
  1157. if len(company.Logo) > 0 {
  1158. imgH, errImg := lib.GetImage(company.Logo)
  1159. if errImg != nil {
  1160. err = errors.New("获取图片失败")
  1161. e.Error(500, err, err.Error())
  1162. return
  1163. }
  1164. imgWidth := float64(imgH.Bounds().Dx())
  1165. imgHeight := float64(imgH.Bounds().Dy())
  1166. W := 50.
  1167. H := (imgHeight * W) / imgWidth
  1168. if strings.Contains(company.Logo, ".png") {
  1169. err = pdf.ImageFrom(imgH, 10, 5, &gopdf.Rect{W: W, H: H})
  1170. if err != nil {
  1171. err = errors.New("写入图片失败")
  1172. e.Error(500, err, err.Error())
  1173. return
  1174. }
  1175. } else {
  1176. fileName := "./ofile/" + path.Base(company.Logo)
  1177. f, _ := os.Create(fileName)
  1178. defer f.Close()
  1179. defer func() {
  1180. os.Remove(fileName)
  1181. }()
  1182. jpeg.Encode(f, imgH, &jpeg.Options{100})
  1183. err = pdf.Image(fileName, (595-W)/2, (840-H)/2, &gopdf.Rect{W: W, H: H})
  1184. if err != nil {
  1185. err = errors.New("写入图片失败")
  1186. e.Error(500, err, err.Error())
  1187. return
  1188. }
  1189. }
  1190. }
  1191. title := "运单" + req.WaybillNo + "温度记录"
  1192. if req.HumidityShow {
  1193. title = "运单" + req.WaybillNo + "温湿度记录"
  1194. }
  1195. var y float64 = 70
  1196. textw, _ := pdf.MeasureTextWidth(title)
  1197. pdf.SetX((595 / 2) - (textw / 2))
  1198. pdf.SetY(y)
  1199. pdf.Text(title)
  1200. y += 30
  1201. pdf.SetFont("wts", "", 16)
  1202. pdf.SetXY(10, y)
  1203. pdf.Text("记录概要信息")
  1204. // 线
  1205. y += 10
  1206. pdf.SetLineWidth(0.5)
  1207. pdf.SetStrokeColor(169, 169, 169)
  1208. pdf.Line(10, y, 585, y)
  1209. y += 20
  1210. pdf.SetFont("wts", "", 10)
  1211. pdf.SetXY(10, y)
  1212. pdf.Text(fmt.Sprintf("记录开始时间:%s", s_time))
  1213. pdf.SetXY(240, y)
  1214. pdf.Text(fmt.Sprintf("记录结束时间:%s", e_time))
  1215. sTime, _ := lib.TimeStrToTime(s_time)
  1216. eTime, _ := lib.TimeStrToTime(e_time)
  1217. pdf.SetXY(470, y)
  1218. minutes := int(eTime.Sub(sTime).Minutes())
  1219. hours := minutes / 60
  1220. remainingMinutes := minutes % 60
  1221. pdf.Text(fmt.Sprintf("记录总时间:%dh%dmin", hours, remainingMinutes))
  1222. // -------------最高温/湿度 最低温/湿度 平均温/湿度
  1223. y += 15
  1224. pdf.SetXY(10, y)
  1225. pdf.Text(fmt.Sprintf("最高温度:%.1f℃,%s", lib.RoundToDecimal(float64(maxTemp), 1), maxTempTime))
  1226. pdf.SetXY(240, y)
  1227. pdf.Text(fmt.Sprintf("最低温度:%.1f℃,%s", lib.RoundToDecimal(float64(minTemp), 1), minTempTime))
  1228. pdf.SetXY(470, y)
  1229. pdf.Text(fmt.Sprintf("平均温度:%.1f℃", lib.RoundToDecimal(float64(avgTemp), 1)))
  1230. if req.HumidityShow {
  1231. y += 15
  1232. pdf.SetXY(10, y)
  1233. pdf.Text(fmt.Sprintf("最高湿度:%.1f%%RH,%s", lib.RoundToDecimal(float64(maxHumidity), 1), maxHumidityTime))
  1234. pdf.SetXY(240, y)
  1235. pdf.Text(fmt.Sprintf("最低湿度:%.1f%%RH,%s", lib.RoundToDecimal(float64(minHumidity), 1), minHumidityTime))
  1236. pdf.SetXY(470, y)
  1237. pdf.Text(fmt.Sprintf("平均湿度:%.1f%%RH", lib.RoundToDecimal(float64(avgHumidity), 1)))
  1238. }
  1239. // -------------温/湿度阈值
  1240. y += 15
  1241. pdf.SetXY(10, y)
  1242. pdf.Text(fmt.Sprintf("温度阈值:%s℃", tempThreshold))
  1243. if req.HumidityShow {
  1244. pdf.SetXY(240, y)
  1245. pdf.Text(fmt.Sprintf("湿度阈值:%s%%", humidityThreshold))
  1246. }
  1247. //-------------发货单位,收货单位,备注
  1248. y += 15
  1249. pdf.SetXY(10, y)
  1250. T_forwarding_unit_temp := []rune(waybill.SenderAddressName)
  1251. if len(T_forwarding_unit_temp) > 17 {
  1252. pdf.Text(fmt.Sprintf("发货人:%s", string(T_forwarding_unit_temp[0:17])))
  1253. pdf.SetXY(60, y+15)
  1254. pdf.Text(fmt.Sprintf("%s", string(T_forwarding_unit_temp[17:])))
  1255. } else {
  1256. pdf.Text(fmt.Sprintf("发货人:%s", string(T_forwarding_unit_temp)))
  1257. }
  1258. pdf.SetXY(240, y)
  1259. T_consignee_unit_temp := []rune(waybill.ConsigneeAddressName)
  1260. if len(T_consignee_unit_temp) > 17 {
  1261. pdf.Text(fmt.Sprintf("收货人:%s", string(T_consignee_unit_temp[0:17])))
  1262. pdf.SetXY(290, y+15)
  1263. pdf.Text(fmt.Sprintf("%s", string(T_consignee_unit_temp[17:])))
  1264. } else {
  1265. pdf.Text(fmt.Sprintf("收货人:%s", string(T_consignee_unit_temp)))
  1266. }
  1267. // 承运方
  1268. y += 15
  1269. pdf.SetXY(10, y)
  1270. company_name := []rune(waybill.Dept.Name)
  1271. pdf.Text(fmt.Sprintf("承运方:%s", string(company_name)))
  1272. y += 15
  1273. pdf.SetXY(10, y)
  1274. T_remark_temp := []rune(waybill.Remark)
  1275. if len(waybill.Remark) > 35 {
  1276. pdf.Text(fmt.Sprintf("备注:%s", string(T_remark_temp[0:35])))
  1277. pdf.SetXY(10, y+15)
  1278. pdf.Text(fmt.Sprintf("%s", string(T_remark_temp[35:])))
  1279. } else {
  1280. pdf.Text(fmt.Sprintf("备注: %s", string(T_remark_temp)))
  1281. }
  1282. y += 15
  1283. //pdf.SetFont("wts", "", 16)
  1284. //pdf.SetXY(10, y)
  1285. //pdf.Text("记录曲线信息")
  1286. //// 线
  1287. //y += 10
  1288. //pdf.SetLineWidth(0.5)
  1289. //pdf.SetStrokeColor(169, 169, 169)
  1290. //pdf.Line(10, y, 585, y)
  1291. //y += 1
  1292. //
  1293. //var tempFilepath string
  1294. //tempFilepath, err = DeviceDataTemperatureJPG2(s_time, e_time, waybillPDF)
  1295. //if err == nil {
  1296. // imgH, _ := gopdf.ImageHolderByPath(tempFilepath)
  1297. // pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 315})
  1298. // y += 315
  1299. //}
  1300. //
  1301. //var humidityFilepath string
  1302. //if req.HumidityShow {
  1303. // humidityFilepath, err = DeviceDataHumidityJPG2(s_time, e_time, waybillPDF)
  1304. // if err == nil {
  1305. // imgH, _ := gopdf.ImageHolderByPath(humidityFilepath)
  1306. // pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 315})
  1307. // y += 315
  1308. // }
  1309. //}
  1310. if y > 841.89 {
  1311. // 图片结束直接分页
  1312. pdf.AddPage()
  1313. y = 20
  1314. }
  1315. y += 20
  1316. pdf.SetFont("wts", "", 16)
  1317. pdf.SetXY(10, y)
  1318. pdf.Text("记录数据信息")
  1319. // 线
  1320. y += 10
  1321. pdf.SetLineWidth(0.5)
  1322. pdf.SetStrokeColor(169, 169, 169)
  1323. pdf.Line(10, y, 585, y)
  1324. y += 10
  1325. pdf.SetFont("wts", "", 10)
  1326. var x float64 = 10
  1327. var w float64 = 112
  1328. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1329. x = x + w
  1330. w = 101
  1331. lib.RectFillColor(pdf, "名称", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1332. if req.HumidityShow {
  1333. x = x + w
  1334. w = 37
  1335. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1336. x = x + w
  1337. w = 37
  1338. lib.RectFillColor(pdf, "湿度%", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1339. } else {
  1340. x = x + w
  1341. w = 37 * 2
  1342. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1343. }
  1344. x = x + w
  1345. w = 112
  1346. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1347. x = x + w
  1348. w = 101
  1349. lib.RectFillColor(pdf, "名称", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1350. if req.HumidityShow {
  1351. x = x + w
  1352. w = 37
  1353. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1354. x = x + w
  1355. w = 37
  1356. lib.RectFillColor(pdf, "湿度%", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1357. } else {
  1358. x = x + w
  1359. w = 37 * 2
  1360. lib.RectFillColor(pdf, "温度℃", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1361. }
  1362. y += 20
  1363. var textH float64 = 25 // if text height is 25px.
  1364. for i, v := range first_column {
  1365. pdf.SetNewY(y, textH)
  1366. y = pdf.GetY()
  1367. x, w = 10, 112
  1368. lib.RectFillColor(pdf, v.T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1369. x = x + w
  1370. w = 101
  1371. lib.RectFillColor(pdf, v.T_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1372. // 显示温湿度
  1373. if req.HumidityShow {
  1374. x = x + w
  1375. w = 37
  1376. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", v.T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1377. x = x + w
  1378. w = 37
  1379. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", v.T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1380. } else {
  1381. x = x + w
  1382. w = 37 * 2
  1383. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", v.T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1384. }
  1385. if i < len(second_column) {
  1386. x = x + w
  1387. w = 112
  1388. lib.RectFillColor(pdf, second_column[i].T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1389. x = x + w
  1390. w = 101
  1391. lib.RectFillColor(pdf, second_column[i].T_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1392. if req.HumidityShow {
  1393. x = x + w
  1394. w = 37
  1395. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1396. x = x + w
  1397. w = 37
  1398. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1399. } else {
  1400. x = x + w
  1401. w = 37 * 2
  1402. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1403. }
  1404. }
  1405. y += 20
  1406. }
  1407. if len(second_column) > len(first_column) {
  1408. for i := len(first_column); i < len(second_column); i++ {
  1409. pdf.SetNewY(y, textH)
  1410. y = pdf.GetY()
  1411. x, w = 297, 112
  1412. lib.RectFillColor(pdf, second_column[i].T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1413. x = x + w
  1414. w = 101
  1415. lib.RectFillColor(pdf, second_column[i].T_name, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1416. if req.HumidityShow {
  1417. x = x + w
  1418. w = 37
  1419. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1420. x = x + w
  1421. w = 37
  1422. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_rh), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1423. } else {
  1424. x = x + w
  1425. w = 37 * 2
  1426. lib.RectFillColor(pdf, fmt.Sprintf(" %.1f ", second_column[i].T_t), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1427. }
  1428. y += 20
  1429. }
  1430. }
  1431. filename := "运单" + req.WaybillNo + "温湿度记录" + time.Now().Format("20060102150405") + ".pdf"
  1432. filePath := "ofile/" + filename
  1433. err = pdf.WritePdf(filePath)
  1434. if err != nil {
  1435. return
  1436. }
  1437. defer func() {
  1438. //os.Remove(tempFilepath)
  1439. //os.Remove(humidityFilepath)
  1440. os.Remove(filePath)
  1441. }()
  1442. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(filename))
  1443. c.Header("Content-Transfer-Encoding", "binary")
  1444. c.File(filePath)
  1445. }
  1446. func (e WaybillController) TemperaturePDF(c *gin.Context) {
  1447. s := service.Waybill{}
  1448. companySvc := service.Company{}
  1449. req := dto.WaybillGetByWaybillPdfReq{}
  1450. err := e.MakeContext(c).
  1451. MakeOrm().
  1452. Bind(&req, binding.Query).
  1453. MakeService(&s.Service).
  1454. MakeService(&companySvc.Service).
  1455. Errors
  1456. if err != nil {
  1457. e.Logger.Error(err)
  1458. e.Error(500, err, err.Error())
  1459. return
  1460. }
  1461. var waybill model.Waybill
  1462. err = s.GetByWaybillNo(&req, &waybill, nil)
  1463. if err != nil {
  1464. e.Error(500, err, err.Error())
  1465. return
  1466. }
  1467. var company model.SysDept
  1468. err = companySvc.Get(&dto.CompanyGetReq{Id: waybill.DeptId}, &company)
  1469. if err != nil {
  1470. e.Error(500, err, err.Error())
  1471. return
  1472. }
  1473. filename, filePath, err := PDF(s, waybill, company, req.HumidityShow)
  1474. defer func() {
  1475. os.Remove(filePath)
  1476. }()
  1477. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(filename))
  1478. c.Header("Content-Transfer-Encoding", "binary")
  1479. c.File(filePath)
  1480. }
  1481. func PDF(s service.Waybill, waybill model.Waybill, company model.SysDept, humidityShow bool) (filename, filePath string, err error) {
  1482. DeviceSensor_data, Pdf_data, waybillPDF, err := s.GetTwoDeviceSensorData(&dto.WaybillGetByWaybillNoReq{WaybillNo: waybill.WaybillNo})
  1483. // 最高温度、最低温度、最高湿度、最低湿度
  1484. var maxTemp, minTemp, maxHumidity, minHumidity float32
  1485. // 最高温度时间、最低温度时间、最高湿度时间、最低湿度时间
  1486. var maxTempTime, minTempTime, maxHumidityTime, minHumidityTime string
  1487. // 总温度 总湿度
  1488. var totalTemp, totalHumidity float32
  1489. // 平均温度 平均湿度
  1490. var avgTemp, avgHumidity float32
  1491. // 温度阈值,湿度阈值
  1492. var tempThreshold, humidityThreshold string
  1493. // 记录开始时间,记录结束时间
  1494. var s_time, e_time string
  1495. if len(DeviceSensor_data) > 0 {
  1496. tempThreshold = fmt.Sprintf("%.1f-%.1f", DeviceSensor_data[0].T_tl, DeviceSensor_data[0].T_tu)
  1497. humidityThreshold = fmt.Sprintf("%.1f-%.1f", DeviceSensor_data[0].T_rhl, DeviceSensor_data[0].T_rhu)
  1498. s_time = DeviceSensor_data[0].T_time
  1499. e_time = DeviceSensor_data[len(DeviceSensor_data)-1].T_time
  1500. // 最高温度及时刻
  1501. maxTemp = DeviceSensor_data[0].T_t
  1502. maxTempTime = DeviceSensor_data[0].T_time
  1503. // 最低温度及时刻
  1504. minTemp = DeviceSensor_data[0].T_t
  1505. minTempTime = DeviceSensor_data[0].T_time
  1506. // 最高湿度及时刻
  1507. maxHumidity = DeviceSensor_data[0].T_rh
  1508. maxHumidityTime = DeviceSensor_data[0].T_time
  1509. // 获取最低湿度及时刻
  1510. minHumidity = DeviceSensor_data[0].T_rh
  1511. minHumidityTime = DeviceSensor_data[0].T_time
  1512. for i := 0; i < len(DeviceSensor_data); i++ {
  1513. data := DeviceSensor_data[i]
  1514. if data.T_t > maxTemp {
  1515. maxTemp = data.T_t
  1516. maxTempTime = data.T_time
  1517. }
  1518. if data.T_t < minTemp {
  1519. minTemp = data.T_t
  1520. minTempTime = data.T_time
  1521. }
  1522. totalTemp += data.T_t
  1523. if data.T_rh > maxHumidity {
  1524. maxHumidity = data.T_rh
  1525. maxHumidityTime = data.T_time
  1526. }
  1527. if data.T_rh < minHumidity {
  1528. minHumidity = data.T_rh
  1529. minHumidityTime = data.T_time
  1530. }
  1531. totalHumidity += data.T_rh
  1532. }
  1533. // 平均温度
  1534. avgTemp = totalTemp / float32(len(DeviceSensor_data))
  1535. // 平均湿度
  1536. avgHumidity = totalHumidity / float32(len(DeviceSensor_data))
  1537. }
  1538. // -------------------获取最高温湿度、温蒂温湿度、平均温湿度结束
  1539. pdf := &gopdf.GoPdf{}
  1540. pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
  1541. err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
  1542. if err != nil {
  1543. return
  1544. }
  1545. err = pdf.SetFont("wts", "", 20)
  1546. if err != nil {
  1547. return
  1548. }
  1549. pdf.SetGrayFill(0.5)
  1550. pdf.SetMargins(0, 20, 0, 20)
  1551. pdf.AddPage()
  1552. if len(company.Logo) > 0 {
  1553. imgH, errImg := lib.GetImage(company.Logo)
  1554. if errImg != nil {
  1555. err = errors.New("获取图片失败")
  1556. return
  1557. }
  1558. imgWidth := float64(imgH.Bounds().Dx())
  1559. imgHeight := float64(imgH.Bounds().Dy())
  1560. H := 60.
  1561. W := (imgWidth * H) / imgHeight
  1562. if strings.Contains(company.Logo, ".png") {
  1563. err = pdf.ImageFrom(imgH, 10, 0, &gopdf.Rect{W: W, H: H})
  1564. if err != nil {
  1565. err = errors.New("写入图片失败")
  1566. return
  1567. }
  1568. } else {
  1569. fileName := "./ofile/" + time.Now().Format("20060102150405") + ".png"
  1570. f, _ := os.Create(fileName)
  1571. defer f.Close()
  1572. defer func() {
  1573. os.Remove(fileName)
  1574. }()
  1575. png.Encode(f, imgH)
  1576. err = pdf.Image(fileName, 10, 0, &gopdf.Rect{W: W, H: H})
  1577. if err != nil {
  1578. if err.Error() == "16-bit depth not supported" {
  1579. fileName2 := "./ofile/" + time.Now().Format("20060102150405") + ".png"
  1580. f2, _ := os.Create(fileName2)
  1581. defer f.Close()
  1582. defer func() {
  1583. os.Remove(fileName2)
  1584. }()
  1585. jpeg.Encode(f2, imgH, &jpeg.Options{100})
  1586. err = pdf.Image(fileName2, 10, 0, &gopdf.Rect{W: W, H: H})
  1587. }
  1588. if err != nil {
  1589. err = errors.New("写入图片失败")
  1590. return
  1591. }
  1592. }
  1593. }
  1594. }
  1595. title := "运单" + waybill.WaybillNo + "温度记录"
  1596. if humidityShow {
  1597. title = "运单" + waybill.WaybillNo + "温湿度记录"
  1598. }
  1599. var y float64 = 70
  1600. textw, _ := pdf.MeasureTextWidth(title)
  1601. pdf.SetX((595 / 2) - (textw / 2))
  1602. pdf.SetY(y)
  1603. pdf.Text(title)
  1604. y += 30
  1605. pdf.SetFont("wts", "", 16)
  1606. pdf.SetXY(10, y)
  1607. pdf.Text("记录概要信息")
  1608. // 线
  1609. y += 10
  1610. pdf.SetLineWidth(0.5)
  1611. pdf.SetStrokeColor(169, 169, 169)
  1612. pdf.Line(10, y, 585, y)
  1613. y += 20
  1614. pdf.SetFont("wts", "", 10)
  1615. pdf.SetXY(10, y)
  1616. pdf.Text(fmt.Sprintf("记录开始时间:%s", s_time))
  1617. pdf.SetXY(240, y)
  1618. pdf.Text(fmt.Sprintf("记录结束时间:%s", e_time))
  1619. sTime, _ := lib.TimeStrToTime(s_time)
  1620. eTime, _ := lib.TimeStrToTime(e_time)
  1621. pdf.SetXY(470, y)
  1622. minutes := int(eTime.Sub(sTime).Minutes())
  1623. hours := minutes / 60
  1624. remainingMinutes := minutes % 60
  1625. pdf.Text(fmt.Sprintf("记录总时间:%dh%dmin", hours, remainingMinutes))
  1626. // -------------最高温/湿度 最低温/湿度 平均温/湿度
  1627. y += 15
  1628. pdf.SetXY(10, y)
  1629. pdf.Text(fmt.Sprintf("最高温度:%.1f℃,%s", lib.RoundToDecimal(float64(maxTemp), 1), maxTempTime))
  1630. pdf.SetXY(240, y)
  1631. pdf.Text(fmt.Sprintf("最低温度:%.1f℃,%s", lib.RoundToDecimal(float64(minTemp), 1), minTempTime))
  1632. pdf.SetXY(470, y)
  1633. pdf.Text(fmt.Sprintf("平均温度:%.1f℃", lib.RoundToDecimal(float64(avgTemp), 1)))
  1634. if humidityShow {
  1635. y += 15
  1636. pdf.SetXY(10, y)
  1637. pdf.Text(fmt.Sprintf("最高湿度:%.1f%%RH,%s", lib.RoundToDecimal(float64(maxHumidity), 1), maxHumidityTime))
  1638. pdf.SetXY(240, y)
  1639. pdf.Text(fmt.Sprintf("最低湿度:%.1f%%RH,%s", lib.RoundToDecimal(float64(minHumidity), 1), minHumidityTime))
  1640. pdf.SetXY(470, y)
  1641. pdf.Text(fmt.Sprintf("平均湿度:%.1f%%RH", lib.RoundToDecimal(float64(avgHumidity), 1)))
  1642. }
  1643. // -------------温/湿度阈值
  1644. y += 15
  1645. pdf.SetXY(10, y)
  1646. pdf.Text(fmt.Sprintf("温度阈值:%s℃", tempThreshold))
  1647. if humidityShow {
  1648. pdf.SetXY(240, y)
  1649. pdf.Text(fmt.Sprintf("温度阈值:%s%%", humidityThreshold))
  1650. }
  1651. //-------------发货单位,收货单位,备注
  1652. y += 15
  1653. pdf.SetXY(10, y)
  1654. T_forwarding_unit_temp := []rune(waybill.SenderAddressName)
  1655. if len(T_forwarding_unit_temp) > 17 {
  1656. pdf.Text(fmt.Sprintf("发货人:%s", string(T_forwarding_unit_temp[0:17])))
  1657. pdf.SetXY(60, y+15)
  1658. pdf.Text(fmt.Sprintf("%s", string(T_forwarding_unit_temp[17:])))
  1659. } else {
  1660. pdf.Text(fmt.Sprintf("发货人:%s", string(T_forwarding_unit_temp)))
  1661. }
  1662. pdf.SetXY(240, y)
  1663. T_consignee_unit_temp := []rune(waybill.ConsigneeAddressName)
  1664. if len(T_consignee_unit_temp) > 17 {
  1665. pdf.Text(fmt.Sprintf("收货人:%s", string(T_consignee_unit_temp[0:17])))
  1666. pdf.SetXY(290, y+15)
  1667. pdf.Text(fmt.Sprintf("%s", string(T_consignee_unit_temp[17:])))
  1668. } else {
  1669. pdf.Text(fmt.Sprintf("收货人:%s", string(T_consignee_unit_temp)))
  1670. }
  1671. // 承运方
  1672. y += 15
  1673. pdf.SetXY(10, y)
  1674. company_name := []rune(waybill.Dept.Name)
  1675. pdf.Text(fmt.Sprintf("承运方:%s", string(company_name)))
  1676. y += 15
  1677. pdf.SetXY(10, y)
  1678. T_remark_temp := []rune(waybill.Remark)
  1679. if len(waybill.Remark) > 35 {
  1680. pdf.Text(fmt.Sprintf("备注:%s", string(T_remark_temp[0:35])))
  1681. pdf.SetXY(10, y+15)
  1682. pdf.Text(fmt.Sprintf("%s", string(T_remark_temp[35:])))
  1683. } else {
  1684. pdf.Text(fmt.Sprintf("备注: %s", string(T_remark_temp)))
  1685. }
  1686. y += 35
  1687. pdf.SetFont("wts", "", 16)
  1688. pdf.SetXY(10, y)
  1689. pdf.Text("记录曲线信息")
  1690. // 线
  1691. y += 10
  1692. pdf.SetLineWidth(0.5)
  1693. pdf.SetStrokeColor(169, 169, 169)
  1694. pdf.Line(10, y, 585, y)
  1695. y += 1
  1696. var tempFilepath string
  1697. tempFilepath, err = DeviceDataTemperatureJPG3(s_time, e_time, waybillPDF)
  1698. if err == nil {
  1699. imgH, _ := gopdf.ImageHolderByPath(tempFilepath)
  1700. pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 315})
  1701. y += 315
  1702. }
  1703. //var humidityFilepath string
  1704. //if req.HumidityShow {
  1705. // humidityFilepath, err = DeviceDataHumidityJPG2(s_time, e_time, waybillPDF)
  1706. // if err == nil {
  1707. // imgH, _ := gopdf.ImageHolderByPath(humidityFilepath)
  1708. // pdf.ImageByHolder(imgH, 10, y, &gopdf.Rect{W: 575, H: 315})
  1709. // y += 315
  1710. // }
  1711. //}
  1712. if y > 841.89 {
  1713. // 图片结束直接分页
  1714. pdf.AddPage()
  1715. y = 20
  1716. }
  1717. y += 20
  1718. pdf.SetFont("wts", "", 16)
  1719. pdf.SetXY(10, y)
  1720. pdf.Text("记录数据信息")
  1721. // 线
  1722. y += 10
  1723. pdf.SetLineWidth(0.5)
  1724. pdf.SetStrokeColor(169, 169, 169)
  1725. pdf.Line(10, y, 585, y)
  1726. y += 10
  1727. pdf.SetFont("wts", "", 10)
  1728. var x float64 = 19
  1729. var w float64 = 112
  1730. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1731. x = x + w
  1732. w = 37
  1733. lib.RectFillColor(pdf, "T1", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1734. x = x + w
  1735. lib.RectFillColor(pdf, "T2", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1736. x = x + w
  1737. w = 112
  1738. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1739. x = x + w
  1740. w = 37
  1741. lib.RectFillColor(pdf, "T1", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1742. x = x + w
  1743. lib.RectFillColor(pdf, "T2", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1744. x = x + w
  1745. w = 112
  1746. lib.RectFillColor(pdf, "时间", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1747. x = x + w
  1748. w = 37
  1749. lib.RectFillColor(pdf, "T1", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1750. x = x + w
  1751. lib.RectFillColor(pdf, "T2", 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1752. for i, v := range Pdf_data {
  1753. if i%3 == 0 {
  1754. y += 20
  1755. var textH float64 = 25 // if text height is 25px.
  1756. pdf.SetNewY(y, textH)
  1757. y = pdf.GetY()
  1758. x, w = 19, 112
  1759. lib.RectFillColor(pdf, v.T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1760. x = x + w
  1761. w = 37
  1762. lib.RectFillColor(pdf, lib.Float32_to_string(&v.T_id1), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1763. x = x + w
  1764. lib.RectFillColor(pdf, lib.Float32_to_string(&v.T_id2), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1765. }
  1766. if i%3 == 1 {
  1767. x = x + w
  1768. w = 112
  1769. lib.RectFillColor(pdf, v.T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1770. x = x + w
  1771. w = 37
  1772. lib.RectFillColor(pdf, lib.Float32_to_string(&v.T_id1), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1773. x = x + w
  1774. lib.RectFillColor(pdf, lib.Float32_to_string(&v.T_id2), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1775. }
  1776. if i%3 == 2 {
  1777. x = x + w
  1778. w = 112
  1779. lib.RectFillColor(pdf, v.T_time, 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1780. x = x + w
  1781. w = 37
  1782. lib.RectFillColor(pdf, lib.Float32_to_string(&v.T_id1), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1783. x = x + w
  1784. lib.RectFillColor(pdf, lib.Float32_to_string(&v.T_id2), 12, x, y, w, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
  1785. }
  1786. }
  1787. filename = "运单" + waybill.WaybillNo + "温度记录" + time.Now().Format("20060102150405") + ".pdf"
  1788. filePath = "ofile/" + filename
  1789. err = pdf.WritePdf(filePath)
  1790. if err != nil {
  1791. return
  1792. }
  1793. defer func() {
  1794. os.Remove(tempFilepath)
  1795. }()
  1796. return filename, filePath, nil
  1797. }
  1798. // WaybillPDF 导出运单pdf
  1799. // @Summary 导出运单pdf
  1800. // @Description 导出运单pdf
  1801. // @Tags 运单
  1802. // @Param no query string false "运单号"
  1803. // @Param pageSize query int false "页条数"
  1804. // @Param page query int false "页码"
  1805. // @Success 200 {object} response.Response{data=response.Page{list=[]model.Waybill}} "{"code": 200, "data": [...]}"
  1806. // @Router /api/waybill [get]
  1807. // @Security Bearer
  1808. func (e WaybillController) WaybillPDF(c *gin.Context) {
  1809. s := service.Waybill{}
  1810. companySvc := service.Company{}
  1811. req := dto.WaybillGetByWaybillPdfReq{}
  1812. err := e.MakeContext(c).
  1813. MakeOrm().
  1814. Bind(&req, binding.Query).
  1815. MakeService(&s.Service).
  1816. MakeService(&companySvc.Service).
  1817. Errors
  1818. if err != nil {
  1819. e.Logger.Error(err)
  1820. e.Error(500, err, err.Error())
  1821. return
  1822. }
  1823. var waybill model.Waybill
  1824. var company model.SysDept
  1825. //err = s.GetByWaybillNo(&req, &waybill, p)
  1826. err = s.GetByWaybillNo(&req, &waybill, nil)
  1827. if err != nil {
  1828. e.Error(500, err, err.Error())
  1829. return
  1830. }
  1831. err = companySvc.Get(&dto.CompanyGetReq{Id: waybill.DeptId}, &company)
  1832. if err != nil {
  1833. e.Error(500, err, err.Error())
  1834. return
  1835. }
  1836. // -------------------生成运单条码
  1837. // 运单条码
  1838. cs, _ := code128.Encode(waybill.WaybillNo)
  1839. // 创建一个要输出数据的文件
  1840. imgPath := "ofile/img/" + waybill.WaybillNo + ".png"
  1841. file, _ := os.Create(imgPath)
  1842. defer file.Close()
  1843. // 设置图片像素大小
  1844. barCode, _ := barcode.Scale(cs, 205, 50)
  1845. // 将code128的条形码编码为png图片
  1846. png.Encode(file, barCode)
  1847. imgPath2 := "ofile/img/" + waybill.WaybillNo + ".jpg"
  1848. png2j.Con2jpg(imgPath, imgPath2)
  1849. qrcode, err := qrcode.Encode(fmt.Sprintf("%s/WaybillInquiry?waybillNo=%s", conf.ExtConfig.Service.Domain, waybill.WaybillNo),
  1850. qrcode.Medium, 70)
  1851. if err != nil {
  1852. e.Error(500, err, err.Error())
  1853. return
  1854. }
  1855. qrCodeImgH, err := gopdf.ImageHolderByBytes(qrcode)
  1856. if err != nil {
  1857. e.Error(500, err, err.Error())
  1858. return
  1859. }
  1860. pdf := &gopdf.GoPdf{}
  1861. pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 283.46, H: 283.46}}) //595.28, 841.89 = A4
  1862. //pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4
  1863. err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
  1864. if err != nil {
  1865. return
  1866. }
  1867. pdf.SetGrayFill(0.5)
  1868. pdf.SetMargins(0, 10, 0, 10)
  1869. for i := 0; i < waybill.Quantity; i++ {
  1870. pdf.AddPage()
  1871. var y float64 = 20
  1872. pdf.SetFont("wts", "", 10)
  1873. //y += 12
  1874. pdf.SetXY(250, 20)
  1875. pdf.SetFont("wts", "", 13)
  1876. if waybill.Quantity > 1 {
  1877. pdf.Text(fmt.Sprintf("%d/%d", i+1, waybill.Quantity))
  1878. }
  1879. pdf.SetFont("wts", "", 10)
  1880. y += 10
  1881. pdf.Image(imgPath2, 20, y, &gopdf.Rect{W: 240, H: 30})
  1882. y += 43
  1883. textw, _ := pdf.MeasureTextWidth(waybill.WaybillNo)
  1884. pdf.SetX((283.46 / 2) - (textw / 2))
  1885. pdf.SetY(y)
  1886. pdf.Text(waybill.WaybillNo)
  1887. if len(company.Logo) > 0 {
  1888. imgH, errImg := lib.GetImage(company.Logo)
  1889. if errImg != nil {
  1890. err = errors.New("获取图片失败")
  1891. e.Error(500, err, err.Error())
  1892. return
  1893. }
  1894. imgWidth := float64(imgH.Bounds().Dx())
  1895. imgHeight := float64(imgH.Bounds().Dy())
  1896. H := 30.
  1897. W := (imgWidth * H) / imgHeight
  1898. if strings.Contains(company.Logo, ".png") {
  1899. err = pdf.ImageFrom(imgH, 10, 0, &gopdf.Rect{W: W, H: H})
  1900. if err != nil {
  1901. err = errors.New("写入图片失败")
  1902. e.Error(500, err, err.Error())
  1903. return
  1904. }
  1905. } else {
  1906. fileName := "./ofile/" + time.Now().Format("20060102150405") + ".png"
  1907. f, _ := os.Create(fileName)
  1908. defer f.Close()
  1909. defer func() {
  1910. os.Remove(fileName)
  1911. }()
  1912. png.Encode(f, imgH)
  1913. err = pdf.Image(fileName, 10, 0, &gopdf.Rect{W: W, H: H})
  1914. if err != nil {
  1915. if err.Error() == "16-bit depth not supported" {
  1916. fileName2 := "./ofile/" + time.Now().Format("20060102150405") + ".png"
  1917. f2, _ := os.Create(fileName2)
  1918. defer f.Close()
  1919. defer func() {
  1920. os.Remove(fileName2)
  1921. }()
  1922. jpeg.Encode(f2, imgH, &jpeg.Options{100})
  1923. err = pdf.Image(fileName2, 10, 0, &gopdf.Rect{W: W, H: H})
  1924. }
  1925. if err != nil {
  1926. err = errors.New("写入图片失败")
  1927. e.Error(500, err, err.Error())
  1928. return
  1929. }
  1930. }
  1931. }
  1932. } else {
  1933. title := "#" + company.Name
  1934. pdf.SetXY(10, 20)
  1935. pdf.Text(title)
  1936. }
  1937. // 线
  1938. y += 6
  1939. pdf.SetLineWidth(0.5)
  1940. pdf.SetLineType("dotted")
  1941. pdf.Line(10, y, 273, y)
  1942. y += 28
  1943. pdf.SetFont("wts", "", 18)
  1944. pdf.SetXY(12, y+3)
  1945. pdf.Text("收")
  1946. pdf.SetFont("wts", "", 10)
  1947. y -= 5
  1948. pdf.SetXY(40, y)
  1949. pdf.Text(fmt.Sprintf("%s %s", lib.MaskStr(waybill.ConsigneeAddressName), lib.MaskPhoneNumber(waybill.ConsigneeAddressPhone)))
  1950. y += 15
  1951. pdf.SetXY(40, y)
  1952. pdf.Text(waybill.ConsigneeAddressDetails)
  1953. // 线
  1954. y += 8
  1955. pdf.SetLineWidth(0.5)
  1956. pdf.SetLineType("dotted")
  1957. pdf.Line(10, y, 273, y)
  1958. y += 22
  1959. pdf.SetFont("wts", "", 13)
  1960. pdf.SetXY(14, y+3)
  1961. pdf.Text("寄")
  1962. pdf.SetFont("wts", "", 10)
  1963. y -= 5
  1964. pdf.SetXY(40, y)
  1965. pdf.Text(fmt.Sprintf("%s %s", lib.MaskStr(waybill.SenderAddressName), lib.MaskPhoneNumber(waybill.SenderAddressPhone)))
  1966. y += 15
  1967. pdf.SetXY(40, y)
  1968. pdf.Text(waybill.SenderAddressDetails)
  1969. // 线
  1970. y += 10
  1971. pdf.SetLineWidth(0.5)
  1972. //pdf.SetLineType("dashed")
  1973. pdf.SetLineType("dotted")
  1974. pdf.Line(10, y, 273, y)
  1975. y += 12
  1976. pdf.SetXY(10, y)
  1977. pdf.SetFont("wts", "", 8)
  1978. pdf.Text("下单时间:" + waybill.OrderTime.String())
  1979. // 线
  1980. y += 6
  1981. pdf.SetLineWidth(0.5)
  1982. pdf.SetLineType("dotted")
  1983. pdf.Line(10, y, 273, y)
  1984. pdf.SetFont("wts", "", 10)
  1985. y += 20
  1986. pdf.SetXY(10, y)
  1987. pdf.Text("备注:")
  1988. pdf.SetFont("wts", "", 8)
  1989. y += 15
  1990. pdf.SetXY(30, y)
  1991. pdf.Text("货物类型:" + waybill.CargoType)
  1992. y += 15
  1993. pdf.SetXY(30, y)
  1994. pdf.Text("温度要求:" + waybill.TemperatureInterval)
  1995. y += 15
  1996. pdf.SetXY(30, y)
  1997. pdf.Text("配送要求:" + waybill.DeliveryCondition)
  1998. x := 170.
  1999. //pdf.Image(qrcodeImgPath2, x, y-55, &gopdf.Rect{W: 70, H: 70})
  2000. pdf.ImageByHolder(qrCodeImgH, x, y-63, &gopdf.Rect{W: 70, H: 70})
  2001. pdf.SetFont("wts", "", 8)
  2002. y += 10
  2003. textw, _ = pdf.MeasureTextWidth("扫码查询")
  2004. pdf.SetX(x + 35 - (textw / 2))
  2005. pdf.SetY(y)
  2006. pdf.Text("扫码查询")
  2007. y += 10
  2008. textw, _ = pdf.MeasureTextWidth("物流温湿度信息")
  2009. pdf.SetX(x + 35 - (textw / 2))
  2010. pdf.SetY(y)
  2011. pdf.Text("物流温湿度信息")
  2012. }
  2013. filename := "运单" + req.WaybillNo + ".pdf"
  2014. filePath := "ofile/" + filename
  2015. err = pdf.WritePdf(filePath)
  2016. if err != nil {
  2017. return
  2018. }
  2019. defer func() {
  2020. os.Remove(filePath)
  2021. os.Remove(imgPath)
  2022. os.Remove(imgPath2)
  2023. }()
  2024. c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(filename))
  2025. c.Header("Content-Transfer-Encoding", "binary")
  2026. c.File(filePath)
  2027. }
  2028. // SendMail 发送邮件
  2029. // @Summary 通过id获取运单
  2030. // @Description 通过id获取运单
  2031. // @Tags 运单
  2032. // @Param id path string true "运单id"
  2033. // @Success 200 {object} response.Response{data=model.Waybill} "{"code": 200, "data": [...]}"
  2034. // @Router /api/waybill/{id} [get]
  2035. // @Security Bearer
  2036. func (e WaybillController) SendMail(c *gin.Context) {
  2037. s := service.Waybill{}
  2038. companySvc := service.Company{}
  2039. req := dto.WaybillSendMailPdfReq{}
  2040. err := e.MakeContext(c).
  2041. MakeOrm().
  2042. Bind(&req, binding.JSON, nil).
  2043. MakeService(&s.Service).
  2044. MakeService(&companySvc.Service).
  2045. Errors
  2046. if err != nil {
  2047. e.Logger.Error(err)
  2048. e.Error(500, err, err.Error())
  2049. return
  2050. }
  2051. var waybill model.Waybill
  2052. err = s.GetByWaybillNo(&dto.WaybillGetByWaybillPdfReq{WaybillNo: req.WaybillNo, HumidityShow: req.HumidityShow}, &waybill, nil)
  2053. if err != nil {
  2054. e.Error(500, err, err.Error())
  2055. return
  2056. }
  2057. var company model.SysDept
  2058. err = companySvc.Get(&dto.CompanyGetReq{Id: waybill.DeptId}, &company)
  2059. if err != nil {
  2060. e.Error(500, err, err.Error())
  2061. return
  2062. }
  2063. _, filePath, err := PDF(s, waybill, company, req.HumidityShow)
  2064. defer func() {
  2065. os.Remove(filePath)
  2066. }()
  2067. em := email.NewEmail()
  2068. em.From = "冷链物流运输 <bzdcold@163.com>"
  2069. em.To = req.To
  2070. em.Subject = fmt.Sprintf("【冷链物流运输】运单%s温湿度记录", waybill.WaybillNo)
  2071. em.Text = []byte(fmt.Sprintf("运单%s温湿度记录", waybill.WaybillNo))
  2072. // 主要就是在这个位置添加了附件,注意:这里AttachFile是Email结构体的方法而不是字段,所以不是用等于而是括号
  2073. em.AttachFile(filePath)
  2074. err = em.Send("smtp.163.com:25", smtp.PlainAuth("", "bzdcold@163.com", "ZIZXBCDKVTMPJMVX", "smtp.163.com"))
  2075. if err != nil {
  2076. e.Logger.Error(err)
  2077. e.Error(500, err, err.Error())
  2078. return
  2079. }
  2080. e.OK(nil, "发送成功")
  2081. }
  2082. // 获取温度图片
  2083. func DeviceDataTemperatureJPG(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  2084. if len(waybillPDF) == 0 {
  2085. return "", errors.New("暂无数据可生成图片")
  2086. }
  2087. // 创建一个新的绘图
  2088. p := plot.New()
  2089. // 设置绘图标题和标签
  2090. p.Title.Text = "temperature"
  2091. //p.Legend.ThumbnailWidth = 20
  2092. deviceSensorList := []nats_server.DeviceSensor_R{}
  2093. dataList := []nats_server.DeviceData_R{}
  2094. for _, w := range waybillPDF {
  2095. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  2096. dataList = append(dataList, w.Data...)
  2097. }
  2098. TemperatureMin := deviceSensorList[0].T_DeviceSensorParameter.T_Tlower
  2099. TemperatureMax := deviceSensorList[0].T_DeviceSensorParameter.T_Tupper
  2100. var ymin, ymax float32
  2101. for i, r := range dataList {
  2102. if i == 0 {
  2103. ymin = r.T_t
  2104. ymax = r.T_t
  2105. }
  2106. if ymin > r.T_t {
  2107. ymin = r.T_t
  2108. }
  2109. if ymax < r.T_t {
  2110. ymax = r.T_t
  2111. }
  2112. }
  2113. var chData = make(chan int, 10)
  2114. var jobGroup sync.WaitGroup
  2115. // 创建温度线
  2116. for i := 0; i < len(deviceSensorList); i++ {
  2117. chData <- 1
  2118. jobGroup.Add(1)
  2119. go func(index int) {
  2120. defer func() {
  2121. <-chData // 完成时chan取出1个
  2122. jobGroup.Done() // 完成时将等待组值减1
  2123. }()
  2124. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  2125. r_maps := []nats_server.DeviceData_R{}
  2126. for _, data := range dataList {
  2127. if data.T_sn == sn && data.T_id == id {
  2128. r_maps = append(r_maps, data)
  2129. }
  2130. }
  2131. fmt.Println(r_maps)
  2132. if len(r_maps) == 0 {
  2133. return
  2134. }
  2135. sort.Slice(r_maps, func(i, j int) bool {
  2136. return r_maps[i].T_time < r_maps[j].T_time
  2137. })
  2138. pts := make(plotter.XYs, len(r_maps))
  2139. for j, d := range r_maps {
  2140. t, _ := lib.TimeStrToTime(d.T_time)
  2141. pts[j].X = float64(t.Unix())
  2142. pts[j].Y = float64(d.T_t)
  2143. }
  2144. line, err := plotter.NewLine(pts)
  2145. if err != nil {
  2146. return
  2147. }
  2148. line.Color = randomColor(index)
  2149. p.Add(line)
  2150. }(i)
  2151. }
  2152. jobGroup.Wait()
  2153. st, _ := lib.TimeStrToTime(startTime)
  2154. et, _ := lib.TimeStrToTime(endTime)
  2155. xmin, xmax := float64(st.Unix()), float64(et.Unix())
  2156. // 添加最高,最低标准线 用红色虚线标识
  2157. p.Add(horizontalLine(xmin, xmax, float64(TemperatureMin)))
  2158. p.Add(horizontalLine(xmin, xmax, float64(TemperatureMax)))
  2159. if ymax < TemperatureMax {
  2160. ymax = TemperatureMax
  2161. }
  2162. if ymin > 0 {
  2163. ymin = 0
  2164. }
  2165. p.Y.Min, p.Y.Max = float64(ymin), float64(ymax)
  2166. p.X.Min, p.X.Max = xmin, xmax
  2167. p.Y.Tick.Marker = commaTicks{}
  2168. p.X.Tick.Marker = timeTicks{}
  2169. p.X.Tick.Label.Rotation = math.Pi / 5
  2170. p.X.Tick.Label.YAlign = draw.YCenter
  2171. p.X.Tick.Label.XAlign = draw.XRight
  2172. filepath := "ofile/" + "temperature" + deviceSensorList[0].T_sn + ".jpg"
  2173. // 保存文件
  2174. if err := p.Save(10*vg.Inch, 4*vg.Inch, filepath); err != nil {
  2175. logs.Error(lib.FuncName(), "生成图片失败", err)
  2176. return "", err
  2177. }
  2178. return filepath, nil
  2179. }
  2180. func DeviceDataTemperatureJPG2(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  2181. if len(waybillPDF) == 0 {
  2182. return "", errors.New("暂无数据可生成图片")
  2183. }
  2184. deviceSensorList := []nats_server.DeviceSensor_R{}
  2185. dataList := []nats_server.DeviceData_R{}
  2186. for _, w := range waybillPDF {
  2187. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  2188. dataList = append(dataList, w.Data...)
  2189. }
  2190. TemperatureMin := deviceSensorList[0].T_DeviceSensorParameter.T_Tlower
  2191. TemperatureMax := deviceSensorList[0].T_DeviceSensorParameter.T_Tupper
  2192. var ymin, ymax float32
  2193. for i, r := range dataList {
  2194. if i == 0 {
  2195. ymin = r.T_t
  2196. ymax = r.T_t
  2197. }
  2198. if ymin > r.T_t {
  2199. ymin = r.T_t
  2200. }
  2201. if ymax < r.T_t {
  2202. ymax = r.T_t
  2203. }
  2204. }
  2205. series := make([]chart.Series, 0)
  2206. var chData = make(chan int, 10)
  2207. var jobGroup sync.WaitGroup
  2208. // 创建温度线
  2209. for i := 0; i < len(deviceSensorList); i++ {
  2210. chData <- 1
  2211. jobGroup.Add(1)
  2212. go func(index int) {
  2213. defer func() {
  2214. <-chData // 完成时chan取出1个
  2215. jobGroup.Done() // 完成时将等待组值减1
  2216. }()
  2217. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  2218. r_maps := []nats_server.DeviceData_R{}
  2219. for _, data := range dataList {
  2220. if data.T_sn == sn && data.T_id == id {
  2221. r_maps = append(r_maps, data)
  2222. }
  2223. }
  2224. fmt.Println(r_maps)
  2225. if len(r_maps) == 0 {
  2226. return
  2227. }
  2228. sort.Slice(r_maps, func(i, j int) bool {
  2229. return r_maps[i].T_time < r_maps[j].T_time
  2230. })
  2231. xValues := make([]time.Time, len(r_maps))
  2232. yValues := make([]float64, len(r_maps))
  2233. for j := 0; j < len(r_maps); j++ {
  2234. t, _ := lib.TimeStrToTime(r_maps[j].T_time)
  2235. xValues[j] = t
  2236. yValues[j] = float64(r_maps[j].T_t)
  2237. }
  2238. series = append(series, chart.TimeSeries{
  2239. Name: fmt.Sprintf("%s-%d", sn, id),
  2240. XValues: xValues,
  2241. YValues: yValues,
  2242. })
  2243. }(i)
  2244. }
  2245. jobGroup.Wait()
  2246. if ymax < TemperatureMax {
  2247. ymax = TemperatureMax
  2248. }
  2249. if ymin > 0 {
  2250. ymin = 0
  2251. }
  2252. if ymin > TemperatureMin {
  2253. ymin = TemperatureMin
  2254. }
  2255. st, _ := lib.TimeStrToTime(startTime)
  2256. et, _ := lib.TimeStrToTime(endTime)
  2257. series = append(series, chart.TimeSeries{
  2258. Style: chart.Style{
  2259. StrokeColor: drawing.ColorRed,
  2260. StrokeDashArray: []float64{5.0, 5.0},
  2261. },
  2262. XValues: []time.Time{st, et},
  2263. YValues: []float64{float64(TemperatureMin), float64(TemperatureMin)},
  2264. })
  2265. series = append(series, chart.TimeSeries{
  2266. Style: chart.Style{
  2267. StrokeColor: drawing.ColorRed,
  2268. StrokeDashArray: []float64{5.0, 5.0},
  2269. },
  2270. XValues: []time.Time{st, et},
  2271. YValues: []float64{float64(TemperatureMax), float64(TemperatureMax)},
  2272. })
  2273. font := getZWFont()
  2274. graph := chart.Chart{
  2275. Title: "温度记录",
  2276. TitleStyle: chart.Style{
  2277. FontSize: 15,
  2278. },
  2279. Background: chart.Style{
  2280. Padding: chart.Box{
  2281. Top: 20,
  2282. },
  2283. },
  2284. Font: font,
  2285. XAxis: chart.XAxis{
  2286. Name: "时间",
  2287. ValueFormatter: chart.TimeValueFormatterWithFormat("2006-01-02 15:04"),
  2288. },
  2289. YAxis: chart.YAxis{
  2290. Name: "温度",
  2291. Range: &chart.ContinuousRange{
  2292. Min: float64(ymin),
  2293. Max: float64(ymax + 2),
  2294. },
  2295. },
  2296. Series: series,
  2297. }
  2298. //graph.Elements = []chart.Renderable{
  2299. // chart.Legend(&graph),
  2300. //}
  2301. filepath := "ofile/" + "temperature" + deviceSensorList[0].T_sn + ".jpg"
  2302. f, _ := os.Create(filepath)
  2303. defer f.Close()
  2304. graph.Render(chart.PNG, f)
  2305. return filepath, nil
  2306. }
  2307. func DeviceDataTemperatureJPG3(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  2308. if len(waybillPDF) == 0 {
  2309. return "", errors.New("暂无数据可生成图片")
  2310. }
  2311. deviceSensorList := []nats_server.DeviceSensor_R{}
  2312. dataList := []nats_server.DeviceData_R{}
  2313. deviceDataPdfList := []service.DeviceDataPdf{}
  2314. for _, w := range waybillPDF {
  2315. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  2316. dataList = append(dataList, w.Data...)
  2317. deviceDataPdfList = append(deviceDataPdfList, w.DeviceDataPdf...)
  2318. }
  2319. TemperatureMin := deviceSensorList[0].T_DeviceSensorParameter.T_Tlower
  2320. TemperatureMax := deviceSensorList[0].T_DeviceSensorParameter.T_Tupper
  2321. var ymin, ymax float32
  2322. for i, r := range dataList {
  2323. if i == 0 {
  2324. ymin = r.T_t
  2325. ymax = r.T_t
  2326. }
  2327. if ymin > r.T_t {
  2328. ymin = r.T_t
  2329. }
  2330. if ymax < r.T_t {
  2331. ymax = r.T_t
  2332. }
  2333. }
  2334. sort.Slice(deviceDataPdfList, func(i, j int) bool {
  2335. return deviceDataPdfList[i].T_time < deviceDataPdfList[j].T_time
  2336. })
  2337. series := make([]chart.Series, 0)
  2338. // 创建温度线
  2339. xValues := make([]time.Time, len(deviceDataPdfList))
  2340. yValues1 := make([]float64, len(deviceDataPdfList))
  2341. yValues2 := make([]float64, len(deviceDataPdfList))
  2342. for i := 0; i < len(deviceDataPdfList); i++ {
  2343. t, _ := lib.TimeStrToTime(deviceDataPdfList[i].T_time)
  2344. xValues[i] = t
  2345. yValues1[i] = float64(deviceDataPdfList[i].T_id1)
  2346. yValues2[i] = float64(deviceDataPdfList[i].T_id2)
  2347. }
  2348. series = append(series, chart.TimeSeries{
  2349. Name: "T1",
  2350. XValues: xValues,
  2351. YValues: yValues1,
  2352. })
  2353. series = append(series, chart.TimeSeries{
  2354. Name: "T2",
  2355. XValues: xValues,
  2356. YValues: yValues2,
  2357. })
  2358. if ymax < TemperatureMax {
  2359. ymax = TemperatureMax
  2360. }
  2361. if ymin > 0 {
  2362. ymin = 0
  2363. }
  2364. if ymin > TemperatureMin {
  2365. ymin = TemperatureMin
  2366. }
  2367. st, _ := lib.TimeStrToTime(startTime)
  2368. et, _ := lib.TimeStrToTime(endTime)
  2369. series = append(series, chart.TimeSeries{
  2370. Style: chart.Style{
  2371. StrokeColor: drawing.ColorRed,
  2372. StrokeDashArray: []float64{5.0, 5.0},
  2373. },
  2374. XValues: []time.Time{st, et},
  2375. YValues: []float64{float64(TemperatureMin), float64(TemperatureMin)},
  2376. })
  2377. series = append(series, chart.TimeSeries{
  2378. Style: chart.Style{
  2379. StrokeColor: drawing.ColorRed,
  2380. StrokeDashArray: []float64{5.0, 5.0},
  2381. },
  2382. XValues: []time.Time{st, et},
  2383. YValues: []float64{float64(TemperatureMax), float64(TemperatureMax)},
  2384. })
  2385. font := getZWFont()
  2386. graph := chart.Chart{
  2387. Title: "温度记录",
  2388. TitleStyle: chart.Style{
  2389. FontSize: 14,
  2390. },
  2391. Background: chart.Style{
  2392. Padding: chart.Box{
  2393. Top: 20,
  2394. },
  2395. },
  2396. Font: font,
  2397. XAxis: chart.XAxis{
  2398. Name: "时间",
  2399. ValueFormatter: chart.TimeValueFormatterWithFormat("2006-01-02 15:04"),
  2400. },
  2401. YAxis: chart.YAxis{
  2402. Name: "温度",
  2403. Range: &chart.ContinuousRange{
  2404. Min: float64(ymin),
  2405. Max: float64(ymax + 2),
  2406. },
  2407. },
  2408. Series: series,
  2409. }
  2410. //graph.Elements = []chart.Renderable{
  2411. // chart.Legend(&graph),
  2412. //}
  2413. filepath := "ofile/" + "temperature" + deviceSensorList[0].T_sn + ".jpg"
  2414. f, _ := os.Create(filepath)
  2415. defer f.Close()
  2416. graph.Render(chart.PNG, f)
  2417. return filepath, nil
  2418. }
  2419. // 获取湿度图片
  2420. func DeviceDataHumidityJPG(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  2421. if len(waybillPDF) == 0 {
  2422. return "", errors.New("暂无数据可生成图片")
  2423. }
  2424. // 创建一个新的绘图
  2425. p := plot.New()
  2426. // 设置绘图标题和标签
  2427. p.Title.Text = "humidity"
  2428. deviceSensorList := []nats_server.DeviceSensor_R{}
  2429. dataList := []nats_server.DeviceData_R{}
  2430. for _, w := range waybillPDF {
  2431. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  2432. dataList = append(dataList, w.Data...)
  2433. }
  2434. humidityMin := deviceSensorList[0].T_DeviceSensorParameter.T_RHlower
  2435. humidityMax := deviceSensorList[0].T_DeviceSensorParameter.T_RHupper
  2436. var ymin, ymax float32
  2437. for i, r := range dataList {
  2438. if i == 0 {
  2439. ymin = r.T_rh
  2440. ymax = r.T_rh
  2441. }
  2442. if ymin > r.T_rh {
  2443. ymin = r.T_rh
  2444. }
  2445. if ymax < r.T_rh {
  2446. ymax = r.T_rh
  2447. }
  2448. }
  2449. var chData = make(chan int, 10)
  2450. var jobGroup sync.WaitGroup
  2451. // 创建温度线
  2452. for i := 0; i < len(deviceSensorList); i++ {
  2453. chData <- 1
  2454. jobGroup.Add(1)
  2455. go func(index int) {
  2456. defer func() {
  2457. <-chData // 完成时chan取出1个
  2458. jobGroup.Done() // 完成时将等待组值减1
  2459. }()
  2460. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  2461. r_maps := []nats_server.DeviceData_R{}
  2462. for _, data := range dataList {
  2463. if data.T_sn == sn && data.T_id == id {
  2464. r_maps = append(r_maps, data)
  2465. }
  2466. }
  2467. if len(r_maps) == 0 {
  2468. return
  2469. }
  2470. sort.Slice(r_maps, func(i, j int) bool {
  2471. return r_maps[i].T_time < r_maps[j].T_time
  2472. })
  2473. pts := make(plotter.XYs, len(r_maps))
  2474. for j, d := range r_maps {
  2475. t, _ := lib.TimeStrToTime(d.T_time)
  2476. pts[j].X = float64(t.Unix())
  2477. pts[j].Y = float64(d.T_rh)
  2478. }
  2479. line, err := plotter.NewLine(pts)
  2480. if err != nil {
  2481. return
  2482. }
  2483. line.Color = randomColor(index)
  2484. p.Add(line)
  2485. }(i)
  2486. }
  2487. jobGroup.Wait()
  2488. st, _ := lib.TimeStrToTime(startTime)
  2489. et, _ := lib.TimeStrToTime(endTime)
  2490. xmin, xmax := float64(st.Unix()), float64(et.Unix())
  2491. // 添加最高,最低标准线 用红色虚线标识
  2492. p.Add(horizontalLine(xmin, xmax, float64(humidityMin)))
  2493. p.Add(horizontalLine(xmin, xmax, float64(humidityMax)))
  2494. if ymax < humidityMax {
  2495. ymax = humidityMax
  2496. }
  2497. if ymin > 0 {
  2498. ymin = 0
  2499. }
  2500. p.Y.Min, p.Y.Max = float64(ymin), float64(ymax)
  2501. p.X.Min, p.X.Max = xmin, xmax
  2502. p.Y.Tick.Marker = commaTicks{}
  2503. //p.X.Tick.Marker = plot.TimeTicks{Format: "2006-01-02 15:04:05"}
  2504. p.X.Tick.Marker = timeTicks{}
  2505. p.X.Tick.Label.Rotation = math.Pi / 5
  2506. p.X.Tick.Label.YAlign = draw.YCenter
  2507. p.X.Tick.Label.XAlign = draw.XRight
  2508. filepath := "ofile/" + "humidity" + deviceSensorList[0].T_sn + ".jpg"
  2509. // 保存文件
  2510. if err := p.Save(10*vg.Inch, 4*vg.Inch, filepath); err != nil {
  2511. logs.Error(lib.FuncName(), "生成图片失败", err)
  2512. return "", err
  2513. }
  2514. return filepath, nil
  2515. }
  2516. func DeviceDataHumidityJPG2(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  2517. if len(waybillPDF) == 0 {
  2518. return "", errors.New("暂无数据可生成图片")
  2519. }
  2520. deviceSensorList := []nats_server.DeviceSensor_R{}
  2521. dataList := []nats_server.DeviceData_R{}
  2522. for _, w := range waybillPDF {
  2523. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  2524. dataList = append(dataList, w.Data...)
  2525. }
  2526. humidityMin := deviceSensorList[0].T_DeviceSensorParameter.T_RHlower
  2527. humidityMax := deviceSensorList[0].T_DeviceSensorParameter.T_RHupper
  2528. var ymin, ymax float32
  2529. for i, r := range dataList {
  2530. if i == 0 {
  2531. ymin = r.T_t
  2532. ymax = r.T_t
  2533. }
  2534. if ymin > r.T_t {
  2535. ymin = r.T_t
  2536. }
  2537. if ymax < r.T_t {
  2538. ymax = r.T_t
  2539. }
  2540. }
  2541. series := make([]chart.Series, 0)
  2542. var chData = make(chan int, 10)
  2543. var jobGroup sync.WaitGroup
  2544. // 创建温度线
  2545. for i := 0; i < len(deviceSensorList); i++ {
  2546. chData <- 1
  2547. jobGroup.Add(1)
  2548. go func(index int) {
  2549. defer func() {
  2550. <-chData // 完成时chan取出1个
  2551. jobGroup.Done() // 完成时将等待组值减1
  2552. }()
  2553. sn, id := deviceSensorList[index].T_sn, deviceSensorList[index].T_id
  2554. r_maps := []nats_server.DeviceData_R{}
  2555. for _, data := range dataList {
  2556. if data.T_sn == sn && data.T_id == id {
  2557. r_maps = append(r_maps, data)
  2558. }
  2559. }
  2560. if len(r_maps) == 0 {
  2561. return
  2562. }
  2563. sort.Slice(r_maps, func(i, j int) bool {
  2564. return r_maps[i].T_time < r_maps[j].T_time
  2565. })
  2566. xValues := make([]time.Time, len(r_maps))
  2567. yValues := make([]float64, len(r_maps))
  2568. for j := 0; j < len(r_maps); j++ {
  2569. t, _ := lib.TimeStrToTime(r_maps[j].T_time)
  2570. xValues[j] = t
  2571. yValues[j] = float64(r_maps[j].T_rh)
  2572. }
  2573. series = append(series, chart.TimeSeries{
  2574. Name: fmt.Sprintf("%s-%d", sn, id),
  2575. XValues: xValues,
  2576. YValues: yValues,
  2577. })
  2578. }(i)
  2579. }
  2580. jobGroup.Wait()
  2581. if ymax < humidityMax {
  2582. ymax = humidityMax
  2583. }
  2584. if ymin > 0 {
  2585. ymin = 0
  2586. }
  2587. if ymin > humidityMin {
  2588. ymin = humidityMin
  2589. }
  2590. st, _ := lib.TimeStrToTime(startTime)
  2591. et, _ := lib.TimeStrToTime(endTime)
  2592. series = append(series, chart.TimeSeries{
  2593. Style: chart.Style{
  2594. StrokeColor: drawing.ColorRed,
  2595. StrokeDashArray: []float64{5.0, 5.0},
  2596. },
  2597. XValues: []time.Time{st, et},
  2598. YValues: []float64{float64(humidityMin), float64(humidityMin)},
  2599. })
  2600. series = append(series, chart.TimeSeries{
  2601. Style: chart.Style{
  2602. StrokeColor: drawing.ColorRed,
  2603. StrokeDashArray: []float64{5.0, 5.0},
  2604. },
  2605. XValues: []time.Time{st, et},
  2606. YValues: []float64{float64(humidityMax), float64(humidityMax)},
  2607. })
  2608. font := getZWFont()
  2609. graph := chart.Chart{
  2610. Title: "湿度记录",
  2611. TitleStyle: chart.Style{
  2612. FontSize: 15,
  2613. },
  2614. Background: chart.Style{
  2615. Padding: chart.Box{
  2616. Top: 20,
  2617. },
  2618. },
  2619. Font: font,
  2620. XAxis: chart.XAxis{
  2621. Name: "时间",
  2622. ValueFormatter: chart.TimeValueFormatterWithFormat("2006-01-02 15:04"),
  2623. },
  2624. YAxis: chart.YAxis{
  2625. Name: "湿度",
  2626. Range: &chart.ContinuousRange{
  2627. Min: float64(ymin),
  2628. Max: float64(ymax + 2),
  2629. },
  2630. },
  2631. Series: series,
  2632. }
  2633. //graph.Elements = []chart.Renderable{
  2634. // chart.Legend(&graph),
  2635. //}
  2636. filepath := "ofile/" + "humidity" + deviceSensorList[0].T_sn + ".jpg"
  2637. f, _ := os.Create(filepath)
  2638. defer f.Close()
  2639. graph.Render(chart.PNG, f)
  2640. return filepath, nil
  2641. }
  2642. func DeviceDataHumidityJPG3(startTime, endTime string, waybillPDF []service.WaybillPDF) (string, error) {
  2643. if len(waybillPDF) == 0 {
  2644. return "", errors.New("暂无数据可生成图片")
  2645. }
  2646. deviceSensorList := []nats_server.DeviceSensor_R{}
  2647. dataList := []nats_server.DeviceData_R{}
  2648. deviceDataPdfList := []service.DeviceDataPdf{}
  2649. for _, w := range waybillPDF {
  2650. deviceSensorList = append(deviceSensorList, w.DeviceSensorList...)
  2651. dataList = append(dataList, w.Data...)
  2652. deviceDataPdfList = append(deviceDataPdfList, w.DeviceDataPdf...)
  2653. }
  2654. TemperatureMin := deviceSensorList[0].T_DeviceSensorParameter.T_Tlower
  2655. TemperatureMax := deviceSensorList[0].T_DeviceSensorParameter.T_Tupper
  2656. var ymin, ymax float32
  2657. for i, r := range dataList {
  2658. if i == 0 {
  2659. ymin = r.T_rh
  2660. ymax = r.T_rh
  2661. }
  2662. if ymin > r.T_rh {
  2663. ymin = r.T_rh
  2664. }
  2665. if ymax < r.T_rh {
  2666. ymax = r.T_rh
  2667. }
  2668. }
  2669. series := make([]chart.Series, 0)
  2670. // 创建温度线
  2671. xValues1 := make([]time.Time, len(deviceDataPdfList))
  2672. yValues1 := make([]float64, len(deviceDataPdfList))
  2673. xValues2 := make([]time.Time, len(deviceDataPdfList))
  2674. yValues2 := make([]float64, len(deviceDataPdfList))
  2675. for i := 0; i < len(deviceDataPdfList); i++ {
  2676. t, _ := lib.TimeStrToTime(deviceDataPdfList[i].T_time)
  2677. xValues1[i] = t
  2678. yValues1[i] = float64(deviceDataPdfList[i].T_id1)
  2679. xValues2[i] = t
  2680. yValues2[i] = float64(deviceDataPdfList[i].T_id2)
  2681. }
  2682. series = append(series, chart.TimeSeries{
  2683. Name: "T1",
  2684. XValues: xValues1,
  2685. YValues: yValues1,
  2686. })
  2687. series = append(series, chart.TimeSeries{
  2688. Name: "T2",
  2689. XValues: xValues2,
  2690. YValues: yValues2,
  2691. })
  2692. if ymax < TemperatureMax {
  2693. ymax = TemperatureMax
  2694. }
  2695. if ymin > 0 {
  2696. ymin = 0
  2697. }
  2698. if ymin > TemperatureMin {
  2699. ymin = TemperatureMin
  2700. }
  2701. st, _ := lib.TimeStrToTime(startTime)
  2702. et, _ := lib.TimeStrToTime(endTime)
  2703. series = append(series, chart.TimeSeries{
  2704. Style: chart.Style{
  2705. StrokeColor: drawing.ColorRed,
  2706. StrokeDashArray: []float64{5.0, 5.0},
  2707. },
  2708. XValues: []time.Time{st, et},
  2709. YValues: []float64{float64(TemperatureMin), float64(TemperatureMin)},
  2710. })
  2711. series = append(series, chart.TimeSeries{
  2712. Style: chart.Style{
  2713. StrokeColor: drawing.ColorRed,
  2714. StrokeDashArray: []float64{5.0, 5.0},
  2715. },
  2716. XValues: []time.Time{st, et},
  2717. YValues: []float64{float64(TemperatureMax), float64(TemperatureMax)},
  2718. })
  2719. font := getZWFont()
  2720. graph := chart.Chart{
  2721. Title: "温度记录",
  2722. TitleStyle: chart.Style{
  2723. FontSize: 15,
  2724. },
  2725. Background: chart.Style{
  2726. Padding: chart.Box{
  2727. Top: 20,
  2728. },
  2729. },
  2730. Font: font,
  2731. XAxis: chart.XAxis{
  2732. Name: "时间",
  2733. ValueFormatter: chart.TimeValueFormatterWithFormat("2006-01-02 15:04"),
  2734. },
  2735. YAxis: chart.YAxis{
  2736. Name: "温度",
  2737. Range: &chart.ContinuousRange{
  2738. Min: float64(ymin),
  2739. Max: float64(ymax + 2),
  2740. },
  2741. },
  2742. Series: series,
  2743. }
  2744. //graph.Elements = []chart.Renderable{
  2745. // chart.Legend(&graph),
  2746. //}
  2747. filepath := "ofile/" + "temperature" + deviceSensorList[0].T_sn + ".jpg"
  2748. f, _ := os.Create(filepath)
  2749. defer f.Close()
  2750. graph.Render(chart.PNG, f)
  2751. return filepath, nil
  2752. }
  2753. func horizontalLine(xmin, xmax, y float64) *plotter.Line {
  2754. pts := make(plotter.XYs, 2)
  2755. pts[0].X = xmin
  2756. pts[0].Y = y
  2757. pts[1].X = xmax
  2758. pts[1].Y = y
  2759. line, err := plotter.NewLine(pts)
  2760. if err != nil {
  2761. panic(err)
  2762. }
  2763. line.LineStyle.Dashes = []vg.Length{vg.Points(8), vg.Points(5), vg.Points(1), vg.Points(5)}
  2764. line.Color = color.RGBA{R: 255, A: 255}
  2765. return line
  2766. }
  2767. type timeTicks struct{}
  2768. func (timeTicks) Ticks(min, max float64) []plot.Tick {
  2769. tks := plot.TimeTicks{}.Ticks(min, max)
  2770. for i, t := range tks {
  2771. //if t.Label == "" { // Skip minor ticks, they are fine.
  2772. // continue
  2773. //}
  2774. tks[i].Label = time.Unix(int64(t.Value), 0).Format("2006-01-02 15:04:05")
  2775. }
  2776. return tks
  2777. }
  2778. type commaTicks struct{}
  2779. // Ticks computes the default tick marks, but inserts commas
  2780. // into the labels for the major tick marks.
  2781. func (commaTicks) Ticks(min, max float64) []plot.Tick {
  2782. tks := plot.DefaultTicks{}.Ticks(min, max)
  2783. for i, t := range tks {
  2784. //if t.Label == "" { // Skip minor ticks, they are fine.
  2785. // continue
  2786. //}
  2787. tks[i].Label = fmt.Sprintf("%.0f", t.Value)
  2788. }
  2789. return tks
  2790. }
  2791. // 生成随机颜色的辅助函数
  2792. func randomColor(i int) color.RGBA {
  2793. var colors []color.RGBA
  2794. colors = append(colors,
  2795. color.RGBA{R: 52, G: 152, B: 219, A: 255},
  2796. color.RGBA{R: 230, G: 126, B: 34, A: 255},
  2797. color.RGBA{R: 142, G: 68, B: 173, A: 255},
  2798. color.RGBA{R: 211, G: 84, B: 0, A: 255},
  2799. color.RGBA{R: 231, G: 76, B: 60, A: 255},
  2800. color.RGBA{R: 26, G: 188, B: 156, A: 255},
  2801. color.RGBA{R: 243, G: 156, B: 18, A: 255},
  2802. color.RGBA{R: 22, G: 160, B: 133, A: 255},
  2803. color.RGBA{R: 46, G: 204, B: 113, A: 255},
  2804. color.RGBA{R: 39, G: 174, B: 96, A: 255},
  2805. color.RGBA{R: 41, G: 128, B: 185, A: 255},
  2806. color.RGBA{R: 155, G: 89, B: 182, A: 255},
  2807. color.RGBA{R: 192, G: 57, B: 43, A: 255},
  2808. color.RGBA{R: 241, G: 196, B: 15, A: 255},
  2809. )
  2810. return colors[i%len(colors)]
  2811. }
  2812. func randomColor2(i int) drawing.Color {
  2813. var colors []drawing.Color
  2814. colors = append(colors,
  2815. drawing.Color{R: 52, G: 152, B: 219, A: 255},
  2816. drawing.Color{R: 230, G: 126, B: 34, A: 255},
  2817. drawing.Color{R: 142, G: 68, B: 173, A: 255},
  2818. drawing.Color{R: 211, G: 84, B: 0, A: 255},
  2819. drawing.Color{R: 231, G: 76, B: 60, A: 255},
  2820. drawing.Color{R: 26, G: 188, B: 156, A: 255},
  2821. drawing.Color{R: 243, G: 156, B: 18, A: 255},
  2822. drawing.Color{R: 22, G: 160, B: 133, A: 255},
  2823. drawing.Color{R: 46, G: 204, B: 113, A: 255},
  2824. drawing.Color{R: 39, G: 174, B: 96, A: 255},
  2825. drawing.Color{R: 41, G: 128, B: 185, A: 255},
  2826. drawing.Color{R: 155, G: 89, B: 182, A: 255},
  2827. drawing.Color{R: 192, G: 57, B: 43, A: 255},
  2828. drawing.Color{R: 241, G: 196, B: 15, A: 255},
  2829. )
  2830. return colors[i%len(colors)]
  2831. }
  2832. // getZWFont 加载字体
  2833. func getZWFont() *truetype.Font {
  2834. fontFile := "./static/fonts/MiSans-Medium.ttf"
  2835. fontBytes, err := os.ReadFile(fontFile)
  2836. if err != nil {
  2837. log.Println(err)
  2838. return nil
  2839. }
  2840. font, err := truetype.Parse(fontBytes)
  2841. if err != nil {
  2842. log.Println(err)
  2843. return nil
  2844. }
  2845. return font
  2846. }