Kaynağa Gözat

feat:剩余问题修复

needcode 2 yıl önce
ebeveyn
işleme
7bfdb9fe4b

+ 1 - 1
README.md

@@ -1 +1 @@
-## 
+## Q

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "dev:quickapp-webview": "uni -p quickapp-webview",
     "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
     "dev:quickapp-webview-union": "uni -p quickapp-webview-union",
+    "build": "uni build -p mp-weixin",
     "build:app": "uni build -p app",
     "build:app-android": "uni build -p app-android",
     "build:app-ios": "uni build -p app-ios",

+ 24 - 12
src/api/charge.ts

@@ -18,6 +18,10 @@ export async function cancelAppointmentCharge() {
   return cHttp.get("/charge/cancelBooking");
 }
 
+export async function searchQRCode(imgUrl: string) {
+  return cHttp.get(`/charge/qrCode?imgUrl=${imgUrl}`);
+}
+
 export async function changeAppointmentTime(
   startChargeSeq: string,
   startTime: string
@@ -257,7 +261,7 @@ export function fetchStationByIds(ids: number[]) {
   });
 }
 
-export function fetchStationByConnectorId(connectorId: string) {
+export function fetchStationByConnectorIdOrShortId(id: string) {
   let equipment = -1;
   return fetchAllStations()
     .then((res) => {
@@ -266,17 +270,25 @@ export function fetchStationByConnectorId(connectorId: string) {
         if (!station && item.equipmentInfos && item.equipmentInfos) {
           item.equipmentInfos.forEach(
             (equipmentInfo: any, equipmentIndex: number) => {
-              if (
-                equipmentInfo.connectorInfos &&
-                equipmentInfo.connectorInfos
-              ) {
-                // connectorId
-                equipmentInfo.connectorInfos.forEach((connectorInfo: any) => {
-                  if (connectorInfo.connectorId === connectorId) {
-                    station = item;
-                    equipment = equipmentIndex;
-                  }
-                });
+              if (id.length <= 16) {
+                // 此处传入的是 shortId
+                if (equipmentInfo.shortId === id) {
+                  station = item;
+                  equipment = equipmentIndex;
+                }
+              } else {
+                if (
+                  equipmentInfo.connectorInfos &&
+                  equipmentInfo.connectorInfos
+                ) {
+                  // connectorId
+                  equipmentInfo.connectorInfos.forEach((connectorInfo: any) => {
+                    if (connectorInfo.connectorId === id) {
+                      station = item;
+                      equipment = equipmentIndex;
+                    }
+                  });
+                }
               }
             }
           );

+ 4 - 0
src/api/index.ts

@@ -18,3 +18,7 @@ export function applyInvoice(startChargeSeqs: string[]) {
     },
   });
 }
+
+export function fetchHomeBanner() {
+  return indexHttp.get('/banner')
+}

+ 22 - 3
src/components/charge-station/charge-station.vue

@@ -5,7 +5,9 @@
       border: border ? '1rpx solid rgba(0, 0, 0, 0.1)' : 'none',
       'border-radius': fromMap ? '20rpx 20rpx 0 0' : '20rpx',
     }"
-    @click="detail"
+    @touchstart="touchstart"
+    @touchend="touchend"
+    data-method="detail"
   >
     <view class="flex-between">
       <view>
@@ -17,7 +19,12 @@
           >{{ address }} | {{ distance }}km</view
         >
       </view>
-      <view class="nav flex-center flex-shrink" @click.stop="nav">
+      <view
+        class="nav flex-center flex-shrink"
+        @touchstart="touchstart"
+        @touchend.stop="touchend"
+        data-method="nav"
+      >
         <image src="/static/images/icon-nav.png" mode="widthFix" />
         <text>导航</text>
       </view>
@@ -68,7 +75,9 @@
       </view>
       <view
         class="btn flex-shrink flex-column flex-center"
-        @click.stop="collect"
+        @touchstart="touchstart"
+        @touchend.stop="touchend"
+        data-method="collect"
       >
         <uni-icons
           :type="collected ? 'star-filled' : 'star'"
@@ -120,6 +129,7 @@ export default {
   },
   data() {
     return {
+      touchtime: 0,
       collected: false,
       tagMap: [
         "",
@@ -183,6 +193,15 @@ export default {
       });
       return length;
     },
+    touchstart() {
+      this.touchtime = new Date().getTime();
+    },
+    touchend(e: any) {
+      const current = new Date().getTime();
+      if (current - this.touchtime < 100) {
+        this[e.currentTarget.dataset.method]();
+      }
+    },
   },
 };
 </script>

+ 14 - 6
src/pages-charge/appointment/appointment.vue

@@ -226,7 +226,7 @@
 <script setup lang="ts">
 import {
   fetchChargeStatus,
-  fetchStationByConnectorId,
+  fetchStationByConnectorIdOrShortId,
   fetchStationPriceDesc,
   startCharge,
   cancelAppointmentCharge,
@@ -595,13 +595,21 @@ const submitNow = () => {
 
 onLoad((_options: any) => {
   // sn=SN100523042860091 测试环境
-  const sn = _options.sn || "SN100523042860091";
+  console.log("options", _options);
+  let sn = _options.sn;
   uni.showLoading({
     title: "加载中",
   });
-  fetchStationByConnectorId(sn)
+  fetchStationByConnectorIdOrShortId(sn)
     .then((res) => {
-      // console.log(res);
+      console.log(res);
+      if (
+        res.equipment &&
+        res.equipment.connectorInfos &&
+        res.equipment.connectorInfos.length
+      ) {
+        sn = res.equipment.connectorInfos[0].connectorId;
+      }
       options.value = _options;
       data.value = res;
       return fetchStationPriceDesc(sn);
@@ -618,9 +626,9 @@ onLoad((_options: any) => {
         startAppointmentCountDown();
       }
     })
-    .catch(() => {
+    .catch((err) => {
+      console.log(err);
       uni.hideLoading();
-      uni.navigateBack();
     });
 });
 </script>

+ 65 - 5
src/pages-charge/camera/camera.vue

@@ -3,7 +3,7 @@
     <cover-image
       class="page_back"
       :style="backStyle"
-      src="/static/images/back.png"
+      src="/pages-charge/static/camera-back.png"
       @click="back"
     ></cover-image>
     <view class="page_camera flex-grow">
@@ -65,13 +65,13 @@
           ></image>
           <view class="fs-24 color-fff mt-20">输入充电桩编码</view>
         </view>
-        <view class="flex-center flex-column">
+        <view class="flex-center flex-column" @click="chooseImage">
           <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 class="fs-24 color-fff mt-20">打开相册</view>
         </view>
       </view>
     </view>
@@ -84,7 +84,8 @@ import { isDevTool } from "../../utils/device";
 import { deCode } from "../../utils/code";
 import { back, redirect } from "../../utils/navigate";
 import { onLoad, onReady } from "@dcloudio/uni-app";
-import { fetchChargeStatus } from "../../api/charge";
+import { fetchChargeStatus, searchQRCode } from "../../api/charge";
+import { upload } from "@/utils/uploader";
 
 const cameraHeight = ref(0);
 const cameraFlash = ref("off");
@@ -153,6 +154,65 @@ const toggleFlash = () => {
   }
   cameraFlash.value = "off";
 };
+
+const chooseImage = () => {
+  uni.chooseImage({
+    count: 1,
+    sizeType: ["compressed"],
+    sourceType: ["album"],
+    success: (res) => {
+      uni.showLoading({
+        title: "正在识别",
+      });
+      upload(res.tempFilePaths[0], {
+        onSuccess: (res) => {
+          searchQRCode(res.url)
+            .then((res) => {
+              if (
+                res.errmsg === "ok" &&
+                res.errcode === 0 &&
+                res.code_results &&
+                res.code_results.length
+              ) {
+                const fi = res.code_results.findIndex(
+                  (item: any) => item.type_name === "QR_CODE"
+                );
+                if (fi >= 0) {
+                  deCode(res.code_results[fi].data);
+                  return;
+                }
+              }
+              console.log(res);
+              return Promise.reject({
+                errMsg: "微信识别出错,请重试",
+              });
+            })
+            .catch((err) => {
+              uni.hideLoading();
+              uni.showModal({
+                content: err.errMsg || "出现错误,请重试",
+              });
+            });
+        },
+        onFail: (err) => {
+          uni.hideLoading();
+          uni.showModal({
+            content: err.errMsg || "出现错误,请重试",
+          });
+        },
+      });
+    },
+    fail: (err) => {
+      console.log(err);
+      if (/cancel/.test(err.errMsg)) {
+        return;
+      }
+      uni.showModal({
+        content: err.errMsg || "出现错误,请重试",
+      });
+    },
+  });
+};
 </script>
 
 <style lang="scss">
@@ -162,7 +222,7 @@ const toggleFlash = () => {
   background-color: #000;
   &_back {
     position: absolute;
-    width: 10px;
+    width: 24px;
     height: auto;
   }
   &_camera {

+ 4 - 4
src/pages-charge/machines/machines.vue

@@ -134,8 +134,8 @@
       class="dialog flex-align-end"
       v-if="dialogVisible && dialogType === 'status'"
     >
-      <view class="desc-dialog">
-        <view class="desc-dialog_head flex-center">
+      <view class="status-dialog">
+        <view class="status-dialog_head flex-center">
           <view class="fw-500 color-000" style="font-size: 16px"
             >选择充电桩状态</view
           >
@@ -143,7 +143,7 @@
             <uni-icons type="closeempty" size="24" color="#2D284B"></uni-icons>
           </view>
         </view>
-        <view class="desc-dialog_body">
+        <view class="status-dialog_body">
           <view class="status">
             <view
               :class="['fs-32', 'flex-align-center']"
@@ -402,7 +402,7 @@ page {
   }
 }
 
-.desc-dialog {
+.status-dialog {
   background-color: transparent;
   width: 100%;
   overflow: hidden;

+ 42 - 6
src/pages-charge/machines/price-desc/price-desc.vue

@@ -28,7 +28,7 @@
           </view>
           <view
             class="tr flex"
-            v-for="(item, index) in desc"
+            v-for="(item, index) in _desc"
             :key="index"
             :style="{
               'border-top': `1rpx solid ${
@@ -36,7 +36,18 @@
               }`,
             }"
           >
-            <view class="td flex-center">{{ item.startTimeFormat }}</view>
+            <view class="td flex-center">
+              <text>{{ item.startTimeFormat }}</text>
+              <text
+                class="ml-16 width-38 height-38 br-round fs-24 flex-center"
+                v-if="item.iconIndex >= 0"
+                :style="{
+                  color: iconColor[item.iconIndex],
+                  backgroundColor: iconBgColor[item.iconIndex],
+                }"
+                >{{ item.pricePeriod }}</text
+              ></view
+            >
             <view class="td flex-center">{{ item.elecPrice }}</view>
             <view class="td flex-center">{{ item.servicePrice }}</view>
           </view>
@@ -47,16 +58,43 @@
 </template>
 
 <script lang="ts">
-export default {
+import { defineComponent } from "vue";
+export default defineComponent({
   props: {
     desc: Array<any>,
   },
+  data() {
+    return {
+      _desc: [],
+      iconText: ["谷", "平", "峰", "尖"],
+      iconBgColor: [
+        "rgba(0, 218, 179, 0.20)",
+        "rgba(52, 125, 255, 0.20)",
+        "rgba(255, 153, 0, 0.20)",
+        "rgba(255, 46, 0, 0.20)",
+      ],
+      iconColor: ["#00DAB3", "#347DFF", "#FF9900", "#FF2E00"],
+    };
+  },
+  mounted() {
+    console.log(this.desc);
+    if (this.desc && this.desc.length) {
+      this._desc = this.desc.map((item) => {
+        return {
+          ...item,
+          iconIndex: this.iconText.findIndex(
+            (text) => item.pricePeriod === text
+          ),
+        };
+      });
+    }
+  },
   methods: {
     close() {
       this.$emit("close");
     },
   },
-};
+});
 </script>
 
 <style lang="scss">
@@ -83,11 +121,9 @@ export default {
   }
 
   &_body {
-    max-height: 860rpx;
     box-sizing: border-box;
     padding: 0rpx 30rpx 80rpx 30rpx;
     background-color: #fff;
-    overflow-y: auto;
 
     .table {
       border: 1rpx solid #e5e5e5;

+ 13 - 9
src/pages-charge/order/order.vue

@@ -26,7 +26,7 @@ onLoad((options: any) => {
     .then((res) => {
       const totalMoney = (res.totalMoney / 100).toFixed(2);
       const discountAmount = (res.discountAmount / 100).toFixed(2);
-      const discountAmountText = "TODO";
+      const discountAmountText = res.rightsDesc;
       const reg = new RegExp("\B(?=(\d{3})+(?!\d))", "g");
       const start = new Date(res.startTime.replace(/-/g, "/"));
       const end = new Date(res.endTime.replace(/-/g, "/"));
@@ -38,7 +38,7 @@ onLoad((options: any) => {
               `${min - parseInt(`${min / 60}`) * 60}`
             )}分钟`
           : `${parseInt(`${diff / 60}`)}分钟`;
-      list.value = [
+      const _list = [
         {
           label: "累计充电量",
           value: `${res.totalPower}度`,
@@ -47,16 +47,10 @@ onLoad((options: any) => {
           label: "订单金额",
           value: `${totalMoney.replace(reg, ",")}元`,
         },
-        {
-          label: "优惠金额",
-          value: `${
-            Number(discountAmount) <= 0 ? "" : "-"
-          }${discountAmount}元${discountAmountText}`,
-          color: "#F43636",
-        },
         {
           label: "开始时间",
           value: res.startTime,
+          color: "",
         },
         {
           label: "结束时间",
@@ -67,6 +61,16 @@ onLoad((options: any) => {
           value: time,
         },
       ];
+      if (Number(discountAmount) > 0) {
+        _list.splice(2, 0, {
+          label: "优惠金额",
+          value: `${
+            Number(discountAmount) <= 0 ? "" : "-"
+          }${discountAmount}元${discountAmountText}`,
+          color: "#F43636",
+        });
+      }
+      list.value = _list;
       price.value = (res.payAmount / 100).toFixed(2);
     })
     .catch(() => {

BIN
src/pages-charge/static/camera-back.png


+ 81 - 0
src/pages-common/activity/activity.vue

@@ -0,0 +1,81 @@
+<template>
+  <view class="page pl-32 pr-32 pt-32">
+    <swiper
+      class="swiper"
+      circular
+      :indicator-dots="true"
+      :autoplay="true"
+      :interval="3000"
+    >
+      <swiper-item
+        class="full-percent"
+        v-for="(item, index) in banner"
+        :key="index"
+        @click="back"
+      >
+        <view
+          class="full-percent"
+          :style="{
+            backgroundImage: `url(${item.bannerUrl})`,
+          }"
+        ></view>
+      </swiper-item>
+    </swiper>
+    <view class="fs-32 fw-500 color-000 pt-40">活动说明</view>
+    <view class="mt-32">
+      <view
+        class="mt-24 fs-28 color-666"
+        v-for="(item, index) in desc"
+        :key="index"
+        >{{ item }}</view
+      >
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { back } from "../../utils/navigate";
+import { onLoad } from "@dcloudio/uni-app";
+import { ref } from "vue";
+
+const desc = ref([]);
+const banner = ref<any[]>([]);
+
+onLoad((options: any) => {
+  if (
+    getApp<any>().globalData.user &&
+    getApp<any>().globalData.user.activityList &&
+    getApp<any>().globalData.user.activityList.length
+  ) {
+    const activity = getApp<any>().globalData.user.activityList.find(
+      (item) => item.id === options.id
+    );
+    uni.setNavigationBarTitle({
+      title: activity.name,
+    });
+    desc.value = activity.activityDesc.split("\n");
+    banner.value = activity.bannerList;
+    uni.hideLoading();
+  } else {
+    back();
+  }
+});
+</script>
+
+<style lang="scss">
+.page {
+  min-height: 100vh;
+  background-color: #fff;
+  .swiper {
+    height: 176rpx;
+    width: 100%;
+    border-radius: 16rpx;
+    overflow: hidden;
+    view {
+      background-position: center;
+      background-repeat: no-repeat;
+      background-size: cover;
+    }
+  }
+}
+</style>

+ 41 - 13
src/pages-user/wallet-recharge/wallet-recharge.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="pl-30 pr-30">
     <view class="pay">
-      <view class="title">充值金额</view>
+      <view class="title pt-30 pb-30">充值金额</view>
       <view class="flex-wrap">
         <view
           :class="[
@@ -13,11 +13,24 @@
           :key="index"
           @click="changeOption(index)"
         >
-          <view class="tag fs-26 color-fff fw-500">充电服务费9折</view>
+          <view
+            class="tag fs-24 color-fff fw-500"
+            v-if="payOptionsDiscount[index]"
+            >{{ payOptionsDiscount[index] }}</view
+          >
           {{ item }}
         </view>
       </view>
-      <view class="title">自定义金额</view>
+      <view v-if="payOptionsDiscountDay[payOption]" class="flex-align-center">
+        <view class="fs-30 color-666"
+          >折扣优惠有效期{{ payOptionsDiscountDay[payOption] }}天</view
+        >
+        <view class="ml-12 color-primary fs-30" @click="toDesc">
+          <text>详细规则</text>
+          <text class="fs-24 ml-6">>></text>
+        </view>
+      </view>
+      <view class="title pt-60 pb-30">自定义金额</view>
       <style-input
         :value="payValue > 0 ? payValue : ''"
         title="金额"
@@ -37,14 +50,17 @@
 </template>
 
 <script setup lang="ts">
-// TODO 充值优惠
 import { ref } from "vue";
 import { fetchProfile, insertMoney } from "../../api/user";
 import { onLoad } from "@dcloudio/uni-app";
+import { to } from "@/utils/navigate";
 const balance = ref(0);
-const payOption = ref(1);
-const payOptions = ref([50, 100, 200, 500, 1000]);
+const payOption = ref(0);
+const payOptions = ref([30, 50, 100, 200, 500, 1000]);
+const payOptionsDiscount = ref(["", "", "", "", "", ""]);
+const payOptionsDiscountDay = ref([0, 0, 0, 0, 0, 0]);
 const payValue = ref(0);
+const activityId = ref();
 const input = (e: any) => {
   payValue.value = e.value;
 };
@@ -94,23 +110,34 @@ const confirm = () => {
       });
     });
 };
+const toDesc = () => {
+  to(`/pages-common/activity/activity?id=${activityId.value}&back=1`);
+};
 onLoad(() => {
-  const user = getApp<any>().globalData.user;
-  if (user) {
-    balance.value = user.balance;
-  }
+  fetchProfile().then((res) => {
+    // console.log(res);
+    balance.value = res.balance;
+    if (res && res.activityList && res.activityList.length) {
+      res.activityList[0].rechargeRightsList.forEach((item: any) => {
+        const val = Number((Number(item.amountMin) / 100).toFixed(2));
+        const fi = payOptions.value.findIndex((o) => o === val);
+        if (fi >= 0) {
+          payOptionsDiscount.value[fi] = item.rightsDesc;
+          payOptionsDiscountDay.value[fi] = item.validity;
+        }
+      });
+      activityId.value = res.activityList[0].id;
+    }
+  });
 });
 </script>
 
 <style lang="scss">
 .pay {
-  padding-top: 20rpx;
   .title {
     font-weight: 500;
     font-size: 32rpx;
     color: #000;
-    padding-bottom: 30rpx;
-    padding-top: 40rpx;
   }
 
   .option {
@@ -136,6 +163,7 @@ onLoad(() => {
       box-sizing: content-box;
       padding: 2rpx 10rpx;
       background: linear-gradient(90deg, #f366ff 0%, #5e98ff 100%);
+      white-space: nowrap;
     }
   }
   .option-active {

+ 8 - 0
src/pages.json

@@ -141,6 +141,14 @@
             "navigationBarTitleText": "开发票",
             "navigationBarBackgroundColor": "#F6F7FA"
           }
+        },
+        {
+          "path": "activity/activity",
+          "style": {
+            "navigationStyle": "default",
+            "navigationBarTitleText": "",
+            "navigationBarBackgroundColor": "#ffffff"
+          }
         }
       ]
     }

+ 86 - 19
src/pages/map/map.vue

@@ -33,7 +33,7 @@
             ></uni-icons>
           </view>
         </view>
-        <view class="width-half flex-center" @click.stop="checkDiscounts">
+        <view class="width-half flex-center" style="opacity: 0">
           <view
             class="width-32 height-32 br-round lh-20 text-center"
             :style="{
@@ -90,8 +90,7 @@
           >
         </view>
       </view>
-      <!-- <view class="dialog_event" v-if="ready && !filterDialog.distanceSelector">
-        // TODO 接入活动接口
+      <view class="dialog_event" v-if="ready && !filterDialog.distanceSelector">
         <swiper
           class="swiper"
           circular
@@ -99,14 +98,21 @@
           :autoplay="true"
           :interval="3000"
         >
-          <swiper-item class="full-percent">
-            <view class="full-percent bg-666"></view>
-          </swiper-item>
-          <swiper-item class="full-percent">
-            <view class="full-percent bg-fff"></view>
+          <swiper-item
+            class="full-percent"
+            v-for="(item, index) in mapBanner"
+            :key="index"
+            @click="toActivity(index)"
+          >
+            <view
+              class="full-percent"
+              :style="{
+                backgroundImage: `url(${item.bannerUrl})`,
+              }"
+            ></view>
           </swiper-item>
         </swiper>
-      </view> -->
+      </view>
     </view>
     <view
       v-if="styleData.dialogPlaceHolderHeight"
@@ -214,6 +220,20 @@
         </view>
       </block>
     </view>
+    <view
+      class="charging flex-align-center"
+      v-if="charging"
+      @click="toCharging"
+    >
+      <image
+        class="width-64 ml-12"
+        src="/static/images/map-charging.png"
+        mode="widthFix"
+      ></image>
+      <view class="fs-26 color-fff ml-12">{{
+        charging.isBooking === 0 ? "充电中" : "已预约"
+      }}</view>
+    </view>
   </view>
   <view class="login-mask" v-if="!token">
     <button open-type="getPhoneNumber" @getphonenumber="loginMask" class="full">
@@ -237,18 +257,17 @@ const pointSize = {
   androidX: -14,
   androidCurrentX: -20,
 };
+import { fetchHomeBanner } from "@/api";
 import { deCode } from "../../utils/code";
 import { rpxToPx } from "../../utils/device";
 import { fetchToken, login, onLogin } from "@/api/auth";
-import { fetchStations } from "@/api/charge";
+import { fetchStations, fetchChargeStatus } from "@/api/charge";
 import { fetchCollectList } from "@/api/user";
 import { fetchLocation } from "@/utils/location";
+import { to } from "@/utils/navigate";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 
-// TODO 支持省钱充电
-// TODO 充电中
-
 const isIOS = ref(false);
 const token = ref<string>();
 const ready = ref(false);
@@ -328,6 +347,7 @@ const stationPage = ref({
   hasNext: false,
 });
 const station = ref<any[]>([]);
+const charging = ref<any>();
 
 const mapMode = ref(true);
 const mapProps = ref({
@@ -339,6 +359,7 @@ const mapProps = ref({
 });
 const markersIndex = ref(-1);
 const markers = ref<any[]>([]);
+const mapBanner = ref<any[]>([]);
 
 let isIgnoreChangeLocation = false;
 
@@ -473,13 +494,15 @@ const handleNavReady = (e: any) => {
     e.detail.statusBarHeight - 6 + searchHeight + filterHeight;
   styleData.value.dialogPlaceHolderHeight =
     styleData.value.dialogHeight - e.detail.navigationBarHeight;
-  styleData.value.cardHeight = rpxToPx(410);
+  styleData.value.cardHeight = rpxToPx(402);
 };
 
 const toSearch = () => {
-  uni.navigateTo({
-    url: "/pages-charge/search/search",
-  });
+  to("/pages-charge/search/search");
+};
+
+const toActivity = (index: number) => {
+  to(`/${mapBanner.value[index].linkUrl}`);
 };
 
 onLoad((query: any) => {
@@ -522,6 +545,8 @@ onLoad((query: any) => {
         token.value = _token;
         fetchCollectList().then(() => {
           refresh();
+          fetchCharging();
+          fetchBanner();
         });
       });
       return;
@@ -533,17 +558,33 @@ onLoad((query: any) => {
         deCode(code);
       }
       refresh();
+      fetchCharging();
+      fetchBanner();
     });
   }, 300);
 });
 
+const fetchCharging = () => {
+  fetchChargeStatus().then((res) => {
+    if (res && [1, 2].includes(res.chargeStatus)) {
+      charging.value = res;
+    }
+  });
+};
+
+const fetchBanner = () => {
+  fetchHomeBanner().then((res) => {
+    mapBanner.value = res;
+  });
+};
+
 const checkDiscounts = () => {
   filterDialog.value.discounts = !filterDialog.value.discounts;
 };
 
 const checkFilterDistance = () => {
   if (!mapMode.value) {
-    mapMode.value = true
+    mapMode.value = true;
   }
   filterDialog.value.distanceSelector = !filterDialog.value.distanceSelector;
 };
@@ -670,6 +711,14 @@ const touchCardMove = (e: any) => {
   }
 };
 
+const toCharging = () => {
+  to(
+    charging.value.isBooking === 1
+      ? `/pages-charge/appointment/appointment?sn=${charging.value.connectorId}`
+      : `/pages-charge/ordering/ordering?sn=${charging.value.connectorId}&start=1`
+  );
+};
+
 // TORM
 // const changeMarker = (e: any) => {
 //   _changeMarker(e.detail.current);
@@ -717,7 +766,7 @@ page {
   top: 0;
   left: 0;
   width: 100%;
-  z-index: 999;
+  z-index: 99;
 
   &_event {
     margin-top: 20rpx;
@@ -727,6 +776,11 @@ page {
       width: 100%;
       border-radius: 16rpx;
       overflow: hidden;
+      view {
+        background-position: center;
+        background-repeat: no-repeat;
+        background-size: cover;
+      }
     }
   }
 
@@ -825,4 +879,17 @@ page {
     }
   }
 }
+
+.charging {
+  position: fixed;
+  z-index: 999;
+  right: 0;
+  bottom: 164rpx;
+  width: 186rpx;
+  height: 88rpx;
+  border-radius: 88rpx 0px 0px 88rpx;
+  background: linear-gradient(106deg, #34b6ff 15.97%, #347dff 72.38%);
+  margin-bottom: constant(safe-area-inset-bottom);
+  margin-bottom: env(safe-area-inset-bottom);
+}
 </style>

BIN
src/static/images/map-charging.png


+ 5 - 6
src/utils/constant.ts

@@ -12,11 +12,10 @@ console.log("env", env);
 isDevelopment = env === "develop" || env === "trial";
 // #endif
 
-export const isDebug = false;
+// debug
+// isDevelopment = false
 
-export const domain = isDebug
-  ? "www.kuaiyuman.cn"
-  : isDevelopment
-  ? "dev.kuaiyuman.cn"
-  : "www.kuaiyuman.cn";
+export const domain = isDevelopment ? "dev.kuaiyuman.cn" : "www.kuaiyuman.cn";
 export const host = `https://${domain}/api`;
+
+export const isDebug = true

+ 63 - 39
src/utils/uploader.ts

@@ -1,4 +1,6 @@
 import { host } from "../utils/constant";
+import Http from "../utils/http";
+const uploaderHttp = new Http(host);
 
 type UploadCallback = {
   onSuccess?(result: { url: string }): void;
@@ -49,51 +51,53 @@ export function uploadByQueue(filePath: string, callback: UploadCallback) {
 
 // 单独上传一个
 export function upload(filePath: string, callback: UploadCallback): void {
-  const uploadTask = wxUploadFile(
-    `${host}/file/upload`,
-    filePath,
-    {},
-    {
-      success: (res: any) => {
-        if (res.statusCode == 200 && res.data) {
-          try {
-            const data = JSON.parse(res.data);
-            if (data.message === "ok") {
+  uploaderHttp
+    .get("/file/getSts")
+    .then((oss) => {
+      const key =
+        "uniapp-scan-code-" +
+        guid() +
+        filePath.slice(filePath.lastIndexOf("."));
+      const uploadTask = wxUploadFile(
+        oss.host,
+        filePath,
+        {
+          key,
+          policy: oss.policy,
+          OSSAccessKeyId: oss.accesskeyId,
+          expire: oss.expire,
+          signature: oss.signature,
+          success_action_status: "200",
+        },
+        {
+          success: (res: any) => {
+            if (res.statusCode == 200 && /ok/.test(res.errMsg)) {
+              // https://kym-static.oss-cn-shenzhen.aliyuncs.com/uniapp-scan-code-41d308c3-2252-1b46-744a-104808f1c0c3.png
               callback.onSuccess &&
                 callback.onSuccess({
-                  url: data.data.url,
+                  url: `${oss.host}/${key}`,
                 });
             } else {
               callback.onFail &&
-              callback.onFail({
-                errMsg: data.message,
-              });
+                callback.onFail({
+                  errMsg: `update error(${JSON.stringify(res)})`,
+                });
             }
-          } catch (error) {
-            callback.onFail &&
-              callback.onFail({
-                errMsg: `update error JSON.parse`,
-              });
-          }
-        } else {
-          callback.onFail &&
-            callback.onFail({
-              errMsg: `update error(${JSON.stringify(res)})`,
-            });
+          },
+          fail: callback.onFail,
+          complete: () => {
+            // 取消监听
+            callback.onProgressUpdate &&
+              uploadTask.offProgressUpdate(callback.onProgressUpdate);
+          },
         }
-      },
-      fail: callback.onFail,
-      complete: () => {
-        // 取消监听
-        callback.onProgressUpdate &&
-          uploadTask.offProgressUpdate(callback.onProgressUpdate);
-      },
-    }
-  );
-  callback.onStart && callback.onStart(uploadTask);
-  if (callback.onProgressUpdate) {
-    uploadTask.onProgressUpdate(callback.onProgressUpdate);
-  }
+      );
+      callback.onStart && callback.onStart(uploadTask);
+      if (callback.onProgressUpdate) {
+        uploadTask.onProgressUpdate(callback.onProgressUpdate);
+      }
+    })
+    .catch(callback.onFail);
 }
 
 function wxUploadFile(
@@ -106,7 +110,7 @@ function wxUploadFile(
     url,
     filePath,
     header: {
-      satoken: getApp<any>().globalData.token || "",
+      // satoken: getApp<any>().globalData.token || "",
     },
     name: "file",
     formData,
@@ -125,3 +129,23 @@ function wxUploadFile(
     },
   });
 }
+
+function guid() {
+  function S4() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+  }
+  return (
+    S4() +
+    S4() +
+    "-" +
+    S4() +
+    "-" +
+    S4() +
+    "-" +
+    S4() +
+    "-" +
+    S4() +
+    S4() +
+    S4()
+  );
+}