hs-scancode.nvue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <template>
  2. <view class="page" :style="{height: height+'px'}" v-if="onlyFromCamera">
  3. <barcode :style="{height: height+'px'}" id="hs-scan" class="barcode" ref="barcode" autostart
  4. frameColor="#0cff00" scanbarColor="#0cff00" background="#000000" :filters="fil" @marked="success"
  5. @error="error">
  6. </barcode>
  7. <view @click="back" class="back" hover-class="css-hover">
  8. <image :src="scan_img.back" style="width: 28px;height: 28px;"></image>
  9. </view>
  10. <text class="msg">{{msg}}</text>
  11. <view class="flash" :style="{bottom: (height/2 - 120)+'px'}" @click="toFlash()" hover-class="css-hover">
  12. <image class="flash-img" :src="flash_img" style="width: 30px;height: 30px;"></image>
  13. <text class="flash-text" :class="flash?'flash-on':''">{{flash?"轻触关闭":"轻触点亮"}}</text>
  14. </view>
  15. </view>
  16. <view class="page" :style="{height: height+'px'}" v-else>
  17. <barcode :style="{height: height+'px'}" id="hs-scan" class="barcode" ref="barcode" autostart
  18. frameColor="#0cff00" scanbarColor="#0cff00" background="#000000" :filters="fil" @marked="success"
  19. @error="error">
  20. </barcode>
  21. <view @click="back" class="back" hover-class="css-hover">
  22. <image :src="scan_img.back" style="width: 28px;height: 28px;"></image>
  23. </view>
  24. <text class="msg">{{msg}}</text>
  25. <view class="flash" :style="{bottom: (height/2 - 120)+'px'}" @click="toFlash()" hover-class="css-hover">
  26. <image class="flash-img" :src="flash_img" style="width: 30px;height: 30px;"></image>
  27. <text class="flash-text" :class="flash?'flash-on':''">{{flash?"轻触关闭":"轻触点亮"}}</text>
  28. </view>
  29. <view @click="toScan" class="album" hover-class="css-hover">
  30. <image :src="scan_img.album" style="height: 26px;width: 26px;"></image>
  31. </view>
  32. </view>
  33. </view>
  34. </template>
  35. <script>
  36. const _image = {
  37. flash_off: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABSElEQVRoge2UMS9DYRRAP20MdOhuEIOIFbXZGAw2xMpiM0vslf6Cpt1MJBabxSLEJuEPiMEiFsSKY3mSG9K+vtfvvit1T3K39+49p2kbguM4/wugBqwrzCJQ0pZfRZe6dsCacsC+akASMQMsKcwC2l8hxxpgA7hWnEPtgJ3Yv9of3BQZcAWcRZpni4CpiHsvPaDHQwMVsBJpZwW4KypgGfhMjr0CtT73DQOn4kM5juXa7eimiHgBZnPuKQMnQv4CGInt2+n4rjj8BEzn2NEUO26BqoZrN4GGEHgAJjK8uyfevQfGFFU7SgwBLfrjEZgsXF5ElICjnPJvwLyZvIiYE1LnQDtlvv8A2tbuIYRfAVs9PP+ePNsswi8VD7DGA6zxAGs8wBoPsMYDrPEAawYt4ADYTpmPvxyQBQ+IAjCaRGSdcWt3xwkhfAHeC7+Yzq/O8QAAAABJRU5ErkJggg==',
  38. flash_on: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABi0lEQVRoge2WPyhFYRiHT0n5k4GyuINRWe5gYrqJQiyKzYRJsir/VgMx3JgMjOyGmyxSVqOSwU0pumVg4zHc9+bonO9c5/rOfTu376lv+r2d9/fU+erzPIej/gBTQB5oqTK3BbwBuYiZduAcWLJeNGLpLWX2qsxdydxaxMyhzNzYb2peOi1Lv4DxiLmKwLohn/V9ZzS5xuHLj2X5E9BlmDEKAD3Ai+QHyTcOFugEHqXApmHmTPL5kGxVsgegI/nGIQA54BoYMuTdwCTQFJL1AkfAQPJNGxFgGHgGShbOqYbAMvYoOoEaBBYtCtxrCLRSvgcjFk5f3QVEYhCYsXDatATGLPw+BZXyPonCP8p/AlltgawUqYUT1fIV+HnYxeEdyGh39zzP84CMFIrDtnbvXwA7McqXMDzB1QAmYghcavcN4AS0MQhcAPsEL3gqBF6BZsk20ihw58sWnEDSNKJA0ZetpFEAYBeYA4ppFTDhBKzjBLRxAto4AW2cgDZOQBugH/j4o0Beu6/DIXwDQ+8GvfIPRuwAAAAASUVORK5CYII=',
  39. back: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAADjElEQVRoge2aW08TQRiGh4QYwg0iSv0fEKAChaRNKychIVj1Qv+UGqOXGhJCDEoiaEwTwqWmGg+pRq64IB5impa0C9vT40W30G6325nulgXDm+xNd3fmfWa+mZ2Zr0Kc6z8V0AH0GleH135sBVwF7gHPgK9AmnqljXtPgbuAz2vTHcAs8BooAjmgYGHcrILxbBHYBGZOvIcM4z8MMzKm7WAKwHdg+iSM9wPrRqUlB8bNKlHukRfA5XaZDwB/Ad1F42bpwB9g1G3z88jHuFMVDJA5N827HTLNVDLqnHVqfpxyy3ulHHCtVfM+yjFf9BCgSHlMXGkFYIP2DlhZHQLrquav423Lm1UEQrLmO4BvnD6AL8h8sYEbKEyXOzs7bG1tUSrJT1L5fJ5YLMbu7q4qxIwMwFskWz+RSNDV1YUQgmg0Sj6fb/qOpmmEw2GEEPT09LC3tycLUAA2mpn3yZoHWF5eRghxdC0tLdlCaJpGKBSqeScWi8lWV4FovNQA7qAw82SzWQYGBqQgrMwHg0GpXquSDty0A3gCKJWYTqfx+/01xqampjg8PDx6Zn9/n9HR0Zpn5ubm0HXlWToHPLID+KxaIkAmkyEQCFhCuGi+oo92AJlWS00mkwwODtYYXVxcJBgM1oVNNptttRqA/UbmLzgpFco9MTExUWPYxZavVqcVwCU3Sm4E4aJ5gN62AVgNaiEEkUiEg4MDN6qABgCOQ6iR+TZA1IeQ00FsFTqRSIShoaGa3+bn552GkvUgNgA+tVKiVcsvLCyQy+XIZDJMTk7W3AuHw0564oMdwGMUd2DJZLLua1wxX1EjCE3TVM3ngId2AFEUlhK6rjf8gJmVSqUYHh6uAy0WlVbtOWDRDqAPhaX0yspKjaHp6WlL83YQ29vbKgB54GJDAAPiDZIr0ng8Tmdnp5T5aoiRkRGEEHR3d6vsCQrAK1vzBoDShiYej7O2tqa0qtQ0jdXVVRKJhPQ7KGxozvaW0oAY52QPspqpBIxJma+CeM7pOFbRgRUl8wZAH/Abb0OpAPzEau0jCTFGee71IpxKlFvf35L5Koize7hrgqikhdqtIm4er1dBBCgftCovYBSkAb9wO8FRBdEPvMR5bsysSu+u0a4UkwnE7SRfgpNI8pkgKmnWTY7TrDLriTzH6aoNvEizWsD4gNvAA+A9kLIwngLeAfeBW3id6G4mztJfDc7lQP8ALX0r5IbFIHwAAAAASUVORK5CYII=',
  40. album: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACgklEQVRoge3YO2gUURiG4WgUMeINQ7xgFZDYiIWilSBesbQTxSKFNipi4Q0URIkgWEhsLAUbsUiTwl6xSCFGIWorIghRRLyLyWMxZ/G4zk5ms7szK+wHpznzH/733ZnZOTNdXZ100kknbRv0YR8GcbTgMRh6980GvB+jmFZ+piUs/XnhN2GyXObUTGLTTPDL8DZadBc7MSA5K0WOgdD7bsTzFsuyBC5Exefruu5aGJyNuC5kFT4NRc8wt0DGzGBuxDaeVfg5FA1XzS/GTXwKx59ge6vBqxhuhN5fsooquRrNdeORfzONvYXQJxyXo97pV0cNgf0p8JU8/h8ErmQITKG73QVOZghMFgHfqMBKvKshcKntBcL8Hryvgr+H+YXQdzUoEI6txjHJQ6Wwf5+of2MCZadtBDAPt/AKJ+pY1zYC56rupW0515UvgDX+bEcqGcOcHGvbQuC29BzKsbZcAWxV+w3vNXoKFcAqOZ8DmIOHNeArOV2YAK5Hv9zaHAIHZoCHD+htuQC2VTUenQF+ib9fU7Nyq6UCkkthLKXxvozGQznh4Rc2tFLgYI3GL6TcD1iHH3UIwP2WCKBHcs3XyqmUNSN1wlfyz16rGQLVT9DqfMSqqH7PLOHhOeY1TQC9kn+JmTKCBZKd68sGBGCwmQLDdTT+LrkZG80bLKpX4FsouBHNDeBnE4Bmk4sRx80w9zUVPhRNhKKxaO5MKehJ7kQcj8PcRJbAtWjx4TC3EDuwq+CxE0sDw5GIayhLoM+fd98pyZahH8tLGusDw1RgmsSKmgJBYje+pp/RUvNd3s+Zkq3veMnAcR5gcy74KpEtOC75ElHGGMTGusE76aSTTgrLbyY65XbJ3W1oAAAAAElFTkSuQmCC',
  41. };
  42. const SCAN_MAPS = {
  43. [0]: "QR_CODE",
  44. [1]: "EAN_13",
  45. [2]: "EAN_8",
  46. [3]: "AZTEC",
  47. [4]: "DATA_MATRIX",
  48. [5]: "UPC_A",
  49. [6]: "UPC_E",
  50. [7]: "CODABAR",
  51. [8]: "CODE_39",
  52. [9]: "CODE_93",
  53. [10]: "CODE_128",
  54. [11]: "CODE_25",
  55. [13]: "PDF_417",
  56. [14]: "RSS_14",
  57. [15]: "RSSEXPANDED"
  58. };
  59. export default {
  60. data: {
  61. evalName: "hs-scancode", //扫码回调监听事件
  62. flash: false, //手电筒
  63. vibrate: true, //震动
  64. sound: "none", //声音 none default
  65. fil: [0, 1, 2], //条码类型
  66. msg: "扫码", //提示文本
  67. height: 600, //高度
  68. isDark: null, //状态栏前景色 黑色
  69. fullScreen: false, //是否全屏
  70. onlyFromCamera: false, //从相册获取
  71. },
  72. computed: {
  73. scan_img() {
  74. return _image
  75. },
  76. flash_img() {
  77. return this.flash ? _image.flash_on : _image.flash_off;
  78. },
  79. },
  80. onLoad(p) {
  81. //参数
  82. if (p.evalName) this.evalName = p.evalName;
  83. if (p.flash) this.flash = p.flash == 'true';
  84. if (p.vibrate) this.vibrate = p.vibrate == 'true';
  85. if (p.sound) this.sound = p.sound;
  86. if (p.msg) this.msg = p.msg;
  87. if (p.fil) this.fil = p.fil.split(',').map(x => parseInt(x));
  88. if (p.fullScreen) this.fullScreen = p.fullScreen == 'true';
  89. if (p.onlyFromCamera) this.onlyFromCamera = p.onlyFromCamera == 'true';
  90. this.setFullOrStatus(true);
  91. uni.getSystemInfo({
  92. success: res => this.height = res.windowHeight
  93. });
  94. setTimeout(() => {
  95. this.toStart();
  96. this.webviewInit();
  97. }, 100);
  98. },
  99. onUnload() {
  100. this.setFullOrStatus(false);
  101. this.toFlash(false);
  102. uni.$off(this.evalName);
  103. },
  104. onBackPress(e) {
  105. if (e.from === 'backbutton') this.back(0);
  106. else this.setFullOrStatus(false);
  107. },
  108. methods: {
  109. webviewInit() {
  110. var pages = getCurrentPages();
  111. var currentWebview = pages[pages.length - 1].$getAppWebview();
  112. //ios 左滑关闭
  113. currentWebview.addEventListener('popGesture', e => {
  114. const type = e.type,
  115. result = e.result;
  116. if (type === 'start') {
  117. this.setFullOrStatus(false);
  118. this.toFlash(false);
  119. this.toCancel();
  120. } else if (type === 'end' && result) {
  121. this.back(0)
  122. } else if (type === 'end' && !result) {
  123. this.setFullOrStatus(true);
  124. this.toStart();
  125. }
  126. });
  127. },
  128. success(e) {
  129. uni.$emit(this.evalName, [null, {
  130. "hsScanCode": true,
  131. "result": e.detail.message,
  132. "scanType": SCAN_MAPS[e.detail.code],
  133. "charSet": "utf8",
  134. "path": e.detail.file || "",
  135. "errMsg": "scanCode:ok"
  136. }]);
  137. },
  138. error(e, cancel) {
  139. uni.$emit(this.evalName, [{
  140. "hsScanCode": true,
  141. "errMsg": cancel === true ? "scanCode:fail cancel" : "scanCode:fail"
  142. }, null]);
  143. if (!cancel) this.toStart();
  144. },
  145. toStart: function() {
  146. this.$refs.barcode && this.$refs.barcode.start({
  147. conserve: false,
  148. vibrate: this.vibrate,
  149. sound: this.sound,
  150. });
  151. },
  152. toCancel: function() {
  153. this.$refs.barcode.cancel();
  154. },
  155. toFlash: function(t) {
  156. this.flash = t == null ? !this.flash : t;
  157. this.$refs.barcode.setFlash(this.flash);
  158. },
  159. toScan: async function() {
  160. this.toCancel();
  161. const [e, res] = await uni.chooseImage({
  162. count: 1,
  163. sizeType: ['original'],
  164. sourceType: ['album']
  165. });
  166. if (res && res.tempFilePaths.length > 0) {
  167. const barcodeModule = uni.requireNativePlugin('barcodeScan');
  168. barcodeModule.scan(res.tempFilePaths[0], e => {
  169. if (e.detail.type === "success") {
  170. this.success(e);
  171. } else {
  172. this.error(e);
  173. }
  174. this.toStart();
  175. });
  176. } else {
  177. this.toStart();
  178. }
  179. },
  180. back(t) {
  181. const p = {
  182. delta: 1
  183. }
  184. this.setFullOrStatus(false);
  185. this.toCancel();
  186. this.toFlash(false);
  187. if (t !== 0) uni.navigateBack(p);
  188. },
  189. setFullOrStatus(t) {
  190. if (this.isDark == null) this.isDark = this.getStatusBarStyle() !== 'light';
  191. this.isDark && plus.navigator.setStatusBarStyle(t ? "light" : "dark");
  192. this.fullScreen && plus.navigator.setFullscreen(t)
  193. },
  194. getStatusBarStyle() {
  195. let style = plus.navigator.getStatusBarStyle()
  196. if (style === 'UIStatusBarStyleBlackTranslucent' || style === 'UIStatusBarStyleBlackOpaque' || style ===
  197. 'null') {
  198. style = 'light'
  199. } else if (style === 'UIStatusBarStyleDefault') {
  200. style = 'dark'
  201. }
  202. return style
  203. }
  204. }
  205. }
  206. </script>
  207. <style scoped>
  208. .page {
  209. top: 0;
  210. position: fixed;
  211. width: 750rpx;
  212. justify-content: center;
  213. align-items: center;
  214. background-color: #000000;
  215. }
  216. .back {
  217. position: fixed;
  218. left: 5px;
  219. top: 20px;
  220. border-radius: 50;
  221. padding: 15px;
  222. }
  223. .msg {
  224. position: fixed;
  225. top: 90px;
  226. width: 750rpx;
  227. text-align: center;
  228. color: #FFFFFF;
  229. font-size: 16px;
  230. }
  231. .css-hover {
  232. opacity: .4;
  233. }
  234. .barcode {
  235. width: 750rpx;
  236. height: 100%;
  237. background-color: #000000;
  238. }
  239. .flash {
  240. position: absolute;
  241. bottom: 500rpx;
  242. justify-content: center;
  243. align-items: center;
  244. padding: 8px;
  245. }
  246. .flash-text {
  247. margin-top: 3px;
  248. color: #bfbfbf;
  249. font-size: 12px;
  250. }
  251. .flash-on {
  252. color: #FFFFFF;
  253. }
  254. .album {
  255. position: fixed;
  256. bottom: 60px;
  257. right: 30px;
  258. height: 42px;
  259. width: 42px;
  260. padding: 16px;
  261. background-color: rgba(157, 157, 157, .3);
  262. border-radius: 50;
  263. justify-content: center;
  264. align-items: center;
  265. }
  266. </style>