index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. <template>
  2. <div class="charge-index">
  3. <div class="background">
  4. <div class="headline">
  5. <span class="text1">电子卡充值享优惠</span>
  6. <span class="text2">会员日充值更优惠</span>
  7. </div>
  8. </div>
  9. <div class="content">
  10. <div class="title">我的卡片 ({{ cardList.length }})</div>
  11. <div
  12. class="gasoline"
  13. v-for="item in cardList"
  14. :key="item.id"
  15. :class="[
  16. item.cardOilsType == 1
  17. ? 'gasoline'
  18. : item.cardOilsType == 2
  19. ? 'diesel'
  20. : '',
  21. ]"
  22. >
  23. <div class="title">
  24. {{
  25. item.cardOilsType == 1
  26. ? "汽油卡"
  27. : item.cardOilsType == 2
  28. ? "柴油卡"
  29. : ""
  30. }}
  31. </div>
  32. <div class="text">
  33. 余额 <span>{{ item.amt.toFixed(2) }}</span
  34. >元
  35. </div>
  36. <button @click="goCharge(item)">充值</button>
  37. </div>
  38. </div>
  39. <van-popup v-model="mask" closeable position="bottom" class="mask" round>
  40. <div class="charge">
  41. <div class="title">充值</div>
  42. <div class="tip">会员日充值更优惠,详情请咨询站长</div>
  43. <div class="amount">
  44. <span>{{
  45. chargeItem.cardOilsType == 1
  46. ? "汽油充值"
  47. : chargeItem.cardOilsType == 2
  48. ? "柴油充值"
  49. : ""
  50. }}</span>
  51. <input
  52. placeholder="输入充值金额"
  53. v-model="chargeAmount"
  54. type="number"
  55. step="0.01"
  56. min="0"
  57. onkeyup="this.value= this.value.match(/\d+(\.\d{0,2})?/) ? this.value.match(/\d+(\.\d{0,2})?/)[0] : ''"
  58. />
  59. <span>¥</span>
  60. </div>
  61. <div class="container">
  62. <div
  63. class="btn"
  64. v-for="item in discountList"
  65. :key="item.cardSettingDetailId"
  66. @click="selectDiscount(item.discountAmtEnd)"
  67. >
  68. <span>¥</span>
  69. <span>{{ item.discountAmtEnd }}</span>
  70. <span>满{{ item.discountAmtEnd }}送{{ item.presentAmt }}元</span>
  71. </div>
  72. </div>
  73. </div>
  74. <van-button
  75. :class="[chargeAmount !== '' ? 'selected' : '']"
  76. :loading="payLoading"
  77. loading-text="拉取支付中..."
  78. @click="charge"
  79. :disabled="chargeAmount === ''"
  80. >
  81. 确认充值
  82. </van-button>
  83. </van-popup>
  84. </div>
  85. </template>
  86. <script>
  87. import ProductList from "../../components/ProductList";
  88. import { mapState, mapGetters, mapActions } from "vuex";
  89. import wx from "weixin-js-sdk";
  90. import Vue from "vue";
  91. import { Toast, Button, Popup, NumberKeyboard } from "vant";
  92. Vue.use(Popup);
  93. Vue.use(Toast);
  94. Vue.use(Button);
  95. Vue.use(NumberKeyboard);
  96. export default {
  97. head() {
  98. return {
  99. title: "会员充值",
  100. };
  101. },
  102. data() {
  103. return {
  104. mask: false,
  105. cardList: [],
  106. chargeItem: {},
  107. chargeAmount: "",
  108. stationInfo: {},
  109. payLoading: false,
  110. show: false,
  111. discountList: [],
  112. };
  113. },
  114. components: {
  115. ProductList,
  116. },
  117. computed: {
  118. ...mapState({
  119. pointInfo: (state) => state.point.pointInfo,
  120. }),
  121. ...mapGetters({
  122. userInfo: "authen/userInfo",
  123. }),
  124. },
  125. created() {
  126. this.init();
  127. },
  128. methods: {
  129. onInput(value) {
  130. Toast(value);
  131. },
  132. onDelete() {
  133. Toast("删除");
  134. },
  135. ...mapActions({
  136. getSdkConfig: "authen/getSdkConfig",
  137. }),
  138. switchMask() {
  139. this.mask = !this.mask;
  140. },
  141. goCharge(ele) {
  142. this.chargeItem = ele;
  143. this.switchMask();
  144. },
  145. charge() {
  146. this.chargeAmount = this.chargeAmount.replace(/\.$/g, "");
  147. this.pay();
  148. },
  149. init() {
  150. // 获取卡片
  151. this.$axios
  152. .$get("/getElectronicCardList", {
  153. params: {
  154. unionId: "o65PX6a8gYoXrRtsay4nid7vaN-k",
  155. stationId: 1,
  156. },
  157. })
  158. .then((res) => {
  159. if (res.retCode === 0) {
  160. this.cardList = res.data;
  161. }
  162. });
  163. // 这一块纯为了后端方便而已,获取station的信息
  164. this.$axios
  165. .$get("/getStationInfo", {
  166. params: {
  167. stationId: 1,
  168. },
  169. })
  170. .then((res) => {
  171. this.stationInfo = res.data;
  172. });
  173. // 拉取折扣
  174. this.$axios
  175. .$get("/getCardRechargeSettingList", {
  176. params: {
  177. stationId: 1,
  178. },
  179. })
  180. .then((res) => {
  181. console.log(res);
  182. if (res.retCode === 0) {
  183. this.discountList = res.data[0].customerCardSettingDetailList;
  184. console.log(this.discountList);
  185. }
  186. });
  187. },
  188. async pay() {
  189. try {
  190. this.payLoading = true;
  191. const orderData = await this.$axios.$post("/rechargeBalance", {
  192. amt: this.chargeAmount,
  193. stationId: this.stationId,
  194. customerName: this.userInfo.nickname,
  195. cardOilsType: this.chargeItem.cardOilsType,
  196. payType: "1",
  197. unionId: this.unionId,
  198. stationName: this.stationInfo.stationName,
  199. });
  200. if (orderData.retCode !== 0) {
  201. throw new Error("生成订单失败");
  202. }
  203. const orderNum = orderData.data;
  204. const subject =
  205. this.stationInfo.stationName +
  206. "_" +
  207. (this.chargeItem.cardOilsType == 1
  208. ? "汽油电子卡充值"
  209. : this.chargeItem.cardOilsType == 2
  210. ? "柴油电子卡充值"
  211. : "");
  212. console.log(subject);
  213. const payInfoData = await this.$axios.$post("/rechargeBalanceSXFPay", {
  214. amt: this.chargeAmount,
  215. openId: this.openId,
  216. stationId: this.stationId,
  217. userType: "1",
  218. subject,
  219. orderNo: orderNum,
  220. });
  221. if (payInfoData.retCode !== 0) {
  222. throw new Error("支付参数拉取失败");
  223. }
  224. if (payInfoData.data.code !== "0000") {
  225. throw new Error(payInfoData.data.msg);
  226. }
  227. const timestamp = payInfoData.data.respData.payTimeStamp;
  228. const nonceStr = payInfoData.data.respData.paynonceStr;
  229. const packageOrg = payInfoData.data.respData.payPackage;
  230. const signType = payInfoData.data.respData.paySignType;
  231. const paySign = payInfoData.data.respData.paySign;
  232. const that = this;
  233. // 拉取微信支付
  234. this.getSdkConfig(["chooseWXPay"]).then((res) => {
  235. wx.config(res);
  236. wx.ready(function (res) {
  237. wx.chooseWXPay({
  238. timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
  239. nonceStr, // 支付签名随机串,不长于 32 位
  240. package: packageOrg, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
  241. signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
  242. paySign, // 支付签名
  243. success: function (res) {
  244. // that.$router.push("/personal/charge");
  245. that.payLoading = false;
  246. alert("支付完成");
  247. },
  248. cancel: function (err) {
  249. that.payLoading = false;
  250. alert("您取消了付款");
  251. },
  252. fail: function (err) {
  253. that.payLoading = false;
  254. alert(err);
  255. },
  256. });
  257. });
  258. wx.error(function (res) {
  259. alert("拉取微信Sdk配置出错");
  260. });
  261. });
  262. } catch (err) {
  263. this.payLoading = false;
  264. alert(err);
  265. }
  266. },
  267. selectDiscount(discount) {
  268. this.chargeAmount = discount;
  269. },
  270. },
  271. };
  272. </script>
  273. <style>
  274. .charge-index {
  275. position: relative;
  276. height: 100vh;
  277. }
  278. .charge-index .background {
  279. background-color: #f3b335;
  280. width: 7.5rem;
  281. height: 7.5rem;
  282. position: relative;
  283. background: url("~static/personal/23@2x.png") no-repeat 0px 0px;
  284. background-size: 100% 100%;
  285. z-index: -1;
  286. overflow: hidden;
  287. }
  288. .charge-index .background .headline {
  289. width: 6.9rem;
  290. height: 4.33rem;
  291. background: url("~static/personal/bj2@2x.png") no-repeat 0px 0px;
  292. background-size: 100% 100%;
  293. margin: 0.3rem auto;
  294. display: relative;
  295. }
  296. .charge-index .background .headline .text1 {
  297. position: absolute;
  298. left: 0.8rem;
  299. top: 1.6rem;
  300. color: #8e9aae;
  301. font-size: 0.3rem;
  302. font-weight:600;
  303. }
  304. .charge-index .background .headline .text2 {
  305. position: absolute;
  306. left: 0.8rem;
  307. top: 2.2rem;
  308. color: #8e9aae;
  309. font-size: 0.3rem;
  310. font-weight:600;
  311. }
  312. .charge-index .content {
  313. position: absolute;
  314. top: 3.78rem;
  315. bottom: 0rem;
  316. left: 0rem;
  317. right: 0rem;
  318. background-color: #ffffff;
  319. border-radius: 0.3rem 0.3rem 0 0;
  320. padding: 0.3rem;
  321. display: flex;
  322. flex-direction: column;
  323. }
  324. .charge-index .content > div:not(.title) {
  325. width: 6.9rem;
  326. height: 1.6rem;
  327. margin-top: 0.3rem;
  328. position: relative;
  329. }
  330. .charge-index .content .title {
  331. font-size: 0.35rem;
  332. color: #333333;
  333. font-weight: 600;
  334. }
  335. .charge-index .content .gasoline {
  336. background: url("~static/personal/bj3@2x.png") no-repeat 0px 0px;
  337. background-size: 100% 100%;
  338. }
  339. .charge-index .content .diesel {
  340. background: url("~static/personal/bj4@2x.png") no-repeat 0px 0px;
  341. background-size: 100% 100%;
  342. }
  343. .charge-index .content div .title {
  344. height: 0.45rem;
  345. font-size: 0.32rem;
  346. font-family: PingFangSC-Medium, PingFang SC;
  347. font-weight: 500;
  348. color: #ffffff;
  349. line-height: 0.45rem;
  350. position: absolute;
  351. top: 0.27rem;
  352. left: 1.67rem;
  353. }
  354. .charge-index .content .gasoline .text {
  355. height: 0.45rem;
  356. font-size: 0.32rem;
  357. font-family: PingFangSC-Medium, PingFang SC;
  358. font-weight: 500;
  359. color: #3db58f;
  360. line-height: 0.45rem;
  361. position: absolute;
  362. top: 0.9rem;
  363. left: 1.67rem;
  364. }
  365. .charge-index .content .diesel .text {
  366. height: 0.45rem;
  367. font-size: 0.32rem;
  368. font-family: PingFangSC-Medium, PingFang SC;
  369. font-weight: 500;
  370. color: #ea8c7d;
  371. line-height: 0.45rem;
  372. position: absolute;
  373. top: 0.9rem;
  374. left: 1.67rem;
  375. }
  376. .charge-index .content div .text span {
  377. color: #fff;
  378. }
  379. .charge-index .content div button {
  380. border: none;
  381. background-color: transparent;
  382. outline: none;
  383. display: block;
  384. width: 1.4rem;
  385. height: 0.6rem;
  386. background: #ffffff;
  387. border-radius: 0.3rem;
  388. position: absolute;
  389. top: 0.5rem;
  390. right: 0.3rem;
  391. }
  392. .charge-index .content .gasoline button {
  393. color: #24ac81;
  394. }
  395. .charge-index .content .diesel button {
  396. color: #e87d6d;
  397. }
  398. .charge-index .mask {
  399. }
  400. .charge-index .mask .charge {
  401. height: 7.5rem;
  402. background: #f2f2f2;
  403. border-radius: 0.42rem 0.42rem 0rem 0rem;
  404. box-sizing: border-box;
  405. padding: 0.3rem 0;
  406. display: flex;
  407. flex-direction: column;
  408. align-items: center;
  409. }
  410. .charge-index .mask .charge > div:not(:nth-child(1)):not(.container) {
  411. margin-top: 0.2rem;
  412. }
  413. .charge-index .mask .charge .title {
  414. width: 6.5rem;
  415. height: 0.45rem;
  416. font-size: 0.32rem;
  417. font-family: PingFangSC-Regular, PingFang SC;
  418. font-weight: 400;
  419. color: #111111;
  420. line-height: 0.45rem;
  421. text-align: center;
  422. }
  423. .charge-index .mask .charge .title .close {
  424. background: url("~static/personal/6_d05_close@2x.png") no-repeat 0px 0px;
  425. background-size: 100% 100%;
  426. width: 0.4rem;
  427. height: 0.4rem;
  428. float: right;
  429. }
  430. .charge-index .mask .charge .tip {
  431. height: 0.33rem;
  432. font-size: 0.24rem;
  433. font-family: PingFangSC-Regular, PingFang SC;
  434. font-weight: 400;
  435. color: #aaaaaa;
  436. line-height: 0.33rem;
  437. }
  438. .charge-index .mask .charge .amount {
  439. width: 6.9rem;
  440. height: 1.2rem;
  441. background: url("~static/personal/biankuang@2x.png") no-repeat 0px 0px;
  442. background-size: 100% 100%;
  443. position: relative;
  444. }
  445. .charge-index .mask .charge .amount span:nth-child(1) {
  446. height: 0.4rem;
  447. font-size: 0.28rem;
  448. font-weight: 600;
  449. color: #884e16;
  450. line-height: 0.4rem;
  451. position: absolute;
  452. top: 0.4rem;
  453. left: 0.51rem;
  454. }
  455. .charge-index .mask .charge .amount input {
  456. background: none;
  457. outline: none;
  458. border: none;
  459. height: 0.4rem;
  460. font-size: 0.28rem;
  461. font-family: PingFangSC-Regular, PingFang SC;
  462. font-weight: 400;
  463. color: #111111;
  464. line-height: 0.4rem;
  465. position: absolute;
  466. top: 0.4rem;
  467. left: 2.54rem;
  468. }
  469. .charge-index .mask .charge .amount span:nth-last-child(1) {
  470. height: 0.4rem;
  471. font-size: 0.28rem;
  472. font-family: PingFangSC-Regular, PingFang SC;
  473. font-weight: 400;
  474. color: #aaaaaa;
  475. line-height: 0.4rem;
  476. position: absolute;
  477. top: 0.4rem;
  478. right: 0.4rem;
  479. }
  480. .charge-index .mask button {
  481. border: none;
  482. outline: none;
  483. bottom: 0.7rem;
  484. position: absolute;
  485. width: 6.9rem;
  486. height: 0.8rem;
  487. left: 0.3rem;
  488. background: #cccccc;
  489. border-radius: 0.45rem;
  490. font-size: 0.32rem;
  491. font-family: PingFangSC-Regular, PingFang SC;
  492. font-weight: 400;
  493. color: #ffffff;
  494. line-height: 0.45rem;
  495. }
  496. .charge-index .mask > button.selected {
  497. background-color: #0ea374;
  498. }
  499. .charge-index .mask .container {
  500. margin-top: 0.4rem;
  501. display: flex;
  502. flex-wrap: wrap;
  503. padding: 0.3rem 0.3rem;
  504. justify-content: space-between;
  505. overflow: scroll;
  506. height: 2rem;
  507. }
  508. .charge-index .mask .container .btn {
  509. display: inline-block;
  510. width: 3.3rem;
  511. height: 0.84rem;
  512. background: #ffffff;
  513. box-shadow: 0 0.04rem 0.08rem 0 #f2f2f2;
  514. border-radius: 0.42rem;
  515. margin-bottom: 0.35rem;
  516. position: relative;
  517. box-sizing: border-box;
  518. padding: 0 0.26rem;
  519. text-align: center;
  520. }
  521. .charge-index .mask .container .btn:nth-child(odd) {
  522. margin-right: 0.3rem;
  523. }
  524. .charge-index .mask .container .btn span {
  525. font-size: 0.35rem;
  526. font-family: PingFangSC-Regular, PingFang SC;
  527. color: #895017;
  528. line-height: 0.84rem;
  529. }
  530. .charge-index .mask .container .btn span:nth-child(1) {
  531. border-radius: 0.42rem;
  532. font-size: 0.2rem;
  533. float: left;
  534. }
  535. .charge-index .mask .container .btn span:nth-child(2) {
  536. float: left;
  537. font-weight: 600;
  538. }
  539. .charge-index .mask .container .btn span:nth-child(3) {
  540. font-size: 0.2rem;
  541. font-weight: 400;
  542. color: rgba(0, 0, 0, 0.29);
  543. float: right;
  544. }
  545. </style>