Ver Fonte

feat:首页优化 & 退款接口

needcode há 2 anos atrás
pai
commit
02c406d3c6

+ 38 - 1
src/App.vue

@@ -35,7 +35,6 @@ view {
   box-sizing: border-box;
   --color-primary: #347dff;
   --color-warning: #ff9900;
-  --color-gray: #666666;
   --color-sec: #f7f7f7;
 }
 
@@ -60,6 +59,18 @@ image {
   color: #000;
 }
 
+.color-000-5 {
+  color: rgba(0, 0, 0, 0.5);
+}
+
+.color-000-6 {
+  color: rgba(0, 0, 0, 0.6);
+}
+
+.color-000-08 {
+  color: rgba(0, 0, 0, 0.08);
+}
+
 .color-333 {
   color: #333;
 }
@@ -84,6 +95,14 @@ image {
   background-color: #fff;
 }
 
+.bg-666 {
+  background-color: #666;
+}
+
+.bg-000-08 {
+  background-color: rgba(0, 0, 0, 0.08);
+}
+
 .full-percent {
   height: 100%;
   width: 100%;
@@ -112,4 +131,22 @@ image {
   transition: all 0.3s;
   transform: scale(0.98);
 }
+
+.animation-loading {
+  animation: animation-turn 2s linear infinite;
+}
+
+@keyframes animation-turn {
+  0% {
+    transform: rotate(0deg);
+  }
+
+  50% {
+    transform: rotate(180deg);
+  }
+
+  100% {
+    transform: rotate(360deg);
+  }
+}
 </style>

+ 9 - 8
src/api/charge.ts

@@ -1,5 +1,5 @@
 import Http from "../utils/http";
-import { host } from "../utils/constant";
+import { host, isDebug } from "../utils/constant";
 const cHttp = new Http(host);
 
 export function startCharge(sn: string) {
@@ -23,8 +23,8 @@ export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
     let currentPrice = 0;
     let currentTime = "00:00~24:00";
     res.useTime = "";
-    if (res && res.policyInfoss && res.policyInfoss.length) {
-      res.policyInfoss.forEach((item: any, index: number) => {
+    if (res && res.policyInfos && res.policyInfos.length) {
+      res.policyInfos.forEach((item: any, index: number) => {
         const hour = item.startTime.substring(0, 2);
         const min = item.startTime.substring(3, 5);
         if (index === 0) {
@@ -33,10 +33,11 @@ export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
         let tempPrice = Number(
           Number(item.elecPrice + item.servicePrice).toFixed(2)
         );
+        item.totalPrice = tempPrice
         if (tempPrice > maxPrice) {
           maxPrice = tempPrice;
         }
-        if (index >= res.policyInfoss.length - 1) {
+        if (index >= res.policyInfos.length - 1) {
           // 最后一个
           item.startTimeFormat = `${hour}:${min}~24:00`;
           if (Number(hour) <= nowHour) {
@@ -48,8 +49,8 @@ export function fetchStationPriceDesc(ConnectorID: string, StationID?: string) {
             minPriceTime = `${hour}:${min}~24:00`;
           }
         } else {
-          const nhour = res.policyInfoss[index + 1].startTime.substring(0, 2);
-          const nmin = res.policyInfoss[index + 1].startTime.substring(3, 5);
+          const nhour = res.policyInfos[index + 1].startTime.substring(0, 2);
+          const nmin = res.policyInfos[index + 1].startTime.substring(3, 5);
           item.startTimeFormat = `${hour}:${min}~${nhour}:${nmin}`;
           if (nowHour >= Number(hour) && nowHour < Number(nhour)) {
             currentPrice = tempPrice;
@@ -119,7 +120,7 @@ export function fetchStations(
         });
       }
       if (options) {
-        if (options.distance) {
+        if (options.distance && !isDebug) {
           list = list.filter(
             (item: any) => item.stationLatDistance <= (options.distance || 20)
           );
@@ -244,7 +245,7 @@ export function searchStation(keyword: string) {
   return fetchAllStations().then((res) => {
     const reg = new RegExp(keyword, "ig");
     const list = res.filter(
-      (item) => reg.test(item.StationName) || reg.test(item.Address)
+      (item) => reg.test(item.stationName) || reg.test(item.address)
     );
     return _fetchStationStatus(list);
   });

+ 5 - 1
src/api/index.ts

@@ -5,4 +5,8 @@ const indexHttp = new Http(host)
 
 export function fetchContact() {
   return indexHttp.get('/common/contact')
-}
+}
+
+export function fetchCommonQuestions() {
+  return indexHttp.get('/qa')
+}

+ 10 - 1
src/api/user.ts

@@ -5,6 +5,9 @@ const userHttp = new Http(host);
 
 export function fetchProfile() {
   return userHttp.get("/user/me").then((res) => {
+    res.balance = (Number(res.balance) / 100).toFixed(2);
+    res.discountAmount = (Number(res.discountAmount) / 100).toFixed(2);
+    res.refundableAmount = (Number(res.refundableAmount) / 100).toFixed(2);
     getApp<any>().globalData.user = res;
     return res;
   });
@@ -101,9 +104,15 @@ export function logout() {
 }
 
 export function fetchWallet(type: number, page: number, pageSize: number) {
-  return userHttp.get(`/account/walletDetail?page=${page}&page_size=${pageSize}&type=${type}`);
+  return userHttp.get(
+    `/account/walletDetail?page=${page}&page_size=${pageSize}&type=${type}`
+  );
 }
 
 export function fetchOrder(orderid: string) {
   return userHttp.get(`/charge/orderDetail/${orderid}`);
 }
+
+export function applyRefund(reason: string) {
+  return userHttp.get(`/payment/wxApplyRefund?reason=${reason}`);
+}

+ 5 - 5
src/components/charge-station/charge-station.vue

@@ -28,17 +28,17 @@
           <text class="fs-32 fw-600" style="color: var(--color-warning)">{{
             price
           }}</text>
-          <text class="fs-22 ml-6" style="color: var(--color-gray)">元/度</text>
+          <text class="fs-22 ml-6 color-666">元/度</text>
         </view>
         <view class="flex-align-center lh-0 mt-auto" v-if="!fromMap">
           <charge-icon type="fast"></charge-icon>
-          <view class="fs-22 ml-8" style="color: var(--color-gray)" v-if="fast"
+          <view class="fs-22 ml-8 color-666" v-if="fast"
             >空闲:{{ freeLength(fast) }}|共:{{ fast.length }}</view
           >
           <view class="ml-60">
             <charge-icon type="slow"></charge-icon>
           </view>
-          <view class="fs-22 ml-8" style="color: var(--color-gray)" v-if="slow"
+          <view class="fs-22 ml-8 color-666" v-if="slow"
             >空闲:{{ freeLength(slow) }}|共:{{ slow.length }}</view
           >
         </view>
@@ -51,7 +51,7 @@
             v-if="slow && slow.length"
           >
             <charge-icon type="slow"></charge-icon>
-            <view class="ml-6 fs-22" style="color: var(--color-gray)"
+            <view class="ml-6 fs-22 color-666"
               >{{ freeLength(slow) }} / {{ slow.length }}</view
             >
           </view>
@@ -60,7 +60,7 @@
             v-if="fast && fast.length"
           >
             <charge-icon type="fast"></charge-icon>
-            <view class="ml-6 fs-22" style="color: var(--color-gray)"
+            <view class="ml-6 fs-22 color-666"
               >{{ freeLength(fast) }} / {{ fast.length }}</view
             >
           </view>

+ 68 - 0
src/components/style-dialog/style-dialog.vue

@@ -0,0 +1,68 @@
+<template>
+  <view class="style-dialog">
+    <view>
+      <view class="style-dialog_head flex-center">
+        <view class="fw-500 color-000 fs-32">{{ title }}</view>
+        <view class="close" @click="close">
+          <uni-icons type="closeempty" size="24" color="#2D284B"></uni-icons>
+        </view>
+      </view>
+      <view class="style-dialog_body">
+        <slot></slot>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+export default {
+  props: {
+    title: String,
+  },
+  methods: {
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.style-dialog {
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  top: 0;
+  z-index: 999;
+  background-color: rgba(0, 0, 0, 0.6);
+  display: flex;
+  align-items: flex-end;
+  & > view {
+    width: 100%;
+    overflow: hidden;
+    border-radius: 20rpx 20rpx 0px 0px;
+    background-color: #fff;
+    box-sizing: content-box;
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+  }
+  &_head {
+    height: 92rpx;
+    position: relative;
+    background-color: #fff;
+    .close {
+      position: absolute;
+      right: 30rpx;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+  }
+  &_body {
+    max-height: 800rpx;
+    overflow-y: auto;
+  }
+}
+</style>

+ 162 - 16
src/pages-charge/appointment/appointment.vue

@@ -7,6 +7,7 @@
             :title="'NO.' + data.equipment.shortId"
             :list="data.equipment.connectorInfos"
             :time="priceInfo.useTime"
+            :parkingNo="data.equipment.parkingNo"
           ></ChargeMachine>
         </view>
         <view class="pt-20 pb-20 pl-30 pr-30 flex-align-center">
@@ -77,8 +78,10 @@
         >
           <view class="fs-28 color-000 fw-500">充电时间</view>
           <view class="flex-align-center lh-28">
-            <view v-if="chargeTime" class="fs-28 color-333 fw-500 mr-16"
-              >TODO</view
+            <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
@@ -89,7 +92,11 @@
         <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" class="fs-28 color-333 fw-500">TODO</view>
+            <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
             >
@@ -102,14 +109,68 @@
         >
       </view>
       <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">{{
+            chargeType === 0 ? "提交申请" : "马上充电"
+          }}</style-button>
+        </view>
+      </style-bottom-view>
     </template>
-    <style-bottom-view>
-      <view class="pt-20 pl-40 pr-40 pb-20 bg-fff">
-        <style-button type="primary" size="small" @click="submit">{{
-          chargeType === 0 ? "提交申请" : "马上充电"
-        }}</style-button>
+    <style-dialog
+      v-if="chargeTimeDialog"
+      @close="closeTime"
+      title="请选择充电时间"
+    >
+      <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"
+        >
+          <view
+            class="flex-align-center pl-32 height-90"
+            v-for="(day, index) in timesInfo.day"
+            :key="index"
+            :style="{
+              backgroundColor:
+                day.format === chargeTime.day ? '#fff' : 'transparent',
+            }"
+            @click="changeTime(index)"
+          >
+            <view
+              :class="[
+                'fs-32',
+                'fw-500',
+                day.format === chargeTime.day ? 'color-primary' : 'color-000',
+              ]"
+              >{{ day.format }}</view
+            >
+            <view
+              class="fs-24 color-666 ml-12 br-8 width-60 height-40 flex-center"
+              style="background-color: rgba(0, 0, 0, 0.07)"
+              v-if="day.year && day.format !== chargeTime.day"
+              >{{ day.year }}年</view
+            >
+          </view>
+        </view>
+        <view class="flex-grow" style="height: 714rpx; overflow-y: auto">
+          <view
+            class="flex-align-center pl-40 height-90 fs-32"
+            v-for="(hour, index) in timesInfo.time"
+            :key="index"
+            :style="{
+              color:
+                hour.format === chargeTime.hour
+                  ? 'var(--color-primary)'
+                  : '#000',
+            }"
+            @click="changeHour(index)"
+          >
+            {{ hour.format }}
+          </view>
+        </view>
       </view>
-    </style-bottom-view>
+    </style-dialog>
   </view>
 </template>
 
@@ -118,10 +179,16 @@ import { fetchStationByConnectorId, fetchStationPriceDesc } from "@/api/charge";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 import ChargeMachine from "../machines/charge-machine/charge-machine.vue";
+import { format } from "@/utils/date";
 
+const DAY = 24 * 60 * 60 * 1000;
 const options = ref<any>();
 const data = ref<any>();
 const priceInfo = ref();
+const timesInfo = ref<any>({
+  day: [],
+  time: [],
+});
 
 const chargeType = ref(1);
 const chargeTypes = ref([
@@ -133,7 +200,14 @@ const chargeTypes = ref([
     title: "立即充电",
   },
 ]);
-const chargeTime = ref();
+const chargeTimeDialog = ref(false);
+const chargeTime = ref({
+  time: 0, // 时间戳
+  day: "",
+  hour: "",
+  format: "",
+  formatPrice: "",
+});
 
 const changeType = (index: number) => {
   chargeType.value = index;
@@ -141,16 +215,88 @@ const changeType = (index: number) => {
 
 const selectTime = () => {
   if (chargeType.value === 1) {
-    return
+    uni.showToast({
+      title: "请选择预约模式",
+      icon: "none",
+    });
+    return;
   }
-  // TODO 选择时间
-}
+  chargeTimeDialog.value = true;
+  const now = new Date();
+  const today = format("M月d日", now.getTime());
+  const tomorrow = format("M月d日", now.getTime() + DAY);
+  const year = format("y", now.getTime());
+  const nextyear = format("y", now.getTime() + DAY);
+
+  // 天数
+  timesInfo.value.day = [
+    {
+      time: now.getTime(),
+      format: today,
+      year: "",
+    },
+    {
+      time: now.getTime() + DAY,
+      format: tomorrow,
+      year: year === nextyear ? "" : nextyear.slice(2),
+    },
+  ];
+  // 时间
+  timesInfo.value.time = priceInfo.value.policyInfos.map((item: any) => {
+    return {
+      format: item.startTime,
+      formatPrice: item.totalPrice,
+    };
+  });
+  if (!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)
+};
+
+const changeTime = (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
+    }`;
+  }
+};
 
-const submit = () => {};
+const changeHour = (index: number) => {
+  chargeTime.value.hour = timesInfo.value.time[index].format;
+  chargeTime.value.format = `${format("y年M月d日", chargeTime.value.time)} ${
+    chargeTime.value.hour
+  }`;
+  chargeTime.value.formatPrice = timesInfo.value.time[index].formatPrice;
+};
+
+const closeTime = () => {
+  chargeTimeDialog.value = false;
+  if (!chargeTime.value.hour) {
+    chargeTime.value.time = 0;
+    chargeTime.value.day = "";
+  }
+};
+
+const submit = () => {
+  if (chargeType.value === 2 && !chargeTime.value.hour) {
+    uni.showToast({
+      title: "请选择充电时间",
+      icon: "none",
+    });
+    return;
+  }
+  // TODO 提交接口
+};
 
 onLoad((_options: any) => {
-  // sn=SN100523051916091
-  const sn = _options.sn || "SN100523051916091";
+  // sn=SN100523042860091 测试环境
+  const sn = _options.sn || "SN100523042860091";
   uni.showLoading({
     title: "加载中",
   });

+ 2 - 1
src/pages-charge/machines/charge-machine/charge-machine.vue

@@ -52,7 +52,7 @@
           }}{{ item.power }}kw</view
         >
         <view class="fs-24 color-666 mr-6 ml-6">|</view>
-        <view class="fs-24 color-666">车位号{{ item.parkNo }}</view>
+        <view class="fs-24 color-666">车位号{{ parkingNo }}</view>
       </view>
     </view>
     <view class="ml-auto" v-if="price">
@@ -79,6 +79,7 @@ export default {
     price: [String, Number],
     time: String,
     list: Array<any>,
+    parkingNo: String,
   },
   data() {
     return {

+ 32 - 9
src/pages-charge/machines/machines.vue

@@ -1,5 +1,8 @@
 <template>
-  <view :class="['pb-40', `container-${dialogVisible ? 'hidden' : ''}`]" v-if="station">
+  <view
+    :class="['pb-40', `container-${dialogVisible ? 'hidden' : ''}`]"
+    v-if="station"
+  >
     <view class="banner">
       <swiper
         class="full-percent"
@@ -8,11 +11,18 @@
         :autoplay="true"
         :interval="3000"
       >
-        <swiper-item class="full-percent">
-          <view class="full-percent"></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 station.bannerImages"
+          :key="index"
+        >
+          <view
+            class="full-percent banner-image"
+            :style="{
+              backgroundImage: `url(${item})`,
+            }"
+            @click="previewImage(item)"
+          ></view>
         </swiper-item>
       </swiper>
     </view>
@@ -111,6 +121,7 @@
           :title="'NO.' + item.shortId"
           :price="station.totalFee"
           :list="item.connectorInfos"
+          :parkingNo="item.parkingNo"
         ></ChargeMachine>
       </template>
     </view>
@@ -251,6 +262,7 @@ onLoad((options: any) => {
           }
         });
       }
+      res.bannerImages = res.pictures.split(",");
       station.value = res;
       stationEquipmentInfos.value = res.equipmentInfos.map((item: any) => {
         return {
@@ -262,7 +274,7 @@ onLoad((options: any) => {
       } else {
         // eslint-disable-next-line promise/no-return-wrap
         return Promise.resolve({
-          policyInfoss: [],
+          policyInfos: [],
         });
       }
     })
@@ -271,7 +283,7 @@ onLoad((options: any) => {
       currentTime.value = res.currentTime;
       canUseTime.value = res.useTime;
       canUsePrice.value = `${res.minPrice}~${res.maxPrice}`;
-      desc.value = res.policyInfoss || [];
+      desc.value = res.policyInfos || [];
     })
     .catch((err) => {
       // eslint-disable-next-line no-console
@@ -344,6 +356,12 @@ const changeStatus = function (index: number) {
   stationEquipmentInfos.value = newStationEquipmentInfos;
   closeDialog();
 };
+const previewImage = (url: string) => {
+  uni.previewImage({
+    urls: station.value.bannerImages,
+    current: url
+  })
+}
 </script>
 
 <style lang="scss">
@@ -360,7 +378,12 @@ page {
 
 .banner {
   height: 440rpx;
-  background-color: #000;
+  background-color: transparent;
+  .banner-image {
+    background-position: center;
+    background-size: cover;
+    background-repeat: no-repeat;
+  }
 }
 
 .station {

+ 20 - 23
src/pages-common/contact/contact.vue

@@ -1,5 +1,12 @@
 <template>
   <view class="page">
+    <view v-if="questions.length <= 0" class="flex-center mt-40 animation-loading"
+      ><uni-icons
+        type="spinner-cycle"
+        size="20"
+        color="rgba(0, 0, 0, 0.5)"
+      ></uni-icons
+    ></view>
     <view class="sheet">
       <view class="sheet_bar" v-for="(item, index) in questions" :key="index">
         <view class="head" @click="toggle(index)">
@@ -38,6 +45,7 @@
       class="flex-center flex-column contact mt-20"
       hover-class="hover-scale"
       @click="call"
+      v-if="questions.length"
     >
       <image
         class="width-96"
@@ -50,31 +58,11 @@
 </template>
 
 <script setup lang="ts">
+import { fetchCommonQuestions } from "@/api";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 
-// TODO 接口
-
-const questions = ref([
-  {
-    question: "预计并充电或开始充电按钮“置灰”无法点击如何处理",
-    answer: [
-      "首先:查看启动页面左上角APP显示信息当显示“请先插抢”时,表示充电抢未完全插好,请双手平直握枪,不要按枪头拔枪按钮,用力插入车内。听到咔哒一声,再进行扫码启动",
-      "当显示“正在充电”时,表示充电枪已开启充电。此时请勿拔枪,同时可查看车内是否充电完成。",
-    ],
-    open: false,
-  },
-  {
-    question: "如何开启充电?",
-    answer: ['TODO'],
-    open: false,
-  },
-  {
-    question: "如何结束充电?",
-    answer: "",
-    open: false,
-  },
-]);
+const questions = ref<any[]>([]);
 const servicerPhone = ref("");
 
 const call = () => {
@@ -83,7 +71,7 @@ const call = () => {
   });
 };
 
-const toggle = (index) => {
+const toggle = (index: number) => {
   questions.value = questions.value.map((item, i) => {
     return {
       ...item,
@@ -96,6 +84,15 @@ onLoad((options) => {
   if (options) {
     servicerPhone.value = options.service;
   }
+  fetchCommonQuestions().then((res) => {
+    questions.value = res.map((item: any) => {
+      return {
+        ...item,
+        answer: item.answer.split("\\r\r\n"),
+        open: false,
+      };
+    });
+  });
 });
 </script>
 

+ 8 - 0
src/pages-common/invoice/invoice.vue

@@ -0,0 +1,8 @@
+<template>
+  <view></view>
+</template>
+
+<script setup lang="ts">
+</script>
+
+<style lang="scss"></style>

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

@@ -79,7 +79,7 @@ const confirm = () => {
       });
       fetchProfile().then((res) => {
         payValue.value = 0;
-        balance.value = Number((Number(res.balance) / 100).toFixed(2))
+        balance.value = res.balance
       });
     })
     .catch((err) => {

+ 30 - 5
src/pages-user/wallet-refund/wallet-refund.vue

@@ -12,13 +12,14 @@
           style="height: 46px; font-size: 46px; line-height: 46px"
           class="fw-600 color-000 ml-18"
           :value="value"
+          :disabled="true"
         />
       </view>
       <view class="height-94 flex-align-center">
         <view class="fs-28 color-999"
-          >当前余额 {{ user ? user.balance : 0 }} 元,</view
+          >可退金额 {{ user ? user.refundableAmount : 0 }} 元,优惠金额 {{ user ? user.discountAmount : 0 }} 元</view
         >
-        <view class="fs-28 color-primary" @click="allRefund">全部提现</view>
+        <!-- <view class="fs-28 color-primary" @click="allRefund">全部提现</view> -->
       </view>
     </view>
     <view class="block mt-16">
@@ -75,11 +76,10 @@
 </template>
 
 <script setup lang="ts">
+import { applyRefund } from "@/api/user";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 
-// TODO 接口
-
 const user = ref();
 const value = ref(0);
 const reasonText = ref("");
@@ -96,6 +96,7 @@ const success = ref(false);
 onLoad(() => {
   if (getApp<any>().globalData.user) {
     user.value = getApp<any>().globalData.user;
+    allRefund();
   }
 });
 
@@ -111,7 +112,31 @@ const inputReasonText = (e: any) => {
   reasonText.value = e.detail.value;
 };
 const submit = () => {
-  success.value = true;
+  uni.showLoading({
+    title: "提交中",
+  });
+  let r = "";
+  if (reason.value >= 0) {
+    r += `${reasons.value[reason.value]}`;
+    if (reasonText.value) {
+      r += "|";
+    }
+  }
+  if (reasonText.value) {
+    r += reasonText.value;
+  }
+  applyRefund(r)
+    .then(() => {
+      uni.hideLoading();
+      success.value = true;
+    })
+    .catch(() => {
+      uni.hideLoading();
+      uni.showModal({
+        title: "温馨提示",
+        content: "提交失败,请重试",
+      });
+    });
 };
 const close = () => {
   success.value = false;

+ 8 - 3
src/pages.json

@@ -133,6 +133,14 @@
             "navigationBarTitleText": "联系我们",
             "navigationBarBackgroundColor": "#ffffff"
           }
+        },
+        {
+          "path": "invoice/invoice",
+          "style": {
+            "navigationStyle": "default",
+            "navigationBarTitleText": "我的发票",
+            "navigationBarBackgroundColor": "#F6F7FA"
+          }
         }
       ]
     }
@@ -162,9 +170,6 @@
       {
         "pagePath": "pages/map/map"
       },
-      {
-        "pagePath": "pages/list/list"
-      },
       {
         "pagePath": "pages/user/user"
       }

+ 1 - 0
src/pages/list/list.vue

@@ -36,6 +36,7 @@
 </template>
 
 <script setup lang="ts">
+// 废弃页面
 import { fetchStations } from "../../api/charge";
 import { fetchCollectList } from "../../api/user";
 import { useInfiniteScroll } from "../../utils/infinite-scroll";

+ 316 - 229
src/pages/map/map.vue

@@ -1,8 +1,128 @@
 <template>
   <view class="container">
+    <navigation-bar @ready="handleNavReady"></navigation-bar>
+    <view class="dialog" v-if="styleData.dialog" :style="styleData.dialog">
+      <view class="height-88 flex-align-center bg-fff">
+        <image
+          mode="widthFix"
+          src="/static/images/map-logo.png"
+          style="width: 156rpx"
+          class="ml-24"
+        ></image>
+        <image
+          mode="widthFix"
+          src="/static/images/map-input.png"
+          class="ml-24"
+          style="width: 352rpx"
+          @click="toSearch"
+        ></image>
+      </view>
+      <view
+        class="height-72 flex"
+        style="background-color: #f9f9f9"
+      >
+        <view class="width-half flex-center" @click.stop="checkFilterDistance">
+          <view class="fs-26 color-000-6 mr-8">距离</view>
+          <view
+            class="width-20 height-20 br-round bg-000-08 lh-10 text-center transition"
+            :style="{
+              transform: filterDialog.distanceSelector ? 'rotate(180deg)' : '',
+            }"
+          >
+            <uni-icons
+              type="bottom"
+              size="8"
+              color="rgba(0,0,0,0.4)"
+            ></uni-icons>
+          </view>
+        </view>
+        <view class="width-half flex-center" @click.stop="checkDiscounts">
+          <view
+            class="width-32 height-32 br-round lh-20 text-center"
+            :style="{
+              border: filterDialog.discounts
+                ? '1px solid var(--color-primary)'
+                : '1px solid rgba(0, 0, 0, 0.4)',
+              backgroundColor: filterDialog.discounts
+                ? 'var(--color-primary)'
+                : '#fff',
+            }"
+          >
+            <uni-icons
+              type="checkmarkempty"
+              size="10"
+              color="#ffffff"
+            ></uni-icons>
+          </view>
+          <view
+            :class="[
+              'fs-26',
+              'ml-8',
+              filterDialog.discounts ? 'color-primary' : 'color-000-6',
+            ]"
+            >支持省钱充电</view
+          >
+        </view>
+      </view>
+      <view
+        class="dialog_selector"
+        :style="{
+          height: filterDialog.distanceSelector ? '190rpx' : '0rpx',
+          borderTop: `1rpx solid rgba(0, 0, 0, ${
+            filterDialog.distanceSelector ? '0.1' : '0'
+          })`,
+        }"
+      >
+        <view class="flex-center flex-wrap pb-14">
+          <view
+            :class="[
+              'type',
+              'flex-shrink',
+              'flex-center',
+              'mt-20',
+              (index + 1) % 5 === 0 ? 'mr-0' : 'mr-20',
+              `type-${
+                item.value === filterDialog.options.distance ? 'active' : ''
+              }`,
+            ]"
+            v-for="(item, index) in filterDialog.distanceRange"
+            :key="index"
+            @click.stop="changeFilterDistance(index)"
+            style="width: 117rpx"
+            >{{ item.value }}km</view
+          >
+        </view>
+      </view>
+      <!-- <view class="dialog_event" v-if="ready && !filterDialog.distanceSelector">
+        // TODO 接入接口
+        <swiper
+          class="swiper"
+          circular
+          :indicator-dots="true"
+          :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>
+        </swiper>
+      </view> -->
+    </view>
+    <view
+      v-if="styleData.dialogHeight"
+      :style="{ height: `${styleData.dialogHeight}px` }"
+    ></view>
     <map
       id="map"
-      style="width: 100%; height: 100%; z-index: 1"
+      :style="{
+        width: '100%',
+        height: `calc(100vh - ${styleData.dialogHeight}px - ${styleData.cardHeight}px)`,
+        zIndex: 1,
+        pointerEvents: loading ? 'none' : 'auto',
+      }"
       :latitude="mapProps.latitude"
       :longitude="mapProps.longitude"
       :markers="markers"
@@ -14,118 +134,70 @@
       @markertap="tapMarker"
       :show-scale="true"
     ></map>
-    <view class="card" v-if="ready">
-      <swiper
-        class="mt-68"
-        :autoplay="false"
-        @change="changeMarker"
-        :current="markersIndex"
-      >
-        <block v-if="!empty">
-          <swiper-item v-for="(item, index) in station" :key="index">
-            <view class="station">
-              <charge-station
-                :title="item.stationName"
-                :address="item.address"
-                :price="item.totalFee"
-                :fast="item.fastEquipmentInfos"
-                :slow="item.slowEquipmentInfos"
-                :sId="item.StationID"
-                :distance="item.stationLatDistance"
-                :latitude="item.location.stationLat"
-                :longitude="item.location.stationLng"
-                :fromMap="true"
-              ></charge-station>
-            </view>
-          </swiper-item>
-        </block>
-        <block v-else>
-          <swiper-item>
-            <view class="station">
-              <view class="station-empty flex-column flex-align-center pt-20">
-                <image src="/static/images/map-empty.png" mode="widthFix" />
-                <view class="fs-22 mt-14" style="color: rgba(0, 0, 0, 0.5)"
-                  >暂无充电站信息</view
-                >
-              </view>
-            </view>
-          </swiper-item>
-        </block>
-      </swiper>
-    </view>
-    <view class="icon-menu" v-if="menuStyle.menu1" :style="menuStyle.menu1">
-      <view class="flex-center mt-40" @click="search" hover-class="hover">
-        <image src="/static/images/map-search.png" mode="widthFix" />
-      </view>
+    <view class="card" :style="{ height: `${styleData.cardHeight}px` }">
       <view
-        class="flex-center mt-40"
-        @click="toggleDialogVisible"
-        hover-class="hover"
+        class="card_location height-64 width-64 bg-fff flex-center"
+        @click="resetLocation"
       >
-        <image src="/static/images/map-filter.png" mode="widthFix" />
-      </view>
-    </view>
-    <view class="icon-menu" v-if="menuStyle.menu2" :style="menuStyle.menu2">
-      <view class="flex-center" hover-class="hover" @click="resetLocation">
-        <image src="/static/images/map-location.png" mode="widthFix" />
+        <image
+          src="/static/images/map-re-location.png"
+          mode="widthFix"
+          class="width-48"
+        ></image>
       </view>
-    </view>
-    <view
-      class="dialog"
-      v-if="filterDialog.visible"
-      @click="toggleDialogVisible"
-    >
-      <view class="filter-dialog" @click.stop="emptyTap">
-        <view :style="filterDialog.style"></view>
-        <view class="pl-40 pr-40">
-          <view class="pt-20 pb-20">
-            <text class="fs-30 fw-500">距离</text>
-          </view>
-          <view class="flex-wrap pb-14">
-            <view
-              :class="[
-                'type',
-                'flex-shrink',
-                'flex-center',
-                'mt-20',
-                (index + 1) % 5 === 0 ? 'mr-0' : 'mr-20',
-                `type-${
-                  item.value === filterDialog.options.distance ? 'active' : ''
-                }`,
-              ]"
-              v-for="(item, index) in filterDialog.range"
-              :key="index"
-              @click.stop="changeFilterDistance(index)"
-              style="width: 117rpx"
-              >{{ item.value }}km</view
-            >
-          </view>
-          <view class="fs-30 fw-500 pt-38 pb-20">充电状态</view>
-          <view class="flex pb-30">
-            <view
-              :class="[
-                'type',
-                'flex-center',
-                'mr-20',
-                `type-${index === filterDialog.options.status ? 'active' : ''}`,
-              ]"
-              v-for="(item, index) in filterDialog.status"
-              :key="index"
-              @click.stop="changeFilterStatus(index)"
-              >{{ item.title }}</view
-            >
-          </view>
-          <view class="foot flex-align-center">
-            <style-button size="small" @click.stop="resetFilter"
-              >重置</style-button
-            >
-            <view style="width: 30rpx"></view>
-            <style-button size="small" type="primary" @click.stop="submitFilter"
-              >确定</style-button
-            >
-          </view>
+      <block v-if="station.length">
+        <!-- 列表 -->
+        <!-- <view class="station" v-for="(item, index) in station" :key="index">
+          <view v-if="index !== 0" class="card_line"></view>
+          <charge-station
+            :title="item.stationName"
+            :address="item.address"
+            :price="item.totalFee"
+            :fast="item.fastEquipmentInfos"
+            :slow="item.slowEquipmentInfos"
+            :sId="item.StationID"
+            :distance="item.stationLatDistance"
+            :latitude="item.location.stationLat"
+            :longitude="item.location.stationLng"
+            :fromMap="true"
+          ></charge-station>
+        </view> -->
+        <!-- 单个 -->
+        <view class="station">
+          <charge-station
+            :title="station[markersIndex].stationName"
+            :address="station[markersIndex].address"
+            :price="station[markersIndex].totalFee"
+            :fast="station[markersIndex].fastEquipmentInfos"
+            :slow="station[markersIndex].slowEquipmentInfos"
+            :sId="station[markersIndex].StationID"
+            :distance="station[markersIndex].stationLatDistance"
+            :latitude="station[markersIndex].location.stationLat"
+            :longitude="station[markersIndex].location.stationLng"
+            :fromMap="true"
+          ></charge-station>
         </view>
-      </view>
+      </block>
+      <block v-else>
+        <view class="card_empty flex-column flex-align-center pt-20">
+          <view v-if="loading" class="mt-60 animation-loading"
+            ><uni-icons
+              type="spinner-cycle"
+              size="20"
+              color="rgba(0, 0, 0, 0.5)"
+            ></uni-icons
+          ></view>
+          <image
+            class="image"
+            v-else
+            src="/static/images/map-empty.png"
+            mode="widthFix"
+          />
+          <view class="fs-22 mt-14 color-000-5">{{
+            loading ? "加载中" : "暂无充电站信息"
+          }}</view>
+        </view>
+      </block>
     </view>
   </view>
   <view class="login-mask" v-if="!token">
@@ -151,27 +223,30 @@ const pointSize = {
   androidCurrentX: -20,
 };
 import { deCode } from "../../utils/code";
+import { rpxToPx } from "../../utils/device";
 import { fetchToken, login, onLogin } from "@/api/auth";
 import { fetchStations } from "@/api/charge";
 import { fetchCollectList } from "@/api/user";
 import { fetchLocation } from "@/utils/location";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
+
+// TODO 手势拖动
+
 const isIOS = ref(false);
 const token = ref<string>();
 const ready = ref(false);
-const empty = ref(true);
-const mapProps = ref({
-  latitude: 23.098994,
-  longitude: 113.32252,
-  selflatitude: 23.098994,
-  selflongitude: 113.32252,
-  scale: defaultScale,
+const loading = ref(false);
+const styleData = ref({
+  dialog: "",
+  dialogHeight: 0,
+  cardHeight: 0,
 });
+
 const filterDialog = ref({
-  visible: false,
-  style: {},
-  range: [
+  discounts: false,
+  distanceSelector: false,
+  distanceRange: [
     {
       value: 1,
       scale: defaultScale + 3,
@@ -229,17 +304,22 @@ const filterDialog = ref({
     },
   ],
 });
-const menuStyle = ref({
-  menu1: {},
-  menu2: {},
-});
+
 const stationPage = ref({
   page: 1,
   pageSize: 6,
   hasNext: false,
 });
 const station = ref<any[]>([]);
-const markersIndex = ref(0);
+
+const mapProps = ref({
+  latitude: 23.098994,
+  longitude: 113.32252,
+  selflatitude: 23.098994,
+  selflongitude: 113.32252,
+  scale: defaultScale,
+});
+const markersIndex = ref(-1);
 const markers = ref<any[]>([]);
 
 let isIgnoreChangeLocation = false;
@@ -323,9 +403,9 @@ const refreshStation = (location: any) => {
         height: 34,
       });
     }
-    isIgnoreChangeLocation = markers.value.length !== _markers.length
+    isIgnoreChangeLocation = markers.value.length !== _markers.length;
     stationPage.value.hasNext = res.length >= stationPage.value.pageSize;
-    empty.value = stationPage.value.page === 1 ? res.length <= 0 : false;
+    // empty.value = stationPage.value.page === 1 ? res.length <= 0 : false;
     station.value =
       stationPage.value.page === 1 ? res : [...station.value, ...res];
     markersIndex.value = _markersIndex;
@@ -335,16 +415,16 @@ const refreshStation = (location: any) => {
 };
 
 const refresh = () => {
+  if (loading.value) {
+    return;
+  }
   console.log("刷新电站");
-  uni.showLoading({
-    title: "加载中",
-  });
+  loading.value = true;
   stationPage.value.page = 1;
   stationPage.value.hasNext = false;
   station.value = [];
   markers.value = [];
   markersIndex.value = 0;
-  filterDialog.value.visible = false;
   fetchLocation()
     .then((res: any) => {
       mapProps.value.latitude = res.latitude;
@@ -355,18 +435,35 @@ const refresh = () => {
       return refreshStation(res);
     })
     .then(() => {
-      uni.hideLoading();
+      loading.value = false;
       ready.value = true;
     })
     .catch((err) => {
       console.log(err);
-      uni.hideLoading();
+      loading.value = false;
       uni.showModal({
         content: `${err.errMsg},请重试`,
       });
     });
 };
 
+const handleNavReady = (e: any) => {
+  styleData.value.dialog = `padding-top:${e.detail.statusBarHeight - 6}px;`;
+  styleData.value.dialogHeight =
+    e.detail.statusBarHeight -
+    6 +
+    rpxToPx(88) +
+    rpxToPx(72) -
+    e.detail.navigationBarHeight;
+  styleData.value.cardHeight = rpxToPx(402);
+};
+
+const toSearch = () => {
+  uni.navigateTo({
+    url: "/pages-charge/search/search",
+  });
+}
+
 onLoad((query: any) => {
   // 只为了打包进tab-bar使用
   console.log(fetchToken, login, onLogin);
@@ -375,17 +472,9 @@ onLoad((query: any) => {
     console.log("扫普通码", decodeURIComponent(query.q));
     getApp<any>().globalData.normalCode = decodeURIComponent(query.q); // 获取到二维码原始链接内容
   }
-  const menu = uni.getMenuButtonBoundingClientRect();
-  const window = uni.getWindowInfo();
   const device = uni.getSystemInfoSync();
   isIOS.value = device.osName === "ios";
-  menuStyle.value.menu1 = `top:${menu.top + menu.height}px;right:${
-    window.windowWidth - menu.right
-  }px;`;
-  menuStyle.value.menu2 = `bottom:420rpx;right:${
-    window.windowWidth - menu.right
-  }px;margin-bottom: constant(safe-area-inset-bottom);margin-bottom: env(safe-area-inset-bottom);`;
-  filterDialog.value.style = `height:${menu.bottom + 6}px;`;
+
   setTimeout(() => {
     token.value = getApp<any>().globalData.token || "";
     if (!token.value) {
@@ -430,33 +519,29 @@ onLoad((query: any) => {
   }, 300);
 });
 
-const toggleDialogVisible = () => {
-  filterDialog.value.visible = !filterDialog.value.visible;
-};
-const changeFilterDistance = (index: number) => {
-  filterDialog.value.options.distance = filterDialog.value.range[index].value;
-};
-const changeFilterStatus = (index: number) => {
-  filterDialog.value.options.status = index;
+const checkDiscounts = () => {
+  filterDialog.value.discounts = !filterDialog.value.discounts;
 };
-const resetFilter = () => {
-  filterDialog.value.options.distance = defaulDistance;
-  filterDialog.value.options.status = 0;
-  refresh();
+
+const checkFilterDistance = () => {
+  filterDialog.value.distanceSelector = !filterDialog.value.distanceSelector;
 };
-const submitFilter = () => {
-  const findIndex = filterDialog.value.range.findIndex(
-    (item) => item.value === filterDialog.value.options.distance
-  );
-  if (mapProps.value.scale === filterDialog.value.range[findIndex].scale) {
-    filterDialog.value.visible = false;
+
+const changeFilterDistance = (index: number) => {
+  filterDialog.value.options.distance =
+    filterDialog.value.distanceRange[index].value;
+  if (mapProps.value.scale === filterDialog.value.distanceRange[index].scale) {
     refresh();
     return;
   }
-  filterDialog.value.visible = false;
-  mapProps.value.scale = filterDialog.value.range[findIndex].scale;
+  mapProps.value.scale = filterDialog.value.distanceRange[index].scale;
+  checkFilterDistance();
 };
+
 const resetLocation = () => {
+  if (loading.value) {
+    return;
+  }
   // eslint-disable-next-line promise/catch-or-return
   fetchLocation().then((res: any) => {
     const mapCtx = uni.createMapContext("map");
@@ -468,6 +553,7 @@ const resetLocation = () => {
     mapProps.value.scale = defaultScale;
   });
 };
+
 const mapUpdated = (e: any) => {
   // console.log('map updated', isIgnoreChangeLocation)
   setTimeout(() => {
@@ -480,7 +566,7 @@ const mapChange = (e: any) => {
   }
   if (e.type === "end" && markers.value.length) {
     console.log("map change end", {
-      ...e.detail.centerLocation
+      ...e.detail.centerLocation,
     });
     const current = e.target.centerLocation;
     const { latitude, longitude } = current;
@@ -523,9 +609,6 @@ const _changeMarker = (current: number) => {
     });
   }
 };
-const changeMarker = (e: any) => {
-  _changeMarker(e.detail.current);
-};
 const tapMarker = (e: any) => {
   if (e.detail.markerId === -1) {
     return;
@@ -537,19 +620,26 @@ const tapMarker = (e: any) => {
     _changeMarker(findIndex);
   }
 };
-const search = () => {
-  uni.navigateTo({
-    url: "/pages-charge/search/search",
-  });
-};
 const loginMask = (e: any) => {
   login(e);
 };
-const emptyTap = () => {};
+
+// TORM
+// const changeMarker = (e: any) => {
+//   _changeMarker(e.detail.current);
+// };
+// const emptyTap = () => {};
+// const changeFilterStatus = (index: number) => {
+//   filterDialog.value.options.status = index;
+// };
+// const resetFilter = () => {
+//   filterDialog.value.options.distance = defaulDistance;
+//   filterDialog.value.options.status = 0;
+//   refresh();
+// };
 </script>
 
 <style lang="scss">
-@import "../../styles/dialog.scss";
 page {
   background-color: #ffffff;
 }
@@ -576,31 +666,45 @@ page {
   }
 }
 
-.icon-menu {
-  position: absolute;
-  z-index: 9;
+.dialog {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  z-index: 999;
 
-  image {
-    width: 60rpx;
+  &_event {
+    margin-top: 20rpx;
+    padding: 0rpx 32rpx;
+    .swiper {
+      height: 176rpx;
+      width: 100%;
+      border-radius: 16rpx;
+      overflow: hidden;
+    }
   }
 
-  & > view {
-    height: 96rpx;
-    width: 96rpx;
-    border-radius: 50%;
-    background-color: #fff;
-    box-shadow: 0px 8rpx 20rpx rgba(0, 0, 0, 0.2);
-  }
+  &_selector {
+    background-color: #f9f9f9;
+    transition: all 0.3s;
+    overflow: hidden;
+    .type {
+      width: 160rpx;
+      height: 60rpx;
+      background: var(--color-sec);
+      border-radius: 4rpx;
+      color: #666;
+      font-size: 26rpx;
+      border: 1px solid var(--color-sec);
+    }
 
-  .hover {
-    box-shadow: none;
+    .type-active {
+      border: 1px solid var(--color-primary);
+      color: var(--color-primary);
+    }
   }
-}
-
-.filter-dialog {
-  background-color: #fff;
 
-  .slider {
+  /* .slider {
     position: relative;
     height: 12rpx;
     width: 100%;
@@ -637,61 +741,44 @@ page {
       margin: 0;
       opacity: 0;
     }
-  }
-
-  .type {
-    width: 160rpx;
-    height: 60rpx;
-    background: var(--color-sec);
-    border-radius: 4rpx;
-    color: var(--color-gray);
-    font-size: 26rpx;
-    border: 1px solid var(--color-sec);
-  }
-
-  .type-active {
-    border: 1px solid var(--color-primary);
-    color: var(--color-primary);
-  }
-
-  .foot {
-    height: 120rpx;
-    border-top: 1rpx solid var(--color-sec);
-  }
+  } */
 }
 
 .card {
-  position: absolute;
+  position: fixed;
   width: 100%;
-  height: 450rpx;
+  /* max-height: 622rpx; */ 
   left: 0px;
   bottom: 0rpx;
-  z-index: 9;
-  background: linear-gradient(180deg, rgba(87, 104, 133, 0) 0%, #576885 100%);
-  padding-left: 10rpx;
+  z-index: 999;
+  box-shadow: 0px 8rpx 20rpx rgba(0, 0, 0, 0.2);
+  background-color: #fff;
   margin-bottom: constant(safe-area-inset-bottom);
   margin-bottom: env(safe-area-inset-bottom);
+  border-radius: 16rpx 16rpx 0px 0px;
 
-  swiper,
-  swiper-item {
-    width: 100%;
-    height: 300rpx;
+  &_location {
+    position: absolute;
+    border-radius: 16rpx;
+    box-shadow: 0px 8rpx 20rpx 0px rgba(0, 0, 0, 0.2);
+    right: 20rpx;
+    top: -104rpx;
   }
 
-  .station {
-    width: 100%;
-    height: 100%;
-    padding: 0rpx 20rpx;
+  &_line {
+    height: 1rpx;
+    background-color: rgba(0, 0, 0, 0.1);
+    margin-left: 30rpx;
+    margin-right: 30rpx;
   }
 
-  .station-empty {
+  &_empty {
     width: 100%;
     height: 100%;
-    background-color: #fff;
-    border-radius: 20rpx 20rpx 0 0;
-    image {
+    .image {
       width: 160rpx;
     }
   }
 }
+
 </style>

+ 0 - 1
src/pages/user/user.vue

@@ -127,7 +127,6 @@ onShow(() => {
   fetchProfile().then((res) => {
     res.mobilePhone =
       res.mobilePhone.slice(0, 3) + "****" + res.mobilePhone.slice(7);
-    res.balance = (Number(res.balance) / 100).toFixed(2);
     res.avatar = res.avatar
       ? res.avatar
       : "https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0";

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


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


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


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


BIN
src/static/images/map-re-location.png


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


+ 4 - 0
src/styles/layout.scss

@@ -47,4 +47,8 @@ $position: top, right, bottom, left;
 
 .width-168 {
   width: 168rpx;
+}
+
+.width-half {
+  width: 50%;
 }

+ 5 - 1
src/utils/constant.ts

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