介绍:菜鸟物流,and design pro版本
效果如图:
第一步:
先看文档=>菜鸟文档:接口文档
第二步:
下载云打印客户端:打印组件,安装打开就完了
第三步:
配置打印机:装驱动,设置为默认打印机(面单打印机),完事儿!
第四步:
注意:
如遇打印报【渲染失败】、【出现打印提示框】或者【打印暂停】,
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),前端操作不了。
结尾:其实复制官方文档就可以了,主要是调试走通有很多坑,文档给的代码,很多不全,需要自己看返回值,一点点加上。