This commit is contained in:
weipengfei 2024-05-15 18:34:11 +08:00
parent 9e7ab18172
commit 43292d0563
14 changed files with 1259 additions and 114 deletions

50
App.vue
View File

@ -1,17 +1,41 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
<script setup>
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app"
const isHaveNetwork = ()=> {
uni.getNetworkType({
success: res => {
if (res.networkType == 'none') {
uni.showModal({
title: '网络不给力~',
content: '是否重新连接',
showCancel: true,
confirmText: '是',
cancelText: '不了',
success: res => {
if (res.confirm) {
setTimeout(() => {
isHaveNetwork() //
}, 200)
}
}
});
}
},
fail: err => console.error('调用失败'),
complete: () => {}
})
}
onLaunch(() => {
console.log('App Launch')
})
onShow(() => {
console.log('App Show')
isHaveNetwork()
})
onHide(() => {
console.log('App Hide')
})
</script>
<style>
/*每个页面公共css */
/*每个页面公共css */
</style>

View File

@ -0,0 +1,61 @@
// 对应的指令 请到手册查询
const esc = (item) => {
let string = '';
//模板字符串 自带换行符 \n (也可以用字符串拼接 每行指令结尾 + \n)
// 字符串拼接:! 0 200 200 210 1\n TEXT 0 0 250 0 test\n PRINT\n
string += `
************
小票打印
************
============================
PRINT
`;
return string;
}
const cpcl = (item) => {
let string = '';
//模板字符串 自带换行符 \n (也可以用字符串拼接 每行指令结尾 + \n)
// 字符串拼接:! 0 200 200 210 1\n TEXT 0 0 250 0 test\n PRINT\n
string += `! 0 ${item.width} ${item.height} 210 1
TEXT 0 0 50 0 标题1${item.title1} ${item.title2}
TEXT 0 0 50 40 标题2${item.title2} 标题3${item.title3}
VB QR 50 60 M 2 U 6
${item.id}
ENDQR
PRINT
`;
return string;
}
const tspl = (item) => {
let string = '';
//模板字符串 自带换行符 \n (也可以用字符串拼接 每行指令结尾 + \n)
// 字符串拼接SIZE 100mm, 100mm\n TEXT 250,0,"TSS24.BF2",0,1,1,"test"\n PRINT 1\n
string += `SIZE ${item.width}mm, ${item.height}mm
GAP 3mm, 0mm
DIRECTION 1
CLS
TEXT 50,0,"TSS24.BF2",0,1,1,"标题1${item.title1} ${item.title2}"
TEXT 50,40,"TSS24.BF2",0,1,1,"标题2${item.title2} 标题3${item.title3}"
QRCODE 50,60,H,6,A,0,"${item.id}"
PRINT 1
`;
return string;
}
const commands = (type, item) => {
switch (type) {
case 'esc':
return esc(item);
case 'cpcl':
return cpcl(item);
case 'tspl':
return tspl(item);
default:
return 'HELLO WORLD';
}
}
export {
commands
}

View File

@ -0,0 +1,20 @@
{
"id": "wangqingzhou311-android-blueTooth",
"name": "Android蓝牙ble低功率及高功率打印机 小票、标签、面单打印插件",
"displayName": "Android蓝牙ble低功率及高功率打印机 小票、标签、面单打印插件",
"version": "1.0",
"description": "蓝牙打印参考示例只支持APP安卓可以对不同型号打印机的指令发送即可打印理论上任何打印机的指令都可以在例子中运行。",
"keywords": [
"蓝牙打印",
"二维码打印",
"小票打印",
"标签打印",
"打印指令"
],
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
]
}
}

View File

@ -0,0 +1,269 @@
//address=""搜索蓝牙//address=设备mac地址自动配对给出mac地址的设备 安卓
var BleDevice
var device = null,
BAdapter = null,
BluetoothAdapter = null,
uuid = null,
main = null,
UUID = null,
bluetoothSocket = null,
num = 0;
// 开始gps定位
function getLocationManager(callback) {
plus.android.requestPermissions(
['android.permission.ACCESS_FINE_LOCATION'],
function(resultObj) {
var result = 0;
for (var i = 0; i < resultObj.granted.length; i++) {
var grantedPermission = resultObj.granted[i]; // 以获取的权限
result = 1;
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
var deniedPresentPermission = resultObj.deniedPresent[i]; // 拒绝本次申请的权限
num += 1;
result = 0;
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
var deniedAlwaysPermission = resultObj.deniedAlways[i]; // 永久拒绝的权限
num += 1;
result = -1;
}
// 权限被拒绝则打开app 设置界面可以再app设置界面打开相应权限
if (result !== 1) {
const Intent = plus.android.importClass("android.content.Intent");
const Settings = plus.android.importClass("android.provider.Settings");
const Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
const intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
} else {
// 因为安卓手机,授权之后还需要打开定位服务功能 当手机授权之后 调用下面的方法
var context = plus.android.importClass("android.content.Context");
var locationManager = plus.android.importClass("android.location.LocationManager");
var main = plus.android.runtimeMainActivity();
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
var gps = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
var agps = mainSvr.isProviderEnabled(locationManager.NETWORK_PROVIDER);
// 只有两个gps开关和agps开关都是关的情况才算关有一个开就认为是开
if (gps || agps) {
startBluetoothDiscovery(callback); // 目前发现 荣耀需要弹框允许蓝牙权限 否则无法搜索即使打开蓝牙也没用
} else {
uni.showModal({
title: "提示",
content: "请授权位置获取附近的蓝牙设备",
showCancel: false,
success() {
if (!mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)) {
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
main.startActivity(intent); // 打开系统设置gps服务页面
} else {
startBluetoothDiscovery(callback); // 目前发现 荣耀需要弹框允许蓝牙权限 否则无法搜索即使打开蓝牙也没用
console.log('定位已开启')
// uni.showToast({
// title: '定位已开启',
// duration: 2000,
// });
}
}
})
}
}
}
)
}
function startBluetoothDiscovery(callback) {
plus.bluetooth.openBluetoothAdapter({
success: function(e) {
plus.bluetooth.startBluetoothDevicesDiscovery({
success: function(e) { callback() },
fail: function(e) { console.log('失败2') }
});
},
fail: function(e) {
console.log('open failed: ' + JSON.stringify(e));
}
});
}
// 搜索设备
function searchDevices(address = '', vlist1 = [], vlist2 = []) {
//注册类
var main = plus.android.runtimeMainActivity();
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
var BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
BAdapter = BluetoothAdapter.getDefaultAdapter();
// 没有开启蓝牙
if (!BAdapter.isEnabled()) {
uni.showToast({
title: '请开启蓝牙',
duration: 2000,
icon: 'error'
});
return;
}
console.log("开始搜索设备");
var filter = new IntentFilter();
var bdevice = new BluetoothDevice();
var on = null;
var un = null;
let titleStr = '正在搜索请稍候';
if (address) {
titleStr = '正在连接蓝牙';
}
uni.showLoading({
title: titleStr
});
BAdapter.startDiscovery(); //开启搜索
var receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
onReceive: function(context, intent) { //实现onReceiver回调函数
plus.android.importClass(context);
plus.android.importClass(intent); //通过intent实例引入intent类方便以后的.’操作
if (intent.getAction() === "android.bluetooth.adapter.action.DISCOVERY_FINISHED") {
main.unregisterReceiver(receiver); //取消监听
uni.hideLoading(); // 默认12秒
// console.log("搜索结束")
} else {
BleDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
const name = BleDevice.getName();
//判断是否配对
if (BleDevice.getBondState() === bdevice.BOND_NONE) {
//参数如果跟取得的mac地址一样就配对
if (address === BleDevice.getAddress()) {
if (BleDevice.createBond()) { //配对命令.createBond()
vlist2.push({ name, address: BleDevice.getAddress() });
BAdapter.cancelDiscovery(); //取消扫描
// main.unregisterReceiver(receiver);//取消监听
uni.hideLoading(); //
}
} else {
if (name !== null && name !== on) { //判断防止重复添加
on = name || '未知设备';
vlist1.push({ name: on, address: BleDevice.getAddress() })
uni.hideLoading();
if (on === 'T58') { //判断连接到T58打印机
uni.$emit('connect', 'T58');
}
}
}
} else {
if (name !== un) { //判断防止重复添加
un = name;
vlist1.push({ name: un, address: BleDevice.getAddress() });
vlist2.push({ name: un, address: BleDevice.getAddress() });
console.log('=========', vlist1);
uni.hideLoading();
if (address) {
BAdapter.cancelDiscovery(); //取消扫描
}
if (un === 'T58') { //判断连接到T58打印机
uni.$emit('connect', 'T58');
}
}
}
}
}
});
filter.addAction(bdevice.ACTION_FOUND);
filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_ACL_DISCONNECTED);
main.registerReceiver(receiver, filter); //注册监听
}
//开始连接打印
function print(mac_address, data, callback) {
if (!mac_address) {
uni.showToast({
title: '请选择蓝牙设备',
duration: 2000,
icon: 'error'
});
return;
}
main = plus.android.runtimeMainActivity();
BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
UUID = plus.android.importClass("java.util.UUID");
uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BAdapter = BluetoothAdapter.getDefaultAdapter();
device = BAdapter.getRemoteDevice(mac_address);
plus.android.importClass(device);
bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
plus.android.importClass(bluetoothSocket);
// const isConnected = bluetoothSocket.isConnected();
// console.log('设备是否连接,',bluetoothSocket.isConnected());
if (!bluetoothSocket.isConnected()) {
uni.showToast({
title: '正在打印小票, 请耐心等待',
duration: 2000,
icon: 'none'
});
bluetoothSocket.connect();
}
if (bluetoothSocket.isConnected()) {
const outputStream = bluetoothSocket.getOutputStream();
plus.android.importClass(outputStream);
// string 直接传输指令就行 哪个打印机需要的指令就传哪个指令 例子(tSPL)
// 宽: X800100mmY800100mm
// const string2 = `
// SIZE 100mm, 100mm
// GAP 3mm, 0mm
// DIRECTION 1
// CLS
// TEXT 291,0,"TSS24.BF2",0,1,1,"货号0075 0075瑜伽体力库"
// TEXT 291,40,"TSS24.BF2",0,1,1,"日期06/30 裁剪:裁剪人"
// TEXT 291,80,"TSS24.BF2",0,1,1,"编号952 包号1"
// TEXT 291,120,"TSS24.BF2",0,1,1,"床号91 颜色:白色"
// TEXT 291,160,"TSS24.BF2",0,1,1,"尺码S 数量100"
// QRCODE 391,200,H,10,A,0,"无效数据-guid"
// PRINT 1
// `;
data.forEach(item => {
const bytes = plus.android.invoke(item, 'getBytes', 'gbk');
outputStream.write(bytes);
});
setTimeout(function() {
outputStream.flush(); // 强制把缓冲区内容输出
device = null //这里关键
// outputStream.clone(); // 关闭输出流
bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
callback();
}, 500)
} else uni.showModal({
content: '连接打印机失败,是否重试',
success: (res) => {
if (res.confirm) {
print(mac_address, data, callback)
}
}
})
}
// 关闭操作
function cancelDiscovery() {
if (BAdapter) {
BAdapter.cancelDiscovery(); //取消扫描
if (bluetoothSocket) {
bluetoothSocket.close(); //关闭蓝牙连接
}
}
}
export { searchDevices, print, getLocationManager, cancelDiscovery }

View File

@ -1,22 +1,22 @@
{
"name" : "cashier-paid",
"appid" : "__UNI__D9AB0FD",
"name" : "采购收银系统",
"appid" : "__UNI__D15002B",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "***",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationStyle": "custom",
"rpxCalcMaxDeviceWidth": 2560, // rpx px 960
"rpxCalcBaseDeviceWidth": 1280, // rpx 使 rpx px 375
"rpxCalcIncludeWidth": 2560, // rpx rpx 750
"app-plus": {
"titleView": false
}
"globalStyle" : {
"navigationBarTextStyle" : "black",
"navigationBarTitleText" : "***",
"navigationBarBackgroundColor" : "#F8F8F8",
"backgroundColor" : "#F8F8F8",
"navigationStyle" : "custom",
"rpxCalcMaxDeviceWidth" : 2560, // rpx px 960
"rpxCalcBaseDeviceWidth" : 1280, // rpx 使 rpx px 375
"rpxCalcIncludeWidth" : 2560, // rpx rpx 750
"app-plus" : {
"titleView" : false
}
},
/* 5+App */
"app-plus" : {
@ -30,7 +30,10 @@
"delay" : 0
},
/* */
"modules" : {},
"modules" : {
"Geolocation" : {},
"Bluetooth" : {}
},
/* */
"distribute" : {
/* android */
@ -51,12 +54,56 @@
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
],
"minSdkVersion" : 29,
"targetSdkVersion" : 31
},
/* ios */
"ios" : {},
"ios" : {
"idfa" : false,
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {}
"sdkConfigs" : {
"ad" : {},
"geolocation" : {
"system" : {
"__platform__" : [ "ios", "android" ]
}
}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* */

View File

@ -13,6 +13,7 @@
"navigationBarBackgroundColor": "#007AFF",
"backgroundColor": "#FFFFFF",
"navigationStyle": "custom",
"pageOrientation": "landscape",
"app-plus": {
"titleView": false
}

View File

@ -1,37 +1,122 @@
<template>
<view class="content">
<web-view src="http://192.168.1.55:5175/"></web-view>
</view>
<web-view src="http://192.168.1.55:5178/" @message="onmessage"></web-view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
// #ifdef APP-PLUS
plus.screen.lockOrientation('default');
plus.navigator.setFullscreen(true);//
// #endif
},
onReady() {
// #ifdef APP-PLUS
plus.screen.lockOrientation('landscape-primary');
// #endif
},
// //
// onUnload() {
// // #ifdef APP-PLUS
// plus.screen.lockOrientation('portrait-primary');
// // #endif
// },
methods: {
<script setup>
import { onLoad, onReady } from "@dcloudio/uni-app"
import { nextTick, reactive, ref } from "vue"
import { getLocationManager, searchDevices, print,
cancelDiscovery } from '@/js_sdk/wangqingzhou311-android-blueTooth/searchDevices.js';
import { commands } from '@/js_sdk/wangqingzhou311-android-blueTooth/command.js';
import * as pos from "@/utils/EscPostUtils.js"
const vw = ref(null); // web-view
}
}
onLoad(() => {
// #ifdef APP-PLUS
// plus.screen.lockOrientation('default'); //
plus.navigator.setFullscreen(true); //
// #endif
getLocationManager(() => {});
})
onReady(() => {
{
// #ifdef APP-PLUS
// plus.screen.lockOrientation('landscape-primary');
nextTick(()=>{
setTimeout(()=>{ //webview
const pages = getCurrentPages();
vw.value = pages[pages.length - 1].$getAppWebview().children()[0];
}, 3000)
})
// #endif
}
})
const state = reactive({
current: 'esc',
deviceData: [],
data: [
{ id: "12345", width: 100, height: 100, title1: 'title_1', title2: 'title_2', title3: 'title_3' },
],
// deviceId: '86:67:7A:2A:0B:08'
});
const onPrintClick = (str) => {
const stringData = [];
// state.data.forEach(item => {
// // stringData.push(commands(state.current, item));
// let str = '\n';
// str += '********************************\n';
// str += '\n';
// str += '1 * 1 \t ¥1.00 \n\n';
// str += '2 * 1 \t ¥1.00 \n\n';
// str += '3 * 1 \t ¥1.00 \n\n';
// str += '================================\n';
// str += '\n\t\t\t';
// stringData.push(str)
// })
if(str) stringData.push(str);
else return uni.showToast({
title: '不可打印空内容',
icon: 'exception'
})
console.log('打印内容', stringData);
let deviceId = uni.getStorageSync('deviceId');
if(!deviceId) {
let obj = state.deviceData.find(item=>item.name=='T58');
if(!obj) return uni.showToast({
title: '蓝牙未连接到T58打印机, 请检查是否已配对T58打印机',
icon: 'exception'
})
else {
deviceId = obj.address;
}
}
console.log('打印机地址=>', deviceId);
print(deviceId, stringData, () => {
uni.showToast({
title: '打印成功',
duration: 2000,
});
uni.setStorageSync('deviceId', deviceId)
})
}
const onBtnClick = (deviceId) => {
state.deviceId = deviceId;
searchDevices(deviceId);
}
// searchDevices('',state.deviceData);
let t = 1;
// webview
const onmessage = (e)=>{
console.log('收到消息', e);
if(e.detail?.data[0]?.type=='print'){
if(e.detail?.data[0]?.content){
onPrintClick(e.detail?.data[0]?.content)
}
}
else if(e.detail?.data[0]?.type=='connect') {
searchDevices('',state.deviceData);
uni.$off('connect');
uni.$once('connect', (e)=>{
uni.hideLoading();
let obj = {
type: 'connect',
data: '打印机已连接'
}
console.log('连接成功',t++);
vw.value.evalJS(`receiveData('${JSON.stringify(obj)}')`);
})
}
}
// //
// onUnload() {
// // #ifdef APP-PLUS
// plus.screen.lockOrientation('portrait-primary');
// // #endif
// },
</script>
<style>

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
;(function(){
let u=void 0,isReady=false,onReadyCallbacks=[],isServiceReady=false,onServiceReadyCallbacks=[];
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#FFFFFF","titleView":false,"navigationBar":{"backgroundColor":"#007AFF","titleText":"uni-app","style":"custom","type":"default","titleColor":"#ffffff"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"cashier-paid","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"4.08","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#FFFFFF","pageOrientation":"landscape","titleView":false,"navigationBar":{"backgroundColor":"#007AFF","titleText":"uni-app","style":"custom","type":"default","titleColor":"#ffffff"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"采购收银系统","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"4.15","entryPagePath":"pages/index/index","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
const __uniRoutes = [{"path":"pages/index/index","meta":{"isQuit":true,"isEntry":true,"navigationBar":{"titleText":"uni-app","type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
__uniConfig.styles=[];//styles
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});

View File

@ -31,6 +31,231 @@ if (uni.restoreGlobal) {
}
(function(vue) {
"use strict";
const ON_SHOW = "onShow";
const ON_HIDE = "onHide";
const ON_LAUNCH = "onLaunch";
const ON_LOAD = "onLoad";
const ON_READY = "onReady";
function formatAppLog(type, filename, ...args) {
if (uni.__log__) {
uni.__log__(type, filename, ...args);
} else {
console[type].apply(console, [...args, filename]);
}
}
const createHook = (lifecycle) => (hook, target = vue.getCurrentInstance()) => {
!vue.isInSSRComponentSetup && vue.injectHook(lifecycle, hook, target);
};
const onShow = /* @__PURE__ */ createHook(ON_SHOW);
const onHide = /* @__PURE__ */ createHook(ON_HIDE);
const onLaunch = /* @__PURE__ */ createHook(ON_LAUNCH);
const onLoad = /* @__PURE__ */ createHook(ON_LOAD);
const onReady = /* @__PURE__ */ createHook(ON_READY);
var BleDevice;
var device = null, BAdapter = null, BluetoothAdapter = null, uuid = null, UUID = null, bluetoothSocket = null;
function getLocationManager(callback) {
plus.android.requestPermissions(
["android.permission.ACCESS_FINE_LOCATION"],
function(resultObj) {
var result = 0;
for (var i = 0; i < resultObj.granted.length; i++) {
resultObj.granted[i];
result = 1;
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
resultObj.deniedPresent[i];
result = 0;
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
resultObj.deniedAlways[i];
result = -1;
}
if (result !== 1) {
const Intent = plus.android.importClass("android.content.Intent");
const Settings = plus.android.importClass("android.provider.Settings");
const Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
const intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
} else {
var context = plus.android.importClass("android.content.Context");
var locationManager = plus.android.importClass("android.location.LocationManager");
var main = plus.android.runtimeMainActivity();
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
var gps = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
var agps = mainSvr.isProviderEnabled(locationManager.NETWORK_PROVIDER);
if (gps || agps) {
startBluetoothDiscovery(callback);
} else {
uni.showModal({
title: "提示",
content: "请授权位置获取附近的蓝牙设备",
showCancel: false,
success() {
if (!mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)) {
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
main.startActivity(intent);
} else {
startBluetoothDiscovery(callback);
formatAppLog("log", "at js_sdk/wangqingzhou311-android-blueTooth/searchDevices.js:66", "定位已开启");
}
}
});
}
}
}
);
}
function startBluetoothDiscovery(callback) {
plus.bluetooth.openBluetoothAdapter({
success: function(e) {
plus.bluetooth.startBluetoothDevicesDiscovery({
success: function(e2) {
callback();
},
fail: function(e2) {
formatAppLog("log", "at js_sdk/wangqingzhou311-android-blueTooth/searchDevices.js:88", "失败2");
}
});
},
fail: function(e) {
formatAppLog("log", "at js_sdk/wangqingzhou311-android-blueTooth/searchDevices.js:92", "open failed: " + JSON.stringify(e));
}
});
}
function searchDevices(address = "", vlist1 = [], vlist2 = []) {
var main = plus.android.runtimeMainActivity();
var IntentFilter = plus.android.importClass("android.content.IntentFilter");
var BluetoothAdapter2 = plus.android.importClass("android.bluetooth.BluetoothAdapter");
var BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
BAdapter = BluetoothAdapter2.getDefaultAdapter();
if (!BAdapter.isEnabled()) {
uni.showToast({
title: "请开启蓝牙",
duration: 2e3,
icon: "error"
});
return;
}
formatAppLog("log", "at js_sdk/wangqingzhou311-android-blueTooth/searchDevices.js:113", "开始搜索设备");
var filter = new IntentFilter();
var bdevice = new BluetoothDevice();
var on = null;
var un = null;
let titleStr = "正在搜索请稍候";
if (address) {
titleStr = "正在连接蓝牙";
}
uni.showLoading({
title: titleStr
});
BAdapter.startDiscovery();
var receiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
onReceive: function(context, intent) {
plus.android.importClass(context);
plus.android.importClass(intent);
if (intent.getAction() === "android.bluetooth.adapter.action.DISCOVERY_FINISHED") {
main.unregisterReceiver(receiver);
uni.hideLoading();
} else {
BleDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
const name = BleDevice.getName();
if (BleDevice.getBondState() === bdevice.BOND_NONE) {
if (address === BleDevice.getAddress()) {
if (BleDevice.createBond()) {
vlist2.push({ name, address: BleDevice.getAddress() });
BAdapter.cancelDiscovery();
uni.hideLoading();
}
} else {
if (name !== null && name !== on) {
on = name || "未知设备";
vlist1.push({ name: on, address: BleDevice.getAddress() });
uni.hideLoading();
if (on === "T58") {
uni.$emit("connect", "T58");
}
}
}
} else {
if (name !== un) {
un = name;
vlist1.push({ name: un, address: BleDevice.getAddress() });
vlist2.push({ name: un, address: BleDevice.getAddress() });
formatAppLog("log", "at js_sdk/wangqingzhou311-android-blueTooth/searchDevices.js:164", "=========", vlist1);
uni.hideLoading();
if (address) {
BAdapter.cancelDiscovery();
}
if (un === "T58") {
uni.$emit("connect", "T58");
}
}
}
}
}
});
filter.addAction(bdevice.ACTION_FOUND);
filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter2.ACTION_ACL_DISCONNECTED);
main.registerReceiver(receiver, filter);
}
function print(mac_address, data, callback) {
if (!mac_address) {
uni.showToast({
title: "请选择蓝牙设备",
duration: 2e3,
icon: "error"
});
return;
}
plus.android.runtimeMainActivity();
BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
UUID = plus.android.importClass("java.util.UUID");
uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BAdapter = BluetoothAdapter.getDefaultAdapter();
device = BAdapter.getRemoteDevice(mac_address);
plus.android.importClass(device);
bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
plus.android.importClass(bluetoothSocket);
if (!bluetoothSocket.isConnected()) {
uni.showToast({
title: "正在打印小票, 请耐心等待",
duration: 2e3,
icon: "none"
});
bluetoothSocket.connect();
}
if (bluetoothSocket.isConnected()) {
const outputStream = bluetoothSocket.getOutputStream();
plus.android.importClass(outputStream);
data.forEach((item) => {
const bytes = plus.android.invoke(item, "getBytes", "gbk");
outputStream.write(bytes);
});
setTimeout(function() {
outputStream.flush();
device = null;
bluetoothSocket.close();
callback();
}, 500);
} else
uni.showModal({
content: "连接打印机失败,是否重试",
success: (res) => {
if (res.confirm) {
print(mac_address, data, callback);
}
}
});
}
const _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
@ -39,49 +264,141 @@ if (uni.restoreGlobal) {
return target;
};
const _sfc_main$1 = {
data() {
return {
title: "Hello"
__name: "index",
setup(__props) {
const vw = vue.ref(null);
onLoad(() => {
plus.navigator.setFullscreen(true);
getLocationManager(() => {
});
});
onReady(() => {
{
vue.nextTick(() => {
setTimeout(() => {
const pages = getCurrentPages();
vw.value = pages[pages.length - 1].$getAppWebview().children()[0];
}, 3e3);
});
}
});
const state = vue.reactive({
current: "esc",
deviceData: [],
data: [
{ id: "12345", width: 100, height: 100, title1: "title_1", title2: "title_2", title3: "title_3" }
]
// deviceId: '86:67:7A:2A:0B:08'
});
const onPrintClick = (str) => {
const stringData = [];
if (str)
stringData.push(str);
else
return uni.showToast({
title: "不可打印空内容",
icon: "exception"
});
formatAppLog("log", "at pages/index/index.vue:63", "打印内容", stringData);
let deviceId = uni.getStorageSync("deviceId");
if (!deviceId) {
let obj = state.deviceData.find((item) => item.name == "T58");
if (!obj)
return uni.showToast({
title: "蓝牙未连接到T58打印机, 请检查是否已配对T58打印机",
icon: "exception"
});
else {
deviceId = obj.address;
}
}
formatAppLog("log", "at pages/index/index.vue:75", "打印机地址=>", deviceId);
print(deviceId, stringData, () => {
uni.showToast({
title: "打印成功",
duration: 2e3
});
uni.setStorageSync("deviceId", deviceId);
});
};
let t = 1;
const onmessage = (e) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
formatAppLog("log", "at pages/index/index.vue:93", "收到消息", e);
if (((_b = (_a = e.detail) == null ? void 0 : _a.data[0]) == null ? void 0 : _b.type) == "print") {
if ((_d = (_c = e.detail) == null ? void 0 : _c.data[0]) == null ? void 0 : _d.content) {
onPrintClick((_f = (_e = e.detail) == null ? void 0 : _e.data[0]) == null ? void 0 : _f.content);
}
} else if (((_h = (_g = e.detail) == null ? void 0 : _g.data[0]) == null ? void 0 : _h.type) == "connect") {
searchDevices("", state.deviceData);
uni.$off("connect");
uni.$once("connect", (e2) => {
uni.hideLoading();
let obj = {
type: "connect",
data: "打印机已连接"
};
formatAppLog("log", "at pages/index/index.vue:108", "连接成功", t++);
vw.value.evalJS(`receiveData('${JSON.stringify(obj)}')`);
});
}
};
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock(
"web-view",
{
src: "http://192.168.1.55:5178/",
onMessage: onmessage
},
null,
32
/* NEED_HYDRATION */
);
};
},
onLoad() {
plus.screen.lockOrientation("default");
plus.navigator.setFullscreen(true);
},
onReady() {
plus.screen.lockOrientation("landscape-primary");
},
// // 页面关闭时清除横屏正方向
// onUnload() {
//
// plus.screen.lockOrientation('portrait-primary');
//
// },
methods: {}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock("view", { class: "content" }, [
vue.createElementVNode("web-view", { src: "http://192.168.1.55:5175/" })
]);
}
const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__file", "D:/里海数字乡村/cashier-paid/pages/index/index.vue"]]);
__definePage("pages/index/index", PagesIndexIndex);
function formatAppLog(type, filename, ...args) {
if (uni.__log__) {
uni.__log__(type, filename, ...args);
} else {
console[type].apply(console, [...args, filename]);
}
}
};
const PagesIndexIndex = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__file", "D:/里海数字乡村/cashier-paid/pages/index/index.vue"]]);
__definePage("pages/index/index", PagesIndexIndex);
const _sfc_main = {
onLaunch: function() {
formatAppLog("log", "at App.vue:4", "App Launch");
},
onShow: function() {
formatAppLog("log", "at App.vue:7", "App Show");
},
onHide: function() {
formatAppLog("log", "at App.vue:10", "App Hide");
__name: "App",
setup(__props) {
const isHaveNetwork = () => {
uni.getNetworkType({
success: (res) => {
if (res.networkType == "none") {
uni.showModal({
title: "网络不给力~",
content: "是否重新连接",
showCancel: true,
confirmText: "是",
cancelText: "不了",
success: (res2) => {
if (res2.confirm) {
setTimeout(() => {
isHaveNetwork();
}, 200);
}
}
});
}
},
fail: (err) => formatAppLog("error", "at App.vue:23", "调用失败"),
complete: () => {
}
});
};
onLaunch(() => {
formatAppLog("log", "at App.vue:28", "App Launch");
});
onShow(() => {
formatAppLog("log", "at App.vue:31", "App Show");
isHaveNetwork();
});
onHide(() => {
formatAppLog("log", "at App.vue:35", "App Hide");
});
return () => {
};
}
};
const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "D:/里海数字乡村/cashier-paid/App.vue"]]);

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,8 @@
"iPhone",
"iPad"
],
"id": "__UNI__D9AB0FD",
"name": "cashier-paid",
"id": "__UNI__D15002B",
"name": "采购收银系统",
"version": {
"name": "1.0.0",
"code": "100"
@ -17,6 +17,8 @@
"url": ""
},
"permissions": {
"Geolocation": {},
"Bluetooth": {},
"UniNView": {
"description": "UniNView原生渲染"
}
@ -42,6 +44,38 @@
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"distribute": {
"icons": {
"android": {
"hdpi": "unpackage/res/icons/72x72.png",
"xhdpi": "unpackage/res/icons/96x96.png",
"xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi": "unpackage/res/icons/192x192.png"
},
"ios": {
"appstore": "unpackage/res/icons/1024x1024.png",
"ipad": {
"app": "unpackage/res/icons/76x76.png",
"app@2x": "unpackage/res/icons/152x152.png",
"notification": "unpackage/res/icons/20x20.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x": "unpackage/res/icons/167x167.png",
"settings": "unpackage/res/icons/29x29.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x": "unpackage/res/icons/80x80.png"
},
"iphone": {
"app@2x": "unpackage/res/icons/120x120.png",
"app@3x": "unpackage/res/icons/180x180.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x": "unpackage/res/icons/120x120.png"
}
}
},
"google": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
@ -59,10 +93,24 @@
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
],
"minSdkVersion": 29,
"targetSdkVersion": 31
},
"apple": {
"idfa": false,
"dSYMs": false
},
"apple": {},
"plugins": {
"ad": {},
"geolocation": {
"system": {
"__platform__": [
"ios",
"android"
]
}
},
"audio": {
"mp3": {
"description": "Android平台录音支持MP3格式文件"
@ -82,7 +130,7 @@
"uni-app": {
"control": "uni-v3",
"vueVersion": "3",
"compilerVersion": "4.08",
"compilerVersion": "4.15",
"nvueCompiler": "uni-app",
"renderer": "auto",
"nvue": {
@ -94,5 +142,9 @@
}
}
},
"screenOrientation": [
"landscape-primary",
"landscape-secondary"
],
"launch_path": "__uniappview.html"
}

File diff suppressed because one or more lines are too long

262
utils/EscPostUtils.js Normal file
View File

@ -0,0 +1,262 @@
// 打印机纸宽58mm页的宽度384字符宽度为1每行最多盛放32个字符
// 打印机纸宽80mm页的宽度576字符宽度为1每行最多盛放48个字符
const PAGE_WIDTH = 576;
const MAX_CHAR_COUNT_EACH_LINE = 48;
//字符串转字节序列
export function stringToByte(str) {
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF);
}
}
return bytes;
}
//字节序列转ASCII码
//[0x24, 0x26, 0x28, 0x2A] ==> "$&C*"
export function byteToString(arr) {
if (typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
}
//居中
export function Center() {
var Center = [];
Center.push(27);
Center.push(97);
Center.push(1);
var strCenter = byteToString(Center);
return strCenter;
}
//居左
export function Left() {
var Left = [];
Left.push(27);
Left.push(97);
Left.push(0);
var strLeft = byteToString(Left);
return strLeft;
}
//居右
export function Right() {
var right = [];
Left.push(27);
Left.push(97);
Left.push(2);
var strRight = byteToString(right);
return strRight;
}
//标准字体
export function Size1() {
var Size1 = [];
Size1.push(29);
Size1.push(33);
Size1.push(0);
var strSize1 = byteToString(Size1);
return strSize1;
}
//大号字体
/* 1 n = 0
* 长宽各放大2倍 n = 17 */
export function Size2(n) {
var Size2 = [];
Size2.push(29);
Size2.push(33);
Size2.push(n);
var strSize2 = byteToString(Size2);
return strSize2;
}
// 字体加粗
export function boldFontOn() {
var arr = []
arr.push(27)
arr.push(69)
arr.push(1)
var cmd = byteToString(arr);
return cmd
}
// 取消字体加粗
export function boldFontOff() {
var arr = []
arr.push(27)
arr.push(69)
arr.push(0)
var cmd = byteToString(arr);
return cmd
}
// 打印并走纸n行
export function feedLines(n = 1) {
var feeds = []
feeds.push(27)
feeds.push(100)
feeds.push(n)
var printFeedsLines = byteToString(feeds);
return printFeedsLines
}
// 切纸
export function cutPaper() {
var cut = []
cut.push(29)
cut.push(86)
cut.push(49)
var cutType = byteToString(cut);
return cutType
}
// 开钱箱
export function open_money_box() {
var open = []
open.push(27)
open.push(112)
open.push(0)
open.push(60)
open.push(255)
var openType = byteToString(open)
return openType
}
// 初始化打印机
export function init() {
var arr = []
arr.push(27)
arr.push(68)
arr.push(0)
var str = byteToString(arr)
return str
}
/*
设置左边距
len:
*/
export function setLeftMargin(len = 1) {
var arr = []
arr.push(29)
arr.push(76)
arr.push(len)
var str = byteToString(arr)
return str
}
// 设置打印区域宽度
export function setPrintAreaWidth(width) {
var arr = []
arr.push(29)
arr.push(87)
arr.push(width)
var str = byteToString(arr)
return str
}
/**
* @param str
* @returns {boolean} str是否全是中文
*/
export function isChinese(str) {
return /^[\u4e00-\u9fa5]$/.test(str);
}
// str是否全含中文或者中文标点
export function isHaveChina(str) {
if (escape(str).indexOf("%u") < 0) {
return 0
} else {
return 1
}
}
/**
* 返回字符串宽度(1个中文=2个英文字符)
* @param str
* @returns {number}
*/
export function getStringWidth(str) {
let width = 0;
for (let i = 0, len = str.length; i < len; i++) {
width += isHaveChina(str.charAt(i)) ? 2 : 1;
}
return width;
}
/**
* 同一行输出str1, str2str1居左, str2居右
* @param {string} str1 内容1
* @param {string} str2 内容2
* @param {string} fillWith str1 str2之间的填充字符
* @param {number} fontWidth 字符宽度 1/2
*
*/
export function inline(str1, str2, fillWith = ' ', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
// 需要填充的字符数量
let fillCount = lineWidth - (getStringWidth(str1) + getStringWidth(str2)) % lineWidth;
let fillStr = new Array(fillCount).fill(fillWith.charAt(0)).join('');
return str1 + fillStr + str2;
}
/**
* 用字符填充一整行
* @param {string} fillWith 填充字符
* @param {number} fontWidth 字符宽度 1/2
*/
export function fillLine(fillWith = '-', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
return new Array(lineWidth).fill(fillWith.charAt(0)).join('');
}
/**
* 文字内容居中左右用字符填充
* @param {string} str 文字内容
* @param {number} fontWidth 字符宽度 1/2
* @param {string} fillWith str1 str2之间的填充字符
*/
export function fillAround(str, fillWith = '-', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
let strWidth = getStringWidth(str);
// 内容已经超过一行了,没必要填充
if (strWidth >= lineWidth) {
return str;
}
// 需要填充的字符数量
let fillCount = lineWidth - strWidth;
// 左侧填充的字符数量
let leftCount = Math.round(fillCount / 2);
// 两侧的填充字符,需要考虑左边需要填充,右边不需要填充的情况
let fillStr = new Array(leftCount).fill(fillWith.charAt(0)).join('');
return fillStr + str + fillStr.substr(0, fillCount - leftCount);
}