Commit 9f0da623 authored by 沈翠玲's avatar 沈翠玲

1、原生蓝牙打印提交

2、公共http请求增加arrayBuffer
parent 4c91c553
......@@ -23,6 +23,8 @@ const install = (Vue, vm) => {
vm.$u.get(config.adminPath + '/mes/qc/qcindex/list', params),
getPrintDown: (params) =>
vm.$u.postJson(config.adminPath + '/common/printDown', params),
getPrintPNG: (params) =>
vm.$u.postJson(config.adminPath + '/common/report2Png', params, {}, {responseType:'arraybuffer'}),
login: (params = {}) =>
vm.$u.post(config.adminPath + '/mobile/login/loginByPassword', params),
sendCode: (params = {}) =>
......
......@@ -145,15 +145,17 @@ const install = (Vue, vm) => {
}
// 封装 post json 请求
vm.$u.postJson = (url, data = {}, header = {}) => {
vm.$u.postJson = (url, data = {}, header = {}, other = {}) => {
header['content-type'] = 'application/json';
return vm.$u.http.request({
url,
method: 'POST',
header,
data
data,
...other
})
}
// 封装 post json 请求
vm.$u.putJson = (url, data = {}, header = {}) => {
......
......@@ -14,6 +14,7 @@ let IntentFilter = plus.android.importClass("android.content.IntentFilter");
let BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
let UUID = plus.android.importClass("java.util.UUID");
let Toast = plus.android.importClass("android.widget.Toast");
var Manifest = plus.android.importClass("android.Manifest");
//连接串口设备的 UUID
let MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
......@@ -38,6 +39,7 @@ var blueToothTool = {
bluetoothState: "", //当前蓝牙状态
discoveryDeviceState: false, //是否正在搜索蓝牙设备
readThreadState: false, //数据读取线程状态
popview: null
},
options : {
/**
......@@ -68,6 +70,7 @@ var blueToothTool = {
init(setOptions) {
Object.assign(this.options, setOptions);
this.state.bluetoothEnable = this.getBluetoothStatus();
if(!this.state.bluetoothEnable) shortToast("没有开启蓝牙");
this.listenBluetoothStatus();
},
shortToast(msg) {
......@@ -168,7 +171,8 @@ var blueToothTool = {
let device = invoke(it, "next");
pairedDevices.push({
"name": invoke(device, "getName"),
"address": invoke(device, "getAddress")
"address": invoke(device, "getAddress"),
device
});
}
return pairedDevices;
......@@ -187,23 +191,73 @@ var blueToothTool = {
this.cancelDiscovery();
}
let Build = plus.android.importClass("android.os.Build");
console.log('Build', Build.VERSION.SDK_INT)
//6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
if(Build.VERSION.SDK_INT >= 6.0){
}
if (Build.VERSION.SDK_INT >= 6.0) {
const location = activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
if (location === -1) {
plus.android.requestPermissions(['android.permission.ACCESS_COARSE_LOCATION'], e => {
if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
uni.showToast({
icon: 'none',
title: '有必要权限未获得,请在设置中打开'
})
} else if (e.granted.length > 0) {
}
})
}
if (activity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) === -1) {
plus.android.requestPermissions(['android.permission.ACCESS_FINE_LOCATION'], e => {
if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
uni.showToast({
icon: 'none',
title: '有必要权限未获得,请在设置中打开'
})
} else if (e.granted.length > 0) {
}
})
}
if (activity.checkSelfPermission(Manifest.permission.BLUETOOTH) === -1) {
plus.android.requestPermissions(['android.permission.BLUETOOTH'], e => {
if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
uni.showToast({
icon: 'none',
title: '有必要权限未获得,请在设置中打开'
})
} else if (e.granted.length > 0) {
}
})
}
if (activity.checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN) === -1) {
plus.android.requestPermissions(['android.permission.BLUETOOTH_ADMIN'], e => {
if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
uni.showToast({
icon: 'none',
title: '有必要权限未获得,请在设置中打开'
})
} else if (e.granted.length > 0) {
}
})
}
}
let options = this.options
btFindReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
"onReceive": function(context, intent) {
plus.android.importClass(context);
plus.android.importClass(intent);
let action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND == action) { // 找到设备
let device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
console.log('device11', device)
let newDevice = {
"name": plus.android.invoke(device, "getName"),
"address": plus.android.invoke(device, "getAddress")
"address": plus.android.invoke(device, "getAddress"),
"type": plus.android.invoke(device, "getType"),
}
options.discoveryDeviceCallback && options.discoveryDeviceCallback(newDevice);
}
......
function getLocalFilePath(path) {
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
return path
}
if (path.indexOf('file://') === 0) {
return path
}
if (path.indexOf('/storage/emulated/0/') === 0) {
return path
}
if (path.indexOf('/') === 0) {
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substr(1)
}
}
return '_www/' + path
}
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
var xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
var fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export function base64ToPath(base64, extName) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
var type = base64[0].match(/:(.*?);/)[1]
var str = atob(base64[1])
var n = str.length
var array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
}
var fileName;
if (!extName) {
extName = base64.match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
fileName = Date.now() + '.' + extName;
} else {
fileName = Date.now() + extName;
}
if (typeof plus === 'object') {
var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, function() {
var filePath = '_doc/uniapp_temp/' + fileName
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
\ No newline at end of file
var tsc = require('./tsc.js')
import bluetoothTool from './BluetoothTool.js'
export default {
data () {
return {
devices: [],
currDev: null,
connId: '',
first:true,
tableDomId: '',
tableImgPath: '',
canvasWidth: 800,
canvasHeight: 600
}
},
created () {
//#ifdef APP-PLUS
// 蓝牙
bluetoothTool.init({
listenBTStatusCallback: (state)=> {
// if(state == 'STATE_ON') {
// let lastBleAddress = uni.getStorageSync('lastBleAddress')
// if(lastBleAddress) {
// uni.showLoading({
// title: '正在连接...'
// })
// console.log(lastBleAddress)
// bluetoothTool.connDevice(lastBleAddress,(result)=>{
// uni.hideLoading()
// uni.showToast({
// title: result?'连接成功!':'连接失败...'
// });
// })
// }
// }
},
discoveryDeviceCallback: this.onDevice,
discoveryFinishedCallback: function() {
console.log('搜索到的设备', that.devices)
},
readDataCallback: function(dataByteArr) {
/* if(that.receiveDataArr.length >= 200) {
that.receiveDataArr = [];
}
that.receiveDataArr.push.apply(that.receiveDataArr, dataByteArr); */
},
connExceptionCallback: function(e) {
console.log(e);
that.msg = "设备连接失败";
}
});
this.searchBle()
//#endif
},
computed: {
},
methods: {
searchBle() {
var that = this
console.log("initBule")
// 使用openBluetoothAdapter 接口,免去主动申请权限的麻烦
uni.openBluetoothAdapter({
success(res) {
this.devices = []
console.log("打开 蓝牙模块,开始搜索模式...")
console.log(res)
bluetoothTool.discoveryNewDevice();
//that.onDevice()
}
})
},
onDevice(newDevice){
console.log("监听寻找到新设备的事件---------------")
console.log(newDevice)
if(newDevice.name && newDevice.name != 'null') {
this.devices.push({
name: newDevice.name,
address: newDevice.address
})
if (newDevice.name === 'CT-428D' && this.first) {
this.onConn(newDevice)
this.first = false
}
}
},
onConn(item) {
console.log("连接蓝牙---------------" + item.address)
/* uni.showLoading({
title: '连接中',
mask: false
}); */
bluetoothTool.connDevice(item.address,(result)=>{
if(result) {
uni.setStorageSync('lastBleAddress', item.address)
}
console.log('连接结果:',result)
});
},
print (filePath) {
const firstCanvas = uni.createCanvasContext('firstCanvas', this);
const that = this
uni.getImageInfo({
src: filePath,
success(res) {
that.canvasWidth = 800
that.canvasHeight = 640
console.log(res, that.canvasWidth, that.canvasHeight)
firstCanvas.drawImage(filePath, 0, 0, that.canvasWidth, that.canvasHeight);
firstCanvas.draw();
that.$nextTick(() => { //获取画布像素数据
uni.canvasGetImageData({
canvasId: 'firstCanvas',
x: 0,
y: 0,
width: that.canvasWidth,
height: that.canvasHeight,
success: (res)=> {
var command = tsc.jpPrinter.createNew()
command.init()
command.setSize(100, 80)
command.setGap(2)
command.setCls()
command.setBitmap2(0, 0, 0, res)
command.setPagePrint()
console.log('数据发送: \n',command.getRawData())
let data = command.getData()
console.log('data', data)
bluetoothTool.sendByteData(data)
console.log('发送完毕')
},
fail: function(res) {
console.log(res)
}
})
})
},
fail(res) {
console.log(res)
}
})
},
}
}
\ No newline at end of file
{
"name" : "mes-pad",
"appid" : "__UNI__EFA4D96",
"appid" : "__UNI__EFAA56F",
"description" : "MES-PAD",
"versionName" : "1.0.4",
"versionCode" : "100",
......@@ -27,7 +27,8 @@
"VideoPlayer" : {},
"Record" : {},
"Bluetooth" : {},
"Camera" : {}
"Camera" : {},
"Geolocation" : {}
},
/* 应用发布信息 */
"distribute" : {
......@@ -48,7 +49,14 @@
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.BLUETOOTH\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" /> ",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" /> ",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />",
"<uses-permission android:name=\"android.permission.BLUETOOTH_PRIVILEGED\" tools:ignore=\"ProtectedPermissions\" />",
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" tools:ignore=\"ScopedStorage\" />"
]
},
/* ios打包配置 */
......@@ -57,7 +65,12 @@
},
/* SDK配置 */
"sdkConfigs" : {
"ad" : {}
"ad" : {},
"geolocation" : {
"system" : {
"__platform__" : [ "android" ]
}
}
},
"icons" : {
"android" : {
......
This diff is collapsed.
......@@ -2,6 +2,7 @@
"dependencies": {
"@hyoga/uni-socket.io": "^2.0.3",
"dayjs": "^1.11.12",
"html2canvas": "^1.4.1",
"svg-sprite-loader": "^6.0.11",
"uni-read-pages": "^1.0.5",
"uni-simple-router": "^2.0.8-beta.4"
......
......@@ -93,6 +93,7 @@
</scroll-view>
</view>
</u-modal>
<canvas :style="{width: canvasWidth +'px', height: canvasHeight +'px'}" canvas-id="firstCanvas" id="firstCanvas" class="firstCanvas" />
</view>
</template>
......@@ -137,7 +138,6 @@ export default {
};
},
async created() {
this.createSocket();
uni.$on('switchTab', (indexCode) => {
this.tabIndex = indexCode;
});
......@@ -244,9 +244,14 @@ export default {
if (res.code === 200) {
this.$u.vuex('vuex_printerInfo', {
hostUrl: 'http://' + res.data.printerIp + ':' + res.data.printerPort,
printerName: res.data.printerName
printerName: res.data.printerName,
connectionType: res.data.connectionType
});
this.createSocket();
if (res.data.connectionType === 'bluetooth') {
this.initBle()
} else {
this.createSocket()
}
}
});
this.getPrint();
......@@ -294,7 +299,7 @@ export default {
};
</script>
<style>
<style lang="scss">
.common-container {
width: 100vw;
height: 100vh;
......@@ -396,7 +401,7 @@ img {
margin: 0;
width: 100%;
overflow: auto;
background-image: linear-gradient(to top right, rgb(19 26 56), rgb(33 64 128));
background-image: linear-gradient(to top right, rgb(19, 26, 56), rgb(33, 64, 128));
}
.setting-body {
......@@ -412,4 +417,10 @@ img {
margin: 10rpx 10rpx;
}
}
.firstCanvas {
position: absolute;
// z-index: 99999999;
pointer-events: none ;
left: -99999px;
}
</style>
......@@ -2056,6 +2056,7 @@ export default {
})
}
}
this.feedbackForms.push(item);
item.workorderOption = res.rows.map((temp) => {
if (temp.saleDirectiveList != null) {
item.directiveData[temp.workorderId] = temp.saleDirectiveList.map((temp2) => {
......@@ -2079,6 +2080,7 @@ export default {
text: temp.workorderCode
};
});
if (item.isPackage === '1' && res.rows.length > 0) {
item.workorderId = res.rows[0].workorderId;
item.packNum = res.rows[0].usagePackNum ? res.rows[0].usagePackNum : 0;
......@@ -2086,7 +2088,6 @@ export default {
item.encasementNum = res.rows[0].usageEncasementNum ? res.rows[0].usageEncasementNum : 0;
this.getWorkorderDirectiveList(res.rows[0].workorderId, index);
}
this.feedbackForms.push(item);
}).catch(() => {
this.feedbackForms.push(item);
});
......
......@@ -88,9 +88,14 @@
if (res.code === 200) {
this.$u.vuex('vuex_printerInfo', {
hostUrl:'http://'+ res.data.printerIp +':'+ res.data.printerPort,
printerName: res.data.printerName
printerName: res.data.printerName,
connectionType: res.data.connectionType
});
this.createSocket()
if (res.data.connectionType === 'bluetooth') {
this.initBle()
} else {
this.createSocket()
}
}
})
setTimeout(() => {
......
......@@ -3,6 +3,9 @@ import {
} from 'vuex'
import store from "@/store"
import io from '@hyoga/uni-socket.io';
var tsc = require('../components/gprint/tsc')
import bluetoothTool from '../components/gprint/BluetoothTool.js'
import { base64ToPath } from '../components/gprint/image-tools.js';
// 尝试将用户在根目录中的store/index.js的vuex的state变量,全部加载到全局变量中
let $uStoreKey = [];
......@@ -25,13 +28,153 @@ module.exports = {
}
},
data() {
return {}
return {
devices: [],
currDev: null,
connId: '',
first:true,
firstDraw: true,
tableDomId: '',
tableImgPath: '',
canvasWidth: 800,
canvasHeight: 600
}
},
computed: {
// 将vuex的state中的所有变量,解构到全局混入的mixin中
...mapState($uStoreKey)
},
methods: {
initBle(){
//#ifdef APP-PLUS
// 蓝牙
this.$u.vuex('vuex_printConnect', false);
bluetoothTool.init({
listenBTStatusCallback: (state)=> {
console.log('listenBTStatusCallback', state);
if (state === 'STATE_OFF') {
this.$u.vuex('vuex_printConnect', false);
}
},
discoveryDeviceCallback: this.onDevice,
discoveryFinishedCallback: function() {
console.log('搜索到的设备', that.devices)
},
readDataCallback: function(dataByteArr) {
this.$u.vuex('vuex_printConnect', false);
},
connExceptionCallback: function(e) {
console.log('connExceptionCallback', e);
this.$u.vuex('vuex_printConnect', false);
}
});
this.first = true
this.searchBle()
//#endif
},
searchBle() {
var that = this
console.log("initBule")
// 使用openBluetoothAdapter 接口,免去主动申请权限的麻烦
uni.openBluetoothAdapter({
success(res) {
this.devices = []
console.log("打开 蓝牙模块,开始搜索模式...", res)
uni.getBluetoothAdapterState({
success: function(res) {
console.log(res)
if (res.available) {
//搜索蓝牙
//开始搜寻附近的蓝牙外围设备
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log('开始搜寻附近的蓝牙外围设备', res)
bluetoothTool.discoveryNewDevice();
}
})
} else {
console.log('本机蓝牙不可用')
}
},
})
//that.onDevice()
}
})
},
onDevice(newDevice){
console.log("监听寻找到新设备的事件---------------")
console.log(newDevice)
if(newDevice.name && newDevice.name != 'null') {
this.devices.push({
name: newDevice.name,
address: newDevice.address
})
if (newDevice.name === 'CT-428D' && newDevice.type === 1 && this.first) {
this.onConn(newDevice)
bluetoothTool.cancelDiscovery()
this.first = false
}
}
},
onConn(item) {
console.log("连接蓝牙---------------" + item.address)
/* uni.showLoading({
title: '连接中',
mask: false
}); */
bluetoothTool.connDevice(item.address,(result)=>{
if(result) {
this.$u.vuex('vuex_printConnect', true);
}
console.log('连接结果:',result)
});
},
blePrint (filePath) {
if(!filePath) {
console.log('没有图片路径')
return
}
const firstCanvas = uni.createCanvasContext('firstCanvas');
console.log('rescanvas前')
const that = this
uni.getImageInfo({
src: filePath,
success(img) {
that.canvasWidth = 800
that.canvasHeight = 640
firstCanvas.drawImage(img.path, 0, 0, that.canvasWidth, that.canvasHeight);
firstCanvas.draw(true, ()=>{
uni.canvasGetImageData({
canvasId: 'firstCanvas',
x: 0,
y: 0,
width: that.canvasWidth,
height: that.canvasHeight,
success: (res)=> {
this.firstDraw = false
var command = tsc.jpPrinter.createNew()
command.init()
command.setSize(100, 80)
command.setGap(2)
command.setCls()
command.setBitmap2(0, 0, 0, res)
command.setPagePrint()
console.log('数据发送: \n',command.getRawData())
let data = command.getData()
console.log('data', data)
bluetoothTool.sendByteData(data)
console.log('发送完毕')
},
fail: function(res) {
console.log(res)
}
})
});
}
})
},
createSocket() {
if (getApp().globalData.printSocket && Object.keys(getApp().globalData.printSocket).length > 0) {
getApp().globalData.printSocket.close && getApp().globalData.printSocket.close()
......@@ -72,22 +215,40 @@ module.exports = {
getApp().globalData.printSocket = socket
},
async printPdfSocket(params) {
if (!this.vuex_printerInfo.hostUrl) {
this.$u.toast('请绑定打印机');
return;
}
if (this.vuex_printConnect) {
this.$u.api.getPrintDown(params).then((res) => {
if (res.code === 200) {
getApp().globalData.printSocket.emit('news', {
client: null,
printer: this.vuex_printerInfo.printerName,
type: 'url_pdf',
// pdf_path: 'http://192.168.3.91:8082/static/123.pdf',
pdf_path: res.fileUrl,
});
}
});
if (this.vuex_printerInfo.connectionType === 'bluetooth') {
console.log('蓝牙开始打印')
await this.$u.api.getPrintPNG(params).then(async (res) => {
console.log('请求接口', res)
const codeUrl = 'data:image/png;base64,'+uni.arrayBufferToBase64(res)
base64ToPath(codeUrl, '.png').then(imgPath=>{
console.log('imgPath', imgPath)
this.blePrint(imgPath)
}).catch(e=> {
console.log('转图片错误')
})
}).catch(e => {
console.log('err', e)
})
} else {
this.$u.api.getPrintDown(params).then((res) => {
if (res.code === 200) {
getApp().globalData.printSocket.emit('news', {
client: null,
printer: this.vuex_printerInfo.printerName,
type: 'url_pdf',
// pdf_path: 'http://192.168.3.91:8082/static/123.pdf',
pdf_path: res.fileUrl,
});
}
});
}
} else {
this.$u.toast('打印机连接失败');
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment