zoukankan      html  css  js  c++  java
  • 餐饮软件打印队列之实现

    餐饮软件,特别是中厨的出品打印机数量非常多,整个酒店可能有N个出品部门,一个出品部门可能有N台出品打印机。

    打印队列的功用:

    (1)打印不掉单,打印任务缓存于队列中,如果某个打印任务失败,则重新加入队列;

    (2)各台打印机都是并行作业,一台打印机发生故障不会影响其它打印机的正常工作。

    打印队列实现方法之一:

    为每一台打印机建立自己专属的打印任务队列和打印任务处理线程。

    // 单元功用:处理打印任务的线程
    // 单元设计:cxg
    // 设计日期:2014-05-12

    unit untPrintTask;

    interface

    uses
    System.SysUtils, System.Classes, Vcl.Dialogs,
    Datasnap.DBClient, Vcl.Forms, frxclass, System.Variants,
    System.Generics.Collections;

    type
    TBillContent = record // 小票内容
    machineNo: string; // POS机号
    skyName: string; // 收款员姓名
    saleNo: string; // 小票号
    saleTime: TDateTime; // 销售时间
    amount: Currency; // 应收
    pay: Currency; // 支付
    change: Currency; // 找零
    prnData: OleVariant; // 商品名称、单价、数量、金额
    end;

    type
    TPrinterInfo = record // 打印机信息
    prnNo: Integer; // 印机编号
    prnName: string; // 印机名称
    prnType: string; // 结账、厨打
    prnWidth: Integer; // 50mm76mm80mm
    remark: string; // 备注
    prnModel: string; // 打印模版
    end;

    type
    TOneTimePrint = record // 一次打印
    printerInfo: TPrinterInfo; // 打印机信息
    billContent: TBillContent; // 小票内容
    end;

    type
    TPrintTask = class(TThread)
    private
    FPrintQueue: TQueue<TOneTimePrint>;
    protected
    procedure Execute; override;
    public
    constructor Create; overload;
    destructor Destroy; override;
    property PrintQueue: TQueue<TOneTimePrint> read FPrintQueue
    write FPrintQueue;
    end;

    var
    PrintTaskArray: array of TPrintTask;

    implementation

    { TPrintTask }

    uses untFastReport;

    constructor TPrintTask.Create;
    begin
    Create(False);
    FPrintQueue := TQueue<TOneTimePrint>.Create;
    end;

    destructor TPrintTask.Destroy;
    begin
    FreeAndNil(FPrintQueue);
    inherited;
    end;

    procedure TPrintTask.Execute;
    var
    OneTimePrint: TOneTimePrint;
    dm: TdmFastReport;
    begin
    while not Self.Terminated do
    begin
    if Assigned(FPrintQueue) and (FPrintQueue.Count > 0) then
    begin
    OneTimePrint := FPrintQueue.Dequeue;
    dm := TdmFastReport.Create(nil);
    try
    try
    dm.cds.Data := OneTimePrint.billContent.prnData;
    dm.report.LoadFromFile(OneTimePrint.printerInfo.prnModel);
    dm.report.PrintOptions.Printer := OneTimePrint.printerInfo.prnName;
    TfrxMemoView(dm.report.FindObject('mmMachineNo')).Memo.Text :=
    OneTimePrint.billContent.machineNo;
    TfrxMemoView(dm.report.FindObject('mmSKY')).Memo.Text :=
    OneTimePrint.billContent.skyName;
    TfrxMemoView(dm.report.FindObject('mmBillNo')).Memo.Text :=
    OneTimePrint.billContent.saleNo;
    TfrxMemoView(dm.report.FindObject('mmSaleTime')).Memo.Text :=
    FormatDateTime('yyyy-mm-dd hh:nn',
    OneTimePrint.billContent.saleTime);
    TfrxMemoView(dm.report.FindObject('mmAmount')).Memo.Text :=
    FormatCurr('0.00', OneTimePrint.billContent.amount);
    TfrxMemoView(dm.report.FindObject('mmPay')).Memo.Text :=
    FormatCurr('0.00', OneTimePrint.billContent.pay);
    TfrxMemoView(dm.report.FindObject('mmGiveChange')).Memo.Text :=
    FormatCurr('0.00', OneTimePrint.billContent.change);
    // dm.report.ShowReport();
    dm.report.PrepareReport();
    dm.report.Print;
    except
    Self.FPrintQueue.Enqueue(OneTimePrint);
    end;
    finally
    FreeAndNil(dm);
    end;
    end;
    Sleep(1000);
    end;
    end;

    end.

    // 为每一台打印机创建队列和线程

    {$IFDEF pool}
    SetLength(PrintTaskArray, cdsPrinter.RecordCount);
    for i := 0 to High(PrintTaskArray) do
    begin
    PrintTaskArray[i] := TPrintTask.Create;
    PrintTaskArray[i].FreeOnTerminate := False;
    end;

    {$ENDIF}

    // 释放所有的线程

    {$IFDEF pool}
    for i := 0 to High(PrintTaskArray) do
    begin
    PrintTaskArray[i].Terminate;
    PrintTaskArray[i].WaitFor;
    FreeAndNil(PrintTaskArray[i]);
    end;

    // 打印小票

    procedure TfrmSettleAccount.PrintBill;
    var
    OneTimePrint: TOneTimePrint;
    begin
    frmPos.cdsPrinter.First;
    while not frmPos.cdsPrinter.Eof do
    begin
    // 打印机信息
    OneTimePrint.printerInfo.prnNo := frmPos.cdsPrinter.FieldByName('prnNo').AsInteger;
    OneTimePrint.printerInfo.prnName := frmPos.cdsPrinter.FieldByName('prnName').Text;
    OneTimePrint.printerInfo.prnType := frmPos.cdsPrinter.FieldByName('prnType').Text;
    OneTimePrint.printerInfo.prnWidth := frmPos.cdsPrinter.FieldByName('prnWidth').AsInteger;
    OneTimePrint.printerInfo.remark := frmPos.cdsPrinter.FieldByName('remark').Text;
    case OneTimePrint.printerInfo.prnWidth of
    58: OneTimePrint.printerInfo.prnModel := ExtractFilePath(Application.ExeName) + 'reportpos58.fr3';
    76: OneTimePrint.printerInfo.prnModel := ExtractFilePath(Application.ExeName) + 'reportpos76.fr3';
    80: OneTimePrint.printerInfo.prnModel := ExtractFilePath(Application.ExeName) + 'reportpos80.fr3';
    end;
    // 小票内容
    OneTimePrint.billContent.machineNo := UserInfo.MachineId;
    OneTimePrint.billContent.skyName := UserInfo.UserName;
    OneTimePrint.billContent.saleNo := UserInfo.SaleNo;
    OneTimePrint.billContent.saleTime := Now;
    OneTimePrint.billContent.amount := self.Total.totalAmount;
    OneTimePrint.billContent.pay := StrToCurrDef(edtCash.Text, 0);
    OneTimePrint.billContent.change := StrToCurrDef(edtChange.Text, 0);
    OneTimePrint.billContent.prnData := frmPos.cdsSaleD.Data;
    // 加入打印队列
    PrintTaskArray[frmPos.cdsPrinter.RecNo - 1].PrintQueue.Enqueue(OneTimePrint);
    frmPos.cdsPrinter.Next;
    end;
    end;


    {$ENDIF}

  • 相关阅读:
    巡回赛 -- 简单的拓扑排序
    最简单的拓扑排序
    blockhouses
    部分和问题
    jfinal路由简单解析
    python mysql
    Gradle--ubuntu
    解决ssh登录后闲置时间过长而断开连接
    业界有很多MQ产品
    avalon---qunar ued
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/3727033.html
Copyright © 2011-2022 走看看