commit 2d417b14723d4b6e3309726c2b3022e5d59c2463 Author: chris <510148846@qq.com> Date: Thu Mar 28 10:04:31 2024 +0800 首次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b9a7f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +Android-SDK*/ +uni_modules/ +unpackage/ + diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..0a68351 --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,20 @@ +{ + "version" : "1.0", + "configurations" : [ + { + "openVueDevtools" : true, + "playground" : "standard", + "type" : "uni-app:app-android" + }, + { + "app-plus" : { + "launchtype" : "local" + }, + "type" : "uniCloud" + }, + { + "openVueDevtools" : true, + "type" : "uni-app:app-ios" + } + ] +} diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..e69de29 diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..71956e0 --- /dev/null +++ b/App.vue @@ -0,0 +1,63 @@ + + + diff --git a/api/common.js b/api/common.js new file mode 100644 index 0000000..f4dbb32 --- /dev/null +++ b/api/common.js @@ -0,0 +1,43 @@ +import request from '@/utils/network/request'; + +/** + * 登录接口 + * @param {Object} params + */ +export function login (params) { + return request({ + url: '/api/user.ashx?act=studentlogin', + method: 'GET', + data: params + }) +} + +/** + * 登出接口 + */ +export function logout () { + return request({ + url: '', + method: 'GET' + }) +} + +export function getImgData(url) { + return new Promise((resolve, reject) => { + uni.request({ + url, + method: 'GET', + responseType: 'arraybuffer', + success: (e) => { + const imgData = uni.arrayBufferToBase64(e.data) + const imgBase64 = 'data:image/png;base64,' + imgData + // resolve(e.data) + resolve(imgBase64) + }, + fail: (error) => { + console.log(error) + reject(error) + } + }) + }) +} diff --git a/api/exam.js b/api/exam.js new file mode 100644 index 0000000..a129dee --- /dev/null +++ b/api/exam.js @@ -0,0 +1,39 @@ +import request from '@/utils/network/request'; + +/** + * 获取考试列表 + * @param {Object} data + * { studentid: 学生id, status: 考试状态(进行中:1, 已结束: 2) } + */ +export function getExamList(data, config = {}) { + return request({ + url: '/api/user.ashx?act=studentexamlist', + method: 'GET', + data + }, config) +} + +/** + * 获取考试详情 + * @param {Object} data + * { examid: 考试id, studentid: 学生id } + */ +export function getExamInfo(data, config = {}) { + return request({ + url: '/api/user.ashx?act=studentexaminfo', + method: 'GET', + data + }) +} + +/** + * 上传考试图片 + */ +export function uploadExamImg(data, config = {}) { + const { userId, examId, file } = data; + return request({ + url: `/api/user.ashx?act=subexaminfo&studentid=${userId}&examid=${examId}`, + method: 'POST', + data: file + }, config) +} diff --git a/api/question.js b/api/question.js new file mode 100644 index 0000000..68a808a --- /dev/null +++ b/api/question.js @@ -0,0 +1,27 @@ +import request from '@/utils/network/request.js'; + +/** + * 获取试题列表 + * @param {Object} data + * { subjectid: 科目id, gradeid: 年纪id } + */ +export function getQuestionList (data, config = {}) { + return request({ + url: '/api/user.ashx?act=questionlist', + method: 'GET', + data + }, config) +} + +/** + * 获取试题列表 + * @param {Object} data + * { questionid: 试题id } + */ +export function getQuestionInfo (data, config = {}) { + return request({ + url: '/api/user.ashx?act=questioninfo', + method: 'GET', + data + }, config) +} diff --git a/api/school.js b/api/school.js new file mode 100644 index 0000000..9754381 --- /dev/null +++ b/api/school.js @@ -0,0 +1,42 @@ +import request from '@/utils/network/request'; + +/** + * 获取学校列表 + */ +export function getSchoolList() { + return request({ + url: '/api/user.ashx?act=getschoollist', + method: 'GET' + }) +} + +/** + * 获取年纪列表 + */ +export function getGradeList () { + return request({ + url: '/api/user.ashx?act=getgradelist', + method: 'GET' + }) +} + +/** + * 获取科目列表 + */ +export function getSubjectList () { + return request({ + url: '/api/user.ashx?act=getsubjectlist', + method: 'GET' + }) +} + +/** + * 获取知识点 + */ +export function getKnowledgeList (data) { + return request({ + url: '/api/user.ashx?act=getknowledgelist', + method: 'GET', + data + }) +} diff --git a/api/task.js b/api/task.js new file mode 100644 index 0000000..b57f48c --- /dev/null +++ b/api/task.js @@ -0,0 +1,39 @@ +import request from '@/utils/network/request'; + +/** + * 获取作业列表 + * @param {Object} data + * { studentid: 学生id, status: 作业状态(已提交:1, 未提交: 2) } + */ +export function getTaskList(data, config = {}) { + return request({ + url: '/api/user.ashx?act=studenthomeworklist', + method: 'GET', + data + }, config) +} + +/** + * 获取作业详情 + * @param {Object} data + * { taskid: 考试id, studentid: 学生id } + */ +export function getTaskInfo(data, config = {}) { + return request({ + url: '/api/user.ashx?act=studenthomeworkinfo', + method: 'GET', + data + }) +} + +/** + * 上传作业图片 + */ +export function uploadTaskImg(data, config = {}) { + const { userId, workId, file } = data; + return request({ + url: `/api/user.ashx?act=subworkinfo&studentid=${userId}&workid=${workId}`, + method: 'POST', + data: file + }, config) +} diff --git a/assets/images/bg/userIndexHeadBg.png b/assets/images/bg/userIndexHeadBg.png new file mode 100644 index 0000000..d165586 Binary files /dev/null and b/assets/images/bg/userIndexHeadBg.png differ diff --git a/assets/images/icons/my_study.png b/assets/images/icons/my_study.png new file mode 100644 index 0000000..d71c6c0 Binary files /dev/null and b/assets/images/icons/my_study.png differ diff --git a/assets/images/icons/task.png b/assets/images/icons/task.png new file mode 100644 index 0000000..6d47e43 Binary files /dev/null and b/assets/images/icons/task.png differ diff --git a/assets/images/icons/userIndex_order.png b/assets/images/icons/userIndex_order.png new file mode 100644 index 0000000..0b86a7e Binary files /dev/null and b/assets/images/icons/userIndex_order.png differ diff --git a/assets/images/logo/ghlogo.png b/assets/images/logo/ghlogo.png new file mode 100644 index 0000000..7ef7165 Binary files /dev/null and b/assets/images/logo/ghlogo.png differ diff --git a/assets/package/hybrid_html_uni.webview.1.5.5.js b/assets/package/hybrid_html_uni.webview.1.5.5.js new file mode 100644 index 0000000..2c9b980 --- /dev/null +++ b/assets/package/hybrid_html_uni.webview.1.5.5.js @@ -0,0 +1 @@ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function i(e,i){return n.call(e,i)}var t=[];function o(){return window.__dcloud_weex_postMessage||window.__dcloud_weex_}function a(){return window.__uniapp_x_postMessage||window.__uniapp_x_}var r=function(e,n){var i={options:{timestamp:+new Date},name:e,arg:n};if(a()){if("postMessage"===e){var r={data:n};return window.__uniapp_x_postMessage?window.__uniapp_x_postMessage(r):window.__uniapp_x_.postMessage(JSON.stringify(r))}var d={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__uniapp_x_postMessage?window.__uniapp_x_postMessageToService(d):window.__uniapp_x_.postMessageToService(JSON.stringify(d))}else if(o()){if("postMessage"===e){var s={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(s):window.__dcloud_weex_.postMessage(JSON.stringify(s))}var w={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(w):window.__dcloud_weex_.postMessageToService(JSON.stringify(w))}else{if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:i,pageId:""},"*");if(0===t.length){var u=plus.webview.currentWebview();if(!u)throw new Error("plus.webview.currentWebview() is undefined");var g=u.parent(),v="";v=g?g.id:u.id,t.push(v)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}},"__uniapp__service");else{var c=JSON.stringify(i);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(c,",").concat(JSON.stringify(t),");"))}}},d={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;r("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("redirectTo",{url:encodeURI(n)})},getEnv:function(e){a()?e({uvue:!0}):o()?e({nvue:!0}):window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};r("postMessage",e.data||{})}},s=/uni-app/i.test(navigator.userAgent),w=/Html5Plus/i.test(navigator.userAgent),u=/complete|loaded|interactive/;var g=window.my&&navigator.userAgent.indexOf(["t","n","e","i","l","C","y","a","p","i","l","A"].reverse().join(""))>-1;var v=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var _=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var m=window.qa&&/quickapp/i.test(navigator.userAgent);var f=window.ks&&window.ks.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var l=window.tt&&window.tt.miniProgram&&/Lark|Feishu/i.test(navigator.userAgent);var E=window.jd&&window.jd.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var x=window.xhs&&window.xhs.miniProgram&&/xhsminiapp/i.test(navigator.userAgent);for(var S,h=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},y=[function(e){if(s||w)return window.__uniapp_x_postMessage||window.__uniapp_x_||window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&u.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),d},function(e){if(_)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(g){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(v)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(p)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(m){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(f)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.ks.miniProgram},function(e){if(l)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(E)return window.JDJSBridgeReady&&window.JDJSBridgeReady.invoke?setTimeout(e,0):document.addEventListener("JDJSBridgeReady",e),window.jd.miniProgram},function(e){if(x)return window.xhs.miniProgram},function(e){return document.addEventListener("DOMContentLoaded",e),d}],M=0;M + + + + + + + + \ No newline at end of file diff --git a/components/ch-flex/ch-flex.scss b/components/ch-flex/ch-flex.scss new file mode 100644 index 0000000..e69de29 diff --git a/components/ch-flex/ch-flex.vue b/components/ch-flex/ch-flex.vue new file mode 100644 index 0000000..8eeba0f --- /dev/null +++ b/components/ch-flex/ch-flex.vue @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file diff --git a/components/ch-image-uploader/ch-image-uploader.scss b/components/ch-image-uploader/ch-image-uploader.scss new file mode 100644 index 0000000..d2b88ba --- /dev/null +++ b/components/ch-image-uploader/ch-image-uploader.scss @@ -0,0 +1,46 @@ +.img-item, +.select-btn { + height: 300rpx; + width: 300rpx; + border-radius: 5rpx; + overflow: hidden; + border: 1px solid $uni-border-color; + margin: 10px; +} + +.img-item { + position: relative; + + + .img-item { + margin-left: 10px; + } + + image { + height: 100%; + width: 100%; + pointer-events: none; + } + + .del-btn { + position: absolute; + top: 7px; + right: 2px; + z-index: 99; + } +} + +.img-list { + display: flex; + flex-wrap: wrap; +} + +.select-btn { + margin-left: 10px; + display: flex; + justify-content: center; + align-items: center; + + .uni-icons { + color: $uni-border-color!important; + } +} \ No newline at end of file diff --git a/components/ch-image-uploader/ch-image-uploader.vue b/components/ch-image-uploader/ch-image-uploader.vue new file mode 100644 index 0000000..b402047 --- /dev/null +++ b/components/ch-image-uploader/ch-image-uploader.vue @@ -0,0 +1,152 @@ + + + + + \ No newline at end of file diff --git a/components/ch-nav-bar/ch-nav-bar.scss b/components/ch-nav-bar/ch-nav-bar.scss new file mode 100644 index 0000000..a4e86ee --- /dev/null +++ b/components/ch-nav-bar/ch-nav-bar.scss @@ -0,0 +1,26 @@ +button { + line-height: 1.7; +} + +.nav-title { + font-size: $uni-font-size-lg; + align-self: center; + margin-left: 20px; + font-weight: bold; +} + +.uni-navbar { + position: relative; +} + +.uni-navbar::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + width: 100%; + height: 1px; + background-color: #fff; + background: linear-gradient(90deg, #000, #fff, #000); + z-index: 99; +} \ No newline at end of file diff --git a/components/ch-nav-bar/ch-nav-bar.vue b/components/ch-nav-bar/ch-nav-bar.vue new file mode 100644 index 0000000..78d809d --- /dev/null +++ b/components/ch-nav-bar/ch-nav-bar.vue @@ -0,0 +1,41 @@ + + + + + \ No newline at end of file diff --git a/components/ch-nav-btn/ch-nav-btn.scss b/components/ch-nav-btn/ch-nav-btn.scss new file mode 100644 index 0000000..8be9e2d --- /dev/null +++ b/components/ch-nav-btn/ch-nav-btn.scss @@ -0,0 +1,11 @@ +.ch-nav-btn { + background-color: $uni-color-primary; + font-size: $uni-font-size-sm; + line-height: 1.8; + border-radius: 8px; + padding: 0 12rpx; + + &:active { + background-color: transparentize($uni-color-primary, 0.3); + } +} \ No newline at end of file diff --git a/components/ch-nav-btn/ch-nav-btn.vue b/components/ch-nav-btn/ch-nav-btn.vue new file mode 100644 index 0000000..e2e88dd --- /dev/null +++ b/components/ch-nav-btn/ch-nav-btn.vue @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/components/cjn-print/bluetooth.js b/components/cjn-print/bluetooth.js new file mode 100644 index 0000000..58cd3e1 --- /dev/null +++ b/components/cjn-print/bluetooth.js @@ -0,0 +1,279 @@ +class Bluetooth { + + constructor() { + this.isOpenBle = false; + this.deviceId = ""; + this.serviceId = ""; + this.writeId = ""; + this.notifyId = ""; + this.openBluetoothAdapter(); + } + + showToast(title) { + uni.showToast({ + title: title, + icon: 'none', + 'duration': 2000 + }); + } + //初始化蓝牙模块,检查蓝牙是否已打开 + openBluetoothAdapter() { + return new Promise((resolve, reject) => { + uni.openBluetoothAdapter({ + success: res => { + this.isOpenBle = true; + resolve(res); + }, + fail: err => { + setTimeout(function() { + uni.showToast({ + title:"请打开蓝牙和定位功能", + icon:"none" + }) + }, 1000); + reject(err); + }, + }); + }); + } + //搜索周边蓝牙设备 + startBluetoothDevicesDiscovery() { + if (!this.isOpenBle) { + this.showToast(`请打开蓝牙和定位功能`) + return; + } + + let self = this; + uni.showLoading({ + title: '正在搜索蓝牙设备' + }) + return new Promise((resolve, reject) => { + setTimeout(() => { + uni.startBluetoothDevicesDiscovery({ + success: res => { + resolve(res) + }, + fail: res => { + self.showToast(`搜索设备失败` + JSON.stringify(err)); + reject(err); + } + }) + }, 300); + }); + } + //停止搜索周报蓝牙设备 + stopBluetoothDevicesDiscovery() { + let self = this; + return new Promise((resolve, reject) => { + uni.stopBluetoothDevicesDiscovery({ + success: e => { + uni.hideLoading(); + }, + fail: e => { + uni.hideLoading(); + self.showToast('停止搜索失败,请重试'); + } + }) + }); + } + //连接设备 + createBLEConnection() { + let deviceId = this.deviceId; + let self = this; + + return new Promise((resolve, reject) => { + uni.createBLEConnection({ + deviceId, + success: (res) => { + console.log("成功连接设备" + JSON.stringify(res)); + resolve(res) + }, + fail: err => { + self.showToast(`设备连接失败` + JSON.stringify(err)); + reject(err); + } + }) + }); + } + + //获取蓝牙设备所有服务(service) + getBLEDeviceServices() { + let _serviceList = []; + let deviceId = this.deviceId; + let self = this; + + return new Promise((resolve, reject) => { + setTimeout(() => { + uni.getBLEDeviceServices({ + deviceId, + success: res => { + //console.log('获取服务成功'); + //console.log(res.services); + for (let service of res.services) { + if (service.isPrimary) { + _serviceList.push(service); + } + } + if(res.services.length<=0){ + self.showToast('成功获取服务,但没有可用服务'); + } + + resolve(_serviceList) + }, + fail: err => { + //设备已连接,但未能获取设备服务,也有可能连接处于断开状态 + self.showToast('未获取蓝牙设备相关服务'); + reject(err); + }, + }) + }, 2000); + }); + } + + //获取蓝牙设备某个服务中所有特征值(characteristic) + getBLEDeviceCharacteristics() { + let deviceId = this.deviceId; + let serviceId = this.serviceId; + + let self = this; + return new Promise((resolve, reject) => { + uni.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: res => { + for (let _obj of res.characteristics) { + //获取notify + if (_obj.properties.notify) { + self.notifyId = _obj.uuid; + uni.setStorageSync('notifyId', self.notifyId); + } + //获取writeId + if (_obj.properties.write) { + self.writeId = _obj.uuid; + uni.setStorageSync('writeId', self.writeId); + } + } + + let result = { + 'notifyId': self.notifyId, + 'writeId': self.writeId + }; + //成功获取到设备的服务特征值,可以测试设备功能了 + //self.showToast('已获取打印机服务,请测试打印功能') + resolve(result) + }, + fail: err => { + //已连接设备,但未能获取设备服务 + self.showToast('未能获取设备相关服务,请重试') + reject(err); + } + }) + }); + } + + //断开蓝牙链接 + closeBLEConnection() { + let deviceId = this.deviceId; + uni.closeBLEConnection({ + deviceId, + success(res) { + console.log('蓝牙连接已断开') + } + }) + } + //启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值 + notifyBLECharacteristicValue() { + let deviceId = this.deviceId; + let serviceId = this.serviceId; + let characteristicId = this.notifyId; + //特征值变化时,异步通知提示 + uni.notifyBLECharacteristicValueChange({ + state: true, // 启用 notify 功能 + deviceId, + serviceId, + characteristicId, + success(res) { + //监听低功耗蓝牙设备的特征值变化事件。必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification + uni.onBLECharacteristicValueChange(function(res) { + + }); + }, + fail(res) { + console.log('notifyBLECharacteristicValueChange failed:' + res.errMsg); + + } + }); + } + //向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用 + writeBLECharacteristicValue(buffer) { + let deviceId = this.deviceId; + let serviceId = this.serviceId; + let characteristicId = this.writeId; + + //console.log("当前连接蓝牙设备服务信息: " + JSON.stringify(this)); + + return new Promise((resolve, reject) => { + uni.writeBLECharacteristicValue({ + deviceId, + serviceId, + characteristicId, + value: buffer, + success(res) { + //console.log('message发送成功', JSON.stringify(res)); + resolve(res); + }, + fail(err) { + console.log('message发送失败', JSON.stringify(err)); + reject(err); + } + }); + }); + } + + //关闭蓝牙连接,想要连接要重新启动 + closeBluetoothAdapter() { + uni.closeBluetoothAdapter({ + success: res => { + //console.log(res) + } + }); + } + + //若APP在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需进行搜索操作。 + reconnect() { + (async () => { + try { + this.deviceId = this.deviceId || uni.getStorageSync("deviceId");//设备id + this.serviceId = this.serviceId || uni.getStorageSync("serviceId");//服务id + this.notifyId = this.notifyId || uni.getStorageSync("notifyId");// + this.writeId = this.writeId || uni.getStorageSync("writeId");//写入二进制数据 特征值id + //连接蓝牙设备 + await this.createBLEConnection(); + //获取蓝牙设备服务 + //await this.getBLEDeviceServices(); + + uni.hideLoading() + if(!this.serviceId || this.serviceId == ''){ + //this.showToast('打印服务已断开,请到开发设置重新搜索蓝牙设备') + uni.showModal({ + title: '打印机断开提示', + content: '打印服务已断开,请到开发设置重新搜索蓝牙设备' + }); + }else if(!this.writeId || this.writeId == ''){ + //重新获取蓝牙设备服务特征值 + await this.getBLEDeviceCharacteristics(); + this.showToast('成功连接打印机') + }else { + this.showToast('成功连接打印机') + } + + } catch (err) { + uni.hideLoading() + console.log("err: " + JSON.stringify(err)); + } + + })(); + } +} + +export default Bluetooth; diff --git a/components/cjn-print/cjn-print.vue b/components/cjn-print/cjn-print.vue new file mode 100644 index 0000000..ce97fb7 --- /dev/null +++ b/components/cjn-print/cjn-print.vue @@ -0,0 +1,290 @@ + + + + + + diff --git a/components/cjn-print/commands.js b/components/cjn-print/commands.js new file mode 100644 index 0000000..3401e76 --- /dev/null +++ b/components/cjn-print/commands.js @@ -0,0 +1,193 @@ +/** + * 修改自https://github.com/song940/node-escpos/blob/master/commands.js + * ESC/POS _ (Constants) + */ +var _ = { + LF: [0x0a], + FS: [0x1c], + FF: [0x0c], + GS: [0x1d], + DLE: [0x10], + EOT: [0x04], + NUL: [0x00], + ESC: [0x1b], + EOL: '\n', +}; + +/** + * [FEED_CONTROL_SEQUENCES Feed control sequences] + * @type {Object} + */ +_.FEED_CONTROL_SEQUENCES = { + CTL_LF: [0x0a], // Print and line feed + CTL_GLF: [0x4a, 0x00], // Print and feed paper (without spaces between lines) + CTL_FF: [0x0c], // Form feed + CTL_CR: [0x0d], // Carriage return + CTL_HT: [0x09], // Horizontal tab + CTL_VT: [0x0b], // Vertical tab +}; + +_.CHARACTER_SPACING = { + CS_DEFAULT: [0x1b, 0x20, 0x00], + CS_SET: [0x1b, 0x20] +}; + +_.LINE_SPACING = { + LS_DEFAULT: [0x1b, 0x32], + LS_SET: [0x1b, 0x33] +}; + +/** + * [HARDWARE Printer hardware] + * @type {Object} + */ +_.HARDWARE = { + HW_INIT: [0x1b, 0x40], // Clear data in buffer and reset modes + HW_SELECT: [0x1b, 0x3d, 0x01], // Printer select + HW_RESET: [0x1b, 0x3f, 0x0a, 0x00], // Reset printer hardware +}; + +/** + * [CASH_DRAWER Cash Drawer] + * @type {Object} + */ +_.CASH_DRAWER = { + CD_KICK_2: [0x1b, 0x70, 0x00], // Sends a pulse to pin 2 [] + CD_KICK_5: [0x1b, 0x70, 0x01], // Sends a pulse to pin 5 [] +}; + +/** + * [MARGINS Margins sizes] + * @type {Object} + */ +_.MARGINS = { + BOTTOM: [0x1b, 0x4f], // Fix bottom size + LEFT: [0x1b, 0x6c], // Fix left size + RIGHT: [0x1b, 0x51], // Fix right size +}; + +/** + * [PAPER Paper] + * @type {Object} + */ +_.PAPER = { + PAPER_FULL_CUT: [0x1d, 0x56, 0x00], // Full cut paper + PAPER_PART_CUT: [0x1d, 0x56, 0x01], // Partial cut paper + PAPER_CUT_A: [0x1d, 0x56, 0x41], // Partial cut paper + PAPER_CUT_B: [0x1d, 0x56, 0x42], // Partial cut paper +}; + +/** + * [TEXT_FORMAT Text format] + * @type {Object} + */ +_.TEXT_FORMAT = { + TXT_NORMAL: [0x1b, 0x21, 0x00], // Normal text + TXT_2HEIGHT: [0x1b, 0x21, 0x10], // Double height text + TXT_2WIDTH: [0x1b, 0x21, 0x20], // Double width text + TXT_4SQUARE: [0x1b, 0x21, 0x30], // Double width & height text + + TXT_UNDERL_OFF: [0x1b, 0x2d, 0x00], // Underline font OFF + TXT_UNDERL_ON: [0x1b, 0x2d, 0x01], // Underline font 1-dot ON + TXT_UNDERL2_ON: [0x1b, 0x2d, 0x02], // Underline font 2-dot ON + TXT_BOLD_OFF: [0x1b, 0x45, 0x00], // Bold font OFF + TXT_BOLD_ON: [0x1b, 0x45, 0x01], // Bold font ON + TXT_ITALIC_OFF: [0x1b, 0x35], // Italic font ON + TXT_ITALIC_ON: [0x1b, 0x34], // Italic font ON + + TXT_FONT_A: [0x1b, 0x4d, 0x00], // Font type A + TXT_FONT_B: [0x1b, 0x4d, 0x01], // Font type B + TXT_FONT_C: [0x1b, 0x4d, 0x02], // Font type C + + TXT_ALIGN_LT: [0x1b, 0x61, 0x00], // Left justification + TXT_ALIGN_CT: [0x1b, 0x61, 0x01], // Centering + TXT_ALIGN_RT: [0x1b, 0x61, 0x02], // Right justification +}; + +/** + * [BARCODE_FORMAT Barcode format] + * @type {Object} + */ +_.BARCODE_FORMAT = { + BARCODE_TXT_OFF: [0x1d, 0x48, 0x00], // HRI barcode chars OFF + BARCODE_TXT_ABV: [0x1d, 0x48, 0x01], // HRI barcode chars above + BARCODE_TXT_BLW: [0x1d, 0x48, 0x02], // HRI barcode chars below + BARCODE_TXT_BTH: [0x1d, 0x48, 0x03], // HRI barcode chars both above and below + + BARCODE_FONT_A: [0x1d, 0x66, 0x00], // Font type A for HRI barcode chars + BARCODE_FONT_B: [0x1d, 0x66, 0x01], // Font type B for HRI barcode chars + + BARCODE_HEIGHT: function (height) { // Barcode Height [1-255] + return [0x1d, 0x68, height]; + }, + BARCODE_WIDTH: function (width) { // Barcode Width [2-6] + return [0x1d, 0x77, width]; + }, + BARCODE_HEIGHT_DEFAULT: [0x1d, 0x68, 0x64], // Barcode height default:100 + BARCODE_WIDTH_DEFAULT: [0x1d, 0x77, 0x01], // Barcode width default:1 + + BARCODE_UPC_A: [0x1d, 0x6b, 0x00], // Barcode type UPC-A + BARCODE_UPC_E: [0x1d, 0x6b, 0x01], // Barcode type UPC-E + BARCODE_EAN13: [0x1d, 0x6b, 0x02], // Barcode type EAN13 + BARCODE_EAN8: [0x1d, 0x6b, 0x03], // Barcode type EAN8 + BARCODE_CODE39: [0x1d, 0x6b, 0x04], // Barcode type CODE39 + BARCODE_ITF: [0x1d, 0x6b, 0x05], // Barcode type ITF + BARCODE_NW7: [0x1d, 0x6b, 0x06], // Barcode type NW7 + BARCODE_CODE93: [0x1d, 0x6b, 0x48], // Barcode type CODE93 + BARCODE_CODE128: [0x1d, 0x6b, 0x49], // Barcode type CODE128 +}; + +/** + * [IMAGE_FORMAT Image format] + * @type {Object} + */ +_.IMAGE_FORMAT = { + S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size + S_RASTER_2W: [0x1d, 0x76, 0x30, 0x01], // Set raster image double width + S_RASTER_2H: [0x1d, 0x76, 0x30, 0x02], // Set raster image double height + S_RASTER_Q: [0x1d, 0x76, 0x30, 0x03], // Set raster image quadruple +}; + +/** + * [BITMAP_FORMAT description] + * @type {Object} + */ +_.BITMAP_FORMAT = { + BITMAP_S8: [0x1b, 0x2a, 0x00], + BITMAP_D8: [0x1b, 0x2a, 0x01], + BITMAP_S24: [0x1b, 0x2a, 0x20], + BITMAP_D24: [0x1b, 0x2a, 0x21] +}; + +/** + * [GSV0_FORMAT description] + * @type {Object} + */ +_.GSV0_FORMAT = { + GSV0_NORMAL: [0x1d, 0x76, 0x30, 0x00], + GSV0_DW: [0x1d, 0x76, 0x30, 0x01], + GSV0_DH: [0x1d, 0x76, 0x30, 0x02], + GSV0_DWDH: [0x1d, 0x76, 0x30, 0x03] +}; + +/** + * [BEEP description] + * @type {string} + */ +_.BEEP = [0x1b, 0x42]; // Printer Buzzer pre hex + +/** + * [COLOR description] + * @type {Object} + */ + +_.COLOR = { + 0: [0x1b, 0x72, 0x00], // black + 1: [0x1b, 0x72, 0x01] // red +}; + +/** + * [exports description] + * @type {[type]} + */ +module.exports = _; \ No newline at end of file diff --git a/components/cjn-print/gbk.js b/components/cjn-print/gbk.js new file mode 100644 index 0000000..6749c80 --- /dev/null +++ b/components/cjn-print/gbk.js @@ -0,0 +1,201 @@ +/*! + * gbk.js v0.3.0 + * Homepage https://github.com/cnwhy/GBK.js + * License MIT + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.GBK = factory()); +}(this, (function () { 'use strict'; + + var GBK = function (gbk_us) { + var arr_index = 0x8140; //33088; + var gbk = { + decode: function (arr) { + var str = ""; + for (var n = 0, max = arr.length; n < max; n++) { + var code = arr[n] & 0xff; + if (code > 0x80 && n + 1 < max) { + var code1 = arr[n + 1] & 0xff; + if(code1 >= 0x40){ + code = gbk_us[(code << 8 | code1) - arr_index]; + n++; + } + } + str += String.fromCharCode(code); + } + return str; + }, + encode: function (str) { + str += ''; + var gbk = []; + var wh = '?'.charCodeAt(0); //gbk中没有的字符的替换符 + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) gbk.push(charcode); + else { + var gcode = gbk_us.indexOf(charcode); + if (~gcode) { + gcode += arr_index; + gbk.push(0xFF & (gcode >> 8), 0xFF & gcode); + } else { + gbk.push(wh); + } + } + } + return gbk; + } + }; + return gbk; + }; + var gbk = GBK; + + var URI = function(GBK){ + var passChars = '!\'()*-._~'; + var otherPassChars = '#$&+,/:;=?@'; + function getModue(passChars){ + var passBits = passChars.split('').sort(); + var isPass = function (s){ + return ~passChars.indexOf(s) || /[0-9a-zA-Z]/.test(s) + }; + return { + encode:function(str){ + return (str+'').replace(/./g,function(v){ + if(isPass(v)) return v; + var bitArr = GBK.encode(v); + for(var i=0; i 0x80){ + var code2; + if(enstr.charAt(_i+1) === '%'){ + code2 = parseInt(enstr.substr(_i+2,2),16); + _i += 3; + }else{ + code2 = enstr.charCodeAt(_i+1); + _i += 1; + } + if(code2 >= 0x40){ + i = _i; + outStr += GBK.decode([code1,code2]); + continue; + } + }else{ + i += 2; + outStr += String.fromCharCode(code1); + continue; + } + } + } + outStr += char; + } + return outStr; + + } + } + } + + var URIComponent = getModue(passChars); + var URI = getModue(passChars + otherPassChars); + + return { + encodeURI:URI.encode, + decodeURI:URI.decode, + encodeURIComponent:URIComponent.encode, + decodeURIComponent:URIComponent.decode + } + }; + + var src = function (gbk_us){ + var gbk$$1 = gbk(gbk_us); + gbk$$1.URI = URI(gbk$$1); + return gbk$$1; + }; + + // 多进制转换后的数字还原函数 构建时会替换占位符 + var Fn_Hex_decode = function decode(){ + var n = 0, str = arguments[0]; + for (var i = 0,w = str.length; i < w; i++) { + var code = str.charCodeAt(i); + if(code < 38 || code > 126) return NaN; + n += (code - 38) * Math.pow(89, w - i - 1); + } + return n; + }; + + // 解压Unicode编码字符串函数 构建时会替换占位符 + var Fn_unzip = function unZip() { + return arguments[0].replace(/\x23(\d+)\x24/g, function (a, b) { + return Array(+b + 4).join("#"); + }) + .replace(/[\x26-\x7e]\x25[\x26-\x7e]/g,function(a){ + var b = a.substr(0,1).charCodeAt(0) + ,e = a.substr(2).charCodeAt(0) + ,str = String.fromCharCode(b); + while(b++ 0) { + data.length += 0x40 + 1; + } + for (var j = 0x40; j <= 0xfe; j++) { + if ( + (j == 0x7f) || + ((0xa1 <= i && i <= 0xa7) && j <= 0xa0) || + ((0xaa <= i && i <= 0xaf) && j >= 0xa1) || + (0xf8 <= i && j >= 0xa1) + ) { + data.push(undefined); + continue; + } + var hex = gbkArr[k++]; + var key = Fn_Hex_decode(hex); + data.push(key ? key : undefined); + } + } + return data; + } + var GBK$1 = function () { + // 生成按GBk编码顺数排列的编码映射数组 构建时会替换 zipData 的占位符 + var gbk_us = gbkArray(Fn_unzip("(T!HJ%LUX]e%gilotuwy{} (U!)-%/137>BDGHO%RTUW%\\_a%jl%rtw} (V!*+-0%27>C%EHJ%MP%R\\`cdfn%ptvz{} (W!()*,/3%579;=%CFGM%QWX\\^cdg%ilnprtvy%} (X!&')%.468CDHJLMOPSTWY%\\_b%dg%ilnprtuwxz%|~ (Y!'(*+-469%=?%GI%KO%RT%V[%_bdikmnptuy{}~ (Z!&')+%-/%;>@ACE%GKMNPR%TW[_%ikmo%rt%vy%{} ([!'(%+-%024%;=%BD%LO%QSTX%[]^`%ce%y{} (\\!()+%/1%7:%LN%SU%WY%cf%im%prt%xz%~ (]!&'%*-%/1%68%EG%cgloqs%uwx|%~ (^!')%-/02356;>FJKOPRSVWZ%]_`dfi%kmor%vyz (_!'+%-124%68;=@ACE%MOQRUVX%]_adegjqwx|~ (`!&)*-%/689;%=?%ADFIKLNOVX^%cehilmoq%uwyz|%~ (a!'),%/124%=?AD%HJ%PRSU%[]e%ho%qu%~ (b!()*,%.024%79;%=?A%FH%KM%WY%`c%ei%loq%tvy%| (c!'*+-.1346%8:%<>%GKLOQSUZ%\\_cghjltwy{| (d!(,/1%4679=>@D%JLMOQRTVWZ]`%ce%km%pr%tvy%} (e!+,-/0279%;>?DQW[%]_bdhqu%wy (f!&().47:;>ACEFHIKMP%SU^a%egikm%tx}~ (g!)*,.02%58<>BCGI%MPY[]`%bdeginpuv (h!(*-2%6=>A%CF%KMPRT%WZ\\%`deg%ln%qswxz{} (i!&+-%/1%469;>@AD%HJ%MP%TV%Y[\\abdh%mrsvx~ (j!&,%.0235%7:;>@%FH%PRTVXZ\\_%cf%hjkn%puw%{~ (k!').04578;=?%CFI%NQRTW%^`acdg%ilmo%ru%wz|~ (l!&(*%,.%9=%ACDHIK%OQS%U[%^`%ce%hk%ru%{~ (m!&')%79%CE%KM%PR%^`%hjkmnqxz%~ (n!&(*+./2%478<%>ACG%WYZ\\%^`%cgmnp%txy{} (o!&'%)+,.5%9;%BE%UWZ\\^%`b%il%ps%ux%~ (s!&)%:<%?A%CE%OQ%SU%bd%ilnpqstvwy%~ (t!&')+,.%246%9=>ACDF%ILNRVXY[\\ac%fiklprsvxy (u!&(%,.013%?BDG%IK%MRVXY[%^abeg%jl%ostyz}~ (v!'(%,.013%9;%=@%CIJMOR%VXZ[]%_a%lnp%rtv~ (w!&(%+-/%24%689<=?A%CE%KNPR%VX%Z\\%`bcf%oq%tv%|~ (x!&'(*+-%5:;=%@B%SU%[^%km%svxy{%~ (y!&(),%1346%:<>@B%DF%HKMNPQSU%Y[%qs%~ (z!()%ACEFH%OQ%_bfnpqwx{}~ ({!&)+-%023569=ADEG%IKMV^%`c%fhinq%swxz (|!&'%)+%-/2%:>@ADEG%KMO%U[\\^`acefi%lnpquwy|%~ (}!&(+-%02%578:%?AI%MP%TVZ%\\^`be%hjlnoq%vx%} )&!&'%+-%356:<>?ABD%MO%TWX[%`b%fhj%mopr%vx{}~ )'!&)%-/%69%@BCG%QSTVX%bdghj%mo%{}~ )(!&'%9;%=?%WY%eg%mo%{} ))!'(+,2458=>@%DGHLOQ%SUVZ[_f%mp%twxz%~ )*!()-%025%:<%BE%IKLNOR%`dfhmp%rtwx{%} )+!(.137%:>%BD%HJP%SU%^a%fjkm%pr%} ),!&(%02568%:B%DFI%KMOQSVWY%[^%aehikmo%uxz%|~ )-!&'%358=%@B%DGIKLORSVX%Z\\^a%cgjq%suwxz~ ).!&(%+-%2467:%?AC%FI%MRSUVY^%`e%gijmnpqstwz{}~ )/!&()+,.9%;=>BCEIJLPQT%V^%`b%fh%loprv%|~ )0!'(*,-/%1457%:>?GJKMNPWY%[^%acdg%jlnp%ruwz{}~ )1!')*.035%79:=%DG%IL%PR%TVWY[^a%ejqruwx{%~ )2!&)%,.1%37%;=%@B%EHILO%QS%eg%nprtvwy%{}~ )3!&'%*,%/1%47%=?%BDF%XZ[]%ac%jl%txy{%~ )4!&'%+-%24%68%<>A%EHJ%Z\\%ik%su%z|~ )5!/058%:@D%FH%KN%SW\\_%afijlmp%su%wy%{} )7!(*+-59;?GHJKNTUZ\\_b%ejm%pt%wyz|%~ )8!&(%*-78:=%?ABD%ILMO%RUXY[b%eg%nqu%wy{%} )9!'(*%-014%79;%>CEIK%MOQ%WY\\^cgijmnqsuw%{} ):!&')%+02%46%<>AC%GJKM%PRTVX%[]bce%ilmpqt%y|~ );!()%+-%/14%9;%?ABDFHIOQ%WY[%]_%ce%lnp%rt%} )!'(+%.2578;%?ABEFHIKM%ORSUWZ%\\_`b%eh%jlnpqs%~ )?!&'(*%,/%146%8:ABD%HJMNP%RTVY%[_%ac%egj%mor%uwy{| )A!'(%+-/024%:=>@AHIK%NPRSUWY%]a%cehik%mo%qsuvx%{}~ )B!&')%,/%35%=@%DF%JL%OQ%TV%oqu%|~ )C!&(%-/34689;?%EJLMO%QTV%XZ\\^%ceglnpqt%wyz|} )D!&)*,/0279:<%@BG%IKLPQSVY[]%`beghjkmoq%tv%y{~ )E!'+%-0258:=>@E%LNQ%Za%cgkmopr%tvwyz~ )F!()%/14%79@CEGHK%OQ%SU%[^%dg%imnrz~ )G!'),0%9DF%MOR%Z\\^a%hj%ln%pr%{}~ )H!&*%-/2357%@BD%IKMO%RTUWXZ\\%`bce%nps%uw%y|~ )I!&'(*%,.%2479;%FI%KM%TVWY%[]%`b%dfhik%{}~ )J!'(*+.01346%9;<>?A%EIJL%NPRTY%[]%befhil%uxy{}~ )K!&()+,.%02%68%?ACEG%IK%PR%TW%bd%gi%rtv%~ )L!&(%36%;=?%DFH%KMO%QS%Y\\%`bce%ln%twy%} )M!&'(*%46%<>?A%CE%GI%QSV%Z\\%ce%lnq%~ )N!&'%~ )O!&'%178:%CE%HJM%OQ%TVWZ\\]_%jl%sz{}~ )P!&'%136%9>AEG%JMNP%RU%Y[%bd%koq%wy|} )Q!&'%*,.018:<%@B%IL%NP%RTV%XZ%\\^%dh%lnrw|%~ )R!'*,2%48:=>@%CEFJ%LOR%VX%Z]_%aijl%nr%vxz|~ )S!&(%*-.2589;ABGINTUWXZ[]%_bd%fh%kmqrt%y{}~ )U!()+,02%46;<>@EHLQ%TWY[]^`acdg%il%oqru%wy%} )V!&')*-.02359%=?EHOPSTVWYZ\\%ad%fk%mp%su%xz}~ )W!&),-/1%479:<>%@BDG%NP%SUY\\]_bcefhilp%rtvxz{} )X!&'(*,%36%=@%CFHJKM%OQ%[]^`%nq%suxy{%~ )Y!&)%/1%35689;<>@AC%FHKMPQTV%X[%^`%bd%fhjnpqs%u{ )Z!&)%24%79%@B%DFGI%MO%QU%^`%bd%gkmoqstv%|~ )[!&'%+.%024%=?%ACE%GI%KM%RU%WY[%]_ac%ik%mpqu%~ )\\!&'(*%-/%35%?ABDEG%LNP%UW%]`%jlo%z}~ )]!&'%DF%MP%VX%hj%ln%~ )^!&()+%8:%EIL%ORT%VX\\%_a%cf%hj%lnrsuvy%~ )_!&'%,246%8<@AF%IKM%Y\\^%`b%eglpr%xz|%~ )`!'(%14%8:;=@D%NP%W[%^`%mo%rtvx%~ )a!&'%+-/%359%=?%AD%GIKLN%SU%Y[%^`%ce%gj%nq%wy%{}~ )b!&'%)+-%/1%9;%DF%JM%VX%[]_%df%oq%|~ )c!&'%:<%EGIK%MP%RXZ\\^%dg%il%oq%suvxz|~ )d!()*-/%25689;%=@%BGHJ%NQSUVX%ce%psv%xz )e!&'%,1%35%8;=?%BDFG 'W!,-. &(+&.'&-~&'u'W!/1 ')>.= '.u'/!K. '0`'/!94 '1t'0T'/!?Bu`\\Q1t '0!)* '/!xy2IH ';!*( &'}')!\\] '+{.;U&'q.>!&' ')Z&'t',5':!GF '9!eiha`;:ML ')e'-!XVWY 'W?'-!67%?#3$ '6!-.%@ '5!rs%~ '6!&'%, '5!^_%g## ']!67%?## '-!&'%1## .;!RST .>+.;!VW%~ .)'W!mn%~ 'X!&'%f#8$t%~ 'Y!&'%p#5$ &0!=>%MO%U#5$]%mo%u#4$ .9!89<=BC@AD%G##>?:;4#67#6$ &1!cd%hTi%~ &2!&'%)#12$*%/K0%I#10$ &.!()7 ')!=?O_ '+}',('-!\\]%_ '/!)37fz{ '0z'8!CD%ft%~ '9!&'%)-%/VW|%~ ':!&J '0P'W!>IJ#8$ &(!uU &+7&(T&).&(]&)6&(\\&)F&(a&+9&(`&)h&(g&+;&(f&*-&(n&+=&(m&+!?ACE &(!p^ &,a-Qc&)!_c -Qd&,q#1$'Z!&'%J#18$ 'W!MN%U '^`'a!@AN%PSv 'b!'*+. .93.>!(*# ',@']G#'):#0$'Yv'X!no 'Y!wx 'W2'X!pq .9!LM%UW%Z\\%ik%n -R!*+%6 'W3#10$'7!LM%~ '8!&'%>#12$ )e!HIKN%SVWabei%lnp%uw%y{%~ )f!'+%-23679%;@BCEFHIM%PS%_abdf%ik%rt%~ )g!(*%79%=?@BDFGIJL%OQ%TV%XZ[]%bdfgkn%prsv%y{}~ )h!&'(,-/3%9;%>@B%EGIK%MO%RT%cehil%or%z}~ )i!&'%)+,/13579:?%CE%HJ%\\^`eh%tvwy%} )j!'(%,.13%57%9;<>@%JLN%UY%hj%~ )k!&')%1357;=%CF%IKN%TV%Y[%bdfhj%mqstv%z|} )l!'+1369:<>%ACDFGJM%PR%UZ%ad%fh%npr%tw%{}~ )m!&()+%.0%2479@%CEFHIMOQ%TVX%Z\\%_aeg%ilnrswyz|} )o!()+%-/346%=@%EGI%MOQ%TV%\\^%`b%iklnq%suw{|~ )p!&()+-.013%<>%FHILN%WYZ\\ (iC*r5(pM)89(gy(h[(gk)p*)o>*A;)s|*9E)ui)cO*s5*ux)R/({@(Z*)7s)B.(~d*4~)F{*42)@K)pg(_l)>Q)a|*2'*Jb(\\0(u2)4?)\\@*9t)8])5n(eJ(f+)|s(^7)mH))<)7>*Yr*ua)6M*2O(o@*t|*0J)cV)oo)E[)op);L(XR*W~)7F)z6)?3)hN);2)66*8L*xa)Dd)cf)61)76(Wo)k9(cY(a_*.d*b,))v)G`)Jk*6R*.k)HS)vH*E'*oR([d*U/*:L*4b(bm*L>(a&)p!]`bdelnrsu%wy%} )q!&'%-035%7:;=?@BCEFJLN%X[%^ac%egj%lnp%ty{}~ )r!&)+%-/%69%@C *B**t=(Yf(qR*{F({T)6!th )BK*V+++A)b})DT)um)12(c!`& *^r*4P*Wv*mT(Z=)e4(t-)1k)`B*K0(tz*:])Cj)}<)&|*/8)l*)TJ*[[*`!0t +3')Q4*cF)}()-`)v**@.*A<)Q!596 ))I)*v)nD*q<)>X),G).P*_0(s@*7;*a^*rQ*v?*_J*/W*X,)5](YH(e5(cm*_!9:< *a,)F:)-N*6j*JF+,1)3Y(`E)nu)-P)?.)\\_)Z'({u);N(^!A| )EP(T_)yA*{Q)_5)r!DE%GKNPQT%_a%ch%jm%rvwz%~ )s!&'%,/12469;%=?@BD%HJLN%Z\\%df%hk%or )mi)*e)gu*=C)(dx*E0)PD)1!mh )^Z*:;*8Q(Vg)SU*Bu)Y)lB(i*(ZQ*Y,)6G*mQ)C[(ky)[T))*(f9)^m*^P)62)*Y(*JJ)<>)yh(pX)Lv)5,(fL(UE)z*)1i)[j*T>)6B*`V*~U)y\\(e`)n?)7k(c()Rg*_p),X*~:*2q+3k(Xj(}?*Xd*1T)?G)_?(]j(^~*D_)&Z({W)7'*d@)lq*ZZ)z?)2()~4(V[*/9)rl(TW*7f(`7(_m)M5(d^*[|*n^*sl)YY*rZ)J))u!`abdfgklnp%ruyz|~ )v!')+%28%;=%@BCE%GI%KO%RT%VY%[]%jl%np%tvxy{|~ )w!&'%*,%.0%6 )tu(\\&)se):o*N`(t*):B)(~){E)Ie(W[*8Y(j8(Tx)mR){])*!Qy *q>(`5(f=)^e)9.*n~(oe)@n)Ig*d[(hY)W=*.I*IY)5O*/1)mY*;=)vD*si*_/)2o)kM*T1)Ov(`T*XP)O3*3G*>{(n-(bn(Vb(Ta(_D*(G*d_*&i(YL*[t*&C){b);m)&g(\\**51)nL*(i)W6*1o)D6(zh(|V)vN)<[):r)9b)8<*ns);3*_O)}h)nt)5o(tM(fJ)P2([z)5P))n)P?(Vw*X7*Ji)-i*`f)w!78%<>%GI%MO%]_%cgil%oqt%|~ )x!&)*2457:%=?A%GJL%PSTW%Z\\%_a%c )/R*2s)7/(U&(cd*b~)9p*4J)@/)R5(X()1n)W+*TB),v*Ef)-7)82(^&*;v)G=(_s)8t*[=(ZB(~G)xH(|Z(`J)zZ)1<*a2)pp).B)-{)ov*[a)^J)om)}])s8(_f*ar(qU(X0)Z3*_{)>G)}/)e0)VG*1n(yJ)6x)++(nl*?3)}@))e),\\*`J*/U*y')9:)Y_)ut)_;(^D*uF(p5)l2(W~)l5)+-)1f(u-)Vc)Px)ue(eY*sr(_!>t )9A(eg*mF*Tg*Ys)cW)u{*G_*_~*Tq(e=)x!de%jl%wy%~ )y!&'%*,%047:<=?@BDF%HKLNOQ%VX%Z]`bdfi%oqrtvwy|} )z!&'%)+.%24578:; (TG)q/(eK*m<*xV+2S*o.({Q*S_(T!hb (^x*>m)47(ai)F>(Xy)0D(_.)Ts(^()6Y)?9*rW*UQ*`O)m|*c*)rJ)Q2)dO)eX*T_(qf)r`*XL)DA*oA*3w)+<)Wk(u_)|\\)s{*o<)Pn)?O*/O(q7(]v*qn(|W(s((f,*[g)>a*x_(my*mP)q>*`y)9?(gq(t!@` (o~*\\N)Cs*ZH*8U(`[)1p(qF*F@)&;+0<(YM*x}*Sv(w@)0O(d:)6?*a.*c/*{T)0B*2B(]d*2i(|r*{J)U-(Uy)z!<>@AC%QS%UWY]_%df%oq%uw%~ ){!&'%57%9;A%DHKMO%RT%VYZ_%adgh *X0(e.*0B)}c(WK(U<*qO)T*)h1*C6))N)lg*21)L')t3*mE*-4(_T)_h(e**_e*:q*X))dt*{B)T0(o-*9z)?[*4.)5[*r((uu(W:*S|*.T)>9*=U*uI(iZ*ye*4)(c9*Ta(e}*4>)+5)Sf*X9*9s*d.(f-)Q{(_y*.Q(oB)`C)S,*(9(tq(W8)/1)2K*(Z(Tv(|_)E7*FD)&C*ne*yU)mS)`&*`Z(^{*/^*Sz(to(_W(X=(f*(tQ)>r*4(({,)69)7,*^z)*4)R&)}:(WJ(Ya)CK){!ijmo%qt%xz%~ )|!&'%+-%79%BDEG%JNOQT%Y[]%ehikm%ortvy%{} )}!&'*%,.0135%7;=A )Uj)VM)x`*K6),T)l()6]*^o(Yx*eW)?I*5!Z| )+2*5{*Xt(a0*MY*XK(t3([\\(Vl*qk)cT*6K*Wx(|**S`*r:(uT*/[(g;(ld(kU*TI)>4)JQ*mL)po)Xz)*a)kn)D+)E])|l*3z*Xv)2F)y>)>]*Xc(^T(`4*mU*/y*3x*.L(~C)Wy)DE*&;)o}+&I*6a*0|*),):}*oQ)z^(fN(h7)O^):`)4}+04*4w)m=(a3*uT*>e)Fo*F&*qP*s1*nF(Tp(ea*.s)Fl*Z-*2K)C2)+0*1H)}!CDFH%KMOQS%XZ\\^abgikmprsuw%~ )~!&'(*+./13578:<%?A%GIJL%NQS%VY%[^%`i%kmnp%rt%{}~ *&&(pL*2u)Gq))-)>6(a`)0F+4-(X}*\\H(^8({b),P))1)Re)7[*Wz(^=*m\\(bf)SM*:M)eC(p,)Di*X-(tE*_-*=*(g@)~H(Wk)Sk(zt(vE+2X(eA*Ee*~r*UB*3~)>@*x^(n6*sd(`H)k2(`j(|?)7l*L.(UC)7:)/\\)H{(^?({O(^l*N<)~\\*{[*08)1o)^'*X/(]n)*n*`S)ix*N>(ni)tz)-6+42*qI*^R+'T*TE)oj)Fu)Eh*Z8*X5(`W*^t)Yr)HN*n_*bs(n9)E(*K~*_X(gs*&!'*%-/%246%:=>@%BD%FI%KM%OQRT%XZ%]_a%hj%lopr%wy%~ *'!&')%.124%@B%GK +&)(zy)Us)R-(V9({j*~Q*d7)3v*b5*v{(f/)VX(|0(_p(j**0=*2&)u*4e*G])e<*(z)XG*'!LM%UW%{~ *(!&'%*.%8:%@CDFI%KPQSV%Y[%]_`d%hjk ),d*DB(h~)6g(V&)SX)5S*9x(h)(c])fQ)Yi)l8(`,(b~*TA)KF)-n)/2)W8(o2)O4)gi)G-*_i*/T)8s)0|(hv)n5*Um)`>)VF({])*j*;g)2s+1b)v}*G@*'0)oy(_c)1v)`u)A3)*;)0&*Tr)^K)86*^s).H)0;*Eo(ms)Pz)0m)35(cX)1`)AV*X?)yu(WU)_k)RN*Sp*TV*.r*;y)@X(wu+'Z)UM)WA*UL)U7(WT)^F*@%EG%NPQS%`b%vxz%} **!&'(*%,.%4 *3i*{:*`1)\\M*Sb+/q(v`*/!*J (ef)Df)HY*^{*'V*sc(e')/W)mb)Ry(d)(y2*.A)85(_S*55))9*@7)6C(^L(zs(WI)x>(`\\)18)UJ({!{y *S!^m )@+).W*r;(u`*/(*.D(kP)EC(t_(XU({m(aa*;o*xj*X>)l/*mq(Zw)z[(W2)EB*~H(y*)P5)pj(o=(|t)}N*qC)`w(^H*4-*97(uE*/E*;<)HA)Ex)v4)uS)7M)8r)~;(Yv(a+(_B*;e)KQ*g=*ZC*X1*N;*o/)~h(W1**!56%km%tv%~ *+!&'%= ([<*8P(`k*{D)WZ)Xv)VJ),7(\\s(vP(|d)UB)Rf)m**?<)GB(t|*So(c/*dE*rC*AH)I:)w+)`O*4z(V8*bP)UC*~N(v{(mQ):d*nJ)sy(Y.*5E)eM*NL*{O*/u*.x(a@)>T*dI*^!im (eH){\\):L)9])ox)yp*J5*r,)5F(al*9I)G.)DU)9/)rR)|Z)TV*.m*N](vD)5.*Bo*9l)lI(ZO(V_)mI*TO(}O))F)}_)?F*eL(V^)Tz*M2*)~*o'(VY*U3*_l*u^)A;)xR*_b)_n)Ut*+!>?%JL%RT%~ *,!&'%F (}B(as*;[(^.*:|)rB)Af++l(V@)1J*(!nc *.i(V)*R|)A_*xh*uD(r[)>g*o])-h)mm*uA)|!LK (_3)_1){^):I){<*.:)gP*w&(U2)^S(UJ*d&(d_)>L)@0*7!u~ (g9(}6)m>*v2)7B)eE)ma(}J*~C*=-(}E(g+)sw(U+)S\\*37)7<)9&))0(^C*Z!+l *o0(Yz(eB)1g)_.(a()8a+0:(w:(ZV)qw(d-*.|)<2)>&)6L)9P(ZD)cS*NC(_&*S}*.w(o**=/*mZ(^g(ex)&N*,!GH%~ *-!&'%-/%35%9;%P (YS)|P)UV*bg*~Y(iy(gA(cp(gZ),=):H)JF(_b)36(_}(q[(b@(o1)tB)qK)+M)3E*)7)5w)6Z(V6)^p*29)7a)_f*uK(oZ*:I)E{)Hv)vX*xw)yI(sr(g^(eL)W~(]p(`U({Y*Tb*43(i<(p0)0L(o4(f1){@)0)(zd)9_)6c(e@)6&({~)E;(h?){e*:T*dK)+)*Ki(t^(p8)7x*Z6*4s(o:)~2(Y2).v({t)OP(c0)}d)e.)Fy)t4)qv)@@(_((U|)pm(~k){k*?&(tt+'Y([W*-!QR%tv%~ *.!&'%46%8HNUVp~ */!-:KQ_xz|%~ *0!&'%)+.%7:; *{])2N)Xt(oG)@O)8W(n,)7V)6,)+i*qc(of)73(j'*Fc*5u*_4(i_*)_[)V@(b:(U=*t;*on*A})vM**-(]F(ou)AC%FHK%OS%UWX[]%`b%eghj%qsuw%{}~ *1!&'(*+/12457%=@B%FIJMOQ%SU%XZ\\^%befh%mqr )n-)|8*(B)SS*sS(a\\)j2(h;(Yr*31*V*5c*nX)/})_>*.]*(^(_<)G[*(a*96(Tj*^p*eJ)An(VB*Ti)(er*n7(Y,)?g(}!jf */V*DE)R6)-o)gA)Y|*/@)&9)8,(zz)Y~(d+(U^)9X)lb)6d*^X(Wa(Ve)ST*.P*Sw*>'*HJ*0?*`s*n})~d*~k*K}*>G)Tp*~P*.v(uU+1Y)gU)t6*Dv*~!6L (kb(et(pU(U]+1D(ce*_Y*54)ry*{g*F0)Yy*@k)C:)30)Zj*3![^_begj%oqrtv{ *4!'*%,0479:<=?IK%OS%Y\\cdfgjry{} *5!&)%,.%02367@BDF%HJ%VXY[^%`bd%hj *U4*9Y*;@)q2)Qs).d**:s*nt)Q;)si*my(c~*:p(^^)*,*V>*X8(U5)ge)E&)G_*dJ*tM)a4)SO)qI(xT*oB)Q/*0v)@p(|.(v-(x\\*q!7F (W'*=o*?J)Mp)px*o1)f.)H'(zo)qo*dn*uL*)3*`/*U'),b*'|)yP*N?)Sz*F^({})*1)HJ)q`*/6(^a(]r(b1(wD*/F*uM*:E):.)rk*Bv)yJ)X+)+/(uf*@i)^H)Qq)7))pX)>J)1/*qL)@W*H/+/s*nG(ej(g(*U7);~*5!kl%prtx%z} *6!()*-%13%68:<%>ADEG%JSU%Y[]%`bd%iklp%tvwy{}~ *7!&'%+-%25%8=>@%BDF%L )<&*C^)L>*6n)vk);o+'l)6|)Ci*)YR*A*)72)*c)vA))UO(^h),A(uA(ak)/D(u@)B-*DD)mC)8;)4[*)F*T^(h8)O9+/u)Pm*B{(fY([M)SR(ic*Y[)cJ))])/G)i>)77)9J)cj)-|)X4)U:)=T)[>)pq)vS)q<)lQ(`>(e8(U@)+4)?c*2`*4Z)6^(g1(`B)_0*Jk*Yx)T6(f|*4^(q**Ky*XT*r`*cz(XK)SI(jW)p_)te)6k)_{)[t)-Q*@D)H[)uX*&Y*6z)CI+0F)8x)v3(oR)tG*t})6!DGHKPU%XZ%\\^`acdfhj%nxy{~ *;!'(+-.2%;>?CEGLPR (i]*5i)mV)pG(cH)n)(\\y(}F*S)*&)([&)ce*~a*y_)ZA)k8)x9)<4)s3)7f*xq*X+(gl*35(U?(oM*:g*=p)*b(_`)kL*T((}T(oD)TQ*xg(wa)ti+'\\*_|*(E(`p)5m*nT(VZ*k*=L*?c(p^)Cr(n?)A^)Ub*U<)Bt)]E)C])OL)FI)56(v/(TI(_7)ZE)E^)S=(^B)HL(tm)Oy)lc)&a*5;+3<)?y)w!rk *~[*Xw(~.(UK(W<(f3(tw)tA(lV)Qt*_U),@)S+)T8*Sh)9H*;!STVWYZ]_%chj%nrw *AE%GI%KN%P )0I)U9)d:)6)*m!Ax (cR*_R)~9(Vs*U1(Uk+1r*m!df (`g)[B*aB)UA*U?(qB)'F)O!2[ )E6(f_*6&*0t(rq*A6),w)6e)Ld*o:)>m)0])G?)s5(UA(Y1))/*v*)(VF)y^)i<(bL*:')=&)y5(|;)S/*u=*^e)R)(Zn(d5)WO)<{)Ad)R7)1E*xW*T[)*u)iD){=)yC(T^*b7)hd)RI(mo*cx)Ss*Y2(cI*Ea)C0*\\K(}M*~;)Wj*=!QRV%Z]%_a%cehj%msu%z|%~ *>!()%-3%:<%AC%EH%OQ%Z\\%`bg%jln%rtx%z|~ *?!(*,- (e3(wQ+3w*YJ(dq(nD*y.)D(*do)Sw(^4)mn)7])dq(`R(a^*/{)^o)o*(d*+0A)K-)uJ*s]*K^*13)`_)b:(^U)E_)k:(sc)=l(mL*Sf*{K)63*.o)1y)_o(sk(V!UN ).X*vy(W6*Sa(_v(uW*.E)5p(Va)@.)5**;M*?z*;x*Gv)ad)YN({p*.l(^c):()E`*3f*;N*IL(]7({1(uO*_B(U`)Rd(^1*LQ*^Y*q}*AI)if*nj*q?)VI*:S),n)2*6@++w(r6*X[(TO(dw*?!./%24%7;>@%GIKLN%QS%_abdf%hlmoqstv%y|} *@!&'*,-/%469:^)G+(js(Tm):s*~d)6.(y+)ig*99)VL)Ho(\\e*1)5g*{k({?(|])9@(i'(e4)nq(^I*A+)E.)H4)PC)6U*^}(e1*82)Vt)m3(US*XN({')ao*BU)B!(p *0Z*FB+1k+2e(}c)Cm*`()FD)DD)5))|C(r])+L)>k)Zp*B!(),.%46%@C%IK%MOQ%SW%\\^`%fh%np%twxz|%~ *C!&'(*%02%57%E )0.(`Q*2C);Z*JN)l&))M)FF)7^*t`(e))c[*Te)R;)rH)z-(f2)s:*xZ*8<*TX)u1)CR)_C)?Q))MD)n;)[S*U8*Tl(oI)QO*Jp)v6)9Z(eV)_/)Rk(r0);0(q3)Ha*6m(hb*)-(ZH*\\V)Vo*YF)_m)9G)V>)Yl*/'*=g)Fv*`;)V{*rl*Se(t})d>*C1*6P)m`*PR)H0(`n*Zp*nk):/*xx*[9(iu(X5)C=(l})1U)V8(`](}N(tO)WE(rC)l-)kr)0E*84*5q)7{)DF*_s)qz*ZA*X4*mt))^(d;(f0)_E*D!acdf%lw%} *E!)*%-/1%69%=@AFHIMNR%TV%Z\\%^`cghmnp%ruwx{%~ *F!'(%*,%.17%9<%?ACF%HMNP%SVX )RG),4([3(VA)+C)8K*8g*`R)G**dB)sA(ei*n6)-H)|R)GP)8V)}f*.y)n&([N)6X(tZ*`G(_k)y;){G(n:)-v*`L)U~(}e(n[(em(]y)X>(mw)9`*xs*6Q*FW*LV*`8(e{(}t*79)7@)5t*5\\+0,*r6*~!8F )IU(ur)7=(i7)8'(gr*Et)U8(vw)k<*Jz)O|(t<*UW),l)Xo)gc*x](T~)_y({C)us)8N)AJ)p/)1K({R(wd(TM*6')Rq)gE(V5)Dn*09)-d)@C)CY).c(uQ(vu*F![]_abfh%jl%oqrtuwxz%|~ *G!&)%/3468%;=%?AC%HJKO%VXZ%\\^`%ch%jmoprsuw%{}~ *H!&(%.0%4 )(n).9(d'*vx*_n)Fx(n0(i()1_(U')[3*/5*:5*=q(vH(W!Ze (}C*.F)Ch*@r(fw)lL*4G(i{+'g(X/)Ww*Tw(|g)3>(cz)nj)Ws*D~)?)*qJ*.S(f?)zR*)a*q=(k(*1P)kD)8.*FY)VD){c)5-)?C(cv):@)S1))3(f`*m[(U9)Rh*TP(}P)@)*9c)H((f!B8 )Q+)Ox(V()8S(cW*8>(WH(Y7(oA)5&*tB)AT)d.(bg(ab)0x*TS)@])ai)Du*MR)u.)t2)A`(l)(f<*n{)d?*H!5679:>@%BDF%IKLNOQ%UW%Y\\%`d%jl%oq%tv%y{%} *I!&'%/1%46%9;%@B%IKN%QS%WZ )yx)0H))T)0b*6o(t;)1\\)aT)_q)YB)RW)dE)MH*K2))u(UM(xu(j<*n=)Tl*)R*s6)5+*.`)ru*Dr(c2*tb*_')Aw)&4(Y))eY(TQ(d\\(t5(ep)98*o)(]m(Vm++P*.>(gc*W}*J2*8W*qA)V1),c(y5)A.*r_)gj)fA(du*6L*{Z*10({a*r!mF *.Y)q8(dX*ow*{n)~l*Lp)XI(UN*1c)x6*TJ)1s(gx(V?*xY))?)L~(\\M(en*Ul*>1)u9*tH(`d(h@(m8*nZ)V+({l)Vi)AC*I![\\%hj%oqrt%vx%z}~ *J!&'%),%13468%>DEHKMOQ%TV%Z^adeghjl%oq%su%y{%~ *K!&(*%/ (|m(zm)FT*3s(iq)|~)>C)I|(V/)OY*G7*uv(c^)80);@*b0)?>*4E*Tt(^e)H1(d.*I0)4=)Sr)TP*U-(}V*BP*9v*nf)O5*_,)?R)/-).N(Yj*I|)@h*67)f<)1z(^@(`+(on)-F*b(*J**df)*g)D4)/Y(vG(]i(_i*4|(bp)S'*sa)aZ(WL(Yw*1-)C{(je*nb)y8*Jt*.}(rw)5(*tD*DN(k_*x[)-t*Su*?u*d+(e6)@6)*~)lY)0=**l(xA*/!+. *^S(jG({Z)1,)?m)g>*K!13%57%;=%@B%EHILMO%RT%VX[\\_%cefkln%twz%| *L!&')+%-/%57%;=@%DH%LN%PR%UX%[]%_ac *`A)oU)qi*.t*u_*BA(zv){:*t.*Iw(b3)a_).5)@5*TF(|Y*~9))))PB)Rb*S!jl *`B*_V(dA)7&+/!v} (fD(Tq*:+)cw*E7)&i*J7)VR*sb(g|(V.*Ss)`2(gh*qX)_a)WC)pi(Tk)tI*FT(~U),3*Nz*x|*q])^i)Sm(tj)9a)q|*J+)ZS*9:(qa)bL(dB)tO*s^(hS)-J)`Y({k*T~*~V)P<(tT+0&)y_)DM)6/(XQ)mE*0r)T`*r))R.(W+)mv(^G)Fj)Z}*a_*6B(uc)i~*L!de%lnoq%~ *M!&'%03%8:%MO%QSUWXZ%t );M(},*aD){W*U.(vN(gW*7y*<+*MT*26)IX(l<*2l)cU*eI(_)(UL*xU)9N(T`(eS)C1*5v(tB)VU(TF(sx(cJ):5*nK(Y&(WE*JA*xp(t]*a6)ys(V~*4t)m5)S0({S(v\\)-A)I-*Du(ZJ)):(UF)sq(Vy*9A)6T)@\\*ap(}~(VS)-]*7?*`p*3a)mO(V:*KY)26)P~).Q(U6)pc)Y:*TG*Sk*T!n5 ),?*22*1[*.h*;J*<'(mu)Pp*w,*r*(vo(e|*nP)W5({|*{C(}>),R*s-*M!uv%~ *N!&'%:=GM%OQ%SUWY%\\^a%df%hj%ln%y{%~ *O!&')%> (d&*:_)LN(x6+0g)+**/i*!./ *;|*G0*__*Xb)pa)-U*xv)uH)@i(h1)7O(XE*7<)ml)+N*sj*ZX*F;(g:)TH)V/)R?)0X(b/)k~)*l(WS)0y).r(}))l.*b4*ms)d~)Sg)X)*cv)CG(e!(P (X3*eD*TU(d~)*k*_S)W.(U{)p[)JU*DR)2A*8&(X;(Yg*`v++0)20)W!g^ *r{(Uu(wL*t,(TT(~+)y1({>*TQ*1L)gC(pi*9R*bG(e^*a&(j[)&=).,)2/)OD)e]*46*PQ*O!?@%^`%hj%~ *P!&'%@B%H )Up(|1*KZ*xd*Uv*~7+0*)WT(^p(]h(p-*J_(dU):S*_&(n)(f\\(nB)fR)Y(*/Y*_m*:?)2f)/Z*rX)C.*.@*Y!1j *mX(~_*(T)CF)1&*qT*2N(U~*bm(bh*r^(]f*_a*As*d1)AE*w.(ze(c,)tm)D')Fp(gt)^Y({g*^g(^Y(nd(g\\)=f)Ar*X!^C *5:*>v*aL*)6(_r*CH)E/)@2)\\.*E?*[v(lX*`X)ot)^Q)b\\*W|)7S(`3)TR*X<)/@(rv)3\\)C<*X`)5j(jS)Wm)Ck*^Q*P!IJ%PS%Z\\%~ *Q!&'%R *n;*qG)qh)F8)Jw(g6(U:)_:*T,);^)?-({<){J(Zj(|F)sI)QA*PA*(H)Sl)ph)?K*_()''(}Z*D,)F;(co)54)|F)XL*/>)L<)|M)-T)Zr),])9D)VK)D;(TN))X*X&(Vk*4D)o&*s9)7E)@v)6A)Sj*Xu)a7*0Q(]k*3d(eI*aM)6[(hD*F2*_**2;*nq*@o*_j)UU)h.)?A)q_)kZ)t\\*7t*Ww*m;(Y/)Dz)m]*T.*tK)8@*oH*r+*?i)84)r()-e)e\\(Uv)/F)>o)7Y)Ou)>:*Q!ST%uw%~ *R!&'%;=%[ ))o)mk*bW*S~*9d)E))>*(f5*FZ)ss*4&*5-)RH(U8*.a*3))q4)I5)PO)6*(Zl(Xf(n|)7q)Ot*Ye(eG)@1*.R).b)8+)9o*7!lm *0V))d)&,(`P)Aj)ya)z9*X()^t)mx)Yv)Si){X(Ts)p^).k*mR*JU*.b)yE*4C*eH(W!-R *8?(fl))&)U.*T0*(U*^^*3u))b(g=)pJ({P)A,*~n)hA)F]*Ev)Co)f=*T!\\? *`H)|f)_])a>)7.)s7(kx(U(*>a)E}(aj*E[*X.*nR)}e*R!\\]%{}~ *S!&'(*%\\inx *T!+4Nm *U)(X1)T=)x.*~E)6V)cH)7g(TY)tK*^V)<]*XZ*&()GC)*s*KJ(uS)*0R(|h*aT)@q)).(X2)Ej([1(X>(o3)+=#2$*U!CD%KM%PSUVX%_a%df%kn%tw%} *V!&'%)-%3568%:=?%EG%IK%_ (Uz(TR(]e(TV),<(cT(T[(V,(Td+'J(z|(lW(Tn)y2(U,(b}(U4(tS)cY(c})Qp(mt*4h*{l)Q3)re+2\\(T|(V3+2U(U!IV (V'*9O(zk(ie(kV(VX(d!CSY[d *uP*X](c)(eR(c!5=M *X\\(c!ur (_!u{ (`!(GMYZfx{v *?`(a!>CBQT (^N*0<(V!OW]V|u (W&(Vr(W!V.] (XF(W!0`bDf (X!@I )>3(X!@A (cx(d0*q!lqp *r'*qy*r!328?JU]bhj~ *s!*4M *a!vz|x *b!2':9<@ *Y|*Z!&'*.%03%57;<>%@BDJL%RT%VY[\\^%ac%jnor%vy{~ *[!'()+%-01348:;A%EH%MO%Z\\]_`cf *b!>6UKDVJMYlhb]aqu *c!+1OKP^\\fps (`'(th(a!cmn (b&(hQ(b!8>X (e<)be)s[),1(_!ho +'G(dl),>)lW))7(o/(p!3+ (rV(s!;DP (n!ehfoujk (o?(n!w~ (o!LhNi_^KPYV (p!7. (oo(p! (ov(p!*_bdc\\B~y (q)(p!ng *[!hjl%prsuw%y{}~ *\\!&'%*-%/1%79;%FIJLMO%UW%ik%~ *]!&' (q!<>. (pw(q!1OJuQ (r!=DYarX *{}+2^)4t*9!@DFVQoKUX^`r *:!&, *9w*:!68Q *9!_~u *:!9:/ *9!p{hqf *:!2< *9k*:!OweR}uJb@FziA *;!&/ *:t*;!)* *:!NC *;!1fpq *:v*!&B *=!ti7Brf[\\M( *<|*>0*=!SD *>!f[dc} *?!89+:) *>!FPs *?!'=? *>!;w *?!r~ *@!(> *?n*@+*?!{pk *@8*?!RjeH *@!=;d )kc*A7*@H*A8*@w*A9*^!/0%OTjv| *_!.1%35%8;=%@C%FHIK%MPQTWZ%^`cghkqrtx} *`!')*,%.2%467?@DFKMP *A!U: *@!WT *A!XGgc]y )s0*A!Bqz *B!JN-5 *Ax*B!TB+_]Vyg *C!)LtRvc *D0),!;E (t!bg *2m(t{(u'(t~(bw(}!'*19 )5h)6!-b~ )7!4DAX )83)7`)8!J\\T )9e):U)9!)2Fl )8~)9!dB )8z)9!ft ):!QW?^ )9|):!=- );X)9!~v );!KG ):!jz );&):k);!,'d )<1);s))),H).])ko),N(cn(e!NZFEXosc (f!OV%XZG (e~(f![]'6 (g!-? (f!{uh (g!EF/ (f!zj (g!H{Xm_}RQ~ (h&(fv(gN(h'(g!fjw (h!+,. (g!TUO (h/(gz(h!0m9rOfEtuacy| (i`(j!/U (i!Bf:N8I5 *b!HILNOQ%SXZ%\\^%`d%fi%koprtv%y{%} *c!&'%),%.02%EG%JL%NQ%[]_%eg%oq (i!0On%p,)U (j!+r (i|(j!QY( (iz(j?(iw(j!v1 (it(k&(j!]^49 (k!1> (ji(kf(jq(k!23 (jt(k-(j!}d (k!6,9: (j!lm (k!/<+ *^~(k!eOSHkjEGnt (l!F'E (ks(l!;PGJ:BtR_Yijs (m!(Dilrv (n!1'5;@FEX ))!Wa\\Yy )*!*+ *c!rtu~ *d!'(%*,-/034:% *U~)(!Xf )-!W[fkmpy} ).!'38@G *J@)-E)d!ruy|} )e!/-:9>T[U^`cm_of *e!ab%~ *f!&'%g )eg)f!*&4 )ev)f!10(5L8?KDc`js )g!&)8 *8;(tK*yn(t!J( *{!8<%AILRUY\\_befh%j )*o)+')*z)+!,;6OKTI *XS)+!hgq~ ),'*73).!OTaZ )/5).y)/6).!lo )/!078 ).!ux )/!*KgXMA?[]%VX%p )0!CVos )1-)0!v\\ket )1!l;1]XFZ4 )2!GMB: )R!op{} )S!4W~ )T))S[)T!LMF, )S`)T!5+O@C )S_)T!(DS *g!qr%vx%~ *h!&'%79%y )U5)T!|a )U!?D )T!\\Ync )U!'I*1 )To)U!KNP/ )V4)Uk)V!AC )UZ)V!67 )U!X\\x_ )Wd)V!jh )W!(X )Vb)W!*[0' )V|)W`)VN)WV)VQ)Wu)X!_?\\ )YJ)X!PwDE )W!|o )X5)Y!wI0x )Zl)Y!z=?USOoLg'Z7 )[!H,- )Z!cT8nu )[!1Z )Z!iHh )[!osr^Xb` )\\^*h!z{%~ *i!&'%TV%~ *j!&') )\\!V4FCOn{km| )]!NWOmi )^!*9 ({!7;LJ\\o )l,*~h);:(|!BL *L\\(|N*[<*Qv*_!Gdfv *`&*_!uzw *`+*_y*`!=(u!xkq (v!F& (u|(v!K2yzQ|WLm (w'(v}(w!MO,>.[ (x)(w!epW} (x7*4p(x!l]9< (y!'T (xt(y!;= (xz(y!ILZ?OAEr (z!'&BGP (|!sz (z!ju ({*(z!acr *~!?ABDIGJKORTZ\\]`be%gijlmoq *.!9;=?BC *k!34%:<%~ *l!&'%: *.!GJXZ%\\cefjnquz{ */!),/023N7;] )FP)G!/@ )Ft)GA)F!sq}|\\ )H6)G!iNQmE )HC)J=)H})I!GH )Hz*o!(4>DILV[aouvx%~ *p!&(%s )IL)Hq)I!3) )J&)Hd)I8)J@)Ia)J/)Ij)J!,S:OgG )I\\)KB)J!VW )KD)J!X52Hjv )K1)J!z| )K!J'7@U )Jd)KV)J\\)Ku)LL)Kc)L!45 )M))Kh)L!a[ )Md)L!mxR )M!R= )L!ZEu )M!@UTm[o )f!Je )P!:;@=KLFSTZc *^!UW[%]_`bacdfhklnqu *p!tu%~ *q!&'%6;NVbgjmor%xz%|~ *r!&-%0479@DEG%IL%PR%TVY[\\ac%gin%z} *s!&' *^!wxy *_!)+ *\\j)5!'37;>=A@H *7`)k!EJUegi )>/)@!789Sb )DW)@!L^I )^`)C5)@!f}z )A&)@~*2<)A!OD1?FQGgt| )B!>4Urs} )C'*X!236;=@EFHIGMUY *N!AD%FH%K )d!3d )c{)d!+4CDIPRTW )7r)8C)9h*s!)+.%02378:%CE%LNOQRTUWX\\_`eghmnpqs%|~ *t!&'%+/%24%689<>%ACFGIN%PT%VXY[%_acd );E)=,*2:)Q!JS]UYegfmux%z )R!(0+19 )>!0Pf )c!kptN *DV(`0*3!|yp *4@)CH*4!A5/18;k%n_FH]Q[ )CN*4!aouxq *5!89 *4v*5')CS*5=*Ue*5!aIWC]sw~ *6!F+,C2;NO?9 (q~(xw*6!ZTc )Ym*6!u| *7E)Cd*7!C4 *t!ef%moprsuw%{~ *u!&'(*%@BCEG%wz *w!'(%+-0%G )/n)0!63@ )/s)0!2< )1+)2!-4 )3!+wk )4!@F{ *3!]\\ )SA)TK)WF)t!+-5>LMF )?M)t!bQRn%pTqZaX^ )u!*I23 )t[)u,)t|)u!(Fwovcx} )v!&5<(W\\Lou )w/)vw)w!=NH^ +4.+2!>@A )q!1DM9GHZbYmfux )r!78.*AO *w!HI%~ *x!&'%N )r!ILftdgsx )s!-.>CK )l!7=KHEXov )m'*0!@IG *Oi*0!P\\Yaif )p!f~ *Ii*m!89:>=?@BCGJHM%OVW^]`_bcegi%moprw{%~ *n!&'(*%,/%13258%:<>?ABD *x!OP%Tknruy *y!*/%TVW[]^b%dg%mp%~ *z!&'%5 *n!CEHIM%OQSVWY]\\`acdg%il%pruw%y| *o!+,*-2357%9=?@C6E%GJMOPS%UW%Z\\_`^bce%mpr%t; )s!uz *sf)y!Me[c~ )'A)y!{z )z!=3 *z!67%:<=?%[]%~ *{!&'(+%79;HMNPSWX^ )z!XVp +1m*{z){6)oz)p!',2= )k!46 )l)+/!prx%| +0!)(-/.01589;=%@BCEHLNQ%SUZ]%chdj )m!68:DAPGWX\\hUTgfzq )n!.31/62N?FLN[lfrnsy *J!BGP[]` *K!'KE.DQ_PiKULJdjO *F!+34/5 *Ek*FU*Ey*F6*E!zsl *F!EI:JLOKe}`gp\\ *G!'1 *F!vsky *G!(k *Fd*G!fgdIY5Wt%ACE%HJ%OQS%VX%[]_a%ikm%su%w *HV*G!qn *H!=' *Gl*H!;u-BE498GR2lnY )~0)}!`qt )~!)6 )}v)~!-,KabsgXc@eW]fo *&3)~|*&!.??A *(,)>D*(!AMLNRblmqw|}xu *)!.? *95)B?*1!N]dtpux} *2)*)O**u*+!KS *-:*.5+1!VR *Xs*Y!+;8X *X!gm *U!RT *c!w}{| *d8+(!;<%~ +)!&'%A *d!65D=CQRFHM`Ydaevw~ *e!()*0/5 *U`+0u*Y_*Z!9S *[!N^ *Y!\\fcak}~ *Z!(, *Y!uv *Z)*Ym*Z!:EF1GI2WKbkmz|q} *[!/5.*2&>67FG?ekqdiz *\\!+0,8: *V!*4<7JF )?=*N!PXTV +)!BC%~ +*!&'%H *N!_ei *O_*R<*u>*t!-73JELSRnqt *u)+3!loq%vx +2!CPR *s!VYZko )sM*s}*g!Ww *h8*iU*j(*k/*jM*l!Jw ++!369%< )zB++!?BD%FHINOR%WY%]_abd%kn%qx%{~ +,&+*!IJ%~ ++!&'%/12478=>@CGJ%MQ^`cmr%v|} +,!,-56;<'%+.%02%478:= *u!gp|} *v!&A=5DF *~!{z +&(+0O+&!'+-2163<=B +'!][_a`ei *yo*z!;\\ *{!*) +&!PRW`\\l^jy +'!'+7; +1![\\ *-.+0!y~ +1!&)0 *k;+1!;=y%{~} +2!'.,*/4gqt~| +3!)*0 +,!>?%~ +-!&'%~ +.!&'%~ +/!&'%ntw~ +0!'+237DGI%KMPTV%Y\\efik%twxz%} +1!'(*%/2%:<>%CE%QS%UWXZ]%ac%fh%jnpqs%uwx| +2!&()+-0%35%=?BD%OQTVWY%[]_%dfh%prsu%{} +3!&(+%/1%;>%jmny%~ +4!&'%+/%14%8 .*f.+!Zv .,!oy .-!;<%>@BCGN%PRSV%X -R!XY%~ -S!&'%N")); + var gbk = src(gbk_us); + return gbk; + }(); + + var gbk_build = GBK$1; + + return gbk_build; + +}))); \ No newline at end of file diff --git a/components/cjn-print/printerjobs.js b/components/cjn-print/printerjobs.js new file mode 100644 index 0000000..8c9981a --- /dev/null +++ b/components/cjn-print/printerjobs.js @@ -0,0 +1,161 @@ +const commands = require('./commands'); +const gbk = require('./gbk'); + +const printerJobs = function() { + this._queue = Array.from(commands.HARDWARE.HW_INIT); + this._enqueue = function(cmd) { + this._queue.push.apply(this._queue, cmd); + } +}; + +/** + * 增加打印内容 + * @param {string} content 文字内容 + */ +printerJobs.prototype.text = function(content) { + if (content) { + let uint8Array = gbk.encode(content); + let encoded = Array.from(uint8Array); + this._enqueue(encoded); + } + return this; +}; + +/** + * 打印文字 + * @param {string} content 文字内容 + */ +printerJobs.prototype.print = function(content) { + this.text(content); + this._enqueue(commands.LF); + return this; +}; + +/** + * 打印文字并换行 + * @param {string} content 文字内容 + */ +printerJobs.prototype.println = function(content = '') { + return this.print(content + commands.EOL); +}; + +/** + * 设置对齐方式 + * @param {string} align 对齐方式 LT/CT/RT + */ +printerJobs.prototype.setAlign = function(align) { + this._enqueue(commands.TEXT_FORMAT['TXT_ALIGN_' + align.toUpperCase()]); + return this; +}; + +/** + * 设置字体 + * @param {string} family A/B/C + */ +printerJobs.prototype.setFont = function(family) { + this._enqueue(commands.TEXT_FORMAT['TXT_FONT_' + family.toUpperCase()]); + return this; +}; + +/** + * 设定字体尺寸 + * @param {number} width 字体宽度 1~2 + * @param {number} height 字体高度 1~2 + */ +printerJobs.prototype.setSize = function(width, height) { + if (2 >= width && 2 >= height) { + this._enqueue(commands.TEXT_FORMAT.TXT_NORMAL); + if (2 === width && 2 === height) { + this._enqueue(commands.TEXT_FORMAT.TXT_4SQUARE); + } else if (1 === width && 2 === height) { + this._enqueue(commands.TEXT_FORMAT.TXT_2HEIGHT); + } else if (2 === width && 1 === height) { + this._enqueue(commands.TEXT_FORMAT.TXT_2WIDTH); + } + } + return this; +}; + +/** + * 设定字体是否加粗 + * @param {boolean} bold + */ +printerJobs.prototype.setBold = function(bold) { + if (typeof bold !== 'boolean') { + bold = true; + } + this._enqueue(bold ? commands.TEXT_FORMAT.TXT_BOLD_ON : commands.TEXT_FORMAT.TXT_BOLD_OFF); + return this; +}; + +/** + * 设定是否开启下划线 + * @param {boolean} underline + */ +printerJobs.prototype.setUnderline = function(underline) { + if (typeof underline !== 'boolean') { + underline = true; + } + this._enqueue(underline ? commands.TEXT_FORMAT.TXT_UNDERL_ON : commands.TEXT_FORMAT.TXT_UNDERL_OFF); + return this; +}; + +/** + * 设置行间距为 n 点行,默认值行间距是 30 点 + * @param {number} n 0≤n≤255 + */ +printerJobs.prototype.setLineSpacing = function(n) { + if (n === undefined || n === null) { + this._enqueue(commands.LINE_SPACING.LS_DEFAULT); + } else { + this._enqueue(commands.LINE_SPACING.LS_SET); + this._enqueue([n]); + } + return this; +}; + +/** + * 打印空行 + * @param {number} n + */ +printerJobs.prototype.lineFeed = function(n = 1) { + return this.print(new Array(n).fill(commands.EOL).join('')); +}; + +/** + * 设置字体颜色,需要打印机支持 + * @param {number} color - 0 默认颜色黑色 1 红色 + */ +printerJobs.prototype.setColor = function(color) { + this._enqueue(commands.COLOR[color === 1 ? 1 : 0]); + return this; +}; + +/** + * https://support.loyverse.com/hardware/printers/use-the-beeper-in-a-escpos-printers + * 蜂鸣警报,需要打印机支持 + * @param {number} n 蜂鸣次数,1-9 + * @param {number} t 蜂鸣长短,1-9 + */ +printerJobs.prototype.beep = function(n, t) { + this._enqueue(commands.BEEP); + this._enqueue([n, t]); + return this; +}; + +/** + * 清空任务 + */ +printerJobs.prototype.clear = function() { + this._queue = Array.from(commands.HARDWARE.HW_INIT); + return this; +}; + +/** + * 返回ArrayBuffer + */ +printerJobs.prototype.buffer = function() { + return new Uint8Array(this._queue).buffer; +}; + +module.exports = printerJobs; diff --git a/components/cjn-print/printerutil.js b/components/cjn-print/printerutil.js new file mode 100644 index 0000000..c541aae --- /dev/null +++ b/components/cjn-print/printerutil.js @@ -0,0 +1,91 @@ +// 打印机纸宽58mm,页的宽度384,字符宽度为1,每行最多盛放32个字符 +const PAGE_WIDTH = 384; +const MAX_CHAR_COUNT_EACH_LINE = 32; + +/** + * @param str + * @returns {boolean} str是否全是中文 + */ +function isChinese(str) { + return /^[\u4e00-\u9fa5]$/.test(str); +} + +/** + * 返回字符串宽度(1个中文=2个英文字符) + * @param str + * @returns {number} + */ +function getStringWidth(str) { + let width = 0; + for (let i = 0, len = str.length; i < len; i++) { + width += isChinese(str.charAt(i)) ? 2 : 1; + } + return width; +} + +/** + * 同一行输出str1, str2,str1居左, str2居右 + * @param {string} str1 内容1 + * @param {string} str2 内容2 + * @param {number} fontWidth 字符宽度 1/2 + * @param {string} fillWith str1 str2之间的填充字符 + * + */ +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 + */ +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之间的填充字符 + */ +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); +} + +// ArrayBuffer转16进度字符串示例 +function ab2hex(buffer) { + const hexArr = Array.prototype.map.call( + new Uint8Array(buffer), + function(bit) { + return ('00' + bit.toString(16)).slice(-2) + } + ) + return hexArr.join(',') +} + + +module.exports = { + inline: inline, + fillLine: fillLine, + fillAround: fillAround, + ab2hex:ab2hex, +}; diff --git a/components/cjn-print/readme.md b/components/cjn-print/readme.md new file mode 100644 index 0000000..a360688 --- /dev/null +++ b/components/cjn-print/readme.md @@ -0,0 +1,6 @@ +#### 已测试 芯烨、汉印、济强、佳博等多个品牌多款机型打印机,均能正常打印(含二维码) +#### 本插件为参考学习打印示例,支持小程序和app,但不同品牌打印机,对打印指令支持不一样,插件无法做到通用,我的小程序已集成esc,cpcl,tspl指令打印 +#### 您可以到我的小程序中的体验测试打印功能,如有打印二维码需求和打印你想要的模板,可咨询定制 +#### 扫码进入微信小程序(选择 手机功能 --> 蓝牙打印机),快来试试呗! +#### 如果您遇到打印问题或者其他方面需求,可添加微信:chengjn1314(宁哥),欢迎骚扰~ +![avatar](https://mp-a9f90fc5-628e-43f8-a370-00b89368841b.cdn.bspapp.com/cloudstorage/16ff40bb-d352-4f46-a9ed-2ef0406b19c0.jpg) diff --git a/components/cjn-print/util.js b/components/cjn-print/util.js new file mode 100644 index 0000000..49cb9bb --- /dev/null +++ b/components/cjn-print/util.js @@ -0,0 +1,66 @@ +const formatTime = date => { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + + return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') +} + +const formatNumber = n => { + n = n.toString() + return n[1] ? n : '0' + n +} + + +//4合1 +function convert4to1(res) { + let arr = []; + for (let i = 0; i < res.length; i++) { + if (i % 4 == 0) { + let rule = 0.29900 * res[i] + 0.58700 * res[i + 1] + 0.11400 * res[i + 2]; + if (rule > 200) { + res[i] = 0; + } else { + res[i] = 1; + } + arr.push(res[i]); + } + } + return arr; +} + +//8合1 +function convert8to1(arr) { + let data = []; + for (let k = 0; k < arr.length; k += 8) { + let temp = arr[k] * 128 + arr[k + 1] * 64 + arr[k + 2] * 32 + arr[k + 3] * 16 + arr[k + 4] * 8 + arr[k + 5] * 4 + + arr[k + 6] * 2 + arr[k + 7] * 1 + data.push(temp); + } + return data; +} + +//我的图片宽度是240,那么拼接的指令就是[29, 118, 48, 0, 30, 0, 240, 0] +//我的图片宽度是160,那么拼接的指令就是[29, 118, 48, 0, 20, 0, 160, 0] +//补充一点,打印非二维码的图片,宽度一定要是24的倍数,不然打印也会出现乱码 +function toArrayBuffer(res) { + let arr = convert4to1(res.data); + let data = convert8to1(arr); + let cmds = [].concat([27, 97, 1], [29, 118, 48, 0, 30, 0, 240, 0], data, [27, 74, 3], [27, 64]); + return new Uint8Array(cmds).buffer; +} + +function zip_image(res) { + let arr = convert4to1(res.data); + let data = convert8to1(arr); + return data; +} + +module.exports = { + formatTime: formatTime, + toArrayBuffer: toArrayBuffer, + zip_image: zip_image, +} diff --git a/components/cjn-print/weapp.qrcode.esm.js b/components/cjn-print/weapp.qrcode.esm.js new file mode 100644 index 0000000..7231270 --- /dev/null +++ b/components/cjn-print/weapp.qrcode.esm.js @@ -0,0 +1,5 @@ +/** + * weapp.qrcode.js v1.0.0 (https://github.com/yingye/weapp-qrcode#readme) + */ + +var hasOwn=Object.prototype.hasOwnProperty,toStr=Object.prototype.toString,defineProperty=Object.defineProperty,gOPD=Object.getOwnPropertyDescriptor,isArray=function(t){return"function"==typeof Array.isArray?Array.isArray(t):"[object Array]"===toStr.call(t)},isPlainObject=function(t){if(!t||"[object Object]"!==toStr.call(t))return!1;var e,r=hasOwn.call(t,"constructor"),o=t.constructor&&t.constructor.prototype&&hasOwn.call(t.constructor.prototype,"isPrototypeOf");if(t.constructor&&!r&&!o)return!1;for(e in t);return void 0===e||hasOwn.call(t,e)},setProperty=function(t,e){defineProperty&&"__proto__"===e.name?defineProperty(t,e.name,{enumerable:!0,configurable:!0,value:e.newValue,writable:!0}):t[e.name]=e.newValue},getProperty=function(t,e){if("__proto__"===e){if(!hasOwn.call(t,e))return;if(gOPD)return gOPD(t,e).value}return t[e]},extend=function t(){var e,r,o,n,i,a,s=arguments[0],u=1,l=arguments.length,h=!1;for("boolean"==typeof s&&(h=s,s=arguments[1]||{},u=2),(null==s||"object"!=typeof s&&"function"!=typeof s)&&(s={});u=7&&this.setupTypeNumber(t),null==this.dataCache&&(this.dataCache=QRCode.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,e)},setupPositionProbePattern:function(t,e){for(var r=-1;r<=7;r++)if(!(t+r<=-1||this.moduleCount<=t+r))for(var o=-1;o<=7;o++)e+o<=-1||this.moduleCount<=e+o||(this.modules[t+r][e+o]=0<=r&&r<=6&&(0==o||6==o)||0<=o&&o<=6&&(0==r||6==r)||2<=r&&r<=4&&2<=o&&o<=4)},getBestMaskPattern:function(){for(var t=0,e=0,r=0;r<8;r++){this.makeImpl(!0,r);var o=QRUtil.getLostPoint(this);(0==r||t>o)&&(t=o,e=r)}return e},createMovieClip:function(t,e,r){var o=t.createEmptyMovieClip(e,r);this.make();for(var n=0;n>r&1);this.modules[Math.floor(r/3)][r%3+this.moduleCount-8-3]=o}for(r=0;r<18;r++){o=!t&&1==(e>>r&1);this.modules[r%3+this.moduleCount-8-3][Math.floor(r/3)]=o}},setupTypeInfo:function(t,e){for(var r=this.errorCorrectLevel<<3|e,o=QRUtil.getBCHTypeInfo(r),n=0;n<15;n++){var i=!t&&1==(o>>n&1);n<6?this.modules[n][8]=i:n<8?this.modules[n+1][8]=i:this.modules[this.moduleCount-15+n][8]=i}for(n=0;n<15;n++){i=!t&&1==(o>>n&1);n<8?this.modules[8][this.moduleCount-n-1]=i:n<9?this.modules[8][15-n-1+1]=i:this.modules[8][15-n-1]=i}this.modules[this.moduleCount-8][8]=!t},mapData:function(t,e){for(var r=-1,o=this.moduleCount-1,n=7,i=0,a=this.moduleCount-1;a>0;a-=2)for(6==a&&a--;;){for(var s=0;s<2;s++)if(null==this.modules[o][a-s]){var u=!1;i>>n&1)),QRUtil.getMask(e,o,a-s)&&(u=!u),this.modules[o][a-s]=u,-1==--n&&(i++,n=7)}if((o+=r)<0||this.moduleCount<=o){o-=r,r=-r;break}}}},QRCode.PAD0=236,QRCode.PAD1=17,QRCode.createData=function(t,e,r){for(var o=QRRSBlock.getRSBlocks(t,e),n=new QRBitBuffer,i=0;i8*s)throw new Error("code length overflow. ("+n.getLengthInBits()+">"+8*s+")");for(n.getLengthInBits()+4<=8*s&&n.put(0,4);n.getLengthInBits()%8!=0;)n.putBit(!1);for(;!(n.getLengthInBits()>=8*s||(n.put(QRCode.PAD0,8),n.getLengthInBits()>=8*s));)n.put(QRCode.PAD1,8);return QRCode.createBytes(n,o)},QRCode.createBytes=function(t,e){for(var r=0,o=0,n=0,i=new Array(e.length),a=new Array(e.length),s=0;s=0?g.get(c):0}}var d=0;for(h=0;h=0;)e^=QRUtil.G15<=0;)e^=QRUtil.G18<>>=1;return e},getPatternPosition:function(t){return QRUtil.PATTERN_POSITION_TABLE[t-1]},getMask:function(t,e,r){switch(t){case QRMaskPattern.PATTERN000:return(e+r)%2==0;case QRMaskPattern.PATTERN001:return e%2==0;case QRMaskPattern.PATTERN010:return r%3==0;case QRMaskPattern.PATTERN011:return(e+r)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(e/2)+Math.floor(r/3))%2==0;case QRMaskPattern.PATTERN101:return e*r%2+e*r%3==0;case QRMaskPattern.PATTERN110:return(e*r%2+e*r%3)%2==0;case QRMaskPattern.PATTERN111:return(e*r%3+(e+r)%2)%2==0;default:throw new Error("bad maskPattern:"+t)}},getErrorCorrectPolynomial:function(t){for(var e=new QRPolynomial([1],0),r=0;r5&&(r+=3+i-5)}for(o=0;o=256;)t-=255;return QRMath.EXP_TABLE[t]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},i=0;i<8;i++)QRMath.EXP_TABLE[i]=1<=1&&n<=127?e+=t.charAt(r):n>2047?(e+=String.fromCharCode(224|n>>12&15),e+=String.fromCharCode(128|n>>6&63),e+=String.fromCharCode(128|n>>0&63)):(e+=String.fromCharCode(192|n>>6&31),e+=String.fromCharCode(128|n>>0&63));return e}function drawQrcode(t){t=t||{},(t=extend(!0,{width:256,height:256,x:0,y:0,typeNumber:-1,correctLevel:QRErrorCorrectLevel.H,background:"#ffffff",foreground:"#000000",image:{imageResource:"",dx:0,dy:0,dWidth:100,dHeight:100}},t)).canvasId||t.ctx?function(){var e,r=new QRCode(t.typeNumber,t.correctLevel);r.addData(utf16to8(t.text)),r.make(),e=t.ctx?t.ctx:t._this?wx.createCanvasContext&&wx.createCanvasContext(t.canvasId,t._this):wx.createCanvasContext&&wx.createCanvasContext(t.canvasId);for(var o=t.width/r.getModuleCount(),n=t.height/r.getModuleCount(),i=0;i>>7-t%8&1)},put:function(t,e){for(var r=0;r>>e-r-1&1))},getLengthInBits:function(){return this.length},putBit:function(t){var e=Math.floor(this.length/8);this.buffer.length<=e&&this.buffer.push(0),t&&(this.buffer[e]|=128>>>this.length%8),this.length++}};export default drawQrcode; \ No newline at end of file diff --git a/components/components.js b/components/components.js new file mode 100644 index 0000000..1b6d000 --- /dev/null +++ b/components/components.js @@ -0,0 +1,7 @@ +import ChNavBar from '@/components/ch-nav-bar/ch-nav-bar.vue' +import ChNavBtn from '@/components/ch-nav-btn/ch-nav-btn.vue' + +export default function registerComponents (app) { + app.component(ChNavBar.name, ChNavBar); + app.component(ChNavBtn.name, ChNavBtn); +} \ No newline at end of file diff --git a/components/nativePrint/index.vue b/components/nativePrint/index.vue new file mode 100644 index 0000000..5d57aa8 --- /dev/null +++ b/components/nativePrint/index.vue @@ -0,0 +1,218 @@ +