needcode преди 2 години
родител
ревизия
1e922bb820

+ 66 - 7
src/api/charge.ts

@@ -2,18 +2,31 @@ import Http from "../utils/http";
 import { host, isDebug } from "../utils/constant";
 const cHttp = new Http(host);
 
-export function startCharge(sn: string) {
+export function startCharge(sn: string, query?: string) {
   return cHttp.get<{
     ConnectorID: string;
     FailReason: number;
     StartChargeSeq: string;
     StartChargeSeqStat: number;
     SuccStat: number;
-  }>(`/charge/startCharge/${sn}`, {
+  }>(`/charge/startCharge/${sn}?${query}`, {
     statusCodeHandle: false,
   });
 }
 
+export async function cancelAppointmentCharge() {
+  return cHttp.get("/charge/cancelBooking");
+}
+
+export async function changeAppointmentTime(
+  startChargeSeq: string,
+  startTime: string
+) {
+  return cHttp.get(
+    `/charge/modifyBookingTime?startChargeSeq=${startChargeSeq}&startTime=${startTime}`
+  );
+}
+
 export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
   return cHttp.get(`/charge/businessPolicy/${ConnectorID}`).then((res) => {
     const nowHour = new Date().getHours();
@@ -33,7 +46,7 @@ export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
         let tempPrice = Number(
           Number(item.elecPrice + item.servicePrice).toFixed(2)
         );
-        item.totalPrice = tempPrice
+        item.totalPrice = tempPrice;
         if (tempPrice > maxPrice) {
           maxPrice = tempPrice;
         }
@@ -81,10 +94,56 @@ export function cancelCharge(sn: string) {
   });
 }
 
-export function fetchChargeStatus() {
-  return cHttp.get("/charge/chargeStatus", {
-    statusCodeHandle: false,
-  });
+export function fetchChargeStatus(
+  checkAppointment?: boolean,
+  checkCharge?: boolean
+) {
+  return cHttp
+    .get("/charge/chargeStatus", {
+      statusCodeHandle: false,
+    })
+    .then((res) => {
+      if (checkAppointment && res && res.isBooking === 1) {
+        uni.hideLoading();
+        uni.showModal({
+          title: "温馨提示",
+          content: "当前已有预约中的订单,请取消再扫码充电",
+          showCancel: false,
+          confirmText: "查看预约",
+          confirmColor: "#347DFF",
+          success(modal) {
+            if (modal.confirm) {
+              uni.redirectTo({
+                url: `/pages-charge/appointment/appointment?sn=${res.connectorId}`,
+              });
+            }
+          },
+        });
+      }
+      if (
+        checkCharge &&
+        res &&
+        res.isBooking === 0 &&
+        [1, 2].includes(res.chargeStatus)
+      ) {
+        uni.hideLoading();
+        uni.showModal({
+          title: "温馨提示",
+          content: "当前已有进行中的订单,请结束订单再扫码充电",
+          showCancel: false,
+          confirmText: "查看当前",
+          confirmColor: "#347DFF",
+          success(modal) {
+            if (modal.confirm) {
+              uni.redirectTo({
+                url: `/pages-charge/ordering/ordering?sn=${res.connectorId}&start=1`,
+              });
+            }
+          },
+        });
+      }
+      return res;
+    });
 }
 
 export function fetchStations(

+ 1 - 1
src/components/style-dialog/style-dialog.vue

@@ -61,7 +61,7 @@ export default {
     }
   }
   &_body {
-    max-height: 800rpx;
+    max-height: 1000rpx;
     overflow-y: auto;
   }
 }

+ 414 - 94
src/pages-charge/appointment/appointment.vue

@@ -20,7 +20,10 @@
         </view>
       </view>
       <view class="mt-40 color-999 fs-32 fw-500">费用说明</view>
-      <view class="mt-20 block height-96 flex-align-center pl-30 pr-30">
+      <view
+        class="mt-20 block height-96 flex-align-center pl-30 pr-30"
+        @click="openPriceDesc"
+      >
         <view class="fs-26 color-666">充电费用</view>
         <view class="ml-64 fs-26 color-333"
           >{{ priceInfo.minPrice }}~{{ priceInfo.maxPrice }}元/度</view
@@ -29,70 +32,129 @@
           <uni-icons type="right" size="16" color="rgba(0,0,0,0.4)"></uni-icons>
         </view>
       </view>
-      <view class="mt-40 color-999 fs-32 fw-500">选择充电方式</view>
-      <view class="mt-20 block pl-30 pr-30">
-        <view
-          v-for="(type, index) in chargeTypes"
-          :key="index"
-          :class="['pt-40', 'pb-40', 'flex-align-center']"
-          :style="{
-            borderTop: index === 0 ? '' : '1rpx solid rgba(0, 0, 0, 0.10)',
-          }"
-          @click="changeType(index)"
-        >
-          <view>
-            <view class="fs-28 lh-28 color-000 fw-500">{{ type.title }}</view>
-            <view class="fs-24 color-999 lh-24 mt-16" v-if="type.tip">{{
-              type.tip
-            }}</view>
-          </view>
-          <view class="ml-auto">
-            <style-checkbox :checked="chargeType === index"></style-checkbox>
-          </view>
-        </view>
-      </view>
-      <view class="mt-20 block pl-30 pr-30">
-        <view
-          class="pt-40 pb-40 flex-between"
-          style="border-bottom: 1rpx solid rgba(0, 0, 0, 0.1)"
-          @click="selectTime"
-        >
-          <view class="fs-28 color-000 fw-500">充电时间</view>
-          <view class="flex-align-center lh-28">
-            <view
-              v-if="chargeTime.format"
-              class="fs-28 color-333 fw-500 mr-16"
-              >{{ chargeTime.format }}</view
-            >
-            <view v-else class="fs-26 mr-16" style="color: #cacaca"
-              >请选择</view
+      <template v-if="appointmentData">
+        <view class="mt-40 color-999 fs-32 fw-500">已预约充电</view>
+        <view class="mt-20 block flex-align-center" style="height: 180rpx">
+          <image
+            class="width-56 ml-30"
+            src="/pages-charge/static/icon-alarm.png"
+            mode="widthFix"
+          ></image>
+          <view class="ml-24">
+            <view class="flex" v-if="appointmentCountDown">
+              <view class="fs-28 color-000">将在</view>
+              <view class="fs-44 lh-36 color-primary ml-8 mr-8">{{
+                appointmentCountDown
+              }}</view>
+              <view class="fs-28 color-000">后开始充电</view>
+            </view>
+            <view class="fs-24 color-999 mt-8"
+              >请在{{ appointmentData.startTime }}前到达充电桩并开始充电</view
             >
-            <uni-icons type="right" size="16" color="#CACACA"></uni-icons>
           </view>
         </view>
-        <view class="pt-40 pb-40 flex-between">
-          <view class="fs-28 color-000 fw-500">预计费用</view>
-          <view class="flex-align-center lh-28">
-            <view
-              v-if="chargeTime.formatPrice"
-              class="fs-28 color-333 fw-500"
-              >{{ chargeTime.formatPrice }}</view
-            >
-            <view v-else class="fs-26 mr-16" style="color: #cacaca"
-              >选择时间后显示</view
-            >
+        <view class="mt-40 flex-center">
+          <view
+            class="flex-center height-68 br-68 fs-26 color-666"
+            style="width: 184rpx; border: 1rpx solid rgba(0, 0, 0, 0.3)"
+            @click="cancelAppointment"
+            >取消预约</view
+          >
+        </view>
+      </template>
+      <template v-else>
+        <view class="mt-40 color-999 fs-32 fw-500">选择充电方式</view>
+        <view class="mt-20 block pl-30 pr-30">
+          <view
+            v-for="(type, index) in chargeTypes"
+            :key="index"
+            :class="['pt-40', 'pb-40', 'flex-align-center']"
+            :style="{
+              borderTop: index === 0 ? '' : '1rpx solid rgba(0, 0, 0, 0.10)',
+            }"
+            @click="changeType(index)"
+          >
+            <view>
+              <view class="fs-28 lh-28 color-000 fw-500">{{ type.title }}</view>
+              <view class="fs-24 color-999 lh-24 mt-16" v-if="type.tip">{{
+                type.tip
+              }}</view>
+            </view>
+            <view class="ml-auto">
+              <style-checkbox :checked="chargeType === index"></style-checkbox>
+            </view>
           </view>
         </view>
-        <view class="pb-24 fs-24 color-primary"
+        <view class="mt-20 block pl-30 pr-30">
+          <view
+            class="pt-40 pb-40 flex-between"
+            style="border-bottom: 1rpx solid rgba(0, 0, 0, 0.1)"
+            @click="selectTime"
+          >
+            <view class="fs-28 color-000 fw-500">充电时间</view>
+            <view class="flex-align-center lh-28">
+              <view
+                v-if="chargeTime.format"
+                class="fs-28 color-333 fw-500 mr-16"
+                >{{ chargeTime.format }}</view
+              >
+              <view v-else class="fs-26 mr-16" style="color: #cacaca"
+                >请选择</view
+              >
+              <uni-icons type="right" size="16" color="#CACACA"></uni-icons>
+            </view>
+          </view>
+          <view class="pt-40 pb-40 flex-between">
+            <view class="fs-28 color-000 fw-500">预计费用</view>
+            <view class="flex-align-center lh-28">
+              <view
+                v-if="chargeTime.formatPrice"
+                class="fs-28 color-333 fw-500"
+                >{{ chargeTime.formatPrice }}</view
+              >
+              <view v-else class="fs-26 mr-16" style="color: #cacaca"
+                >选择时间后显示</view
+              >
+            </view>
+          </view>
+          <!-- <view class="pb-24 fs-24 color-primary"
           >{{ priceInfo.minPriceTime }}充电,电费低至{{
             priceInfo.minPrice
           }}元/kwh</view
-        >
-      </view>
+        > -->
+        </view>
+        <view class="mt-20 block flex-align-center pl-30 pr-30 pt-30 pb-30">
+          <view class="flex-column">
+            <view class="fs-28 lh-28 color-000 fw-500">省电模式</view>
+            <view class="fs-24 lh-30 color-999 mt-8"
+              >处于00:00-08:00时,电费低至{{ priceInfo.minPrice }}元/kwh</view
+            >
+          </view>
+          <view class="ml-auto">
+            <switch
+              :checked="chargeTime.isPowerSaving"
+              color="#347DFF"
+              @change="changePowerSaving"
+            />
+          </view>
+        </view>
+      </template>
       <view class="pt-60 pb-80"></view>
       <style-bottom-view>
-        <view class="pt-20 pl-40 pr-40 pb-20 bg-fff">
-          <style-button type="primary" size="small" @click="submit">{{
+        <view class="pt-20 pl-40 pr-40 pb-20 bg-fff flex">
+          <template v-if="appointmentData">
+            <view class="mr-10" style="width: 50%">
+              <style-button size="small" @click="selectTime"
+                >修改时间</style-button
+              ></view
+            >
+            <view class="ml-10" style="width: 50%">
+              <style-button type="primary" size="small" @click="submitNow"
+                >立即开始</style-button
+              >
+            </view>
+          </template>
+          <style-button v-else type="primary" size="small" @click="submit">{{
             chargeType === 0 ? "提交申请" : "马上充电"
           }}</style-button>
         </view>
@@ -106,7 +168,7 @@
       <view class="flex" style="border-top: 1rpx solid rgba(0, 0, 0, 0.1)">
         <view
           class="flex-shrink"
-          style="height: 714rpx; width: 256rpx; background-color: #f0f0f0"
+          style="height: 840rpx; width: 256rpx; background-color: #f0f0f0"
         >
           <view
             class="flex-align-center pl-32 height-90"
@@ -116,7 +178,7 @@
               backgroundColor:
                 day.format === chargeTime.day ? '#fff' : 'transparent',
             }"
-            @click="changeTime(index)"
+            @click="changeDay(index)"
           >
             <view
               :class="[
@@ -134,16 +196,17 @@
             >
           </view>
         </view>
-        <view class="flex-grow" style="height: 714rpx; overflow-y: auto">
+        <view class="flex-grow" style="height: 840rpx; overflow-y: auto">
           <view
             class="flex-align-center pl-40 height-90 fs-32"
-            v-for="(hour, index) in timesInfo.time"
+            v-for="(hour, index) in timesInfo.hour"
             :key="index"
             :style="{
-              color:
-                hour.format === chargeTime.hour
-                  ? 'var(--color-primary)'
-                  : '#000',
+              color: hour.disabled
+                ? '#999'
+                : hour.format === chargeTime.hour
+                ? 'var(--color-primary)'
+                : '#000',
             }"
             @click="changeHour(index)"
           >
@@ -152,20 +215,34 @@
         </view>
       </view>
     </style-dialog>
+    <PriceDesc
+      v-if="priceDescVisible"
+      :desc="priceInfo.policyInfos || []"
+      @close="closePriceDesc"
+    ></PriceDesc>
   </view>
 </template>
 
 <script setup lang="ts">
-import { fetchStationByConnectorId, fetchStationPriceDesc } from "@/api/charge";
+import {
+  fetchChargeStatus,
+  fetchStationByConnectorId,
+  fetchStationPriceDesc,
+  startCharge,
+  cancelAppointmentCharge,
+  changeAppointmentTime,
+} from "@/api/charge";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 import ChargeMachine from "../machines/charge-machine/charge-machine.vue";
+import PriceDesc from "../machines/price-desc/price-desc.vue";
 import { format } from "@/utils/date";
 
 const DAY = 24 * 60 * 60 * 1000;
 const options = ref<any>();
 const data = ref<any>();
 const priceInfo = ref();
+const priceDescVisible = ref(false);
 const timesInfo = ref<any>({
   day: [],
   time: [],
@@ -183,120 +260,363 @@ const chargeTypes = ref([
 ]);
 const chargeTimeDialog = ref(false);
 const chargeTime = ref({
+  isPowerSaving: false, // 省电模式
   time: 0, // 时间戳
   day: "",
   hour: "",
   format: "",
   formatPrice: "",
 });
+const appointmentData = ref();
+const appointmentCountDown = ref();
 
 const changeType = (index: number) => {
   chargeType.value = index;
 };
 
+const isPassTime = (hour: string, time: number) => {
+  const now = new Date();
+  const _hour = Number(hour.substring(0, 2));
+  if (typeof _hour !== "number") {
+    return true;
+  }
+  return now.getHours() >= _hour && now.getDate() === Number(format("d", time));
+};
+
 const selectTime = () => {
-  if (chargeType.value === 1) {
+  if (!appointmentData.value && chargeType.value === 1) {
     uni.showToast({
       title: "请选择预约模式",
       icon: "none",
     });
     return;
   }
-  chargeTimeDialog.value = true;
-  const now = new Date();
-  const today = format("M月d日", now.getTime());
-  const tomorrow = format("M月d日", now.getTime() + DAY);
+  const now = appointmentData.value
+    ? new Date(appointmentData.value.startTime.replace(/-/g, "/"))
+    : new Date();
   const year = format("y", now.getTime());
   const nextyear = format("y", now.getTime() + DAY);
 
-  // 天
+  // 天
   timesInfo.value.day = [
     {
       time: now.getTime(),
-      format: today,
+      format: format("M月d日", now.getTime()),
       year: "",
     },
     {
       time: now.getTime() + DAY,
-      format: tomorrow,
+      format: format("M月d日", now.getTime() + DAY),
       year: year === nextyear ? "" : nextyear.slice(2),
     },
   ];
   // 时间
-  timesInfo.value.time = priceInfo.value.policyInfos.map((item: any) => {
+  timesInfo.value.hour = priceInfo.value.policyInfos.map((item: any) => {
     return {
       format: item.startTime,
       formatPrice: item.totalPrice,
+      disabled: isPassTime(
+        item.startTime,
+        chargeTime.value.time ? chargeTime.value.time : now.getTime()
+      ),
     };
   });
-  if (!chargeTime.value.day) {
+
+  // 预约时间
+  if (!appointmentData.value && !chargeTime.value.day) {
     chargeTime.value.time = timesInfo.value.day[0].time;
     chargeTime.value.day = timesInfo.value.day[0].format;
-    // chargeTime.value.hour = timesInfo.value.time[0].format;
-    // chargeTime.value.formatPrice = timesInfo.value.time[0].formatPrice;
   }
-  // console.log(chargeTime.value)
+  // 修改时间
+  if (appointmentData.value) {
+    chargeTime.value.time = timesInfo.value.day[0].time;
+    chargeTime.value.day = timesInfo.value.day[0].format;
+    const findIndex = timesInfo.value.hour.findIndex(
+      (item: any) => item.format === format("h:m:s", now.getTime())
+    );
+    if (findIndex >= 0) {
+      chargeTime.value.hour = timesInfo.value.hour[findIndex].format;
+      chargeTime.value.formatPrice =
+        timesInfo.value.hour[findIndex].formatPrice;
+    }
+  }
+  chargeTimeDialog.value = true;
 };
 
-const changeTime = (index: number) => {
+const changeDay = (index: number) => {
   chargeTime.value.time = timesInfo.value.day[index].time;
   chargeTime.value.day = timesInfo.value.day[index].format;
   if (chargeTime.value.hour) {
-    chargeTime.value.format = `${format("y年M月d日", chargeTime.value.time)} ${
-      chargeTime.value.hour
-    }`;
+    chargeTime.value.hour = "";
+    chargeTime.value.formatPrice = "";
   }
+  timesInfo.value.hour = priceInfo.value.policyInfos.map((item: any) => {
+    return {
+      format: item.startTime,
+      formatPrice: item.totalPrice,
+      disabled: isPassTime(item.startTime, chargeTime.value.time),
+    };
+  });
 };
 
 const changeHour = (index: number) => {
-  chargeTime.value.hour = timesInfo.value.time[index].format;
+  if (timesInfo.value.hour[index].disabled) {
+    uni.showToast({
+      title: "无法选择过去的时间",
+      icon: "none",
+    });
+    return;
+  }
+  if (appointmentData.value) {
+    // 修改时间
+    uni.showModal({
+      title: "温馨提示",
+      content: `确认修改为${timesInfo.value.hour[index].format}吗?`,
+      confirmText: "确定",
+      confirmColor: "#347DFF",
+      success(modal) {
+        if (modal.confirm) {
+          uni.showLoading({
+            title: "提交中",
+            mask: true,
+          });
+          changeAppointmentTime(
+            appointmentData.value.startChargeSeq,
+            `${format("y-M-d", chargeTime.value.time)} ${
+              timesInfo.value.hour[index].format
+            }`
+          )
+            .then(() => {
+              return fetchChargeStatus();
+            })
+            .then((res) => {
+              uni.hideLoading();
+              if (res && res.isBooking === 1) {
+                uni.showToast({
+                  icon: "success",
+                  title: "修改成功",
+                });
+                closeTime();
+                appointmentData.value = res;
+                startAppointmentCountDown();
+              }
+            });
+        }
+      },
+    });
+    return;
+  }
+  chargeTime.value.hour = timesInfo.value.hour[index].format;
   chargeTime.value.format = `${format("y年M月d日", chargeTime.value.time)} ${
     chargeTime.value.hour
   }`;
-  chargeTime.value.formatPrice = timesInfo.value.time[index].formatPrice;
+  chargeTime.value.formatPrice = timesInfo.value.hour[index].formatPrice;
+  closeTime();
+};
+
+const changePowerSaving = (e: any) => {
+  chargeTime.value.isPowerSaving = e.detail.value;
 };
 
 const closeTime = () => {
   chargeTimeDialog.value = false;
+  if (appointmentData.value) {
+    return;
+  }
   if (!chargeTime.value.hour) {
-    chargeTime.value.time = 0;
-    chargeTime.value.day = "";
+    chargeTime.value = {
+      time: 0, // 时间戳
+      day: "",
+      hour: "",
+      isPowerSaving: chargeTime.value.isPowerSaving, // 省电模式
+      format: "",
+      formatPrice: "",
+    };
+  }
+};
+
+const openPriceDesc = () => {
+  priceDescVisible.value = true;
+};
+
+const closePriceDesc = () => {
+  priceDescVisible.value = false;
+};
+
+const cancelAppointment = () => {
+  uni.showModal({
+    title: "取消预约",
+    content: "确定取消预约吗?",
+    cancelText: "取消预约",
+    cancelColor: "#999999",
+    confirmText: "点错了",
+    confirmColor: "#347DFF",
+    success: (res) => {
+      if (res.cancel) {
+        uni.showLoading({
+          title: "提交中",
+          mask: true,
+        });
+        cancelAppointmentCharge()
+          .then(() => {
+            uni.hideLoading();
+            uni.showToast({
+              icon: "success",
+              title: "已取消",
+            });
+            appointmentData.value = undefined;
+            startAppointmentCountDown();
+          })
+          .catch((err) => {
+            uni.hideLoading();
+          });
+      }
+    },
+  });
+};
+
+let appointmentCountDownTimer = 0;
+
+const startAppointmentCountDown = () => {
+  appointmentCountDownTimer && clearTimeout(appointmentCountDownTimer);
+  if (!appointmentData.value) {
+    appointmentCountDown.value = "";
+    return;
   }
+  appointmentCountDown.value = formatAppointmentCountDown(
+    appointmentData.value.startTime
+  );
+  appointmentCountDownTimer = setTimeout(() => {
+    startAppointmentCountDown();
+  }, 1000);
+};
+
+const formatAppointmentCountDown = (time: string) => {
+  const now = new Date();
+  const date = new Date(time.replace(/-/g, "/"));
+  let secondTime = parseInt(`${(date.getTime() - now.getTime()) / 1000}`);
+  let hourTime = 0;
+  let minuteTime = 0; // 分
+  if (secondTime >= 60) {
+    minuteTime = parseInt(`${secondTime / 60}`);
+    secondTime = parseInt(`${secondTime % 60}`);
+    if (minuteTime >= 60) {
+      hourTime = parseInt(`${minuteTime / 60}`);
+      minuteTime = parseInt(`${minuteTime % 60}`);
+    }
+  }
+  return `${hourTime < 10 ? "0" + hourTime : hourTime}:${
+    minuteTime < 10 ? "0" + minuteTime : minuteTime
+  }:${secondTime < 10 ? "0" + secondTime : secondTime}`;
 };
 
 const submit = () => {
-  if (chargeType.value === 2 && !chargeTime.value.hour) {
+  if (chargeType.value === 0 && !chargeTime.value.hour) {
     uni.showToast({
       title: "请选择充电时间",
       icon: "none",
     });
     return;
   }
-  // TODO 提交接口
+  const now = new Date();
+  let startTime = chargeTime.value.time;
+  if (chargeTime.value.isPowerSaving) {
+    // 省电模式
+    if (
+      now.getHours() >= 8 &&
+      now.getDate() === Number(format("d", chargeTime.value.time))
+    ) {
+      startTime += DAY;
+    }
+  }
+  let query = "";
+  if (chargeType.value === 0) {
+    query += "isBooking=true";
+    query += `&startTime=${format("y-M-d", startTime)} ${
+      chargeTime.value.isPowerSaving ? "00:00:00" : chargeTime.value.hour
+    }`;
+    if (chargeTime.value.isPowerSaving) {
+      query += `&endTime=${format("y-M-d", startTime)} 08:00:00`;
+    }
+  }
+  if (chargeType.value === 1) {
+    query += "isBooking=false";
+  }
+  console.log(query);
+  uni.showLoading({
+    title: "提交中",
+    mask: true,
+  });
+  startCharge(options.value.sn, query)
+    .then(() => {
+      if (chargeType.value === 0) {
+        fetchChargeStatus()
+          .then((res) => {
+            if (res && res.isBooking === 1) {
+              uni.hideLoading();
+              uni.showToast({
+                icon: "success",
+                title: "预约成功",
+              });
+              appointmentData.value = res;
+              startAppointmentCountDown();
+            }
+          })
+          .catch(() => {
+            uni.navigateBack();
+          });
+      }
+      if (chargeType.value === 1) {
+        uni.navigateTo({
+          url: `/pages-charge/ordering/ordering?sn=${options.value.sn}&start=1`,
+        });
+      }
+    })
+    .catch((err) => {
+      uni.hideLoading();
+    });
+};
+
+const submitNow = () => {
+  uni.showLoading({
+    title: "提交中",
+    mask: true,
+  });
+  cancelAppointmentCharge()
+    .then(() => {
+      return startCharge(options.value.sn, "isBooking=false");
+    })
+    .then(() => {
+      uni.navigateTo({
+        url: `/pages-charge/ordering/ordering?sn=${options.value.sn}&start=1`,
+      });
+    });
 };
 
 onLoad((_options: any) => {
   // sn=SN100523042860091 测试环境
   const sn = _options.sn || "SN100523042860091";
-  // debug
-  uni.navigateTo({
-    url: `/pages-charge/ordering/ordering?sn=${sn}`,
-  });
-  return
   uni.showLoading({
     title: "加载中",
   });
   fetchStationByConnectorId(sn)
     .then((res) => {
-      console.log(res);
+      // console.log(res);
       options.value = _options;
       data.value = res;
       return fetchStationPriceDesc(sn);
     })
     .then((res) => {
-      console.log(res);
+      // console.log(res);
       uni.hideLoading();
       priceInfo.value = res;
+      return fetchChargeStatus(false, true);
+    })
+    .then((res) => {
+      if (res && res.isBooking === 1) {
+        appointmentData.value = res;
+        startAppointmentCountDown();
+      }
     })
     .catch(() => {
       uni.hideLoading();

+ 22 - 19
src/pages-charge/camera/camera.vue

@@ -1,5 +1,11 @@
 <template>
   <view class="page flex-column">
+    <cover-image
+      class="page_back"
+      :style="backStyle"
+      src="/static/images/back.png"
+      @click="back"
+    ></cover-image>
     <view class="page_camera flex-grow">
       <camera
         v-if="!isDevTool"
@@ -76,36 +82,27 @@
 import { ref } from "vue";
 import { isDevTool } from "../../utils/device";
 import { deCode } from "../../utils/code";
-import { redirect } from "../../utils/navigate";
+import { back, redirect } from "../../utils/navigate";
 import { onLoad, onReady } from "@dcloudio/uni-app";
 import { fetchChargeStatus } from "../../api/charge";
 
 const cameraHeight = ref(0);
 const cameraFlash = ref("off");
+const backStyle = ref("");
 
 onLoad(() => {
+  const menuButtonRect = uni.getMenuButtonBoundingClientRect();
+  backStyle.value = `left:12px;top:${menuButtonRect.top + 6}px;`;
   uni.showLoading({
     title: "加载中",
   });
-  fetchChargeStatus().then((res) => {
-    if ([1, 2].includes(res.chargeStatus)) {
+  fetchChargeStatus(true, true)
+    .then(() => {
       uni.hideLoading();
-      uni.showModal({
-        title: "温馨提示",
-        content: "当前已有进行中的订单,请结束订单再扫码充电",
-        showCancel: false,
-        confirmText: "查看当前",
-        confirmColor: "#347DFF",
-        success(modal) {
-          if (modal.confirm) {
-            uni.navigateTo({
-              url: `/pages-charge/appointment/appointment?sn=${res.connectorId}&start=1`,
-            });
-          }
-        },
-      });
-    }
-  });
+    })
+    .catch(() => {
+      uni.hideLoading();
+    });
 });
 
 onReady(() => {
@@ -160,8 +157,14 @@ const toggleFlash = () => {
 
 <style lang="scss">
 .page {
+  position: relative;
   height: 100vh;
   background-color: #000;
+  &_back {
+    position: absolute;
+    width: 10px;
+    height: auto;
+  }
   &_camera {
     height: 100%;
     .mock-camera {

+ 18 - 88
src/pages-charge/machines/machines.vue

@@ -125,49 +125,26 @@
         ></ChargeMachine>
       </template>
     </view>
-    <view class="dialog flex-align-end" v-if="dialogVisible">
+    <PriceDesc
+      v-if="dialogVisible && dialogType === 'desc'"
+      :desc="desc"
+      @close="closeDialog"
+    ></PriceDesc>
+    <view
+      class="dialog flex-align-end"
+      v-if="dialogVisible && dialogType === 'status'"
+    >
       <view class="desc-dialog">
         <view class="desc-dialog_head flex-center">
-          <view class="fw-500 color-000" style="font-size: 16px">{{
-            dialogType === "desc" ? "充电费用说明" : "选择充电桩状态"
-          }}</view>
+          <view class="fw-500 color-000" style="font-size: 16px"
+            >选择充电桩状态</view
+          >
           <view class="close" @click="closeDialog">
             <uni-icons type="closeempty" size="24" color="#2D284B"></uni-icons>
           </view>
         </view>
         <view class="desc-dialog_body">
-          <view class="table" v-if="dialogType === 'desc'">
-            <view class="tr flex">
-              <view class="th flex-center fs-28">时间</view>
-              <view class="th flex-center flex-column">
-                <view>电费</view>
-                <view class="fs-24 lh-24" style="color: rgba(0, 0, 0, 0.5)"
-                  >(元/kwh)</view
-                >
-              </view>
-              <view class="th flex-center flex-column">
-                <view>服务费</view>
-                <view class="fs-24 lh-24" style="color: rgba(0, 0, 0, 0.5)"
-                  >(元/kwh)</view
-                >
-              </view>
-            </view>
-            <view
-              class="tr flex"
-              v-for="(item, index) in desc"
-              :key="index"
-              :style="{
-                'border-top': `1rpx solid ${
-                  index === 0 ? 'transparent' : '#E5E5E5'
-                }`,
-              }"
-            >
-              <view class="td flex-center">{{ item.startTimeFormat }}</view>
-              <view class="td flex-center">{{ item.elecPrice }}</view>
-              <view class="td flex-center">{{ item.servicePrice }}</view>
-            </view>
-          </view>
-          <view class="status" v-if="dialogType === 'status'">
+          <view class="status">
             <view
               :class="['fs-32', 'flex-align-center']"
               :style="{ color: status === index ? '#347DFF' : '#2d284b' }"
@@ -189,6 +166,7 @@ import { ref } from "vue";
 import { fetchStation, fetchStationPriceDesc } from "../../api/charge";
 import { onLoad } from "@dcloudio/uni-app";
 import ChargeMachine from "./charge-machine/charge-machine.vue";
+import PriceDesc from "./price-desc/price-desc.vue";
 const dialogVisible = ref(false);
 const dialogType = ref("");
 const desc = ref<any[]>([]);
@@ -309,9 +287,6 @@ const openDesc = function () {
   dialogType.value = "desc";
 };
 const openStatus = function () {
-  if (!stationEquipmentInfos.value || stationEquipmentInfos.value.length <= 0) {
-    return;
-  }
   dialogVisible.value = true;
   dialogType.value = "status";
 };
@@ -359,9 +334,9 @@ const changeStatus = function (index: number) {
 const previewImage = (url: string) => {
   uni.previewImage({
     urls: station.value.bannerImages,
-    current: url
-  })
-}
+    current: url,
+  });
+};
 </script>
 
 <style lang="scss">
@@ -431,7 +406,7 @@ page {
   background-color: transparent;
   width: 100%;
   overflow: hidden;
-  border-radius: 20rpx;
+  border-radius: 20rpx 20rpx 0px 0px;
 
   &_head {
     padding: 24rpx 0px;
@@ -452,51 +427,6 @@ page {
     background-color: #fff;
     overflow-y: auto;
 
-    .table {
-      border: 1rpx solid #e5e5e5;
-      border-radius: 10rpx;
-      overflow: hidden;
-    }
-
-    .tr {
-      width: 100%;
-
-      & > view:nth-child(1) {
-        width: 254rpx;
-        flex-shrink: 0;
-        border-right: 1rpx solid #e5e5e5;
-      }
-
-      & > view:nth-child(2) {
-        width: 200rpx;
-        flex-shrink: 0;
-        border-right: 1rpx solid #e5e5e5;
-      }
-
-      & > view:nth-child(3) {
-        flex-grow: 1;
-      }
-    }
-
-    .th {
-      border-bottom: 1rpx solid #e5e5e5;
-      background-color: #f1f6ff;
-      height: 92rpx;
-      color: rgba(0, 0, 0, 0.7);
-      font-size: 28rpx;
-
-      view {
-        color: rgba(0, 0, 0, 0.7);
-        font-size: 28rpx;
-      }
-    }
-
-    .td {
-      color: #000;
-      font-size: 26rpx;
-      height: 76rpx;
-    }
-
     .status {
       & > view {
         height: 92rpx;

+ 138 - 0
src/pages-charge/machines/price-desc/price-desc.vue

@@ -0,0 +1,138 @@
+<template>
+  <view class="dialog flex-align-end">
+    <view class="desc-dialog">
+      <view class="desc-dialog_head flex-center">
+        <view class="fw-500 color-000" style="font-size: 16px"
+          >充电费用说明</view
+        >
+        <view class="close" @click="close">
+          <uni-icons type="closeempty" size="24" color="#2D284B"></uni-icons>
+        </view>
+      </view>
+      <view class="desc-dialog_body">
+        <view class="table">
+          <view class="tr flex">
+            <view class="th flex-center fs-28">时间</view>
+            <view class="th flex-center flex-column">
+              <view>电费</view>
+              <view class="fs-24 lh-24" style="color: rgba(0, 0, 0, 0.5)"
+                >(元/kwh)</view
+              >
+            </view>
+            <view class="th flex-center flex-column">
+              <view>服务费</view>
+              <view class="fs-24 lh-24" style="color: rgba(0, 0, 0, 0.5)"
+                >(元/kwh)</view
+              >
+            </view>
+          </view>
+          <view
+            class="tr flex"
+            v-for="(item, index) in desc"
+            :key="index"
+            :style="{
+              'border-top': `1rpx solid ${
+                index === 0 ? 'transparent' : '#E5E5E5'
+              }`,
+            }"
+          >
+            <view class="td flex-center">{{ item.startTimeFormat }}</view>
+            <view class="td flex-center">{{ item.elecPrice }}</view>
+            <view class="td flex-center">{{ item.servicePrice }}</view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+export default {
+  props: {
+    desc: Array<any>,
+  },
+  methods: {
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+@import "../../../styles/font.scss";
+@import "../../../styles/flex.scss";
+@import "../../../styles/layout.scss";
+@import "../../../styles/dialog.scss";
+.desc-dialog {
+  background-color: transparent;
+  width: 100%;
+  overflow: hidden;
+  border-radius: 20rpx 20rpx 0px 0px;
+
+  &_head {
+    padding: 24rpx 0px;
+    position: relative;
+    background-color: #fff;
+    .close {
+      position: absolute;
+      right: 30rpx;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+  }
+
+  &_body {
+    max-height: 860rpx;
+    box-sizing: border-box;
+    padding: 0rpx 30rpx 80rpx 30rpx;
+    background-color: #fff;
+    overflow-y: auto;
+
+    .table {
+      border: 1rpx solid #e5e5e5;
+      border-radius: 10rpx;
+      overflow: hidden;
+    }
+
+    .tr {
+      width: 100%;
+
+      & > view:nth-child(1) {
+        width: 254rpx;
+        flex-shrink: 0;
+        border-right: 1rpx solid #e5e5e5;
+      }
+
+      & > view:nth-child(2) {
+        width: 200rpx;
+        flex-shrink: 0;
+        border-right: 1rpx solid #e5e5e5;
+      }
+
+      & > view:nth-child(3) {
+        flex-grow: 1;
+      }
+    }
+
+    .th {
+      border-bottom: 1rpx solid #e5e5e5;
+      background-color: #f1f6ff;
+      height: 92rpx;
+      color: rgba(0, 0, 0, 0.7);
+      font-size: 28rpx;
+
+      view {
+        color: rgba(0, 0, 0, 0.7);
+        font-size: 28rpx;
+      }
+    }
+
+    .td {
+      color: #000;
+      font-size: 26rpx;
+      height: 76rpx;
+    }
+  }
+}
+</style>

+ 11 - 4
src/pages-charge/ordering/ordering.vue

@@ -64,7 +64,11 @@
         @click="cancel"
         >取消充电</style-button
       >
-      <style-button v-if="step === 3" type="primary" size="small" @click="back"
+      <style-button
+        v-if="step === 3"
+        type="primary"
+        size="small"
+        @click="reLaunch"
         >返回首页</style-button
       >
     </view>
@@ -76,6 +80,7 @@ import { onHide, onLoad, onShow } from "@dcloudio/uni-app";
 import { cancelCharge, fetchChargeStatus, startCharge } from "../../api/charge";
 import { ref } from "vue";
 import { format } from "../../utils/date";
+import { to, reLaunch } from "@/utils/navigate";
 
 let timer: any;
 let statusTimer: any;
@@ -149,9 +154,7 @@ const start = () => {
       }, 300);
     });
 };
-const back = () => {
-  uni.navigateBack();
-};
+
 const cancel = () => {
   uni.showModal({
     title: "停止充电",
@@ -356,6 +359,10 @@ const fetchStatus = (data?: any) => {
 const onImgLoad = () => {
   fetchChargeStatus()
     .then((res) => {
+      if (res && res.isBooking === 1) {
+        to(`/pages-charge/appointment/appointment?sn=${options.value.sn}`);
+        return;
+      }
       if ([1, 2].includes(res.chargeStatus)) {
         if (options.value && options.value.sn === res.connectorId) {
           fetchStatus(res);

+ 1 - 1
src/pages-charge/orders/orders.vue

@@ -119,7 +119,7 @@ const detail = (index: number) => {
   if (!infiniteScroller.list) {
     return;
   }
-  if (isInvoice) {
+  if (isInvoice.value) {
     infiniteScroller.list[index].checked =
       !infiniteScroller.list[index].checked;
     setCheckData();

BIN
src/pages-charge/static/icon-alarm.png


+ 6 - 0
src/utils/navigate.ts

@@ -13,3 +13,9 @@ export function redirect(url: string) {
     url,
   });
 }
+
+export function reLaunch() {
+  uni.reLaunch({
+    url: '/pages/map/map',
+  });
+}