|
|
@@ -1,9 +1,458 @@
|
|
|
<template>
|
|
|
- <view></view>
|
|
|
+ <view class="container">
|
|
|
+ <image class="bg" src="../images/charge-ordering-bg.png" mode="widthFix" />
|
|
|
+ <view class="body">
|
|
|
+ <view class="iphonex-placeholder"></view>
|
|
|
+ <view
|
|
|
+ class="status flex-center transition"
|
|
|
+ :style="{
|
|
|
+ opacity: step >= 1 ? '1' : '0',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <image
|
|
|
+ :class="['border', `${step <= 2 ? 'border-animation' : ''}`]"
|
|
|
+ src="../images/charge-ordering-border.png"
|
|
|
+ @load="onImgLoad"
|
|
|
+ />
|
|
|
+ <view class="timer flex-column flex-center">
|
|
|
+ <block v-if="step === 1">
|
|
|
+ <view>
|
|
|
+ <text class="fw-600" style="font-size: 100rpx">{{
|
|
|
+ status.time
|
|
|
+ }}</text>
|
|
|
+ <text class="fs-40 fw-500 ml-10">s</text>
|
|
|
+ </view>
|
|
|
+ <view class="fs-26">充电启动中</view>
|
|
|
+ </block>
|
|
|
+ <block v-if="step === 2">
|
|
|
+ <image class="icon" src="../images/charge-ordering-icon.png" />
|
|
|
+ <view class="fs-26 mt-10">充电中...</view>
|
|
|
+ </block>
|
|
|
+ <block v-if="step === 3">
|
|
|
+ <image class="icon" src="../images/charge-ordering-finish.png" />
|
|
|
+ <view class="fs-26 mt-10">充电结束</view>
|
|
|
+ </block>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <style-bottom-view>
|
|
|
+ <view
|
|
|
+ class="transition pl-60 pr-60 pb-40"
|
|
|
+ :style="{
|
|
|
+ opacity: step >= 1 ? '1' : '0',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <view class="mb-40" v-if="step === 2 || step === 3">
|
|
|
+ <shadow-card :list="chargeInfo"></shadow-card>
|
|
|
+ </view>
|
|
|
+ <style-button
|
|
|
+ v-if="step === 1 || step === 2"
|
|
|
+ type="warning"
|
|
|
+ size="small"
|
|
|
+ @click="cancel"
|
|
|
+ >取消充电</style-button
|
|
|
+ >
|
|
|
+ <style-button v-if="step === 3" type="primary" size="small" @click="back"
|
|
|
+ >返回首页</style-button
|
|
|
+ >
|
|
|
+ </view>
|
|
|
+ </style-bottom-view>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
+import { onHide, onLoad, onShow } from "@dcloudio/uni-app";
|
|
|
+import { cancelCharge, fetchChargeStatus, startCharge } from "../../api/charge";
|
|
|
+import { ref } from "vue";
|
|
|
+import { format } from "../../utils/date";
|
|
|
+
|
|
|
+let timer: any;
|
|
|
+const step = ref(0);
|
|
|
+const options = ref<any>();
|
|
|
+const status = ref({
|
|
|
+ time: 30,
|
|
|
+ start: false,
|
|
|
+ cancel: false,
|
|
|
+ error: false
|
|
|
+});
|
|
|
+const chargeInfo = ref<any[]>([]);
|
|
|
+const startStartTimer = () => {
|
|
|
+ if (status.value.start || status.value.cancel || status.value.error) {
|
|
|
+ timer && clearTimeout(timer);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ timer = setTimeout(() => {
|
|
|
+ if (status.value.time <= 1 && !status.value.start) {
|
|
|
+ uni.showModal({
|
|
|
+ title: "充电错误",
|
|
|
+ content: "出现问题,请重试",
|
|
|
+ showCancel: false,
|
|
|
+ confirmText: "知道了",
|
|
|
+ confirmColor: "#347DFF",
|
|
|
+ success() {
|
|
|
+ uni.navigateBack();
|
|
|
+ },
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ status.value.time = status.value.time - 1;
|
|
|
+ startStartTimer();
|
|
|
+ }, 1000);
|
|
|
+};
|
|
|
+const startStatusTimer = () => {
|
|
|
+ setTimeout(() => {
|
|
|
+ fetchChargeStatus()
|
|
|
+ .then((res) => {
|
|
|
+ if (status.value.cancel) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if ([1, 2].includes(res.StartChargeSeqStat)) {
|
|
|
+ setChargeData(res);
|
|
|
+ }
|
|
|
+ startStatusTimer();
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ startStatusTimer();
|
|
|
+ });
|
|
|
+ }, 30000);
|
|
|
+};
|
|
|
+const start = () => {
|
|
|
+ step.value = 1;
|
|
|
+ startStartTimer();
|
|
|
+ startCharge(options.value && options.value.sn ? options.value.sn : "")
|
|
|
+ .then(() => {
|
|
|
+ fetchStatus();
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ setTimeout(() => {
|
|
|
+ status.value.error = true
|
|
|
+ timer && clearTimeout(timer);
|
|
|
+ uni.showModal({
|
|
|
+ content: `${err.errMsg}`,
|
|
|
+ showCancel: false,
|
|
|
+ success: () => {
|
|
|
+ uni.navigateBack();
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }, 300);
|
|
|
+ });
|
|
|
+};
|
|
|
+const back = () => {
|
|
|
+ uni.navigateBack();
|
|
|
+};
|
|
|
+const cancel = () => {
|
|
|
+ uni.showModal({
|
|
|
+ title: "停止充电",
|
|
|
+ content: "是否停止充电",
|
|
|
+ cancelText: "停止",
|
|
|
+ cancelColor: "#999999",
|
|
|
+ confirmText: "点错了",
|
|
|
+ confirmColor: "#347DFF",
|
|
|
+ success: (res) => {
|
|
|
+ if (res.cancel) {
|
|
|
+ clearTimeout(timer);
|
|
|
+ status.value.cancel = true;
|
|
|
+ if ([1, 2].includes(step.value)) {
|
|
|
+ if (status.value.start) {
|
|
|
+ finish();
|
|
|
+ } else {
|
|
|
+ uni.showLoading({
|
|
|
+ title: "正在取消",
|
|
|
+ });
|
|
|
+ cancelCharge(
|
|
|
+ options.value && options.value.sn ? options.value.sn : ""
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ // console.log(res)
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: "已取消充电",
|
|
|
+ icon: "none",
|
|
|
+ });
|
|
|
+ setTimeout(() => {
|
|
|
+ uni.navigateBack();
|
|
|
+ }, 2000);
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: "已取消充电",
|
|
|
+ icon: "none",
|
|
|
+ });
|
|
|
+ setTimeout(() => {
|
|
|
+ uni.navigateBack();
|
|
|
+ }, 2000);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+};
|
|
|
+const finish = () => {
|
|
|
+ uni.showLoading({
|
|
|
+ title: "正在结束中",
|
|
|
+ });
|
|
|
+ fetchChargeStatus()
|
|
|
+ .then((res) => {
|
|
|
+ if ([1, 2].includes(res.StartChargeSeqStat)) {
|
|
|
+ // 当前充电中
|
|
|
+ const start = new Date(res.StartTime.replace(/-/g, "/"));
|
|
|
+ const end = new Date();
|
|
|
+ const diff = parseInt(`${(end.getTime() - start.getTime()) / 1000}`);
|
|
|
+ const min = parseInt(`${diff / 60}`);
|
|
|
+ const time =
|
|
|
+ min >= 60
|
|
|
+ ? `${parseInt(`${min / 60}`)}小时${parseInt(
|
|
|
+ `${min - parseInt(`${min / 60}`) * 60}`
|
|
|
+ )}分钟`
|
|
|
+ : `${parseInt(`${diff / 60}`)}分钟`;
|
|
|
+ const endFormat = format("y-M-d h:m:s");
|
|
|
+ const _chargeInfo = [
|
|
|
+ {
|
|
|
+ label: "累计充电量",
|
|
|
+ value: `${res.TotalPower}度`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "累计费用",
|
|
|
+ value: `${res.ElecMoney}元`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "开始时间",
|
|
|
+ value: res.StartTime,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "结束时间",
|
|
|
+ value: endFormat,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "累计用时",
|
|
|
+ value: time,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ if (res.Soc) {
|
|
|
+ _chargeInfo.unshift({
|
|
|
+ label: "剩余电量",
|
|
|
+ value: `${res.Soc}%`,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ chargeInfo.value = _chargeInfo;
|
|
|
+ cancelCharge(options.value && options.value.sn ? options.value.sn : "")
|
|
|
+ .then(() => {
|
|
|
+ uni.hideLoading();
|
|
|
+ if (res.FailReason) {
|
|
|
+ uni.showModal({
|
|
|
+ content: res.FailReason,
|
|
|
+ showCancel: false,
|
|
|
+ success() {
|
|
|
+ uni.navigateBack();
|
|
|
+ },
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ step.value = 3;
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: "已取消充电",
|
|
|
+ icon: "none",
|
|
|
+ });
|
|
|
+ setTimeout(() => {
|
|
|
+ uni.navigateBack();
|
|
|
+ }, 2000);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showModal({
|
|
|
+ title: "温馨提示",
|
|
|
+ content: "出现错误,请重试",
|
|
|
+ showCancel: false,
|
|
|
+ confirmText: "重试",
|
|
|
+ confirmColor: "#347DFF",
|
|
|
+ success: () => {
|
|
|
+ finish();
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+const setChargeData = (res: any) => {
|
|
|
+ const start = new Date(res.StartTime.replace(/-/g, "/"));
|
|
|
+ const end = new Date();
|
|
|
+ const diff = parseInt(`${(end.getTime() - start.getTime()) / 1000}`);
|
|
|
+ const min = parseInt(`${diff / 60}`);
|
|
|
+ const time =
|
|
|
+ min >= 60
|
|
|
+ ? `${parseInt(`${min / 60}`)}小时${parseInt(
|
|
|
+ `${min - parseInt(`${min / 60}`) * 60}`
|
|
|
+ )}分钟`
|
|
|
+ : `${parseInt(`${diff / 60}`)}分钟`;
|
|
|
+ const _chargeInfo = [
|
|
|
+ {
|
|
|
+ label: "累计充电量",
|
|
|
+ value: `${res.TotalPower}度`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "累计费用",
|
|
|
+ value: `${res.ElecMoney}元`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "开始时间",
|
|
|
+ value: res.StartTime,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "累计用时",
|
|
|
+ value: time,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ if (res.Soc) {
|
|
|
+ _chargeInfo.unshift({
|
|
|
+ label: "剩余电量",
|
|
|
+ value: `${res.Soc}%`,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ chargeInfo.value = _chargeInfo;
|
|
|
+};
|
|
|
+const fetchStatus = (data?: any) => {
|
|
|
+ if (status.value.cancel) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const promise = status ? Promise.resolve(data) : fetchChargeStatus();
|
|
|
+ promise
|
|
|
+ .then((res) => {
|
|
|
+ if ([1, 2].includes(res.StartChargeSeqStat)) {
|
|
|
+ // 当前充电中
|
|
|
+ status.value.start = true;
|
|
|
+ step.value = 2;
|
|
|
+ setChargeData(res);
|
|
|
+ startStatusTimer();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ setTimeout(() => {
|
|
|
+ fetchStatus(data);
|
|
|
+ }, 1000);
|
|
|
+ });
|
|
|
+};
|
|
|
+const onImgLoad = () => {
|
|
|
+ fetchChargeStatus()
|
|
|
+ .then((res) => {
|
|
|
+ if ([1, 2].includes(res.StartChargeSeqStat)) {
|
|
|
+ if (options.value && options.value.sn === res.ConnectorID) {
|
|
|
+ fetchStatus(res);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 当前充电中
|
|
|
+ uni.showModal({
|
|
|
+ title: "温馨提示",
|
|
|
+ content: "当前有正在充电中的订单",
|
|
|
+ showCancel: false,
|
|
|
+ confirmText: "查看订单",
|
|
|
+ confirmColor: "#347DFF",
|
|
|
+ success: () => {
|
|
|
+ fetchStatus(res);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ start();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ start();
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+onLoad((_options: any) => {
|
|
|
+ options.value = _options;
|
|
|
+});
|
|
|
+onHide(() => {
|
|
|
+ timer && clearTimeout(timer);
|
|
|
+});
|
|
|
+onShow(() => {
|
|
|
+ startStartTimer();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
-<style>
|
|
|
+<style lang="scss">
|
|
|
+.container {
|
|
|
+ height: 100vh;
|
|
|
+ width: 100%;
|
|
|
+ background-color: #fff;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .bg {
|
|
|
+ width: 100%;
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ transform-origin: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .body {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .iphonex-placeholder {
|
|
|
+ box-sizing: content-box;
|
|
|
+ padding-bottom: constant(safe-area-inset-bottom);
|
|
|
+ padding-bottom: env(safe-area-inset-bottom);
|
|
|
+ }
|
|
|
+
|
|
|
+ .status {
|
|
|
+ width: 420rpx;
|
|
|
+ height: 420rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ position: relative;
|
|
|
+ margin: 0 auto;
|
|
|
+ margin-top: 130rpx;
|
|
|
+
|
|
|
+ .border {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .border-animation {
|
|
|
+ animation: rot 3s linear infinite;
|
|
|
+ }
|
|
|
+
|
|
|
+ .timer {
|
|
|
+ position: absolute;
|
|
|
+ width: 340rpx;
|
|
|
+ height: 340rpx;
|
|
|
+ left: 50%;
|
|
|
+ top: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ background: linear-gradient(180deg, #ffffff 0%, #ecf3ff 100%);
|
|
|
+ box-shadow: 0px 18rpx 30rpx rgba(0, 0, 0, 0.1);
|
|
|
+ border-radius: 50%;
|
|
|
+ .icon {
|
|
|
+ width: 152rpx;
|
|
|
+ height: 152rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes rot {
|
|
|
+ 0% {
|
|
|
+ transform: rotate(0deg);
|
|
|
+ }
|
|
|
+
|
|
|
+ 100% {
|
|
|
+ transform: rotate(360deg);
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|