Browse Source

feat:相机页面

needcode 2 năm trước cách đây
mục cha
commit
bd2787d349

+ 4 - 1
src/components/style-bottom-view/style-bottom-view.vue

@@ -6,7 +6,10 @@
       'fixed-bottom-view-shadow ': shadow,
       'fixed-bottom-view-hidden': hidden,
     }"
-    style="z-index: {{zIndex}};background:{{background}};"
+    :style="{
+      zIndex,
+      background,
+    }"
   >
     <slot></slot>
   </view>

+ 4 - 5
src/custom-tab-bar/index.js

@@ -13,10 +13,6 @@ Component({
         path: "/pages-charge/camera/camera",
         text: "扫码充电",
       },
-      {
-        path: "/pages/list/list",
-        text: "电站列表",
-      },
       {
         path: "/pages/user/user",
         text: "个人中心",
@@ -49,7 +45,10 @@ Component({
     switchTab(e) {
       const data = e.currentTarget.dataset;
       const url = data.path;
-      if (!url) {
+      if (/camera/.test(url)) {
+        wx.navigateTo({
+          url,
+        });
         return;
       }
       wx.vibrateShort &&

+ 124 - 3
src/pages-charge/camera/camera.vue

@@ -1,7 +1,128 @@
 <template>
-  <view class="list"> </view>
+  <view class="page flex-column">
+    <view class="page_camera flex-grow">
+      <camera
+        v-if="!isDevTool"
+        device-position="back"
+        mode="scanCode"
+        @scancode="handleScancode"
+        @ready="handleReady"
+        @error="handleError"
+        :style="{
+          width: '100%',
+          height: `${cameraHeight}px`,
+        }"
+      ></camera>
+      <view
+        v-else
+        class="mock-camera"
+        :style="{
+          width: '100%',
+          height: `${cameraHeight}px`,
+        }"
+      ></view>
+    </view>
+    <view class="page_action flex-shrink" id="page_action">
+      <view class="flex">
+        <view class="flex-center flex-column" @click="redirect('/pages-charge/codeing/codeing')">
+          <image
+            class="width-96"
+            mode="widthFix"
+            src="/pages-charge/static/scan-code-input.png"
+          ></image>
+          <view class="fs-24 color-fff mt-20">输入充电桩编码</view>
+        </view>
+        <view class="flex-center flex-column">
+          <image
+            class="width-96"
+            mode="widthFix"
+            src="/pages-charge/static/scan-code-album.png"
+          ></image>
+          <view class="fs-24 color-fff mt-20">打开相册TODO</view>
+        </view>
+      </view>
+    </view>
+  </view>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { ref } from "vue";
+import { isDevTool } from "../../utils/device";
+import { deCode } from "../../utils/code";
+import { redirect } from "../../utils/navigate";
+import { onLoad, onReady } from "@dcloudio/uni-app";
 
-<style></style>
+const cameraHeight = ref(0);
+
+onLoad(() => {
+  uni.showLoading({
+    title: "加载中",
+  });
+});
+
+onReady(() => {
+  // #ifdef MP-WEIXIN
+  const query = wx.createSelectorQuery();
+  query.select("#page_action").boundingClientRect();
+  query.exec(function (res: any) {
+    if (res && res.length) {
+      cameraHeight.value =
+        getApp<any>().globalData.device.windowHeight - res[0].height;
+      uni.hideLoading();
+    }
+  });
+  // #endif
+});
+
+const handleReady = () => {
+  uni.hideLoading();
+};
+
+const handleScancode = (e: any) => {
+  uni.vibrateShort({});
+  if (e.detail && e.detail.result) {
+    deCode(e.detail.result);
+  }
+};
+
+const handleError = (e: any) => {
+  uni.hideLoading();
+  if (e.detail && e.detail.errMsg && /auth/.test(e.detail.errMsg)) {
+    uni.showModal({
+      content: "请打开摄像头权限开关",
+      success: () => {
+        uni.openSetting();
+      },
+    });
+    return;
+  }
+  uni.showModal({
+    content: e.detail.errMsg,
+  });
+};
+</script>
+
+<style lang="scss">
+.page {
+  height: 100vh;
+  background-color: #000;
+  &_camera {
+    height: 100%;
+    .mock-camera {
+      background-color: #999;
+    }
+  }
+  &_action {
+    box-sizing: content-box;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+    & > view {
+      height: 222rpx;
+      & > view {
+        width: 50%;
+        height: 222rpx;
+      }
+    }
+  }
+}
+</style>

BIN
src/pages-charge/static/scan-code-album.png


BIN
src/pages-charge/static/scan-code-input.png


+ 2 - 0
src/pages-common/contact/contact.vue

@@ -53,6 +53,8 @@
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 
+// TODO 接口
+
 const questions = ref([
   {
     question: "预计并充电或开始充电按钮“置灰”无法点击如何处理",

+ 1 - 63
src/pages-user/wallet-recharge/wallet-recharge.vue

@@ -1,27 +1,5 @@
 <template>
   <view class="pl-30 pr-30">
-    <view class="wallet">
-      <image
-        src="/static/images/wallet-logo.png"
-        mode="widthFix"
-        class="image"
-      />
-      <view class="tag flex-center" @click="detail">
-        <view class="fs-26" style="color: #fff; line-height: 58rpx"
-          >钱包明细</view
-        >
-        <view style="margin-top: -8rpx; margin-left: 6rpx">
-          <uni-icons type="right" size="10" color="#FFFFFF"></uni-icons>
-        </view>
-      </view>
-      <view class="label">钱包余额</view>
-      <view class="value mt-16">
-        <text class="fs-40 lh-48 fw-500 mr-12">¥</text>
-        <text class="fw-500" style="font-size: 60rpx; line-height: 72rpx">{{
-          balance
-        }}</text>
-      </view>
-    </view>
     <view class="pay">
       <view class="title">充值金额</view>
       <view class="flex-wrap">
@@ -56,6 +34,7 @@
 </template>
 
 <script setup lang="ts">
+// 样式、 充值优惠
 import { ref } from "vue";
 import { fetchProfile, insertMoney } from "../../api/user";
 import { onLoad } from "@dcloudio/uni-app";
@@ -70,11 +49,6 @@ const changeOption = (index: number) => {
   payValue.value = 0;
   payOption.value = index;
 };
-const detail = () => {
-  uni.navigateTo({
-    url: "/pages-user/wallet/wallet",
-  });
-};
 const confirm = () => {
   if (payValue.value && !/^[0-9]*(\.\d{1,2})?$/.test(`${payValue.value}`)) {
     uni.showModal({
@@ -126,42 +100,6 @@ onLoad(() => {
 </script>
 
 <style lang="scss">
-.wallet {
-  height: 220rpx;
-  background: linear-gradient(180deg, #347dff 0%, #4faaff 100%);
-  box-shadow: 0px 12rpx 22rpx rgba(13, 21, 62, 0.1);
-  border-radius: 40rpx;
-  position: relative;
-  margin-top: 100rpx;
-  padding: 44rpx 40rpx;
-
-  .image {
-    position: absolute;
-    width: 148rpx;
-    right: 40rpx;
-    top: -60rpx;
-  }
-
-  .label {
-    font-size: 26rpx;
-    color: rgba(255, 255, 255, 0.8);
-  }
-
-  .value {
-    color: #fff;
-  }
-
-  .tag {
-    position: absolute;
-    width: 170rpx;
-    height: 58rpx;
-    right: 0;
-    bottom: 0;
-    background: var(--color-primary);
-    border-radius: 29rpx 0 29rpx 0;
-  }
-}
-
 .pay {
   padding-top: 20rpx;
   .title {

+ 2 - 0
src/pages-user/wallet-refund/wallet-refund.vue

@@ -78,6 +78,8 @@
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 
+// TODO 接口
+
 const user = ref();
 const value = ref(0);
 const reasonText = ref("");

+ 75 - 69
src/pages-user/wallet/wallet.vue

@@ -1,6 +1,10 @@
 <template>
   <view class="page flex-column">
-    <navigation-bar title="我的钱包" @ready="ready"></navigation-bar>
+    <navigation-bar
+      autoFixedStyle="background-color:#fff;"
+      title="我的钱包"
+      @ready="ready"
+    ></navigation-bar>
     <view class="head flex-shrink">
       <view>
         <image class="bg" src="/pages-user/static/wallet-banner.png"></image>
@@ -12,7 +16,11 @@
               color="#ffffff"
             ></uni-icons>
             <view class="fs-36 color-fff fw-500 ml-16">我的钱包</view>
-            <view class="btn flex-center fs-28 ml-auto" @click="toRefund">退款</view>
+            <view
+              class="btn flex-center fs-28 ml-auto"
+              @click="to(`/pages-user/wallet-refund/wallet-refund`)"
+              >退款</view
+            >
           </view>
           <view class="price mt-50" v-if="user">
             <text class="color-fff fw-600 fs-48" style="vertical-align: top"
@@ -45,54 +53,56 @@
           ></view
         ></view>
       </view>
-      <view class="list flex-grow">
-        <scroll-view
-          class="scroll-view"
-          :style="{
-            height: `${scrollViewHeight}px`,
-          }"
-          scroll-y="true"
-          v-if="scrollViewHeight"
+      <view class="list pl-30 pr-30">
+        <view
+          class="item flex-align-center"
+          v-for="(item, index) in infiniteScroller.list"
+          :key="index"
+          @click="detail(index)"
         >
-          <view
-            class="item flex-align-center"
-            v-for="(item, index) in list"
-            :key="index"
-            @click="detail(index)"
-          >
-            <view>
-              <view class="fs-30 fw-500" key="title" duration="300">{{
-                typeMap[item.type - 1]
-              }}</view>
-              <view class="fs-24" style="color: rgba(0, 0, 0, 0.4)">余额</view>
-            </view>
-            <view class="ml-auto" style="text-align: right">
-              <view class="fs-30 fw-500">
-                <text>{{ item.type > 1 ? "- " : "" }}{{ item.amount }}</text>
-                <text class="fs-24 ml-6">元</text>
-              </view>
-              <view class="fs-24" style="color: rgba(0, 0, 0, 0.4)">{{
-                item.transactionTime
-              }}</view>
-            </view>
-            <view class="ml-32" v-if="item.type === 3">
-              <uni-icons
-                type="right"
-                size="12"
-                color="rgba(0,0,0,0.4)"
-              ></uni-icons>
+          <view>
+            <view class="fs-30 fw-500" key="title" duration="300">{{
+              typeMap[item.type - 1]
+            }}</view>
+            <view class="fs-24" style="color: rgba(0, 0, 0, 0.4)">余额</view>
+          </view>
+          <view class="ml-auto" style="text-align: right">
+            <view class="fs-30 fw-500">
+              <text>{{ item.type > 1 ? "- " : "" }}{{ item.amount }}</text>
+              <text class="fs-24 ml-6">元</text>
             </view>
+            <view class="fs-24" style="color: rgba(0, 0, 0, 0.4)">{{
+              item.transactionTime
+            }}</view>
+          </view>
+          <view class="ml-32" v-if="item.type === 3">
+            <uni-icons
+              type="right"
+              size="12"
+              color="rgba(0,0,0,0.4)"
+            ></uni-icons>
           </view>
-          <view style="height: 200rpx"></view>
-        </scroll-view>
+        </view>
       </view>
+      <view style="height: 170rpx;"></view>
     </view>
+    <style-bottom-view background="#ffffff">
+      <view class="pl-40 pr-40 pb-30 pt-30">
+        <style-button
+          type="primary"
+          @click="to(`/pages-user/wallet-recharge/wallet-recharge`)"
+          >充值</style-button
+        >
+      </view>
+    </style-bottom-view>
   </view>
 </template>
 
 <script setup lang="ts">
-import { onLoad } from "@dcloudio/uni-app";
+import { useInfiniteScroll } from "../../utils/infinite-scroll";
+import { onLoad, onReachBottom, onPullDownRefresh } from "@dcloudio/uni-app";
 import { fetchWallet } from "../../api/user";
+import { to } from "../../utils/navigate";
 import { ref } from "vue";
 import { rpxToPx } from "@/utils/device";
 
@@ -119,17 +129,33 @@ const tabs = ref([
 ]);
 
 const typeMap = ref(["充值", "提现", "消费"]);
-const list = ref<any[]>([]);
+const infiniteScroller = useInfiniteScroll(10, (page) => {
+  return fetchWallet(tab.value, page, 10).then((res: any) => {
+    if (res && res.length) {
+      res.forEach((item: any) => {
+        item.amount = (Number(item.amount) / 100).toFixed(2);
+      });
+    }
+    return res;
+  });
+});
 const scrollViewHeight = ref(0);
 
 onLoad(() => {
-  refresh();
-
+  infiniteScroller.refresh();
   if (getApp<any>().globalData.user) {
     user.value = getApp<any>().globalData.user;
   }
 });
 
+onReachBottom(() => {
+  infiniteScroller.next();
+});
+
+onPullDownRefresh(() => {
+  infiniteScroller.refresh();
+});
+
 const ready = (e: any) => {
   scrollViewHeight.value =
     getApp<any>().globalData.device.windowHeight -
@@ -138,33 +164,19 @@ const ready = (e: any) => {
 
 const changeTab = (index: number) => {
   tab.value = tabs.value[index].value;
-  refresh();
-};
-
-const refresh = () => {
-  fetchWallet(tab.value, 1, 10).then((res: any) => {
-    if (res && res.length) {
-      res.forEach((item: any) => {
-        item.amount = (Number(item.amount) / 100).toFixed(2);
-      });
-    }
-    list.value = res;
-  });
+  infiniteScroller.refresh();
 };
 
 const detail = (index: number) => {
-  if (list.value[index].type === 3) {
+  if (!infiniteScroller.list) {
+    return;
+  }
+  if (infiniteScroller.list[index].type === 3) {
     uni.navigateTo({
-      url: `/pages-charge/order/order?id=${list.value[index].orderNo}`,
+      url: `/pages-charge/order/order?id=${infiniteScroller.list[index].orderNo}`,
     });
   }
 };
-
-const toRefund = () => {
-  uni.navigateTo({
-    url: `/pages-user/wallet-refund/wallet-refund`,
-  });
-}
 </script>
 
 <style lang="scss">
@@ -222,12 +234,6 @@ const toRefund = () => {
       }
     }
     .list {
-      height: 100%;
-      .scroll-view {
-        width: 100%;
-        box-sizing: border-box;
-        padding: 0rpx 30rpx;
-      }
       .item {
         height: 170rpx;
         border-bottom: 1rpx solid rgba(0, 0, 0, 0.1);

+ 9 - 2
src/pages.json

@@ -71,7 +71,11 @@
           }
         },
         {
-          "path": "camera/camera"
+          "path": "camera/camera",
+          "style": {
+            "navigationBarTextStyle": "white",
+            "disableScroll": true
+          }
         }
       ]
     },
@@ -101,7 +105,10 @@
           }
         },
         {
-          "path": "wallet/wallet"
+          "path": "wallet/wallet",
+          "style": {
+            "enablePullDownRefresh": true
+          }
         },
         {
           "path": "wallet-refund/wallet-refund",

BIN
src/static/images/custom-tab-bar/2-2.png


BIN
src/static/images/custom-tab-bar/2-3.png


BIN
src/static/images/custom-tab-bar/2-4.png


+ 4 - 0
src/utils/device.ts

@@ -11,3 +11,7 @@ export function pxToRpx(px: number): number {
   }
   return px;
 }
+
+export const isDevTool =
+  getApp<any>().globalData.device &&
+  getApp<any>().globalData.device.platform === "devtools";

+ 15 - 0
src/utils/navigate.ts

@@ -0,0 +1,15 @@
+export function to(url: string) {
+  uni.navigateTo({
+    url,
+  });
+}
+
+export function back() {
+  uni.navigateBack();
+}
+
+export function redirect(url: string) {
+  uni.redirectTo({
+    url,
+  });
+}