index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. <template>
  2. <view :data-theme="theme" class="user_payment">
  3. <form @submit="submitSub" report-submit='true'>
  4. <view class="payment-top acea-row row-column row-center-wrapper">
  5. <span class="name1">我的余额</span>
  6. <view class="pic">
  7. ¥<span class="pic-font">{{ nowMoney || 0 }}</span>
  8. </view>
  9. </view>
  10. <view class="payment">
  11. <view class='tip picList'>
  12. <view class="pic-box pic-box-color acea-row row-center-wrapper row-column"
  13. :class="activePic === index ? 'pic-box-color-active' : ''" v-for="(item, index) in packageList"
  14. :key="index" @click="picCharge(index, item)">
  15. <view class="pic-number-pic">
  16. {{ item.price }}<span class="pic-number"> 元</span>
  17. </view>
  18. <view class="pic-number">赠送:{{ item.giveMoney }} 元</view>
  19. </view>
  20. <view class="pic-box pic-box-color acea-row row-center-wrapper"
  21. :class="parseFloat(activePic)===parseFloat(packageList.length)?'pic-box-color-active':''"
  22. @click="picCharge(packageList.length)">
  23. <input type="digit" placeholder="其他" v-model="money" @input="onInput($event)" maxlength="5"
  24. class="pic-box-money pic-number-pic uni-input" :placeholder-class="parseFloat(activePic) === parseFloat(packageList.length) ? 'placeColor':''"
  25. :class="parseFloat(activePic) === parseFloat(packageList.length) ? 'pic-box-color-active' : ''"
  26. @blur="addMoney()" />
  27. </view>
  28. <view class="tips-box">
  29. <view class="tips mt-30">注意事项:</view>
  30. <view class="tips-samll" v-for="item in noticeList" :key="item">
  31. {{ item }}
  32. </view>
  33. </view>
  34. </view>
  35. <!-- #ifndef MP-->
  36. <view class='wrapper borRadius14 px-30' v-if='!active'>
  37. <view class='item'>
  38. <view>支付方式</view>
  39. <view class='list'>
  40. <view class='payItem acea-row row-middle' :class='curActive==index ?"on":""'
  41. @tap='payItem(index)' v-for="(item,index) in cartArr" :key='index'
  42. v-if="item.payStatus==1">
  43. <view class='name acea-row row-center-wrapper'>
  44. <view class='iconfont animated'
  45. :class='(item.icon) + " " + (animated==true&&active==index ?"bounceIn":"")'>
  46. </view>
  47. {{item.name}}
  48. </view>
  49. <view class='tip'>{{item.title}}</view>
  50. </view>
  51. </view>
  52. </view>
  53. </view>
  54. <!-- #endif -->
  55. <button class='but' formType="submit"> {{active ? '立即转入': '立即充值' }}</button>
  56. <view class="alipaysubmit" v-html="formContent"></view>
  57. </view>
  58. </form>
  59. </view>
  60. </template>
  61. <script>
  62. // +----------------------------------------------------------------------
  63. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  64. // +----------------------------------------------------------------------
  65. // | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
  66. // +----------------------------------------------------------------------
  67. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  68. // +----------------------------------------------------------------------
  69. // | Author: CRMEB Team <admin@crmeb.com>
  70. // +----------------------------------------------------------------------
  71. import {
  72. rechargeRoutine,
  73. rechargeWechat,
  74. getRechargeApi,
  75. transferIn,
  76. appWechat,
  77. alipayFull,
  78. rechargeCreateApi
  79. } from '@/api/user.js';
  80. import {
  81. wechatQueryPayResult
  82. } from '@/api/order.js';
  83. import {
  84. toLogin
  85. } from '@/libs/login.js';
  86. import {
  87. mapGetters
  88. } from "vuex";
  89. import {
  90. Debounce
  91. } from '@/utils/validate.js'
  92. let app = getApp();
  93. export default {
  94. data() {
  95. let that = this;
  96. return {
  97. navRecharge: ['账户充值', '佣金转入'],
  98. active: 0,
  99. toPrice: '',
  100. placeholder: "0.00",
  101. payChannel: '',
  102. packageList: [],
  103. activePic: 0,
  104. money: "",
  105. numberPic: '',
  106. rechar_id: 0,
  107. noticeList: [],
  108. theme: app.globalData.theme,
  109. cartArr: [],
  110. payType: '', //支付方式
  111. openType: 1, //优惠券打开方式 1=使用
  112. curActive: 0, //支付方式切换
  113. animated: false,
  114. formContent: '',
  115. nowMoney: 0
  116. };
  117. },
  118. computed: mapGetters(['isLogin', 'systemPlatform', 'userInfo']),
  119. watch: {
  120. isLogin: {
  121. handler: function(newV, oldV) {
  122. if (newV) {
  123. this.getRecharge();
  124. }
  125. },
  126. deep: true
  127. }
  128. },
  129. onLoad() {
  130. if (this.isLogin) {
  131. this.getRecharge();
  132. this.payConfig();
  133. } else {
  134. toLogin();
  135. }
  136. },
  137. methods: {
  138. // 支付配置
  139. payConfig() {
  140. // 支付方式
  141. this.$store.dispatch('getPayConfig').then((res) => {
  142. this.nowMoney = res.userBalance;
  143. let cartArrs = res.payConfig.filter(e => e.value !== 'yue');
  144. this.cartArr = cartArrs;
  145. if (this.cartArr.length) {
  146. this.payType = this.cartArr[0].value;
  147. }
  148. });
  149. },
  150. onInput(e) {
  151. let val = e.target.value.replace(/(^\s*)|(\s*$)/g, "")
  152. if (!val) {
  153. this.val = '';
  154. return
  155. }
  156. var reg = /[^\d.]/g
  157. // 只能是数字和小数点,不能是其他输入
  158. val = val.replace(reg, "")
  159. // // 保证第一位只能是数字,不能是点
  160. val = val.replace(/^\./g, "");
  161. // // 小数只能出现1位
  162. val = val.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".");
  163. // // 小数点后面保留2位
  164. val = val.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
  165. this.$nextTick(() => {
  166. this.money = val;
  167. })
  168. },
  169. getAll() {
  170. this.toPrice = this.userInfo.brokeragePrice
  171. },
  172. /**
  173. * 选择金额
  174. */
  175. picCharge(idx, item) {
  176. this.activePic = idx;
  177. if (!item) {
  178. this.rechar_id = null;
  179. this.numberPic = "";
  180. } else {
  181. this.money = null;
  182. this.rechar_id = item.id;
  183. this.numberPic = null;
  184. }
  185. },
  186. /**
  187. * 充值额度选择
  188. */
  189. getRecharge() {
  190. getRechargeApi()
  191. .then(res => {
  192. this.packageList = res.data.packageList;
  193. if (this.packageList[0]) {
  194. this.rechar_id = this.packageList[0].id;
  195. this.numberPic = this.packageList[0].price;
  196. }
  197. this.noticeList = res.data.noticeList || [];
  198. })
  199. .catch(res => {
  200. this.$dialog.toast({
  201. mes: res
  202. });
  203. });
  204. },
  205. navRecharges: function(index) {
  206. this.active = index;
  207. },
  208. payItem: function(e) {
  209. let that = this;
  210. let active = e;
  211. that.curActive = active;
  212. that.animated = true;
  213. that.payType = that.cartArr[active].value;
  214. },
  215. /*
  216. * 用户充值
  217. */
  218. submitSub: Debounce(function(e) {
  219. let that = this
  220. let value = e.detail.value.number ? e.detail.value.number : that.numberPic;
  221. // 转入余额
  222. if (that.active) {
  223. if (parseFloat(value) < 0 || parseFloat(value) == NaN || value == undefined || value == "") {
  224. return that.$util.Tips({
  225. title: '请输入金额'
  226. });
  227. }
  228. uni.showModal({
  229. title: '转入余额',
  230. content: '转入余额后无法再次转出,确认是否转入余额',
  231. success(res) {
  232. if (res.confirm) {
  233. transferIn({
  234. price: parseFloat(value)
  235. }).then(res => {
  236. that.$store.commit("changInfo", {
  237. amount1: 'brokeragePrice',
  238. amount2: that.$util.$h.Sub(that.userInfo
  239. .brokeragePrice, parseFloat(value))
  240. });
  241. return that.$util.Tips({
  242. title: '转入成功',
  243. icon: 'success'
  244. }, {
  245. tab: 5,
  246. url: '/pages/users/user_money/index'
  247. });
  248. }).catch(err => {
  249. return that.$util.Tips({
  250. title: err
  251. });
  252. })
  253. } else if (res.cancel) {
  254. return that.$util.Tips({
  255. title: '已取消'
  256. });
  257. }
  258. },
  259. })
  260. } else {
  261. if (!this.payType) return this.$util.Tips({
  262. title: '请选择支付方式'
  263. });
  264. uni.showLoading({
  265. title: '正在支付',
  266. })
  267. let money = parseFloat(that.money);
  268. if (that.rechar_id == 0) {
  269. if (Number.isNaN(money)) {
  270. return that.$util.Tips({
  271. title: '充值金额必须为数字'
  272. });
  273. }
  274. if (money <= 0) {
  275. return that.$util.Tips({
  276. title: '充值金额不能为0'
  277. });
  278. }
  279. if (money > 50000) {
  280. return that.$util.Tips({
  281. title: '充值金额最大值为50000'
  282. });
  283. }
  284. } else {
  285. money = that.money
  286. }
  287. if (that.payType == 'alipay') {
  288. // #ifdef H5
  289. that.payChannel = 'alipay';
  290. // #endif
  291. // #ifdef APP-PLUS
  292. that.payChannel = 'alipayApp';
  293. // #endif
  294. } else {
  295. // #ifdef H5
  296. that.payChannel = that.$wechat.isWeixin() ? "public" : "h5";
  297. // #endif
  298. // #ifdef MP
  299. that.payChannel = "mini";
  300. // #endif
  301. // #ifdef APP-PLUS
  302. that.payChannel = that.systemPlatform === 'ios' ? 'wechatIos' : 'wechatAndroid';
  303. // #endif
  304. }
  305. rechargeCreateApi({
  306. payChannel: that.payChannel,
  307. price: money,
  308. payType: that.payType,
  309. groupDataId: that.rechar_id
  310. }).then(res => {
  311. uni.hideLoading();
  312. that.pay(res);
  313. }).catch(err => {
  314. uni.hideLoading();
  315. return that.$util.Tips({
  316. title: err
  317. })
  318. });
  319. }
  320. }),
  321. pay(res) {
  322. let that = this
  323. switch (that.payType) {
  324. case 'weixin':
  325. // #ifdef APP-PLUS
  326. let jsConfig = res.data.jsConfig;
  327. uni.requestPayment({
  328. provider: 'wxpay',
  329. orderInfo: {
  330. "appid": jsConfig.appId, // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致
  331. "noncestr": jsConfig.nonceStr, // 随机字符串
  332. "package": "Sign=WXPay", // 固定值
  333. "partnerid": jsConfig.partnerid, // 微信支付商户号
  334. "prepayid": jsConfig.packages, // 统一下单订单号
  335. "timestamp": Number(jsConfig.timeStamp), // 时间戳(单位:秒)
  336. "sign": that.systemPlatform === 'ios' ? 'MD5' : jsConfig.paySign // 签名,这里用的 MD5 签名
  337. }, //微信、支付宝订单数据 【注意微信的订单信息,键值应该全部是小写,不能采用驼峰命名】
  338. success: function(res) {
  339. return that.$util.Tips({
  340. title: '支付成功',
  341. icon: 'success'
  342. }, {
  343. tab: 5,
  344. url: '/pages/users/user_money/index'
  345. });
  346. },
  347. fail: function(err) {
  348. return that.$util.Tips({
  349. title: '支付失败'
  350. });
  351. },
  352. complete: function(res) {
  353. if (res.errMsg == 'requestPayment:cancel') return that.$util.Tips({
  354. title: '取消支付'
  355. });
  356. }
  357. })
  358. // #endif
  359. // #ifdef MP
  360. let jsConfig = res.data.jsConfig;
  361. uni.requestPayment({
  362. timeStamp: jsConfig.timeStamp,
  363. nonceStr: jsConfig.nonceStr,
  364. package: jsConfig.packages,
  365. signType: jsConfig.signType,
  366. paySign: jsConfig.paySign,
  367. success: function(res) {
  368. return that.$util.Tips({
  369. title: '支付成功',
  370. icon: 'success'
  371. }, {
  372. tab: 5,
  373. url: '/pages/users/user_money/index'
  374. });
  375. },
  376. fail: function(err) {
  377. return that.$util.Tips({
  378. title: '支付失败'
  379. });
  380. },
  381. complete: function(res) {
  382. if (res.errMsg == 'requestPayment:cancel') return that.$util.Tips({
  383. title: '取消支付'
  384. });
  385. }
  386. })
  387. // #endif
  388. // #ifdef H5
  389. let jsConfig = res.data.jsConfig;
  390. let orderNo = res.data.orderNo;
  391. let data = {
  392. timestamp: jsConfig.timeStamp,
  393. nonceStr: jsConfig.nonceStr,
  394. package: jsConfig.packages,
  395. signType: jsConfig.signType,
  396. paySign: jsConfig.paySign
  397. };
  398. if (that.payChannel == "h5") {
  399. uni.hideLoading();
  400. // that.$util.Tips({
  401. // title: '支付成功'
  402. // }, {
  403. // tab: 5,
  404. // url: '/pages/users/user_money/index'
  405. // });
  406. setTimeout(() => {
  407. location.href = jsConfig.mwebUrl;
  408. }, 100)
  409. } else {
  410. that.$wechat.pay(data)
  411. .finally(() => {
  412. return that.$util.Tips({
  413. title: '支付成功',
  414. icon: 'success'
  415. }, {
  416. tab: 5,
  417. url: '/pages/users/user_money/index'
  418. });
  419. })
  420. .catch(function(err) {
  421. return that.$util.Tips({
  422. title: '支付失败'
  423. });
  424. });
  425. }
  426. // #endif
  427. break;
  428. case 'alipay':
  429. // alipayFull
  430. // #ifdef APP-PLUS
  431. let alipayRequest = res.data.alipayRequest;
  432. uni.requestPayment({
  433. provider: 'alipay',
  434. orderInfo: alipayRequest,
  435. success: (e) => {
  436. return that.$util.Tips({
  437. title: '支付成功',
  438. icon: 'success'
  439. }, {
  440. tab: 5,
  441. url: '/pages/users/user_money/index'
  442. });
  443. },
  444. fail: (e) => {
  445. return that.$util.Tips({
  446. title: '支付失败'
  447. });
  448. },
  449. complete: () => {
  450. uni.hideLoading();
  451. },
  452. });
  453. // #endif
  454. // #ifdef H5
  455. that.formContent = res.data.alipayRequest;
  456. that.$nextTick(() => {
  457. document.forms['punchout_form'].submit();
  458. })
  459. // #endif
  460. break;
  461. }
  462. },
  463. addMoney() {
  464. //this.money = this.money.replace(/[^\d]/g, '').replace(/^0{1,}/g, '');
  465. }
  466. }
  467. }
  468. </script>
  469. <style lang="scss">
  470. .placeColor{
  471. color: #fff;
  472. }
  473. .user_payment {
  474. height: 100vh;
  475. background-color: #fff;
  476. }
  477. .payment {
  478. position: relative;
  479. top: -60rpx;
  480. width: 100%;
  481. background-color: #fff;
  482. border-radius: 10rpx;
  483. padding-top: 25rpx;
  484. border-top-right-radius: 14rpx;
  485. border-top-left-radius: 14rpx;
  486. }
  487. .payment .nav {
  488. height: 75rpx;
  489. line-height: 75rpx;
  490. padding: 0 100rpx;
  491. }
  492. .payment .nav .item {
  493. font-size: 30rpx;
  494. color: #333;
  495. }
  496. .payment .nav .item.on {
  497. font-weight: bold;
  498. @include tab_border_bottom(theme);
  499. }
  500. .payment .input {
  501. display: flex;
  502. align-items: center;
  503. justify-content: center;
  504. border-bottom: 1px dashed #dddddd;
  505. margin: 60rpx auto 0 auto;
  506. padding-bottom: 20rpx;
  507. font-size: 56rpx;
  508. color: #333333;
  509. flex-wrap: nowrap;
  510. }
  511. .payment .input text {
  512. padding-left: 106rpx;
  513. }
  514. .payment .input input {
  515. padding-right: 106rpx;
  516. width: 310rpx;
  517. height: 94rpx;
  518. text-align: center;
  519. font-size: 70rpx;
  520. }
  521. .payment .placeholder {
  522. color: #fff;
  523. height: 100%;
  524. line-height: 94rpx;
  525. }
  526. .payment .tip {
  527. font-size: 26rpx;
  528. color: #888888;
  529. padding: 0 30rpx;
  530. // margin-top: 25rpx;
  531. }
  532. .payment .but {
  533. color: #fff;
  534. font-size: 30rpx;
  535. width: 700rpx;
  536. height: 86rpx;
  537. border-radius: 43rpx;
  538. margin: 50rpx auto 0 auto;
  539. @include linear-gradient(theme);
  540. line-height: 86rpx;
  541. }
  542. .payment-top {
  543. width: 100%;
  544. height: 278rpx;
  545. @include main_bg_color(theme);
  546. .name1 {
  547. font-size: 26rpx;
  548. color: rgba(255, 255, 255, 0.8);
  549. margin-top: -38rpx;
  550. margin-bottom: 30rpx;
  551. }
  552. .pic {
  553. font-size: 32rpx;
  554. color: #fff;
  555. }
  556. .pic-font {
  557. font-size: 78rpx;
  558. color: #fff;
  559. }
  560. }
  561. .picList {
  562. display: flex;
  563. flex-wrap: wrap;
  564. margin: 30rpx 0;
  565. .pic-box {
  566. width: 32%;
  567. height: auto;
  568. border-radius: 20rpx;
  569. margin-top: 21rpx;
  570. padding: 20rpx 0;
  571. margin-right: 12rpx;
  572. &:nth-child(3n) {
  573. margin-right: 0;
  574. }
  575. }
  576. .pic-box-color {
  577. background-color: #f4f4f4;
  578. color: #656565;
  579. }
  580. .pic-number {
  581. font-size: 22rpx;
  582. }
  583. .pic-number-pic {
  584. font-size: 38rpx;
  585. margin-right: 10rpx;
  586. text-align: center;
  587. }
  588. }
  589. .pic-box-color-active {
  590. @include linear-gradient(theme);
  591. color: #fff !important;
  592. }
  593. .tips-box {
  594. .tips {
  595. font-size: 28rpx;
  596. color: #333333;
  597. font-weight: 800;
  598. margin-bottom: 14rpx;
  599. margin-top: 20rpx;
  600. }
  601. .tips-samll {
  602. font-size: 24rpx;
  603. color: #333333;
  604. margin-bottom: 14rpx;
  605. }
  606. .tip-box {
  607. margin-top: 30rpx;
  608. }
  609. }
  610. .tips-title {
  611. margin-top: 20rpx;
  612. font-size: 24rpx;
  613. color: #333;
  614. }
  615. .wrapper .item textarea {
  616. background-color: #f9f9f9;
  617. width: auto !important;
  618. height: 140rpx;
  619. border-radius: 14rpx;
  620. margin-top: 30rpx;
  621. padding: 15rpx;
  622. box-sizing: border-box;
  623. font-weight: 400;
  624. }
  625. .px-30 {
  626. padding-left: 30rpx;
  627. padding-rigt: 30rpx;
  628. }
  629. .wrapper .item .placeholder {
  630. color: #ccc;
  631. }
  632. .wrapper .item .list {
  633. margin-top: 35rpx;
  634. }
  635. .wrapper .item .list .payItem {
  636. border: 1px solid #eee;
  637. border-radius: 14rpx;
  638. height: 86rpx;
  639. width: 95%;
  640. box-sizing: border-box;
  641. margin-top: 20rpx;
  642. font-size: 28rpx;
  643. color: #282828;
  644. }
  645. .wrapper .item .list .payItem.on {
  646. // border-color: #fc5445;
  647. @include coupons_border_color(theme);
  648. color: $theme-color;
  649. }
  650. .name {
  651. width: 50%;
  652. text-align: center;
  653. border-right: 1px solid #eee;
  654. }
  655. .name .iconfont {
  656. width: 44rpx;
  657. height: 44rpx;
  658. border-radius: 50%;
  659. text-align: center;
  660. line-height: 44rpx;
  661. background-color: #fe960f;
  662. color: #fff;
  663. font-size: 30rpx;
  664. margin-right: 15rpx;
  665. }
  666. .name .iconfont.icon-weixin2 {
  667. background-color: #41b035;
  668. }
  669. .name .iconfont.icon-zhifubao {
  670. background-color: #00AAEA;
  671. }
  672. .payItem .tip {
  673. width: 49%;
  674. text-align: center;
  675. font-size: 26rpx;
  676. color: #aaa;
  677. }
  678. </style>