scan.vue 5.0 KB

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