package printer import ( "fmt" "time" "github.com/gin-gonic/gin" "wails-app/internal/dao" "wails-app/internal/global" "wails-app/internal/model/common/response" "wails-app/internal/model/vehicle/request" printService "wails-app/internal/modules/printer/service" svc "wails-app/internal/service" ) var printSvc = printService.NewPrintService() var vehicleSvc = svc.ServiceGroupApp.VehicleServiceGroup.VehicleService type buttonReq struct { PrinterID uint `json:"printer_id"` ChannelCode string `json:"channel_code"` PlateNo string `json:"plate_number"` } func TicketMachineButton(c *gin.Context) { var req buttonReq if err := c.ShouldBindJSON(&req); err != nil { response.FailWithMessage(err.Error(), c) return } // 创建入场记录(临时车,可能无车牌) entryResp, err := vehicleSvc.VehicleEntry(request.VehicleEntry{ PlateNumber: req.PlateNo, RFIDTag: "", ParkingLotID: 1, ParkingSpaceID: 1, }) if err != nil { response.FailWithMessage(err.Error(), c) return } // 获取刚创建的数字票 var tickets []dao.DigitalTicket global.GVA_DB.Where("plate_number = ?", entryResp.Data.PlateNumber).Order("id DESC").Limit(1).Find(&tickets) if len(tickets) == 0 { response.FailWithMessage("数字票创建失败", c) return } // 获取停车场名 var lot dao.ParkingLot global.GVA_DB.First(&lot, entryResp.Data.ParkingLotID) // 打印小票 if err := printSvc.PrintTicket(req.PrinterID, lot.LotName, req.ChannelCode, req.PlateNo, tickets[0].ID, tickets[0].TicketNo); err != nil { response.FailWithMessage("打印失败: "+err.Error(), c) return } response.OkWithData(gin.H{ "ticket_id": tickets[0].ID, "ticket_no": tickets[0].TicketNo, "slip_no": tickets[0].ID, "entry_time": entryResp.Data.EntryTime, "plate_number": entryResp.Data.PlateNumber, }, c) } func SetupPrinterRouter(router *gin.RouterGroup) { router.POST("/ticket-machine/button", TicketMachineButton) } // SetupPrinterPublic 公开测试路由(无需JWT) func SetupPrinterPublic(router *gin.RouterGroup) { router.GET("/ticket-machine/test", TicketMachineButtonTest) router.GET("/ticket-machine/debug", func(c *gin.Context) { printService.InitCSN(printService.FindCsnDllPath()) printService.Csn_EnumUSB() printService.Csn_EnumPRN() h, e := printService.Csn_OpenUSB("VID_0FE6&PID_811E#USB001") printService.Csn_SetPort(h) testData := []byte{0x1B, 0x40, 'T', 'E', 'S', 'T', ' ', 'P', 'R', 'I', 'N', 'T', '\n', '\n', '\n', '\n', 0x1B, 0x69} n := printService.Csn_WriteData(testData) response.OkWithData(gin.H{ "handle": h, "err": fmt.Sprint(e), "bytes_written": n, }, c) }) router.GET("/ticket-machine/usb-list", func(c *gin.Context) { printService.InitCSN(printService.FindCsnDllPath()) usb := printService.Csn_EnumUSBNames() prn := printService.Csn_EnumPRNNames() response.OkWithData(gin.H{"usb": usb, "prn": prn}, c) }) } func TicketMachineButtonTest(c *gin.Context) { // 每次生成唯一测试车牌 testPlate := fmt.Sprintf("TEST%04d", time.Now().Unix()%10000) entryResp, err := vehicleSvc.VehicleEntry(request.VehicleEntry{ PlateNumber: testPlate, RFIDTag: "", ParkingLotID: 1, ParkingSpaceID: 1, }) if err != nil { response.FailWithMessage(err.Error(), c) return } var tickets []dao.DigitalTicket global.GVA_DB.Where("plate_number = ?", entryResp.Data.PlateNumber).Order("id DESC").Limit(1).Find(&tickets) if len(tickets) == 0 { response.FailWithMessage("票创建失败", c) return } // 从入场记录获取真实 ParkingLotID,再查停车场名 var rec dao.VehicleRecord if err := global.GVA_DB.Where("plate_number = ?", entryResp.Data.PlateNumber).Order("id DESC").First(&rec).Error; err != nil { response.FailWithMessage("查入场记录失败: "+err.Error(), c) return } var lot dao.ParkingLot lot.ID = rec.ParkingLotID global.GVA_DB.First(&lot) lotName := lot.LotName if lotName == "" { lotName = fmt.Sprintf("Lot#%d", rec.ParkingLotID) } // 尝试打印 printErr := "" if err := printSvc.PrintTicket(1, lotName, "IN01", entryResp.Data.PlateNumber, tickets[0].ID, tickets[0].TicketNo); err != nil { printErr = err.Error() } response.OkWithData(gin.H{ "ticket_id": tickets[0].ID, "ticket_no": tickets[0].TicketNo, "slip_no": tickets[0].ID, "plate_number": entryResp.Data.PlateNumber, "entry_time": entryResp.Data.EntryTime, "lot_name": lotName, "channel_code": "IN01", "print_result": printErr, }, c) }