zoukankan      html  css  js  c++  java
  • 打印机池的设计与实现

    打印机池的设计与实现

    先说一个应用场景——中厨。

    服务员先在点菜电脑上点菜,点好的菜单信息要在各出品部的“出品印机”上打印出来,各出品部的师傅再按照菜单来做菜。

    不同的菜,要在不同的出品打印机上打印,有的菜要在多个出品打印机上打印。

    整个中厨大概有十来个出品部门,有的出品部门有一台出品打印机,有的出口部门有几台。

    笔者把这些打印机统称为“打印机池”。

    // 单元功用:打印相关
    // 单元设计:cxg
    // 设计日期:2014-05-12
    // 每一台打印机都有自己的任务队列和处理任务队列的线程
    // 快餐只有一个出品部门
    
    unit untPrintTask;
    
    interface
    
    uses
      System.SysUtils, System.Classes,
      Datasnap.DBClient, frxclass,
      System.Generics.Collections;
    
    type
      TBillContent = record // 小票内容
        machineNo: string; // POS机号
        skyName: string; // 收款员姓名
        saleNo: string; // 小票号
        saleTime: TDateTime; // 销售时间
        amount: Currency; // 应收
        pay: Currency; // 支付
        change: Currency; // 找零
        prnData: OleVariant; // 小票明细:商品名称、单价、数量、金额。。。。。。
        deskNo:string; // 台号
        payType: string; // 支付方式
      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
      TPrintTaskThread = 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
      g_PrintTasks: TDictionary<string, TPrintTaskThread>;  // <打印机名字, TPrintTask>
    
    implementation
    
    { TPrintTask }
    
    uses untFastReport, UntSysConst;
    
    constructor TPrintTaskThread.Create;
    begin
      Create(False);
      FreeOnTerminate := False;
      // 创建打印队列
      FPrintQueue := TQueue<TOneTimePrint>.Create;
    end;
    
    destructor TPrintTaskThread.Destroy;
    begin
      // 释放打印队列
      FreeAndNil(FPrintQueue);
      inherited;
    end;
    
    procedure TPrintTaskThread.Execute;
    var
      OneTimePrint: TOneTimePrint;
      dm: TdmFastReport;
      c: TfrxComponent;
    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;
              // 变量赋值
    
              c:=dm.report.FindObject('mmShopName');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := UserInfo.ShopName;
    
              c := dm.report.FindObject('mmMachineNo');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.machineNo;
    
              c:=dm.report.FindObject('mmSKY');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.skyName;
    
              c:= dm.report.FindObject('mmBillNo');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.saleNo;
    
              c:=dm.report.FindObject('mmSaleTime');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := FormatDateTime('yyyy-mm-dd hh:nn',OneTimePrint.billContent.saleTime);
    
              c:= dm.report.FindObject('mmDeskNo');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.deskNo;  // 台号
    
              c:= dm.report.FindObject('mmPayType');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := OneTimePrint.billContent.payType;
    
              c:= dm.report.FindObject('mmAmount');
              if c<> nil then
                TfrxMemoView(c).Memo.Text := FormatCurr('0.00', OneTimePrint.billContent.amount);
    
              c:=dm.report.FindObject('mmPay');
              if c<>nil then
                TfrxMemoView(c).Memo.Text := FormatCurr('0.00', OneTimePrint.billContent.pay);
    
              c:= dm.report.FindObject('mmGiveChange');
              if c<> nil then
                TfrxMemoView(c).Memo.Text := FormatCurr('0.00', OneTimePrint.billContent.change);
    
              // 开始打印
              dm.report.PrepareReport();
              dm.report.Print;
            except
              // 打印失败,重新加入任务队列
              Self.FPrintQueue.Enqueue(OneTimePrint);
            end;
          finally
            FreeAndNil(dm);
          end;
        end;
        // 线程休眠
        Sleep(1000);
      end;
    end;
    
    end.
    
    procedure TfrmSettleAccount.PrintBill;
    var
      OneTimePrint: TOneTimePrint;
      p: TPrintTaskThread;
    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 := UserInfo.PaperWidth;
        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 := self.Total.totalAmount;
        OneTimePrint.billContent.Change := StrToCurr(edtChange.Text);
        OneTimePrint.billContent.prnData := frmPos.cdsSaleD.Data;
        OneTimePrint.billContent.payType := frmPos.cdsSaleM.FieldByName
          ('payType').Text;
        OneTimePrint.billContent.deskNo := frmPos.edtDeskNo.Text;
        // 加入打印队列
        if g_PrintTasks.TryGetValue(frmPos.cdsPrinter.FieldByName('prnName').Text, p)
        then
        begin
          p.PrintQueue.Enqueue(OneTimePrint);
        end;
        frmPos.cdsPrinter.Next;
      end;
    end;
    

      

  • 相关阅读:
    js加密
    sharepoint更新左侧列表的名字
    HTML转换JS
    Html空格字符代码:
    docker 与host互传文件
    Ubuntu里node命令出错,找不到
    docker查看运行容器详细信息
    docker保存容器的修改
    Docker容器中安装新的程序
    运行docker容器镜像
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/9929640.html
Copyright © 2011-2022 走看看