Jelajahi Sumber

feat:发票

needcode 2 tahun lalu
induk
melakukan
8e19af496e

+ 10 - 0
src/App.vue

@@ -103,11 +103,21 @@ image {
   background-color: rgba(0, 0, 0, 0.08);
 }
 
+.bg-primary {
+  background-color: var(--color-primary);
+}
+
 .full-percent {
   height: 100%;
   width: 100%;
 }
 
+.absolute-top-left {
+  position: absolute;
+  left: 0px;
+  top: 0px;
+}
+
 .absolute-full {
   position: absolute;
   left: 0px;

+ 13 - 5
src/api/index.ts

@@ -1,12 +1,20 @@
-import Http from '../utils/http'
-import { host } from '../utils/constant'
+import Http from "../utils/http";
+import { host } from "../utils/constant";
 
-const indexHttp = new Http(host)
+const indexHttp = new Http(host);
 
 export function fetchContact() {
-  return indexHttp.get('/common/contact')
+  return indexHttp.get("/common/contact");
 }
 
 export function fetchCommonQuestions() {
-  return indexHttp.get('/qa')
+  return indexHttp.get("/qa");
+}
+
+export function applyInvoice(startChargeSeqs: string[]) {
+  return indexHttp.post("/invoice/applyInvoice", {
+    data: {
+      startChargeSeqs,
+    },
+  });
 }

+ 29 - 0
src/components/style-checkbox/style-checkbox.vue

@@ -0,0 +1,29 @@
+<template>
+  <view
+    class="height-32 width-32 lh-24 br-round flex-justify-center"
+    :style="{
+      border: checked
+        ? '1rpx solid var(--color-primary)'
+        : '1rpx solid rgba(0,0,0,0.15)',
+      backgroundColor: checked ? 'var(--color-primary)' : 'rgba(0,0,0,0.1)',
+    }"
+  >
+    <uni-icons
+      v-if="checked"
+      type="checkmarkempty"
+      size="10"
+      color="#ffffff"
+    ></uni-icons>
+  </view>
+</template>
+
+<script lang="ts">
+export default {
+  props: {
+    checked: Boolean,
+  },
+};
+</script>
+
+<style lang="scss">
+</style>

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

@@ -47,26 +47,7 @@
             }}</view>
           </view>
           <view class="ml-auto">
-            <view
-              class="height-32 width-32 lh-24 br-round flex-justify-center"
-              :style="{
-                border:
-                  chargeType === index
-                    ? '1rpx solid var(--color-primary)'
-                    : '1rpx solid rgba(0,0,0,0.15)',
-                backgroundColor:
-                  chargeType === index
-                    ? 'var(--color-primary)'
-                    : 'rgba(0,0,0,0.1)',
-              }"
-            >
-              <uni-icons
-                v-if="chargeType === index"
-                type="checkmarkempty"
-                size="10"
-                color="#ffffff"
-              ></uni-icons>
-            </view>
+            <style-checkbox :checked="chargeType === index"></style-checkbox>
           </view>
         </view>
       </view>
@@ -297,6 +278,11 @@ const submit = () => {
 onLoad((_options: any) => {
   // sn=SN100523042860091 测试环境
   const sn = _options.sn || "SN100523042860091";
+  // debug
+  uni.navigateTo({
+    url: `/pages-charge/ordering/ordering?sn=${sn}`,
+  });
+  return
   uni.showLoading({
     title: "加载中",
   });

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

@@ -100,7 +100,8 @@ export default {
         list &&
         list[index].connectorStatusInfo &&
         list[index].connectorStatusInfo.status &&
-        list[index].connectorStatusInfo.status === 1
+        (list[index].connectorStatusInfo.status === 1 ||
+          list[index].connectorStatusInfo.status === 2)
       ) {
         uni.showActionSheet({
           itemList: ["去充电"],

+ 2 - 0
src/pages-charge/order/order.vue

@@ -9,6 +9,8 @@ import { fetchOrder } from "../../api/user";
 import { onLoad } from "@dcloudio/uni-app";
 import { ref } from "vue";
 
+// TODO 优惠金额
+
 const list = ref<any[]>();
 onLoad((options: any) => {
   fetchOrder(options.id)

+ 128 - 0
src/pages-charge/orders/orders.vue

@@ -9,6 +9,9 @@
       :key="index"
       @click="detail(index)"
     >
+      <view class="mr-28" v-if="isInvoice">
+        <style-checkbox :checked="item.checked"></style-checkbox>
+      </view>
       <view>
         <view class="fs-30 fw-500" key="title" duration="300">充电费用</view>
         <view class="fs-24 mt-10" style="color: rgba(0, 0, 0, 0.4)">{{
@@ -33,34 +36,152 @@
     v-if="infiniteScroller.list && infiniteScroller.list.length <= 0"
     >暂无数据</view
   >
+
+  <view class="foot-placeholder"></view>
+
+  <style-bottom-view>
+    <view class="foot flex-align-center flex-justify-end" v-if="!isInvoice">
+      <view
+        class="flex-center mr-40 height-72 br-72"
+        style="width: 176rpx; border: 1rpx solid rgba(0, 0, 0, 0.2)"
+        @click="openInvoice"
+      >
+        <view class="fs-28 color-333 mr-12">开发票</view>
+        <uni-icons type="right" size="14" color="#333"></uni-icons>
+      </view>
+    </view>
+    <view class="foot flex-align-center relative" v-else>
+      <view
+        class="height-56 flex-align-center absolute-top-left pl-30"
+        style="
+          background-color: #f6f7fa;
+          width: 100%;
+          transform: translateY(-100%);
+        "
+      >
+        <view class="fs-28 color-primary mr-8">{{ checkedCount }}</view>
+        <view class="fs-28 color-000">个订单,共</view>
+        <view class="fs-28 color-primary mr-8 ml-8">{{ checkedPrice }}</view>
+        <view class="fs-28 color-000">元</view>
+      </view>
+      <view class="flex-align-center ml-30" @click="checkPage">
+        <style-checkbox :checked="checkAll"></style-checkbox>
+        <view class="ml-16 fs-28 color666">本页全选</view>
+      </view>
+      <view
+        class="ml-auto mr-40 bg-primary height-80 br-80 fs-32 fw-500 color-fff flex-center"
+        style="width: 216rpx"
+        @click="nextInvoice"
+        >下一步</view
+      >
+    </view>
+  </style-bottom-view>
 </template>
 
 <script setup lang="ts">
 import { onLoad, onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app";
 import { fetchWallet } from "../../api/user";
+import { applyInvoice } from "../../api/index";
 import { useInfiniteScroll } from "../../utils/infinite-scroll";
+import { ref } from "vue";
+
+const isInvoice = ref(false);
+const checkAll = ref(false);
+const checkedPrice = ref(0);
+const checkedCount = ref(0);
+
 const infiniteScroller = useInfiniteScroll(10, (page) => {
   return fetchWallet(3, page, 10).then((res: any) => {
     if (res && res.length) {
       res.forEach((item: any) => {
         item.amount = (Number(item.amount) / 100).toFixed(2);
+        item.checked = false;
       });
     }
     return res;
   });
 });
+
+const setCheckData = () => {
+  let count = 0;
+  let price = 0;
+  infiniteScroller.list.forEach((item: any) => {
+    if (item.checked) {
+      count++;
+      price += Number(item.amount);
+    }
+  });
+  checkAll.value = infiniteScroller.list.every((item: any) => item.checked);
+  checkedCount.value = count;
+  checkedPrice.value = Number(Number(price).toFixed(2));
+};
 const detail = (index: number) => {
   if (!infiniteScroller.list) {
     return;
   }
+  if (isInvoice) {
+    infiniteScroller.list[index].checked =
+      !infiniteScroller.list[index].checked;
+    setCheckData();
+    return;
+  }
   uni.navigateTo({
     url: `/pages-charge/order/order?id=${infiniteScroller.list[index].orderNo}`,
   });
 };
+const openInvoice = () => {
+  isInvoice.value = true;
+};
+const nextInvoice = () => {
+  // const ids = infiniteScroller.list
+  //   .filter((item: any) => item.checked)
+  //   .map((item: any) => item.orderNo)
+  //   .join("|");
+  //   uni.navigateTo({
+  //   url: `/pages-common/invoice/invoice?ids=${ids}`,
+  // });
+  uni.showLoading({
+    title: "请求中",
+  });
+  applyInvoice(
+    infiniteScroller.list
+      .filter((item: any) => item.checked)
+      .map((item: any) => item.orderNo)
+  )
+    .then((res) => {
+      uni.hideLoading();
+      uni.navigateToMiniProgram({
+        appId: res.miniprogramAppid,
+        path: res.miniprogramPath,
+        success(res) {
+          console.log("打开成功");
+        },
+      });
+    })
+    .catch((err) => {
+      uni.hideLoading();
+      uni.showModal({
+        content: `${err.errMsg},请重试`,
+      });
+    });
+};
+const checkPage = () => {
+  infiniteScroller.list = infiniteScroller.list.map((item: any) => {
+    return {
+      ...item,
+      checked: checkAll.value ? false : true,
+    };
+  });
+  setCheckData();
+};
+
 onLoad(() => {
   infiniteScroller.refresh();
 });
 onPullDownRefresh(() => {
+  if (isInvoice.value) {
+    return
+  }
   infiniteScroller.refresh();
 });
 onReachBottom(() => {
@@ -73,4 +194,11 @@ onReachBottom(() => {
   height: 170rpx;
   border-bottom: 1rpx solid rgba(0, 0, 0, 0.1);
 }
+.foot-placeholder {
+  height: 112rpx;
+}
+.foot {
+  height: 112rpx;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
 </style>

+ 53 - 2
src/pages-common/invoice/invoice.vue

@@ -1,8 +1,59 @@
 <template>
-  <view></view>
+  <view class="page">
+    <style-bottom-view background="#f6f7fa">
+      <view class="pt-20 pl-60 pr-60 pb-20">
+        <style-button type="primary" size="small" @click="openPath">提交</style-button>
+      </view>
+    </style-bottom-view>
+  </view>
 </template>
 
 <script setup lang="ts">
+import { applyInvoice } from "@/api";
+import { onLoad } from "@dcloudio/uni-app";
+import { ref } from "vue";
+
+const path = ref();
+
+onLoad((options: any) => {
+  uni.showLoading({
+    title: "加载中",
+  });
+  applyInvoice(options.ids.split("|"))
+    .then((res) => {
+      console.log(res);
+      path.value = res;
+      uni.hideLoading();
+    })
+    .catch((err) => {
+      uni.hideLoading();
+      uni.showModal({
+        content: `${err.errMsg},请重试`,
+      });
+    });
+});
+
+const openPath = () => {
+  uni.navigateToMiniProgram({
+    appId: path.value.miniprogramAppid,
+    path: path.value.miniprogramPath,
+    success(res) {
+      console.log('打开成功')
+    },
+  });
+};
+const chooseInvoiceTitle = () => {
+  uni.chooseInvoiceTitle({
+    success: (res) => {
+      console.log(res);
+    },
+  });
+};
 </script>
 
-<style lang="scss"></style>
+<style lang="scss">
+.page {
+  min-height: 100vh;
+  background-color: #f6f7fa;
+}
+</style>

+ 22 - 5
src/pages-user/wallet-recharge/wallet-recharge.vue

@@ -13,6 +13,7 @@
           :key="index"
           @click="changeOption(index)"
         >
+          <view class="tag fs-26 color-fff fw-500">充电服务费9折</view>
           {{ item }}
         </view>
       </view>
@@ -27,14 +28,16 @@
   </view>
 
   <style-bottom-view>
-    <view class="pl-30 pr-30 pb-20">
-      <style-button type="primary" @click="confirm">充值</style-button>
+    <view class="pl-60 pr-60 pb-20">
+      <style-button size="small" type="primary" @click="confirm"
+        >充值</style-button
+      >
     </view>
   </style-bottom-view>
 </template>
 
 <script setup lang="ts">
-// 样式、 充值优惠
+// TODO 充值优惠
 import { ref } from "vue";
 import { fetchProfile, insertMoney } from "../../api/user";
 import { onLoad } from "@dcloudio/uni-app";
@@ -79,7 +82,7 @@ const confirm = () => {
       });
       fetchProfile().then((res) => {
         payValue.value = 0;
-        balance.value = res.balance
+        balance.value = res.balance;
       });
     })
     .catch((err) => {
@@ -111,15 +114,29 @@ onLoad(() => {
   }
 
   .option {
+    position: relative;
     width: 214rpx;
-    height: 82rpx;
+    height: 140rpx;
     background: var(--color-sec);
     border-radius: 10rpx;
     margin-left: 20rpx;
     margin-bottom: 20rpx;
+    font-size: 36rpx;
+    color: #000;
+    font-weight: 500;
+    overflow: hidden;
     &:nth-child(3n + 1) {
       margin-left: 0;
     }
+    .tag {
+      position: absolute;
+      top: 0px;
+      right: 0px;
+      border-radius: 30rpx 0px 0px 30rpx;
+      box-sizing: content-box;
+      padding: 2rpx 10rpx;
+      background: linear-gradient(90deg, #f366ff 0%, #5e98ff 100%);
+    }
   }
   .option-active {
     background-color: var(--color-primary);

+ 1 - 1
src/pages.json

@@ -138,7 +138,7 @@
           "path": "invoice/invoice",
           "style": {
             "navigationStyle": "default",
-            "navigationBarTitleText": "我的发票",
+            "navigationBarTitleText": "发票",
             "navigationBarBackgroundColor": "#F6F7FA"
           }
         }

+ 1 - 1
src/utils/constant.ts

@@ -13,7 +13,7 @@ isDevelopment = env === "develop" || env === "trial";
 // #endif
 
 // debug
-isDevelopment = false
+// isDevelopment = false
 
 export const domain = isDevelopment ? "dev.kuaiyuman.cn" : "www.kuaiyuman.cn";
 export const host = `https://${domain}/api`;