and design pro实现打印电子面单(菜鸟物流-可批量打印)

介绍:菜鸟物流,and design pro版本
效果如图:
and design pro实现打印电子面单(菜鸟物流-可批量打印)_第1张图片

第一步:

先看文档=>菜鸟文档:接口文档

第二步:
下载云打印客户端:打印组件,安装打开就完了
and design pro实现打印电子面单(菜鸟物流-可批量打印)_第2张图片
第三步:
配置打印机:装驱动,设置为默认打印机(面单打印机),完事儿!

第四步:

注意:
如遇打印报【渲染失败】、【出现打印提示框】或者【打印暂停】,
1.重装一下驱动,
2.重启电脑,
3.cainiao打印组件中,选择工具-清楚缓存,然后再选择-重启cainiao组件 (我试了1和2都没解决,使用3解决的)

源代码:

import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import { Card, Table, Tabs, Form, message, notification , Input, Select, Button ,Divider,Modal ,Pagination ,Icon ,Upload ,Popconfirm} from 'antd';
import { } from '../../../utils/utils';
import stylesUtil from '../../../utils/utils.less';  /只是给打印按钮字体,变蓝色

let defaultPageSize = 20; //用来控制用户选择分页的

@connect(({ shippingStatistics, loading ,}) => ({
  shippingStatistics,
  loading: loading.models.shippingStatistics,
  submitting: loading.effects['form/submitAdvancedForm'],
}))

@Form.create()
export default class EditShippingStatistics extends PureComponent {
  state = {
    page:1,
    defaultPrinter:'',//打印机
    socket:{}, 
    selectedRowKeys:[], //选中数据
    printerids:[] //选中的list id
  };

  componentDidMount() { 
    const { editId } = this.props;
    this.props.dispatch({//获取list
      type: 'shippingStatistics/getCheckList',
      payload: {
        id:editId.ids,
        rows: defaultPageSize,
        page: 1,
      },
    });
    //如果是http的话socket =  new WebSocket('ws://127.0.0.1:13528')
    //如果是https的话socket = new WebSocket('wss://localhost:13529'); 
    let socket = new WebSocket('wss://localhost:13529');
    let that = this
    let timer = ''
    this.setState({ //存下来,后面用得到
      socket:socket
    })
    // 打开Socket
    socket.onopen = function(event){
      that.getPrintList()//打印机列表
      // 监听消息
      socket.onmessage = function(event){
          console.log('Client received a message',event);
          console.log(JSON.parse(event.data).defaultPrinter ,that.state.defaultPrinter)
          let info = JSON.parse(event.data)
          if(event&&event.data){ //获取打印机
            that.setState({
              defaultPrinter:info.defaultPrinter
            }) 
          }
          //打印一次,socket会返回三次,一次print,两次notifyPrintResult,导致我会对请求一次标记已打印接口,我就不优化,咋滴
          if(event&&info.cmd == 'print'){ //监听打印机是否完成
            if(info.status != 'success'){
              notification.error({ //出错提示
                message: '哎呀!面单号:'+info.taskID.split(',')[1]+' 打印出错了',
                description: info.msg,
                duration:null,
              });
            }
          }
          if(event&&info.cmd == 'notifyPrintResult'){ //监听打印机是否完成
            if(info.printStatus[0].status == 'success'){
              console.log('成功' ,info.taskID.split(',')[1]) //利用字符串拼接,给socket传值,调用接口标记已打印
              if(timer){
                clearTimeout(timer)
                timer = ''
              }
              //标记已打印,会多调用一次,优化了,还是有几率出现(2019-08-01)
              timer = setTimeout(()=>{
              	//标记已打印,会多调用一次,可是我就不优化(2019-04-24)
	              that.props.dispatch({
	                type: 'shippingStatistics/changePrintStaus',
	                payload: {
	                  waybillCode:info.taskID.split(',')[1]
	                },
	              }).then(()=>{
	                const { editId } = that.props;
	                that.props.dispatch({//获取list
	                  type: 'shippingStatistics/getCheckList',
	                  payload: {
	                    id:editId.ids,
	                    rows: defaultPageSize,
	                    page: 1,
	                  },
	                });
	              })
              },10)
            }else{
              notification.error({//出错提示
                message: '哎呀!面单号:'+info.taskID.split(',')[1]+' 打印出错了',
                description: info.msg,
                duration:null,
              });
            }
          }
      };
      // 监听Socket的关闭
      socket.onclose = function(event){
          console.log('Client notified this.state.socket has closed',event);
      };
    };
  }


      //菜鸟打印 start
    /***
		 * 
		 * 获取请求的UUID,指定长度和进制,如 
		 * getUUID(8, 2)   //"01001010" 8 character (base=2)
		 * getUUID(8, 10) // "47473046" 8 character ID (base=10)
		 * getUUID(8, 16) // "098F4D35"。 8 character ID (base=16)
		 *   
		 */
		getUUID =(len, radix)=> {
      let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
      let uuid = [], i;
      radix = radix || chars.length; 
      if (len) {
        for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
      } else {
        let r;
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
        uuid[14] = '4';
        for (i = 0; i < 36; i++) {
          if (!uuid[i]) {
            r = 0 | Math.random()*16;
            uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
          }
        }
      }
      return uuid.join('');
  }
  /***
   * 构造request对象
   */
  getRequestObject =(cmd) => {
      let request  = new Object();
      request.requestID=this.getUUID(8, 16);
      request.version="1.0";
      request.cmd=cmd;
      return request;
  }

  /**
   * 请求打印机列表demo
   * */
  getPrintList=()=>{
    let request  = this.getRequestObject("getPrinters");
  
    if (this.state.socket.readyState===1) {
      console.log(request ,this.state.socket)
          this.state.socket.send(JSON.stringify(request));
      }
  }
  
  /**
   * 打印电子面单
   * printer 指定要使用那台打印机
   * waybillArray 要打印的电子面单的数组
   */
  
  doPrint=(printer, waybillArray ,waybillCode)=>{
      let request = this.getRequestObject("print");    
      request.task = new Object();
      request.task.taskID = this.getUUID(8,10)+','+waybillCode;//利用字符串拼接,给socket传值,调用接口标记已打印
      request.task.preview = false;
      request.task.printer = printer;
      let documents = new Array();
      for(let i=0;i<waybillArray.length;i++) {
        let doc = new Object();
        doc.documentID = waybillArray[i];
        let content = new Array();
        let waybillJson = {//获取电子面单Json 数据 ,必须用content包裹
          content:waybillArray[i]
        }
        let customAreaData = {  //获取自定义区数据以及模板URL
          templateURL:waybillArray[i].templateURL,
          data:waybillArray[i].data
        }
        content.push(waybillJson,customAreaData);
        doc.contents = content; //重要
        documents.push(doc);
      }
      
      request.task.documents = documents //重要
      this.state.socket.send(JSON.stringify(request));
  }
  //菜鸟打印 end

  handleCancel = (e) => {
    const { popHide } = this.props
    popHide()
  }

  getPages = (page) => {
    const { editId } = this.props;
    let obj ={
      rows: defaultPageSize,
      page: page,
      id:editId.ids
    }
    this.setState({selectedRowKeys:[],printerids:[],loading:true})
    this.props.dispatch({
      type: 'shippingStatistics/getCheckList',
      payload: {...obj },
    }).then(()=>{
      this.setState({loading:false,page:page})
    })
  }
  onShowSizeChange=(current, pageSize)=>{
    console.log(current, pageSize);
    
    const { editId } = this.props;
    defaultPageSize = pageSize
    this.props.dispatch({//获取list
      type: 'shippingStatistics/getCheckList',
      payload: {
        id:editId.ids,
        rows: defaultPageSize,
        page: 1,
      },
    });
  }

  onValidateForm = () => {
    const { validateFields } = this.props.form;
    const { popHide , editId} = this.props;
    
    validateFields((err, values) => {
      if(editId&&editId.id){
        values.id = editId.id
        values.batchStatisId = editId.ids
        values.batch = editId.idp
      }
      if (!err) {
        this.props.dispatch({
          type: 'shippingStatistics/finishCheck',
          payload: values,
        }).then(()=>{
          this.props.form.resetFields() 
          popHide()
          this.props.dispatch({
            type: 'shippingStatistics/getList',
            payload: {
              rows: defaultPageSize,
              page: 1,
            },
          });
        })
      }
    });
  }

  confirmPrint=(code ,isbatch)=>{ 
    if(isbatch){ //批量打印
      this.props.dispatch({
        type: 'shippingStatistics/getBatchPrintData',
        payload: {
          ids:code.join(',')
        },
      }).then(()=>{
        const { shippingStatistics: { printData } } = this.props;
        printData.map((item)=>{
          this.doPrint(this.state.defaultPrinter,[JSON.parse(item.data)] ,item.waybillCode)
        })
        this.setState({selectedRowKeys:[],printerids:[]})
      })
    }else{
      this.props.dispatch({
        type: 'shippingStatistics/getOne',
        payload: {
          code:code
        },
      }).then(()=>{
        const { shippingStatistics: { txt } } = this.props;
        this.doPrint(this.state.defaultPrinter,[JSON.parse(txt.data)] ,txt.waybillCode)
      })
    }   
  }

  onSelectChange = (selectedRowKeys, selectedRows) => {
    let printerids = []
    selectedRows.map((item)=>{
      printerids.push(item.id)
    })
    this.setState({ selectedRowKeys ,printerids});
  }


  render() {
    const { shippingStatistics: { data ,checkList }, loading, form } = this.props;
    const { validateFields ,getFieldDecorator} = form;
    const { selectedRowKeys ,printerids} = this.state;

    const rowSelection = {
      selectedRowKeys,
      onChange: this.onSelectChange,
    };

    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 2 },
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
      },
    };

    const columns = [
      {
        title: '手机号',
        dataIndex: 'mobile',
        width: 120,
        render:val=>(<span>{val?val:'无'}</span>)
      },
      {
        title: '面单号',
        dataIndex: 'waybillCode',
        width: 120,
        render:val=>(<span>{val?val:'无'}</span>)
      },
      {
        title: '状态',
        dataIndex: 'isPrinted',
        width: 80,
        render:val=>(<span>{val==0?'未打印':'已打印'}</span>)
      },
      {
        title: '操作',
        dataIndex: 'waybillCode',
        width: 80,
        render:val =>{
          return (
            <Popconfirm title="确认打印单子面单吗?" onConfirm={() => this.confirmPrint(val)}>
              <span className={stylesUtil.linkBtn}>打印</span>
            </Popconfirm>
          )
        }
      }
    ]

    return (
      <div>
          <Table 
          size='small'
          dataSource={checkList.list} 
          columns={columns} 
          rowKey='agentId' 
          pagination={false} 
          bordered={false} 
          loading={loading}
          rowSelection={rowSelection}
          />
          <div style={{overflow:'hidden',marginBottom:'10px'}}>
            <Pagination 
              current={this.state.page} 
              defaultPageSize={defaultPageSize} 
              onShowSizeChange={this.onShowSizeChange}
              showSizeChanger
              pageSizeOptions={['20','40','80']}
              total={checkList.total} 
              onChange={this.getPages} 
              style={{marginTop:"20px",float:"right"}}
              
            />
          </div>
         
          <Form onSubmit={this.onValidateForm}>
            <Form.Item label='备注' {...formItemLayout}>
              {getFieldDecorator('remark', {
                rules: [{ required: true, message: '请输入' }],
                initialValue:'' ,
              })(
                <Input></Input>
              )}
            </Form.Item>   

            <div span={24} style={{ textAlign: 'right' }}>
              <Button type="primary" onClick={this.handleCancel} offset={16}>返回</Button>
              <Button type="primary" onClick={()=>this.confirmPrint(printerids ,true)} disabled={printerids.length == 0?true:false} offset={20} style={{ marginLeft: 8 }}>批量打印</Button>
              <Popconfirm title="确认核对完成吗?" onConfirm={this.onValidateForm}>
                <Button type="primary" offset={20} style={{ marginLeft: 8 }}>核对完成</Button>
              </Popconfirm>
            </div>
          </Form>
      </div>
    );
  }
}


关于局域网打印:在菜鸟打印组建中->添加打印机->选择远程打印(输入ip地址)->选中对应打印机;另一台电脑也要安装菜鸟打印组件和配置打印驱动
备注:修改纸张大小,只能从菜鸟后台配置一联二联三联(https://fahuo.cainiao.com),前端操作不了。
结尾:其实复制官方文档就可以了,主要是调试走通有很多坑,文档给的代码,很多不全,需要自己看返回值,一点点加上。

你可能感兴趣的:(ant,design,pro)