|
@@ -0,0 +1,492 @@
|
|
|
+<template>
|
|
|
+ <div class="charge-index">
|
|
|
+ <div class="background">
|
|
|
+ <div class="headline"></div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="title">我的卡片 (2)</div>
|
|
|
+ <div
|
|
|
+ class="gasoline"
|
|
|
+ v-for="item in cardList"
|
|
|
+ :key="item.id"
|
|
|
+ :class="[
|
|
|
+ item.cardOilsType == 1
|
|
|
+ ? 'gasoline'
|
|
|
+ : item.cardOilsType == 2
|
|
|
+ ? 'diesel'
|
|
|
+ : '',
|
|
|
+ ]"
|
|
|
+ >
|
|
|
+ <div class="title">
|
|
|
+ {{
|
|
|
+ item.cardOilsType == 1
|
|
|
+ ? "汽油卡"
|
|
|
+ : item.cardOilsType == 2
|
|
|
+ ? "柴油卡"
|
|
|
+ : ""
|
|
|
+ }}
|
|
|
+ </div>
|
|
|
+ <div class="text">
|
|
|
+ 余额 <span>{{ item.amt.toFixed(2) }}</span
|
|
|
+ >元
|
|
|
+ </div>
|
|
|
+ <button @click="goCharge(item)">充值</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="mask" :class="[mask ? '' : 'hidden']">
|
|
|
+ <div class="layer" @click="switchMask"></div>
|
|
|
+ <div class="charge">
|
|
|
+ <div class="title">
|
|
|
+ 充值
|
|
|
+ <div class="close" @click="switchMask"></div>
|
|
|
+ </div>
|
|
|
+ <div class="tip">提示:充值汽油1000元,赠送100元,实际到账1100元</div>
|
|
|
+ <div class="amount">
|
|
|
+ <span>{{
|
|
|
+ chargeItem.cardOilsType == 1
|
|
|
+ ? "汽油充值"
|
|
|
+ : chargeItem.cardOilsType == 2
|
|
|
+ ? "柴油充值"
|
|
|
+ : ""
|
|
|
+ }}</span>
|
|
|
+ <input
|
|
|
+ placeholder="输入充值金额"
|
|
|
+ v-model="chargeAmount"
|
|
|
+ type="number"
|
|
|
+ step="0.01"
|
|
|
+ min="0"
|
|
|
+ onkeyup="this.value= this.value.match(/\d+(\.\d{0,2})?/) ? this.value.match(/\d+(\.\d{0,2})?/)[0] : ''"
|
|
|
+ />
|
|
|
+ <span>¥</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <van-button
|
|
|
+ :class="[chargeAmount !== '' ? 'selected' : '']"
|
|
|
+ :loading="payLoading"
|
|
|
+ loading-text="拉取支付中..."
|
|
|
+ @click="charge"
|
|
|
+ :disabled="chargeAmount === ''"
|
|
|
+ >
|
|
|
+ 确认充值
|
|
|
+ </van-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import ProductList from "../../components/ProductList";
|
|
|
+import { mapState, mapGetters, mapActions } from "vuex";
|
|
|
+import wx from "weixin-js-sdk";
|
|
|
+import Vue from "vue";
|
|
|
+import { Toast, Button } from "vant";
|
|
|
+
|
|
|
+Vue.use(Toast);
|
|
|
+Vue.use(Button);
|
|
|
+
|
|
|
+export default {
|
|
|
+ head() {
|
|
|
+ return {
|
|
|
+ title: "会员充值",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ mask: false,
|
|
|
+ cardList: [],
|
|
|
+ chargeItem: {},
|
|
|
+ chargeAmount: "",
|
|
|
+ stationInfo: {},
|
|
|
+ payLoading: false,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ components: {
|
|
|
+ ProductList,
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapState({
|
|
|
+ pointInfo: (state) => state.point.pointInfo,
|
|
|
+ }),
|
|
|
+ ...mapGetters({
|
|
|
+ userInfo: "authen/userInfo",
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.init();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ ...mapActions({
|
|
|
+ getSdkConfig: "authen/getSdkConfig",
|
|
|
+ }),
|
|
|
+ switchMask() {
|
|
|
+ this.mask = !this.mask;
|
|
|
+ },
|
|
|
+ goCharge(ele) {
|
|
|
+ this.chargeItem = ele;
|
|
|
+ this.switchMask();
|
|
|
+ },
|
|
|
+ charge() {
|
|
|
+ this.chargeAmount = this.chargeAmount.replace(/\.$/g, "");
|
|
|
+ this.pay();
|
|
|
+ },
|
|
|
+ init() {
|
|
|
+ // 获取卡片
|
|
|
+ this.$axios
|
|
|
+ .$get("/getElectronicCardList", {
|
|
|
+ params: {
|
|
|
+ unionId: this.unionId,
|
|
|
+ stationId: 1,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ if (res.retCode === 0) {
|
|
|
+ this.cardList = res.data;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 这一块纯为了后端方便而已,获取station的信息
|
|
|
+ this.$axios
|
|
|
+ .$get("/getStationInfo", {
|
|
|
+ params: {
|
|
|
+ stationId: this.stationId,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ this.stationInfo = res.data;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async pay() {
|
|
|
+ try {
|
|
|
+ this.payLoading = true;
|
|
|
+ const orderData = await this.$axios.$post("/rechargeBalance", {
|
|
|
+ amt: this.chargeAmount,
|
|
|
+ stationId: this.stationId,
|
|
|
+ customerName: this.userInfo.nickname,
|
|
|
+ cardOilsType: this.chargeItem.cardOilsType,
|
|
|
+ payType: "1",
|
|
|
+ unionId: this.unionId,
|
|
|
+ stationName: this.stationInfo.stationName,
|
|
|
+ });
|
|
|
+ if (orderData.retCode !== 0) {
|
|
|
+ throw new Error("生成订单失败");
|
|
|
+ }
|
|
|
+ const orderNum = orderData.data;
|
|
|
+ const subject =
|
|
|
+ this.stationInfo.stationName +
|
|
|
+ "_" +
|
|
|
+ (this.chargeItem.cardOilsType == 1
|
|
|
+ ? "汽油电子卡充值"
|
|
|
+ : this.chargeItem.cardOilsType == 2
|
|
|
+ ? "柴油电子卡充值"
|
|
|
+ : "");
|
|
|
+ console.log(subject);
|
|
|
+ const payInfoData = await this.$axios.$post("/rechargeBalanceSXFPay", {
|
|
|
+ amt: this.chargeAmount,
|
|
|
+ openId: this.openId,
|
|
|
+ stationId: this.stationId,
|
|
|
+ userType: "1",
|
|
|
+ subject,
|
|
|
+ orderNo: orderNum,
|
|
|
+ });
|
|
|
+ if (payInfoData.retCode !== 0) {
|
|
|
+ throw new Error("支付参数拉取失败");
|
|
|
+ }
|
|
|
+ if (payInfoData.data.code !== "0000") {
|
|
|
+ throw new Error(payInfoData.data.msg);
|
|
|
+ }
|
|
|
+ const timestamp = payInfoData.data.respData.payTimeStamp;
|
|
|
+ const nonceStr = payInfoData.data.respData.paynonceStr;
|
|
|
+ const packageOrg = payInfoData.data.respData.payPackage;
|
|
|
+ const signType = payInfoData.data.respData.paySignType;
|
|
|
+ const paySign = payInfoData.data.respData.paySign;
|
|
|
+
|
|
|
+ // 拉取微信支付
|
|
|
+ this.getSdkConfig([
|
|
|
+ "openLocation",
|
|
|
+ "getNetworkType",
|
|
|
+ "chooseWXPay",
|
|
|
+ ]).then((res) => {
|
|
|
+ wx.config(res);
|
|
|
+ });
|
|
|
+ const that = this;
|
|
|
+ wx.ready(function (res) {
|
|
|
+ wx.chooseWXPay({
|
|
|
+ timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
|
|
|
+ nonceStr, // 支付签名随机串,不长于 32 位
|
|
|
+ package: packageOrg, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
|
|
|
+ signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
|
|
|
+ paySign, // 支付签名
|
|
|
+ success: function (res) {
|
|
|
+ // that.$router.push("/personal/charge");
|
|
|
+ that.payLoading = false;
|
|
|
+ alert("支付完成");
|
|
|
+ },
|
|
|
+ cancel: function (err) {
|
|
|
+ that.payLoading = false;
|
|
|
+ alert("您取消了付款");
|
|
|
+ },
|
|
|
+ fail: function (err) {
|
|
|
+ that.payLoading = false;
|
|
|
+ alert(err);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+ wx.error(function (res) {
|
|
|
+ alert("拉取微信Sdk配置出错");
|
|
|
+ });
|
|
|
+ } catch (err) {
|
|
|
+ this.payLoading = false;
|
|
|
+ alert(err);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+.charge-index {
|
|
|
+ position: relative;
|
|
|
+ height: 100vh;
|
|
|
+}
|
|
|
+.charge-index .background {
|
|
|
+ background-color: #f3b335;
|
|
|
+ width: 7.5rem;
|
|
|
+ height: 7.5rem;
|
|
|
+ position: relative;
|
|
|
+ background: url("~static/personal/23@2x.png") no-repeat 0px 0px;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ z-index: -1;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .background .headline {
|
|
|
+ width: 6.9rem;
|
|
|
+ height: 4.33rem;
|
|
|
+ background: url("~static/personal/bj2@2x.png") no-repeat 0px 0px;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ margin: 0.3rem auto;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .content {
|
|
|
+ position: absolute;
|
|
|
+ top: 3.78rem;
|
|
|
+ bottom: 0rem;
|
|
|
+ left: 0rem;
|
|
|
+ right: 0rem;
|
|
|
+ background-color: #ffffff;
|
|
|
+ border-radius: 0.3rem 0.3rem 0 0;
|
|
|
+ padding: 0.3rem;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+.charge-index .content > div:not(.title) {
|
|
|
+ width: 6.9rem;
|
|
|
+ height: 1.6rem;
|
|
|
+ margin-top: 0.3rem;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+.charge-index .content .title {
|
|
|
+ font-size: 0.35rem;
|
|
|
+ color: #333333;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+.charge-index .content .gasoline {
|
|
|
+ background: url("~static/personal/bj3@2x.png") no-repeat 0px 0px;
|
|
|
+ background-size: 100% 100%;
|
|
|
+}
|
|
|
+.charge-index .content .diesel {
|
|
|
+ background: url("~static/personal/bj4@2x.png") no-repeat 0px 0px;
|
|
|
+ background-size: 100% 100%;
|
|
|
+}
|
|
|
+.charge-index .content div .title {
|
|
|
+ height: 0.45rem;
|
|
|
+ font-size: 0.32rem;
|
|
|
+ font-family: PingFangSC-Medium, PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 0.45rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.27rem;
|
|
|
+ left: 1.67rem;
|
|
|
+}
|
|
|
+.charge-index .content .gasoline .text {
|
|
|
+ height: 0.45rem;
|
|
|
+ font-size: 0.32rem;
|
|
|
+ font-family: PingFangSC-Medium, PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #3db58f;
|
|
|
+ line-height: 0.45rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.9rem;
|
|
|
+ left: 1.67rem;
|
|
|
+}
|
|
|
+.charge-index .content .diesel .text {
|
|
|
+ height: 0.45rem;
|
|
|
+ font-size: 0.32rem;
|
|
|
+ font-family: PingFangSC-Medium, PingFang SC;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ea8c7d;
|
|
|
+ line-height: 0.45rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.9rem;
|
|
|
+ left: 1.67rem;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .content div .text span {
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+.charge-index .content div button {
|
|
|
+ border: none;
|
|
|
+ background-color: transparent;
|
|
|
+ outline: none;
|
|
|
+ display: block;
|
|
|
+ width: 1.4rem;
|
|
|
+ height: 0.6rem;
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 0.3rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.5rem;
|
|
|
+ right: 0.3rem;
|
|
|
+}
|
|
|
+.charge-index .content .gasoline button {
|
|
|
+ color: #24ac81;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .content .diesel button {
|
|
|
+ color: #e87d6d;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .mask {
|
|
|
+ position: fixed;
|
|
|
+ height: 100%;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ transition: all 2s linear 2s;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .hidden {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .mask .layer {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ background: #111111;
|
|
|
+ opacity: 0.59;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .mask .charge {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ height: 7.5rem;
|
|
|
+ background: #f2f2f2;
|
|
|
+ border-radius: 0.42rem 0.42rem 0rem 0rem;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 0.3rem 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ transition: all 2s linear;
|
|
|
+}
|
|
|
+/*
|
|
|
+.charge-index .hidden .charge{
|
|
|
+ height: 0;
|
|
|
+}
|
|
|
+*/
|
|
|
+
|
|
|
+.charge-index .mask .charge div:not(:nth-child(1)) {
|
|
|
+ margin-top: 0.2rem;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .title {
|
|
|
+ width: 6.5rem;
|
|
|
+ height: 0.45rem;
|
|
|
+ font-size: 0.32rem;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #111111;
|
|
|
+ line-height: 0.45rem;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .title .close {
|
|
|
+ background: url("~static/personal/6_d05_close@2x.png") no-repeat 0px 0px;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ width: 0.4rem;
|
|
|
+ height: 0.4rem;
|
|
|
+ float: right;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .tip {
|
|
|
+ height: 0.33rem;
|
|
|
+ font-size: 0.24rem;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #aaaaaa;
|
|
|
+ line-height: 0.33rem;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .amount {
|
|
|
+ width: 6.9rem;
|
|
|
+ height: 1.2rem;
|
|
|
+ background: url("~static/personal/biankuang@2x.png") no-repeat 0px 0px;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .amount span:nth-child(1) {
|
|
|
+ height: 0.4rem;
|
|
|
+ font-size: 0.28rem;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #884e16;
|
|
|
+ line-height: 0.4rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.4rem;
|
|
|
+ left: 0.51rem;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .amount input {
|
|
|
+ background: none;
|
|
|
+ outline: none;
|
|
|
+ border: none;
|
|
|
+ height: 0.4rem;
|
|
|
+ font-size: 0.28rem;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #111111;
|
|
|
+ line-height: 0.4rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.4rem;
|
|
|
+ left: 2.54rem;
|
|
|
+}
|
|
|
+.charge-index .mask .charge .amount span:nth-last-child(1) {
|
|
|
+ height: 0.4rem;
|
|
|
+ font-size: 0.28rem;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #aaaaaa;
|
|
|
+ line-height: 0.4rem;
|
|
|
+ position: absolute;
|
|
|
+ top: 0.4rem;
|
|
|
+ right: 0.4rem;
|
|
|
+}
|
|
|
+
|
|
|
+.charge-index .mask button {
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ bottom: 0.83rem;
|
|
|
+ position: absolute;
|
|
|
+ width: 6.9rem;
|
|
|
+ height: 0.8rem;
|
|
|
+ left: 0.3rem;
|
|
|
+ background: #cccccc;
|
|
|
+ border-radius: 0.45rem;
|
|
|
+ font-size: 0.32rem;
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 0.45rem;
|
|
|
+}
|
|
|
+.charge-index .mask button.selected {
|
|
|
+ background-color: #0ea374;
|
|
|
+}
|
|
|
+</style>
|