/// <summary> /// 打印订单及菜品信息 /// </summary> async Task printDine(string dineId, List <int> dineMenuIds, List <PrintType> printTypes) { DineForPrinting dp = null; try { dp = await getDineForPrinting(dineId, dineMenuIds); if (dp == null) { serverLog("获取订单信息失败,请检查网络设置", LogLevel.Error); return; } serverLog($"发送打印命令 单号: {dineId}", LogLevel.Info); if (Config.IsIPPrinter) { DinePrinter dinePrinter = new DinePrinter(); await dinePrinter.Print(dp, printTypes, dineMenuIds.Count == 0); } else { DineDriverPrinter dineDriverPrinter = new DineDriverPrinter(); dineDriverPrinter.Print(dp, printTypes, dineMenuIds.Count == 0); } serverLog($"发送命令成功 单号: {dineId}", LogLevel.Success); printCompleted(dineId); } catch (Exception e) { serverLog($"无法打印 单号: {dineId}, 错误信息: {e.Message}", LogLevel.Error); remoteLog(Log.LogLevel.Error, $"DineId: {dineId}, {e.Message}", $"Data: {JsonConvert.SerializeObject(dp)}, Error: {e}"); } }
/// <summary> /// 打印本地测试 /// </summary> async Task printLocalTest(List <PrintType> printTypes, string ipOrName) { DineForPrinting dp = Config.GetTestProtocol(ipOrName); try { serverLog($"开始本地测试, 打印机: {ipOrName}", LogLevel.Info); serverLog($"发送本地测试单命令", LogLevel.Info); if (Config.IsIPPrinter) { DinePrinter dinePrinter = new DinePrinter(); await dinePrinter.Print(dp, printTypes, true); } else { DineDriverPrinter dineDriverPrinter = new DineDriverPrinter(); dineDriverPrinter.Print(dp, printTypes, true); } serverLog($"发送本地测试单命令成功", LogLevel.Success); } catch (Exception e) { serverLog($"无法打印本地测试单, 错误信息: {e.Message}", LogLevel.Error); remoteLog(Log.LogLevel.Error, $"Local Test, {e.Message}", $"Data: {JsonConvert.SerializeObject(dp)}, Error: {e}"); } }
/// <summary> /// 生成厨房单图片 /// </summary> protected Bitmap generateKitchenOrderBmp(DineForPrinting protocol, DineMenu dineMenu, SetMealMenu setMealMenu) { Bitmap bmp = new Bitmap(protocol.PrinterFormat.PaperSize, maxHeight); Graphics g = Graphics.FromImage(bmp); int realHeight = drawKitchenOrder(g, protocol, dineMenu, setMealMenu); return(cutBmp(bmp, realHeight)); }
/// <summary> /// 生成传菜单图片 /// </summary> protected Bitmap generateServeOrderBmp(DineForPrinting protocol) { Bitmap bmp = new Bitmap(protocol.PrinterFormat.PaperSize, maxHeight); Graphics g = Graphics.FromImage(bmp); int realHeight = drawServeOrder(g, protocol); return(cutBmp(bmp, realHeight)); }
/// <summary> /// 生成收银条图片 /// </summary> protected Bitmap generateReciptBmp(DineForPrinting protocol, bool isFullDineMenus) { Bitmap bmp = new Bitmap(protocol.PrinterFormat.PaperSize, maxHeight); Graphics g = Graphics.FromImage(bmp); int realHeight = drawRecipt(g, protocol, isFullDineMenus); return(cutBmp(bmp, realHeight)); }
/// <summary> /// 根据Graphics绘制传菜单 /// </summary> protected int drawServeOrder(Graphics g, DineForPrinting protocol) { PrinterGraphics printerG = new PrinterGraphics(g, protocol.PrinterFormat.PaperSize, protocol.PrinterFormat.Font, protocol.PrinterFormat.PaddingRight); printerG.DrawStringLine(protocol.Dine.Desk.ServeDepartmentName, protocol.PrinterFormat.ServeOrderFontSize); printerG.DrawStringLine($"单号: {protocol.Dine.Id}", protocol.PrinterFormat.ServeOrderSmallFontSize); printerG.DrawStringLine($"时间: {protocol.Dine.BeginTime.ToString("M-d HH:mm")}", protocol.PrinterFormat.ServeOrderSmallFontSize); printerG.DrawStringLine($"餐桌: {protocol.Dine.Desk.Name}", protocol.PrinterFormat.ServeOrderFontSize); printHr(printerG); printGrid82(printerG, new string[] { "名称", "数量" }, protocol.PrinterFormat.ServeOrderSmallFontSize); printHr(printerG); foreach (DineMenu dineMenu in protocol.Dine.DineMenus.Where(p => p.Status != HotelDAO.Models.DineMenuStatus.Returned)) { // 打印具体菜品信息 printGrid82(printerG, new string[] { dineMenu.Menu.Name, dineMenu.Count.ToString() }, protocol.PrinterFormat.ServeOrderFontSize); // 如果菜品为套餐,则打印套餐包含的具体菜品信息 if (dineMenu.Menu.IsSetMeal) { List <SetMealMenu> setMealMenus = dineMenu.Menu.SetMealMenus; for (int i = 0; i < setMealMenus.Count; i++) { char tab = '├'; if (i == setMealMenus.Count - 1) { tab = '└'; } printGrid82(printerG, new string[] { $"{tab} {setMealMenus[i].Name}", setMealMenus[i].Count.ToString() }, protocol.PrinterFormat.ServeOrderFontSize); } } // 打印菜品的备注信息 var remarks = dineMenu.Remarks.ToList(); for (int i = 0; i < dineMenu.Remarks.Count; i++) { char tab = '├'; if (i == dineMenu.Remarks.Count - 1) { tab = '└'; } printGrid82(printerG, new string[] { $"{tab} {remarks[i].Name}", null, }, protocol.PrinterFormat.ServeOrderFontSize); } } ; printEnd(printerG); return(printerG.GetHeight()); }
/// <summary> /// 根据Graphics绘制厨房单 /// </summary> protected int drawKitchenOrder(Graphics g, DineForPrinting protocol, DineMenu dineMenu, SetMealMenu setMealMenu) { PrinterGraphics printerG = new PrinterGraphics(g, protocol.PrinterFormat.PaperSize, protocol.PrinterFormat.Font, protocol.PrinterFormat.PaddingRight); printerG.DrawStringLine(dineMenu.Menu.DepartmentName, protocol.PrinterFormat.KitchenOrderFontSize); printerG.DrawStringLine($"单号: {protocol.Dine.Id}", protocol.PrinterFormat.KitchenOrderSmallFontSize); printerG.DrawStringLine($"时间: {protocol.Dine.BeginTime.ToString("M-d HH:mm")}", protocol.PrinterFormat.KitchenOrderSmallFontSize); if (dineMenu.Status == HotelDAO.Models.DineMenuStatus.Returned) { string returnStr = "退菜"; if (dineMenu.ReturnedReason != null) { returnStr += $", 理由: {dineMenu.ReturnedReason}"; } printerG.DrawStringLine(returnStr, protocol.PrinterFormat.KitchenOrderFontSize); } printerG.DrawStringLine($"餐桌: {protocol.Dine.Desk.Name}", protocol.PrinterFormat.KitchenOrderFontSize); printGrid82(printerG, new string[] { dineMenu.Menu.Name, dineMenu.Count.ToString() }, protocol.PrinterFormat.KitchenOrderFontSize); if (setMealMenu != null) { printGrid82(printerG, new string[] { $"└ {setMealMenu.Name}", setMealMenu.Count.ToString() }, protocol.PrinterFormat.KitchenOrderFontSize); } // 打印菜品的备注信息 var remarks = dineMenu.Remarks.ToList(); for (int i = 0; i < dineMenu.Remarks.Count; i++) { char tab = '├'; if (i == dineMenu.Remarks.Count - 1) { tab = '└'; } printGrid82(printerG, new string[] { $"{tab} {remarks[i].Name}", null, }, protocol.PrinterFormat.KitchenOrderFontSize); } printEnd(printerG); return(printerG.GetHeight()); }
/// <summary> /// 打印远程测试 /// </summary> async Task printRemoteTest(List <PrintType> printTypes, string ipOrName) { DineForPrinting dp = null; try { serverLog($"开始测试, 打印机: {ipOrName}", LogLevel.Info); dp = await getDineForPrinting("00000000000000"); if (dp == null) { serverLog("获取订单信息失败,请检查网络设置", LogLevel.Error); return; } dp.Dine.Desk.ReciptPrinter.IpAddress = ipOrName; dp.Dine.Desk.ReciptPrinter.Name = ipOrName; dp.Dine.Desk.ServePrinter.IpAddress = ipOrName; dp.Dine.Desk.ServePrinter.Name = ipOrName; foreach (var dineMenu in dp.Dine.DineMenus) { dineMenu.Menu.Printer.IpAddress = ipOrName; dineMenu.Menu.Printer.Name = ipOrName; } serverLog($"发送测试单命令", LogLevel.Info); if (Config.IsIPPrinter) { DinePrinter dinePrinter = new DinePrinter(); await dinePrinter.Print(dp, printTypes, true); } else { DineDriverPrinter dineDriverPrinter = new DineDriverPrinter(); dineDriverPrinter.Print(dp, printTypes, true); } serverLog($"发送测试单命令成功", LogLevel.Success); printCompleted("00000000000000"); } catch (Exception e) { serverLog($"无法打印测试单, 错误信息: {e}", LogLevel.Error); remoteLog(Log.LogLevel.Error, $"Online Test, {e.Message}", $"Data: {JsonConvert.SerializeObject(dp)}, Error: {e}"); } }
async Task <DineForPrinting> getDineForPrinting(string dineId, List <int> dineMenuIds = null) { object postData = new { HotelId = Config.HotelId, DineId = dineId, DineMenuIds = dineMenuIds }; string response = await HttpPost.PostAsync(Config.RemoteGetDineForPrintingUrl, postData); if (response == null) { return(null); } DineForPrinting protocol = JsonConvert.DeserializeObject <DineForPrinting>(response); if (protocol.Hotel == null) { return(null); } return(protocol); }
public static DineForPrinting GetTestProtocol(string ipOrName) { DineForPrinting p = new DineForPrinting { Hotel = new Hotel { Id = 1, Name = "本地测试饭店名", Address = "本地测试饭店地址", OpenTime = new TimeSpan(8, 0, 0), CloseTime = new TimeSpan(22, 0, 0), Tel = "000-00000000", Usable = true }, Dine = new Dine { Id = "00000000000000", Status = HotelDAO.Models.DineStatus.Untreated, Type = HotelDAO.Models.DineType.ToStay, HeadCount = 10, Price = 123.56m, OriPrice = 987.65m, Change = 123.456m, Discount = 0.5, DiscountName = "本地测试折扣名", DiscountType = HotelDAO.Models.DiscountType.PayKind, BeginTime = DateTime.Now, IsPaid = true, IsOnline = true, UserId = "0000000000", Waiter = new Staff { Id = "00000000", Name = "本地测试服务员名" }, Clerk = new Staff { Id = "00000000", Name = "本地测试收银员名" }, Remarks = new List <Remark> { new Remark { Id = 1, Name = "本地测试备注1", Price = 12.34m }, new Remark { Id = 2, Name = "本地测试备注2", Price = 56.78m }, new Remark { Id = 3, Name = "本地测试备注3", Price = 90.12m }, new Remark { Id = 4, Name = "本地测试备注4", Price = 34.56m } }, Desk = new Desk { Id = "000", QrCode = "111", Name = "本地测试桌名", Description = "本地测试桌子备注信息", AreaType = HotelDAO.Models.AreaType.Normal, ReciptPrinter = new Printer { Id = 0, Name = ipOrName, IpAddress = ipOrName, Usable = true }, ServePrinter = new Printer { Id = 1, Name = ipOrName, IpAddress = ipOrName, Usable = true }, ReciptDepartmentName = "测试收银部门名", ServeDepartmentName = "测试传菜部门名" }, DineMenus = new List <DineMenu>(), DinePaidDetails = new List <DinePaidDetail> { new DinePaidDetail { Price = 12.34m, RecordId = "1234567890abcdeABCDE", PayKind = new PayKind { Id = 0, Name = "本地测试支付1", Type = HotelDAO.Models.PayKindType.Online } }, new DinePaidDetail { Price = 12.34m, RecordId = "1234567890abcdeABCDE", PayKind = new PayKind { Id = 0, Name = "本地测试支付2", Type = HotelDAO.Models.PayKindType.Offline } }, new DinePaidDetail { Price = 12.34m, RecordId = "1234567890abcdeABCDE", PayKind = new PayKind { Id = 0, Name = "本地测试支付3", Type = HotelDAO.Models.PayKindType.Points } } } }, User = new User { Id = "00000000", Email = "*****@*****.**", UserName = "******", PhoneNumber = "12345678900" }, PrinterFormat = new PrinterFormat { PaperSize = 278, Font = " 宋体", ColorDepth = 55, ReciptBigFontSize = 10, ReciptFontSize = 10, ReciptSmallFontSize = 7, KitchenOrderFontSize = 10, KitchenOrderSmallFontSize = 8, ServeOrderFontSize = 10, ServeOrderSmallFontSize = 8, ShiftBigFontSize = 12, ShiftFontSize = 8, ShiftSmallFontSize = 7, PaddingRight = 0 } }; for (int i = 1; i <= 2; i++) { p.Dine.DineMenus.Add(new DineMenu { Status = HotelDAO.Models.DineMenuStatus.Normal, Count = 10, OriPrice = 156.78m, Price = 12.34m, RemarkPrice = 12.34m, Remarks = new List <Remark> { new Remark { Id = 0, Name = "本地测试备注1", Price = 12.34m }, new Remark { Id = 1, Name = "本地测试备注2", Price = 56.78m }, new Remark { Id = 2, Name = "本地测试备注3", Price = 90.12m }, new Remark { Id = 3, Name = "本地测试备注4", Price = 34.56m } }, Menu = new Menu { Id = $"0000{i}", Code = "test", Name = $"本地测试菜品名{i}", NameAbbr = $"本地测试{i}", Unit = "份", IsSetMeal = false, Printer = new Printer { Id = 2, Name = ipOrName, IpAddress = ipOrName, Usable = true }, DepartmentName = $"测试厨房名{i}" } }); } return(p); }
public async Task Print(DineForPrinting protocol, List <PrintType> printTypes, bool isFullDineMenus) { handleIPPrinterFormat(protocol.PrinterFormat); List <Task> allTasks = new List <Task>(); foreach (PrintType type in printTypes) { if (type == PrintType.Recipt) { if (protocol.Dine.Desk.ReciptPrinter == null) { continue; } IPAddress ip = IPAddress.Parse(protocol.Dine.Desk.ReciptPrinter.IpAddress); Bitmap bmp = generateReciptBmp(protocol, isFullDineMenus); allTasks.Add(IPPrinter.GetInstance().Print(ip, bmp, protocol.PrinterFormat.ColorDepth)); } else if (type == PrintType.ServeOrder) { if (protocol.Dine.Desk.ServePrinter == null) { continue; } IPAddress ip = IPAddress.Parse(protocol.Dine.Desk.ServePrinter.IpAddress); Bitmap bmp = generateServeOrderBmp(protocol); allTasks.Add(IPPrinter.GetInstance().Print(ip, bmp, protocol.PrinterFormat.ColorDepth)); } else if (type == PrintType.KitchenOrder) { foreach (DineMenu dineMenu in protocol.Dine.DineMenus.Where(p => p.Status != HotelDAO.Models.DineMenuStatus.Returned)) { if (dineMenu.Menu.Printer == null) { continue; } if (!dineMenu.Menu.IsSetMeal) { IPAddress ip = IPAddress.Parse(dineMenu.Menu.Printer.IpAddress); Bitmap bmp = generateKitchenOrderBmp(protocol, dineMenu, null); allTasks.Add(IPPrinter.GetInstance().Print(ip, bmp, protocol.PrinterFormat.ColorDepth)); } else { foreach (SetMealMenu setMealMenu in dineMenu.Menu.SetMealMenus) { IPAddress ip = IPAddress.Parse(dineMenu.Menu.Printer.IpAddress); Bitmap bmp = generateKitchenOrderBmp(protocol, dineMenu, setMealMenu); allTasks.Add(IPPrinter.GetInstance().Print(ip, bmp, protocol.PrinterFormat.ColorDepth)); } } } } } foreach (var t in allTasks) { await t; } }
public void Print(DineForPrinting protocol, List <PrintType> printTypes, bool isFullDineMenus) { foreach (PrintType type in printTypes) { if (type == PrintType.Recipt) { if (protocol.Dine.Desk.ReciptPrinter == null) { continue; } PrintDocument pd = new PrintDocument(); pd.PrinterSettings.PrinterName = protocol.Dine.Desk.ReciptPrinter.Name; pd.DefaultPageSettings.PaperSize = new PaperSize("Custom", protocol.PrinterFormat.PaperSize, maxHeight); pd.PrintPage += (sender, e) => { drawRecipt(e.Graphics, protocol, isFullDineMenus); }; pd.Print(); } else if (type == PrintType.ServeOrder) { if (protocol.Dine.Desk.ServePrinter == null) { continue; } PrintDocument pd = new PrintDocument(); pd.PrinterSettings.PrinterName = protocol.Dine.Desk.ServePrinter.Name; pd.DefaultPageSettings.PaperSize = new PaperSize("Custom", protocol.PrinterFormat.PaperSize, maxHeight); pd.PrintPage += (sender, e) => { drawServeOrder(e.Graphics, protocol); }; pd.Print(); } else if (type == PrintType.KitchenOrder) { foreach (DineMenu dineMenu in protocol.Dine.DineMenus.Where(p => p.Status != HotelDAO.Models.DineMenuStatus.Returned)) { if (dineMenu.Menu.Printer == null) { continue; } if (!dineMenu.Menu.IsSetMeal) { PrintDocument pd = new PrintDocument(); pd.PrinterSettings.PrinterName = dineMenu.Menu.Printer.Name; pd.DefaultPageSettings.PaperSize = new PaperSize("Custom", protocol.PrinterFormat.PaperSize, maxHeight); pd.PrintPage += (sender, e) => { drawKitchenOrder(e.Graphics, protocol, dineMenu, null); }; pd.Print(); } else { foreach (SetMealMenu setMealMenu in dineMenu.Menu.SetMealMenus) { PrintDocument pd = new PrintDocument(); pd.PrinterSettings.PrinterName = dineMenu.Menu.Printer.Name; pd.DefaultPageSettings.PaperSize = new PaperSize("Custom", protocol.PrinterFormat.PaperSize, maxHeight); pd.PrintPage += (sender, e) => { drawKitchenOrder(e.Graphics, protocol, dineMenu, setMealMenu); }; pd.Print(); } } } } } }
/// <summary> /// 根据Graphics绘制收银条 /// </summary> protected int drawRecipt(Graphics g, DineForPrinting protocol, bool isFullDineMenus) { PrinterGraphics printerG = new PrinterGraphics(g, protocol.PrinterFormat.PaperSize, protocol.PrinterFormat.Font, protocol.PrinterFormat.PaddingRight); printerG.DrawStringLine($"欢迎光临{protocol.Hotel.Name}", protocol.PrinterFormat.ReciptBigFontSize, align: StringAlignment.Center); printerG.DrawStringLine($"TEL: {protocol.Hotel.Tel}", protocol.PrinterFormat.ReciptSmallFontSize, align: StringAlignment.Center); printerG.DrawStringLine($"{protocol.Hotel.Address}", protocol.PrinterFormat.ReciptSmallFontSize, align: StringAlignment.Center); printerG.DrawStringLine($"收据", protocol.PrinterFormat.ReciptSmallFontSize, align: StringAlignment.Center); printerG.TrimY(5); printerG.DrawStringLine($"单号: {protocol.Dine.Id}", protocol.PrinterFormat.ReciptFontSize); printerG.DrawStringLine($"时间: {protocol.Dine.BeginTime.ToString("M-d HH:mm")}", protocol.PrinterFormat.ReciptFontSize); if (protocol.Dine.Type == HotelDAO.Models.DineType.ToStay) { printerG.DrawStringLine($"餐桌: {protocol.Dine.Desk.Name}", protocol.PrinterFormat.ReciptFontSize); } else if (protocol.Dine.Type == HotelDAO.Models.DineType.ToGo) { printerG.DrawStringLine($"外卖: {protocol.Dine.Desk.Name}", protocol.PrinterFormat.ReciptBigFontSize); if (protocol.Dine.TakeOut.RecordId != null) { printerG.DrawStringLine($"外卖平台编号: {protocol.Dine.TakeOut.RecordId}", protocol.PrinterFormat.ReciptBigFontSize); } printerG.DrawStringLine($"手机: {protocol.User.PhoneNumber}", protocol.PrinterFormat.ReciptBigFontSize); printerG.DrawStringLine($"地址: {protocol.Dine.TakeOut.Address}", protocol.PrinterFormat.ReciptBigFontSize); } printHr(printerG); printGridRecipt(printerG, new string[] { "名称", "数量", "单价", "折后小计" }, protocol.PrinterFormat.ReciptFontSize); printHr(printerG); decimal priceAll = 0m; foreach (DineMenu dineMenu in protocol.Dine.DineMenus.Where(p => p.Status != HotelDAO.Models.DineMenuStatus.Returned)) { // 打印具体菜品信息 printGridRecipt(printerG, new string[] { dineMenu.Menu.Name, dineMenu.Count.ToString(), dineMenu.OriPrice.ToString(), (dineMenu.Price * dineMenu.Count).ToString() }, protocol.PrinterFormat.ReciptFontSize); priceAll += dineMenu.Price * dineMenu.Count; // 如果菜品为套餐,则打印套餐包含的具体菜品信息 if (dineMenu.Menu.IsSetMeal) { List <SetMealMenu> setMealMenus = dineMenu.Menu.SetMealMenus; for (int i = 0; i < setMealMenus.Count; i++) { char tab = '├'; if (i == setMealMenus.Count - 1) { tab = '└'; } printGridRecipt(printerG, new string[] { $"{tab} {setMealMenus[i].Name}", setMealMenus[i].Count.ToString(), null, null }, protocol.PrinterFormat.ReciptFontSize); } } // 打印菜品的备注信息 var remarks = dineMenu.Remarks.ToList(); for (int i = 0; i < dineMenu.Remarks.Count; i++) { char tab = '├'; if (i == dineMenu.Remarks.Count - 1) { tab = '└'; } printGridRecipt(printerG, new string[] { $"{tab} {remarks[i].Name}", null, 0 == remarks[i].Price ? null : remarks[i].Price.ToString(), 0 == remarks[i].Price ? null : remarks[i].Price.ToString() }, protocol.PrinterFormat.ReciptFontSize); priceAll += remarks[i].Price; } } ; printHr(printerG); if (isFullDineMenus) { priceAll = protocol.Dine.Price; } printGrid55f(printerG, new string[] { "总计", priceAll.ToString() }, protocol.PrinterFormat.ReciptBigFontSize); if (protocol.Dine.Discount < 1) { printerG.DrawStringLine($"{protocol.Dine.DiscountName}: {protocol.Dine.Discount * 10}折", protocol.PrinterFormat.ReciptFontSize); } string paidWay = protocol.Dine.IsOnline ? "线上支付" : "线下支付"; printerG.DrawStringLine($"支付方式: {paidWay}", protocol.PrinterFormat.ReciptFontSize); foreach (DinePaidDetail dinePaidDetail in protocol.Dine.DinePaidDetails) { decimal dinePaidDetailPrice = dinePaidDetail.Price; if (dinePaidDetail.PayKind.Type == HotelDAO.Models.PayKindType.Cash) { dinePaidDetailPrice += protocol.Dine.Change; } printerG.DrawStringLine($"{dinePaidDetail.PayKind.Name}: ¥{dinePaidDetailPrice}", protocol.PrinterFormat.ReciptFontSize); } if (protocol.Dine.IsPaid) { printerG.DrawStringLine($"找零: ¥{protocol.Dine.Change}", protocol.PrinterFormat.ReciptFontSize); } else { printerG.DrawStringLine("未支付", protocol.PrinterFormat.ReciptFontSize); } printEnd(printerG); g.Dispose(); return(printerG.GetHeight()); }