camera.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <view class="page flex-column">
  3. <cover-image
  4. class="page_back"
  5. :style="backStyle"
  6. src="/pages-charge/static/camera-back.png"
  7. @click="back"
  8. ></cover-image>
  9. <view class="page_camera flex-grow">
  10. <camera
  11. v-if="!isDevTool"
  12. device-position="back"
  13. mode="scanCode"
  14. :flash="cameraFlash"
  15. @scancode="handleScancode"
  16. @ready="handleReady"
  17. @error="handleError"
  18. :style="{
  19. width: '100%',
  20. height: `${cameraHeight}px`,
  21. }"
  22. ></camera>
  23. <view
  24. v-else
  25. class="mock-camera"
  26. :style="{
  27. width: '100%',
  28. height: `${cameraHeight}px`,
  29. }"
  30. ></view>
  31. </view>
  32. <view class="page_action flex-shrink" id="page_action">
  33. <cover-view
  34. @click="toggleFlash"
  35. style="
  36. text-align: center;
  37. position: absolute;
  38. width: 100%;
  39. left: 0;
  40. top: -96px;
  41. "
  42. >
  43. <cover-image
  44. style="width: 28px; height: 28px; margin: 0 auto"
  45. src="/pages-charge/static/scan-code-light.png"
  46. ></cover-image>
  47. <cover-view
  48. style="
  49. color: rgba(255, 255, 255, 0.7);
  50. font-size: 13px;
  51. margin-top: 10px;
  52. "
  53. >{{ cameraFlash === "off" ? "轻触照亮" : "轻触关闭" }}</cover-view
  54. >
  55. </cover-view>
  56. <view class="flex">
  57. <view
  58. class="flex-center flex-column"
  59. @click="redirect('/pages-charge/codeing/codeing')"
  60. >
  61. <image
  62. class="width-96"
  63. mode="widthFix"
  64. src="/pages-charge/static/scan-code-input.png"
  65. ></image>
  66. <view class="fs-24 color-fff mt-20">输入充电桩编码</view>
  67. </view>
  68. <view class="flex-center flex-column" @click="chooseImage">
  69. <image
  70. class="width-96"
  71. mode="widthFix"
  72. src="/pages-charge/static/scan-code-album.png"
  73. ></image>
  74. <view class="fs-24 color-fff mt-20">打开相册</view>
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. </template>
  80. <script setup lang="ts">
  81. import { ref } from "vue";
  82. import { isDevTool } from "../../utils/device";
  83. import { deCode } from "../../utils/code";
  84. import { back, redirect } from "../../utils/navigate";
  85. import { onLoad, onReady } from "@dcloudio/uni-app";
  86. import { fetchChargeStatus, searchQRCode } from "../../api/charge";
  87. import { upload } from "@/utils/uploader";
  88. const cameraHeight = ref(0);
  89. const cameraFlash = ref("off");
  90. const backStyle = ref("");
  91. onLoad(() => {
  92. const menuButtonRect = uni.getMenuButtonBoundingClientRect();
  93. backStyle.value = `left:12px;top:${menuButtonRect.top + 6}px;`;
  94. uni.showLoading({
  95. title: "加载中",
  96. });
  97. fetchChargeStatus(true, true)
  98. .then(() => {
  99. uni.hideLoading();
  100. })
  101. .catch(() => {
  102. uni.hideLoading();
  103. });
  104. });
  105. onReady(() => {
  106. // #ifdef MP-WEIXIN
  107. const query = wx.createSelectorQuery();
  108. query.select("#page_action").boundingClientRect();
  109. query.exec(function (res: any) {
  110. if (res && res.length) {
  111. cameraHeight.value =
  112. getApp<any>().globalData.device.windowHeight - res[0].height;
  113. uni.hideLoading();
  114. }
  115. });
  116. // #endif
  117. });
  118. const handleReady = () => {
  119. uni.hideLoading();
  120. };
  121. const handleScancode = (e: any) => {
  122. uni.vibrateShort({});
  123. if (e.detail && e.detail.result) {
  124. deCode(e.detail.result);
  125. }
  126. };
  127. const handleError = (e: any) => {
  128. uni.hideLoading();
  129. if (e.detail && e.detail.errMsg && /auth/.test(e.detail.errMsg)) {
  130. uni.showModal({
  131. content: "请打开摄像头权限开关",
  132. success: () => {
  133. uni.openSetting();
  134. },
  135. });
  136. return;
  137. }
  138. uni.showModal({
  139. content: e.detail.errMsg,
  140. });
  141. };
  142. const toggleFlash = () => {
  143. if (cameraFlash.value === "off") {
  144. cameraFlash.value = "on";
  145. return;
  146. }
  147. cameraFlash.value = "off";
  148. };
  149. const chooseImage = () => {
  150. // #ifdef MP-WEIXIN
  151. wx.scanCode({
  152. onlyFromCamera:false,
  153. scanType:['qrcode','barcode'],
  154. success: (res1) => {
  155. console.log("scanCode",res1);
  156. deCode(res1.result);
  157. },
  158. fail: (err) => {
  159. console.error("scanCode",err);
  160. uni.hideLoading();
  161. uni.showModal({
  162. content: err.errMsg || "出现错误,请重试",
  163. });
  164. }
  165. })
  166. // #endif
  167. }
  168. const chooseImage1 = () => {
  169. uni.chooseImage({
  170. count: 1,
  171. sizeType: ["compressed"],
  172. sourceType: ["album"],
  173. success: (res) => {
  174. uni.showLoading({
  175. title: "正在识别",
  176. });
  177. upload(res.tempFilePaths[0], {
  178. onSuccess: (res) => {
  179. searchQRCode(res.url)
  180. .then((res) => {
  181. if (
  182. res.errmsg === "ok" &&
  183. res.errcode === 0 &&
  184. res.code_results &&
  185. res.code_results.length
  186. ) {
  187. const fi = res.code_results.findIndex(
  188. (item: any) => item.type_name === "QR_CODE"
  189. );
  190. if (fi >= 0) {
  191. deCode(res.code_results[fi].data);
  192. return;
  193. }
  194. }
  195. console.log(res);
  196. return Promise.reject({
  197. errMsg: "微信识别出错,请重试",
  198. });
  199. })
  200. .catch((err) => {
  201. uni.hideLoading();
  202. uni.showModal({
  203. content: err.errMsg || "出现错误,请重试",
  204. });
  205. });
  206. },
  207. onFail: (err) => {
  208. uni.hideLoading();
  209. uni.showModal({
  210. content: err.errMsg || "出现错误,请重试",
  211. });
  212. },
  213. });
  214. },
  215. fail: (err) => {
  216. console.log(err);
  217. if (/cancel/.test(err.errMsg)) {
  218. return;
  219. }
  220. uni.showModal({
  221. content: err.errMsg || "出现错误,请重试",
  222. });
  223. },
  224. });
  225. };
  226. </script>
  227. <style lang="scss">
  228. .page {
  229. position: relative;
  230. height: 100vh;
  231. background-color: #000;
  232. &_back {
  233. position: absolute;
  234. width: 24px;
  235. height: auto;
  236. }
  237. &_camera {
  238. height: 100%;
  239. .mock-camera {
  240. background-color: #999;
  241. }
  242. }
  243. &_action {
  244. position: relative;
  245. box-sizing: content-box;
  246. padding-bottom: constant(safe-area-inset-bottom);
  247. padding-bottom: env(safe-area-inset-bottom);
  248. & > view {
  249. height: 222rpx;
  250. & > view {
  251. width: 50%;
  252. height: 222rpx;
  253. }
  254. }
  255. }
  256. }
  257. </style>