king-scan.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <template>
  2. <view class="scan-container">
  3. <!-- 如果scanMode是normal去掉下面的@scancode方法 -->
  4. <view class="scan-cameraCon">
  5. <camera
  6. class="scan-camera"
  7. device-position="back"
  8. flash="off"
  9. @error="error"
  10. :mode="scanMode"
  11. @scancode="cameraScan"
  12. :style="{ width: scanCameraWid, height: scanCameraHei }"
  13. >
  14. <view v-if="scanMode == 'scanCode'">
  15. <!-- 温馨提示:如果你觉得自定义弄四个角的边框太麻烦,可以叫ui切四个角的图片,直接插进来即可,本人因为没有ui才这样做 -->
  16. <!-- 左上角 -->
  17. <cover-view class="scan-border scan-left-top scan-verLine"></cover-view>
  18. <cover-view class="scan-border scan-left-top scan-horLine"></cover-view>
  19. <!-- 左下角 -->
  20. <cover-view class="scan-border scan-left-bottom scan-verLine"></cover-view>
  21. <cover-view class="scan-border scan-left-bottom scan-horLine"></cover-view>
  22. <!-- 右上角 -->
  23. <cover-view class="scan-border scan-right-top scan-verLine"></cover-view>
  24. <cover-view class="scan-border scan-right-top scan-horLine"></cover-view>
  25. <!-- 右下角 -->
  26. <cover-view class="scan-border scan-right-bottom scan-verLine"></cover-view>
  27. <cover-view class="scan-border scan-right-bottom scan-horLine"></cover-view>
  28. <!-- 上下移动的动画线 -->
  29. <cover-view class="scan-animation" :animation="scanAnimation"></cover-view>
  30. </view>
  31. </camera>
  32. </view>
  33. <!-- 下面两种模式暂时写死,具体样式要根据你们的代码来写,也可以使用插槽模式 -->
  34. <view class="" v-if="scanMode == 'normal'">
  35. <button type="primary" @click="takePhoto">拍照</button>
  36. <view>预览</view>
  37. <image mode="widthFix" :src="src"></image>
  38. </view>
  39. <view class="" v-if="scanMode == 'scanCode'">
  40. <!-- <view class="">扫码结果如下:</view>
  41. <view v-for="(item, index) in kingList" key="index">{{ item }}</view> -->
  42. </view>
  43. <u-toast ref="uToast" />
  44. </view>
  45. </template>
  46. <script>
  47. // 移动动画
  48. let animation = wx.createAnimation({});
  49. // 提示音(如果有可以导入,这个我用手机震动来提示扫码完成)
  50. let innerAudioContext = wx.createInnerAudioContext();
  51. innerAudioContext.src = '/static/music/beep.mp3';
  52. export default {
  53. data() {
  54. return {
  55. // 照相模式下图片临时路径
  56. src: '',
  57. // 扫码模式下的多次扫码列表
  58. kingList: [],
  59. // 动画
  60. scanAnimation: null
  61. };
  62. },
  63. props: {
  64. // 照相模式还是扫码模式(normal:代表照相模式,scanCode:代表扫码模式,注意微信暂不支持扫描小程序码,不要问为什么,微信功能是这样)
  65. scanMode: {
  66. type: String,
  67. default: 'scanCode'
  68. },
  69. // 扫码成功用是否用震动来提示(1:表示震动模式,2:表示mp3模式)
  70. scanTip: {
  71. type: Number,
  72. default: 1
  73. },
  74. // 相机的宽度
  75. scanCameraWid: {
  76. type: String,
  77. default: '250px'
  78. },
  79. // 相机的高度
  80. scanCameraHei: {
  81. type: String,
  82. default: '250px'
  83. }
  84. },
  85. created() {
  86. if (this.scanMode == 'scanCode') {
  87. // 初始化扫码动画
  88. this.initAnimation();
  89. }
  90. },
  91. methods: {
  92. initAnimation() {
  93. var that = this;
  94. // 控制向上还是向下移动
  95. let m = true;
  96. setInterval(
  97. function() {
  98. if (m) {
  99. animation.translateY(240).step({ duration: 3000 });
  100. m = !m;
  101. } else {
  102. animation.translateY(10).step({ duration: 3000 });
  103. m = !m;
  104. }
  105. that.scanAnimation = animation.export();
  106. }.bind(this),
  107. 3000
  108. );
  109. },
  110. cameraScan(e) {
  111. if (e) {
  112. let result = e.detail.result;
  113. // 如果已经扫描过了,就不添加到列表里面了
  114. if (this.kingList.indexOf(result) == -1) {
  115. switch (this.scanTip) {
  116. case 1:
  117. // 方式1,扫码成功后让手机震动
  118. uni.vibrateShort({
  119. success: function() {
  120. console.log('success');
  121. }
  122. });
  123. break;
  124. case 2:
  125. // 方式2,扫码成功后让手机播放声音
  126. innerAudioContext.play();
  127. break;
  128. default:
  129. // 方式1,扫码成功后让手机震动
  130. uni.vibrateShort({
  131. success: function() {
  132. console.log('success');
  133. }
  134. });
  135. break;
  136. }
  137. this.kingList.push(result);
  138. let list = JSON.parse(this.kingList[0])
  139. let sysTime = Date.parse(new Date()) / 1000;
  140. let time = list.time;
  141. console.log('list.time',list.time);
  142. let date = (new Date(Date.parse(time.replace(/-/g,"/")))).getTime() / 1000;
  143. let count= list.id;
  144. let last =list.type;
  145. console.log('sysTime',sysTime)
  146. console.log('date',date)
  147. console.log('sysTime-date',sysTime-date)
  148. console.log('sysTime-date <= 300000',sysTime-date <= 300000);
  149. if(sysTime-date <= 300000){
  150. this.$emit('handle', count, last);
  151. }
  152. } else {
  153. this.$refs.uToast.show({
  154. title: '扫描过了,二维码已失效!',
  155. type: 'default',
  156. })
  157. }
  158. }
  159. },
  160. // 如果不是扫码模式就用这个
  161. takePhoto() {
  162. const ctx = uni.createCameraContext();
  163. ctx.takePhoto({
  164. quality: 'high',
  165. success: res => {
  166. this.src = res.tempImagePath;
  167. }
  168. });
  169. },
  170. error(e) {
  171. if (e) {
  172. let that = this;
  173. // 如果用户不允许使用摄像头,需要提示引导用户授权
  174. wx.getSetting({
  175. success(res) {
  176. if (!res.authSetting['scope.camera']) {
  177. //获取摄像头权限
  178. wx.authorize({
  179. scope: 'scope.camera',
  180. success() {
  181. console.log('授权成功');
  182. },
  183. fail() {
  184. wx.showModal({
  185. title: '提示',
  186. content: '尚未进行摄像头权限授权,摄像头功能将无法使用',
  187. showCancel: false,
  188. success(res) {
  189. that.openAuthor();
  190. }
  191. });
  192. }
  193. });
  194. }
  195. },
  196. fail(res) {}
  197. });
  198. }
  199. },
  200. // 打开设置进行授权
  201. openAuthor(){
  202. let that = this;
  203. wx.openSetting({
  204. //这里的方法是调到一个添加权限的页面,可以自己尝试
  205. success: res => {
  206. console.log(1111);
  207. if (!res.authSetting['scope.camera']) {
  208. wx.showModal({
  209. title: '提示',
  210. content: '尚未进行摄像头权限授权,摄像头功能将无法使用',
  211. showCancel: false,
  212. success(res) {
  213. if (res.confirm) {
  214. console.log('用户点击确定');
  215. that.openAuthor();
  216. } else if (res.cancel) {
  217. console.log('用户点击取消');
  218. }
  219. }
  220. });
  221. }else {
  222. wx.showModal({
  223. title: '提示',
  224. content: '授权成功!',
  225. showCancel: false,
  226. success: resData => {
  227. // 授权成功后,需要重新进入页面能调起相机组件
  228. uni.reLaunch({
  229. url:'/pages/index/index'
  230. })
  231. }
  232. });
  233. }
  234. },
  235. fail: function() {
  236. console.log('授权摄像头权限失败');
  237. }
  238. });
  239. }
  240. }
  241. };
  242. </script>
  243. <style lang="scss">
  244. .scan-container {
  245. .scan-cameraCon {
  246. display: flex;
  247. align-items: center;
  248. justify-content: center;
  249. width: 100vw;
  250. height: 50vh;
  251. .scan-camera {
  252. width: 250px;
  253. height: 250px;
  254. position: relative;
  255. // 四个角边框
  256. .scan-border {
  257. background-color: #007aff;
  258. position: absolute;
  259. }
  260. .scan-verLine {
  261. width: 5px;
  262. height: 20px;
  263. }
  264. .scan-horLine {
  265. width: 20px;
  266. height: 5px;
  267. }
  268. // 左上角
  269. .scan-left-top {
  270. left: 0;
  271. top: 0;
  272. }
  273. // 左下角
  274. .scan-left-bottom {
  275. left: 0;
  276. bottom: 0;
  277. }
  278. // 右上角
  279. .scan-right-top {
  280. right: 0;
  281. top: 0;
  282. }
  283. // 右下角
  284. .scan-right-bottom {
  285. right: 0;
  286. bottom: 0;
  287. }
  288. // 相机中上下移动的线条
  289. .scan-animation {
  290. position: absolute;
  291. top: 5px;
  292. left: 5px;
  293. width: 240px;
  294. height: 4px;
  295. background-color: #007aff;
  296. border-radius: 50%;
  297. }
  298. }
  299. }
  300. }
  301. </style>