scan.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <template>
  2. <view class="pages">
  3. <view class="scan">
  4. <!-- <view class="loop_line"></view> -->
  5. <u-icon class="close" name="close-circle" color="#fff" size="30" @click="closeScan"></u-icon>
  6. <view class="video-container">
  7. <video class="video" id="video_nav_id" :controls="false"></video>
  8. </view>
  9. <!-- v-if="videoInputDevices.length>1" -->
  10. <view class="camera-container" >
  11. <label>摄像头:</label>
  12. <select v-model="currentVideoInputDevice">
  13. <option
  14. v-for="(videoInputDevice, index) in videoInputDevices"
  15. :key="index"
  16. :value="videoInputDevice"
  17. >
  18. {{ videoInputDevice.label }}
  19. </option>
  20. </select>
  21. </view>
  22. </view>
  23. </view>
  24. </template>
  25. <script>
  26. import {
  27. BrowserMultiFormatReader,
  28. ChecksumException,
  29. FormatException,
  30. } from "@zxing/library";
  31. // import { LOG } from "@zxing/library/esm/core/datamatrix/encoder/constants";
  32. export default {
  33. data() {
  34. return {
  35. exchangeCode:'',
  36. codeReader: null,
  37. videoInputDevices: [],
  38. currentVideoInputDevice: {},
  39. decodeResult: undefined,
  40. }
  41. },
  42. onShow() {
  43. },
  44. beforeDestroy() {
  45. this.codeReader.reset(); //关闭摄像头
  46. // alert('销毁')
  47. },
  48. onHide(){
  49. // alert('销毁')
  50. this.codeReader.reset(); //关闭摄像头
  51. },
  52. mounted() {
  53. var video = document.getElementById('video_nav_id').getElementsByTagName('video')[0]
  54. video.setAttribute('id','video-1')
  55. video.setAttribute('class','video_calss')
  56. this.codeReader = new BrowserMultiFormatReader();
  57. this.openScan();
  58. },
  59. onLoad() {
  60. },
  61. watch: {
  62. currentVideoInputDevice: function () {
  63. this.decodeFromInputVideo();
  64. },
  65. decodeResult: function () {
  66. this.successDecode();
  67. },
  68. },
  69. methods: {
  70. async openScan() {
  71. const _this = this;
  72. // console.log('codeReader', this.codeReader);
  73. // camera.setDisplayOrientation(90);
  74. _this.codeReader
  75. .getVideoInputDevices() //老版本listVideoInputDevices()
  76. .then((videoInputDevices) => {
  77. if (videoInputDevices && videoInputDevices.length) {
  78. if (videoInputDevices.length > 1) {
  79. // videoInputDevices.reverse();
  80. // 把前置摄像头设置默认
  81. let secondElement = videoInputDevices.splice(1, 1)[0]; // 从索引为 1 的位置删除一个元素并返回它
  82. videoInputDevices.splice(0, 0, secondElement); // 在索引为 0 的位置插入第二个元素
  83. } //有多个摄像头的情况
  84. _this.videoInputDevices = videoInputDevices;
  85. _this.currentVideoInputDevice = videoInputDevices[0];
  86. }else{
  87. alert('没有检测到摄像头')
  88. }
  89. })
  90. .catch(() => {});
  91. },
  92. decodeFromInputVideo() {
  93. const _this = this;
  94. _this.codeReader.reset();
  95. // 多次
  96. try {
  97. _this.codeReader.decodeFromVideoDevice(_this.currentVideoInputDevice.deviceId, 'video-1',(res,err) => {
  98. if(res) {
  99. _this.decodeResult = res.text;
  100. }
  101. if (err) {
  102. // alert(err)
  103. if (err instanceof ChecksumException) {
  104. alert("A code was found, but it's read value was not valid.")
  105. console.log(
  106. "A code was found, but it's read value was not valid."
  107. );
  108. }
  109. if (err instanceof FormatException) {
  110. alert("A code was found, but it was in a invalid format.")
  111. console.log("A code was found, but it was in a invalid format.");
  112. }
  113. }
  114. })
  115. }catch(err){
  116. uni.showToast({title: `初始化失败${err}`,icon: 'none'});
  117. }
  118. },
  119. closeScan(){
  120. // this.$router.go(-1)
  121. // uni.navigateBack()
  122. uni.$u.route('/pages/index/index');
  123. // uni.reLaunch({//不传递数据
  124. // url:'/pages/index/index'
  125. // })
  126. },
  127. successDecode() {
  128. const _this = this;
  129. let result = JSON.parse(_this.decodeResult);
  130. this.exchangeCode = result.qrcode;
  131. let pages = getCurrentPages(); //获取所有页面栈实例列表
  132. let nowPage = pages[ pages.length - 1]; //当前页页面实例
  133. let prevPage = pages[ pages.length - 2 ]; //上一页页面实例
  134. this.$u.vuex('vuexExchangeCode', this.exchangeCode);
  135. // prevPage.$vm.exchangeCode = this.exchangeCode; // 修改上一页data里面的数据
  136. this.closeScan();
  137. // this.getCheckGoods();
  138. // alert(_this.decodeResult);
  139. },
  140. }
  141. }
  142. </script>
  143. <style lang="scss" scoped>
  144. #video_nav_id {
  145. height: 80vh;
  146. width: 100%;
  147. }
  148. /deep/.uni-video-cover {
  149. display: none;
  150. }
  151. .scan {
  152. position: fixed;
  153. left: 0;
  154. top: 0;
  155. z-index: 9999;
  156. display: flex;
  157. flex-direction: column;
  158. align-items: center;
  159. color: #ff9900;
  160. width: 100%;
  161. height: 100vh;
  162. background: #000;
  163. .video-container {
  164. margin-top: 20px;
  165. width: 100%;
  166. height: 75vh;
  167. display: flex;
  168. justify-content: center;
  169. /deep/ #video-1{
  170. width: 100%;
  171. height: 100%;
  172. }
  173. @media (min-width: 500px) {
  174. video {
  175. // width: 80vh;
  176. // max-width: 96vw;
  177. height: 80vh;
  178. }
  179. }
  180. }
  181. .camera-container {
  182. position: relative;
  183. margin-top: 10px;
  184. width: 80%;
  185. height: 50px;
  186. line-height: 44px;
  187. border-radius: 10px;
  188. border: 3px solid #ff9900;
  189. display: flex;
  190. justify-content: center;
  191. align-items: center;
  192. padding-left: 8px;
  193. select {
  194. width: calc(100% - 90px);
  195. color: #ff9900;
  196. background: transparent;
  197. border: none;
  198. outline: none;
  199. }
  200. z-index: 100;
  201. }
  202. .close{
  203. position: absolute;
  204. right: 40rpx;
  205. top: 40rpx;
  206. z-index: 100;
  207. }
  208. }
  209. </style>