service.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package service
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "time"
  7. "wails-app/internal/dao"
  8. "wails-app/internal/global"
  9. )
  10. const sdkDllPath = `D:\lq\资料\停车场 道闸 车牌识别 收费机\票机自制\打印机\EMD807嵌入式热敏票据打印模组\5、SDK指令集\Win_SDK_Demo_2023_08_14\Win_SDK_Demo_2023_08_14\lib\x64\CsnPrinterLibs.dll`
  11. type PrintService struct{}
  12. func NewPrintService() *PrintService { return &PrintService{} }
  13. func (s *PrintService) PrintTicket(printerID uint, lotName, channelCode, plateNo string, ticketID uint, ticketNo string) error {
  14. var printer dao.Printer
  15. if err := global.GVA_DB.First(&printer, printerID).Error; err != nil {
  16. return fmt.Errorf("打印机未配置: id=%d", printerID)
  17. }
  18. var err error
  19. var srl *SerialPrinter
  20. var usbHandle uintptr
  21. useCSN := false
  22. if len(printer.PortName) >= 3 && printer.PortName[:3] == "COM" {
  23. srl, err = NewSerialPrinter(printer.PortName, printer.BaudRate)
  24. if err == nil {
  25. defer srl.Close()
  26. }
  27. } else {
  28. err = InitCSN(sdkDllPath)
  29. if err != nil {
  30. return fmt.Errorf("加载 CSN DLL 失败: %w (path=%s)", err, sdkDllPath)
  31. }
  32. // 枚举初始化(C# Demo 在 initForm() 中调用,可能是必要的初始化步骤)
  33. Csn_EnumUSB()
  34. Csn_EnumPRN()
  35. // 尝试 OpenUSB → OpenPRN
  36. name := printer.PortName
  37. if name == "USB" || name == "auto" || name == "" {
  38. name = Csn_EnumUSB()
  39. }
  40. usbHandle, err = csn_OpenUSB(name)
  41. if err != nil {
  42. usbHandle, err = csn_OpenPRN(name)
  43. }
  44. if err != nil {
  45. return fmt.Errorf("打开打印机失败: %w (name=%s)", err, name)
  46. }
  47. useCSN = true
  48. csn_SetPort(usbHandle) // 激活端口!
  49. defer csn_Close(usbHandle)
  50. }
  51. now := time.Now().Format("02-01-2006 15:04:05")
  52. slipNo := fmt.Sprintf("%d", ticketID)
  53. if useCSN {
  54. // 构造 ESC/POS 数据 → 写成临时文件 → 调 32 位辅助工具打印
  55. var buf []byte
  56. add := func(b []byte) { buf = append(buf, b...) }
  57. add(InitCmd); add(AlignCenterCmd); add(DoubleHeightCmd); add(BoldOnCmd)
  58. add(ESCPOS_Text("PARKING TICKET"))
  59. add(BoldOffCmd); add(NormalCmd)
  60. add(ESCPOS_Text("")); add(ESCPOS_Text(lotName))
  61. add(ESCPOS_Text("A-General Car")); add(ESCPOS_Text(""))
  62. add(ESCPOS_Text("PARK AT YOUR OWN RISK"))
  63. add(ESCPOS_Text("================================"))
  64. add(AlignLeftCmd)
  65. add(ESCPOS_Text("In-Time::"+now))
  66. if channelCode != "" { add(ESCPOS_Text("InGate::"+channelCode)) }
  67. if plateNo != "" { add(ESCPOS_Text("Veh No::"+plateNo)) }
  68. add(ESCPOS_Text("================================"))
  69. add(ESCPOS_Text("Slip No::"+slipNo))
  70. add(ESCPOS_Text("================================"))
  71. add(AlignCenterCmd); add(ESCPOS_Text(""))
  72. add(ESCPOS_QRCode(ticketNo))
  73. add(ESCPOS_Text(""))
  74. add(ESCPOS_Text("SCAN AND PAY WITH"))
  75. add(ESCPOS_Text("NEW THE CANADIA BANK APP"))
  76. add(InitCmd); add(ESCPOS_Text("")); add(ESCPOS_Text("")); add(ESCPOS_Text(""))
  77. add(CutPaperCmd)
  78. // 先尝试 CSN DLL WriteData,失败则用 32 位辅助工具
  79. n := Csn_WriteData(buf)
  80. if n == 0 {
  81. tmp, _ := os.CreateTemp("", "ticket_*.bin")
  82. if tmp != nil {
  83. tmp.Write(buf); tmp.Close()
  84. exec.Command("build/bin/ticket-print.exe", printer.PortName, tmp.Name()).Run()
  85. os.Remove(tmp.Name())
  86. }
  87. }
  88. global.GVA_DB.Model(&printer).Update("status", "online")
  89. return nil
  90. }
  91. // Serial ESC/POS fallback
  92. write := func(data []byte) { srl.Write(data) }
  93. line32 := "================================"
  94. write(InitCmd); write(AlignCenterCmd); write(DoubleHeightCmd); write(BoldOnCmd)
  95. write(ESCPOS_Text("PARKING TICKET"))
  96. write(BoldOffCmd); write(NormalCmd)
  97. write(ESCPOS_Text("")); write(ESCPOS_Text(lotName))
  98. write(ESCPOS_Text("A-General Car")); write(ESCPOS_Text(""))
  99. write(ESCPOS_Text("PARK AT YOUR OWN RISK")); write(ESCPOS_Text(line32))
  100. write(AlignLeftCmd)
  101. write(ESCPOS_Text("In-Time::"+now))
  102. if channelCode != "" { write(ESCPOS_Text("InGate::"+channelCode)) }
  103. if plateNo != "" { write(ESCPOS_Text("Veh No::"+plateNo)) }
  104. write(ESCPOS_Text(line32)); write(ESCPOS_Text("Slip No::"+slipNo)); write(ESCPOS_Text(line32))
  105. write(AlignCenterCmd); write(ESCPOS_Text(""))
  106. write(ESCPOS_QRCode(ticketNo)); write(ESCPOS_Text(""))
  107. write(AlignCenterCmd)
  108. write(ESCPOS_Text("SCAN AND PAY WITH"))
  109. write(ESCPOS_Text("NEW THE CANADIA BANK APP"))
  110. write(InitCmd); write(ESCPOS_Text("")); write(ESCPOS_Text("")); write(ESCPOS_Text(""))
  111. write(CutPaperCmd)
  112. global.GVA_DB.Model(&printer).Update("status", "online")
  113. return nil
  114. }