buy.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. <template>
  2. <app-layout>
  3. <!-- 卡片 -->
  4. <view class="head-card" :style="[{'background-color': `${list.form.card_bg}`}]">
  5. <image class="card-bottom" :src="svipImg.card_bottom" alt=""></image>
  6. </view>
  7. <view class="list">
  8. <view class="title main-center cross-center">
  9. <image :src="svipImg.left" alt=""></image>
  10. <view class="title-text">购买会员</view>
  11. <image :src="svipImg.right" alt=""></image>
  12. </view>
  13. <view class="item dir-left-nowrap" style="border-top: 0">
  14. <view class="label">超级会员卡名称</view>
  15. <view class="content">{{list.name}}</view>
  16. </view>
  17. <view class="item dir-left-nowrap">
  18. <view class="label">会员卡标题</view>
  19. <view class="content">{{card.name}}</view>
  20. </view>
  21. <view class="item dir-left-nowrap">
  22. <view class="label">有效时间</view>
  23. <view class="content">{{end_time > 0 ? end_time : today}}-{{end_day}}</view>
  24. </view>
  25. <view class="item dir-left-nowrap">
  26. <view class="label">有效期</view>
  27. <view class="content">{{card.expire_day}}天</view>
  28. </view>
  29. <view class="item dir-left-nowrap">
  30. <view class="label">会员卡权益</view>
  31. <view v-if="card.main" class="content cross-center main-between">
  32. <view style="min-width: 70%">
  33. <view v-if="card.main.is_free_delivery == 1">自营商品包邮</view>
  34. <view v-if="card.main.is_discount && card.type_info.all">
  35. <text>自营商品{{card.main.discount == 0 ? '免费' : card.main.discount + '折'}}</text>
  36. <text class="about" v-if="(card && card.type_info.ignore_goods && card.type_info.ignore_goods.length > 0) || (card && card.type_info.ignore_cats && card.type_info.ignore_cats.length > 0)">(特殊商品除外)</text>
  37. </view>
  38. <view v-if="card && card.main.is_discount && card.type_info.cats && card.type_info.cats.length > 0">指定分类{{card.main.discount == 0 ? '免费' : card.main.discount + '折'}}</view>
  39. <view v-if="card && card.main.is_discount && card.type_info.goods && card.type_info.goods.length > 0">指定商品{{card.main.discount == 0 ? '免费' : card.main.discount + '折'}}</view>
  40. </view>
  41. <view @click="toDetail" class="to-detail main-center cross-center">
  42. <view>详情</view>
  43. <image src="/static/image/icon/arrow-right.png"></image>
  44. </view>
  45. </view>
  46. </view>
  47. <view class="item dir-left-nowrap" v-if="card.send_integral_num > 0 || card.send_balance > 0 || (card.coupons && card.coupons.length > 0) || (card.cards && card.cards.length > 0)">
  48. <view class="label">购买即赠</view>
  49. <view class="content">
  50. <view v-if="card.send_integral_num > 0">积分{{card.send_integral_num}}</view>
  51. <view v-if="card.send_balance > 0">余额{{card.send_balance}}</view>
  52. <view v-if="card.coupons.length > 0" v-for="item in card.coupons" :key="item.id">{{item.name}}优惠券{{item.send_num}}张</view>
  53. <view v-if="card.cards.length > 0" v-for="item in card.cards" :key="item.id">{{item.name}}卡券{{item.send_num}}张</view>
  54. </view>
  55. </view>
  56. </view>
  57. <view class="buy-form" v-if="list.order_form && list.is_order_form === 1">
  58. <app-diy-form label-position="top" :show-required-icon="true" :label-fs28="true" @validate="handleOrderFormValidate" @input="handleGoodsFormInput" :list="list.order_form"></app-diy-form>
  59. </view>
  60. <view :class="['bottom-place', `${iphone_x? 'iphone_x':''}`]"></view>
  61. <view :class="['foot', `${iphone_x? 'iphone_x':''}`]">
  62. <view @click="showClose = true" class="foot-button">支付</view>
  63. </view>
  64. <view v-if="success" class="dialog main-center cross-center">
  65. <view class="gift">
  66. <image class="gift-bg" src="./../image/gift.png"></image>
  67. <view class="gift-list">
  68. <view @click="toIntegral" class="gift-item" v-if="card.send_integral_num > 0">
  69. <image class="gift-icon" :src="list.form.integral_icon != 'statics/img/app/vip_card/integral.png'?list.form.integral_icon:svipImg.integral"></image>
  70. <view>积分{{card.send_integral_num}}</view>
  71. <image src="/static/image/icon/arrow-right.png"></image>
  72. </view>
  73. <view @click="toBalance" class="gift-item" v-if="card.send_balance > 0">
  74. <image class="gift-icon" :src="list.form.balance_icon != 'statics/img/app/vip_card/balance.png'?list.form.balance_icon:svipImg.balance"></image>
  75. <view>余额{{card.send_balance}}</view>
  76. <image src="/static/image/icon/arrow-right.png"></image>
  77. </view>
  78. <view @click="toCoupon" class="gift-item" v-if="card.coupons.length > 0">
  79. <image class="gift-icon" :src="list.form.coupon_icon != 'statics/img/app/vip_card/coupon.png'?list.form.coupon_icon:svipImg.coupon"></image>
  80. <view>优惠券{{total_coupon}}张</view>
  81. <image src="/static/image/icon/arrow-right.png"></image>
  82. </view>
  83. <view @click="toCard" class="gift-item" v-if="card.cards.length > 0">
  84. <image class="gift-icon" :src="list.form.card_icon != 'statics/img/app/vip_card/card.png'?list.form.card_icon:svipImg.card"></image>
  85. <view>卡券{{total_card}}张</view>
  86. <image src="/static/image/icon/arrow-right.png"></image>
  87. </view>
  88. <view @click="toBack" class="dialog-btn">我知道了</view>
  89. </view>
  90. </view>
  91. </view>
  92. <app-close v-if="showClose" :toBack="true" @update="getMall"></app-close>
  93. </app-layout>
  94. </template>
  95. <script>
  96. import { mapState } from "vuex";
  97. import AppDiyForm from "../../../components/page-component/app-diy-form/app-diy-form";
  98. import AppClose from '../../../components/basic-component/app-close/app-close.vue';
  99. export default {
  100. data() {
  101. return {
  102. detail: {},
  103. list: {
  104. form: {
  105. card_bg: ''
  106. }
  107. },
  108. card: {
  109. expire_day: '',
  110. type_info: {
  111. ignore_goods: [],
  112. ignore_cats: [],
  113. }
  114. },
  115. today: '',
  116. end_day: '',
  117. total_coupon: 0,
  118. total_card: 0,
  119. id: 0,
  120. end_time: '',
  121. start_day: '',
  122. success: false,
  123. iphone_x: false,
  124. template_message: [],
  125. loading: false,
  126. validateResult: {
  127. hasError: false
  128. },
  129. showClose: false,
  130. is_open: false
  131. }
  132. },
  133. components: {
  134. AppDiyForm,
  135. AppClose
  136. },
  137. computed: {
  138. ...mapState({
  139. svipImg: state => state.mallConfig.__wxapp_img.vip_card
  140. })
  141. },
  142. methods: {
  143. getMall(e) {
  144. this.is_open = e.is_open == 1 ? true : false;
  145. if(this.is_open) {
  146. this.subscribe();
  147. }
  148. },
  149. toDetail() {
  150. uni.navigateTo({
  151. url: '/plugins/vip_card/rights/rights?id='+ this.id
  152. })
  153. },
  154. toBack() {
  155. this.success = false;
  156. uni.navigateBack();
  157. },
  158. toCoupon() {
  159. uni.navigateTo({
  160. url: '/pages/coupon/index/index'
  161. })
  162. },
  163. toCard() {
  164. uni.navigateTo({
  165. url: '/pages/card/index/index'
  166. })
  167. },
  168. toBalance() {
  169. uni.navigateTo({
  170. url: '/pages/balance/balance'
  171. })
  172. },
  173. toIntegral() {
  174. uni.navigateTo({
  175. url: '/plugins/integral_mall/index/index'
  176. })
  177. },
  178. getSetting() {
  179. let that = this;
  180. that.$showLoading({
  181. type: 'global',
  182. text: '加载中...'
  183. });
  184. that.$request({
  185. url: that.$api.vip_card.setting,
  186. }).then(response=>{
  187. if(response.code == 0) {
  188. that.list = response.data;
  189. uni.setNavigationBarTitle({
  190. title: '购买' + that.list.name,
  191. })
  192. that.template_message = response.data.template_message;
  193. that.getCard();
  194. }else {
  195. uni.showToast({
  196. title: response.msg,
  197. icon: 'none',
  198. duration: 1000
  199. });
  200. }
  201. }).catch(response => {
  202. that.$hideLoading();
  203. });
  204. },
  205. getCard() {
  206. let that = this;
  207. that.$request({
  208. url: that.$api.vip_card.card_detail,
  209. data: {
  210. id: this.id
  211. }
  212. }).then(response=>{
  213. that.$hideLoading();
  214. if(response.code == 0) {
  215. that.card = response.data;
  216. var timestamp = Date.parse(new Date());
  217. if(that.end_time > 0) {
  218. timestamp = Date.parse(new Date(that.end_time));
  219. }
  220. // 结束
  221. let endTime = (timestamp / 1000 + 24 * 60 * 60 * response.data.expire_day) * 1000;
  222. let endDate = new Date(endTime)
  223. let end_year = endDate.getFullYear();
  224. let end_month = endDate.getMonth() + 1;
  225. if (end_month >= 1 && end_month <= 9) {
  226. end_month = "0" + end_month;
  227. }
  228. let end_now = endDate.getDate();
  229. if (end_now >= 1 && end_now <= 9) {
  230. end_now = "0" + end_now;
  231. }
  232. that.end_day = end_year + "/" + end_month + "/" + end_now;
  233. that.card.coupons.forEach(v => {
  234. that.total_coupon += +v.send_num
  235. })
  236. that.card.cards.forEach(v => {
  237. that.total_card += +v.send_num
  238. })
  239. }else {
  240. uni.showToast({
  241. title: response.msg,
  242. icon: 'none',
  243. duration: 1000
  244. });
  245. }
  246. }).catch(response => {
  247. that.$hideLoading();
  248. });
  249. },
  250. subscribe() {
  251. if (this.validateResult.hasError) {
  252. uni.showToast({
  253. title: this.validateResult.errors[0].msg,
  254. icon: 'none'
  255. })
  256. return;
  257. }
  258. if(!this.is_open) {
  259. return false
  260. }
  261. this.$subscribe(this.template_message).then(res => {
  262. this.toSubmit();
  263. }).catch(res => {
  264. this.toSubmit();
  265. });
  266. },
  267. toSubmit() {
  268. let that = this;
  269. if(this.loading) {
  270. return false
  271. }
  272. this.loading = true;
  273. uni.showLoading({
  274. mask: true,
  275. title: '购买中...'
  276. });
  277. that.$request({
  278. url: that.$api.vip_card.order_submit,
  279. data: {
  280. id: this.id,
  281. order_form: JSON.stringify(that.list.order_form)
  282. },
  283. method: 'post'
  284. }).then(response => {
  285. if (response.code === 0) {
  286. that.getPayOrderId(response.data.queue_id, response.data.token);
  287. } else {
  288. that.loading = false;
  289. uni.hideLoading();
  290. uni.showModal({
  291. title: '提示',
  292. content: response.msg,
  293. showCancel: false,
  294. });
  295. }
  296. }).catch(e => {
  297. that.loading = false;
  298. uni.hideLoading();
  299. uni.showModal({
  300. title: '提示',
  301. content: e.errMsg,
  302. showCancel: false,
  303. });
  304. });
  305. },
  306. handleOrderFormValidate({result}) {
  307. this.validateResult = result;
  308. this.showClose = false;
  309. },
  310. handleGoodsFormInput({data, sign}) {
  311. const result = [];
  312. for (let i in data) {
  313. result[i] = {
  314. key: data[i].key,
  315. label: data[i].name,
  316. value: data[i].value,
  317. required: data[i].is_required,
  318. };
  319. }
  320. this.list.order_form = result;
  321. },
  322. getPayOrderId(queue_id, token) {
  323. this.$request({
  324. url: this.$api.vip_card.pay_data,
  325. method: 'post',
  326. data: {
  327. queue_id: queue_id,
  328. token: token,
  329. },
  330. }).then(response => {
  331. if (response.code === 0) {
  332. if (response.data.retry && response.data.retry === 1) {
  333. this.getPayDataTimer = setTimeout(() => {
  334. this.getPayOrderId(queue_id, token);
  335. }, 1000);
  336. } else {
  337. this.pay(response.data.id);
  338. }
  339. } else {
  340. uni.hideLoading();
  341. this.loading = false;
  342. uni.showModal({
  343. title: '提示',
  344. content: response.msg,
  345. showCancel: false,
  346. });
  347. }
  348. }).catch(e => {
  349. this.loading = false;
  350. uni.hideLoading();
  351. uni.showModal({
  352. title: '提示',
  353. content: e.errMsg,
  354. showCancel: false,
  355. });
  356. });
  357. },
  358. pay(id) {
  359. let that = this;
  360. that.$payment.pay(id).then(res => {
  361. uni.hideLoading();
  362. that.loading = false;
  363. uni.showToast({
  364. title: '购买成功',
  365. duration: 1000
  366. });
  367. if(that.card.send_integral_num > 0 || that.card.send_balance > 0 || that.card.coupons.length > 0 || that.card.cards.length > 0) {
  368. that.success = true;
  369. }else {
  370. setTimeout(v=>{
  371. uni.navigateBack();
  372. },1000)
  373. }
  374. }).catch(res => {
  375. uni.hideLoading();
  376. that.loading = false;
  377. uni.showToast({
  378. title: '支付失败',
  379. icon: 'none',
  380. duration: 1000
  381. });
  382. });
  383. },
  384. },
  385. onUnload() {
  386. clearInterval(this.getPayDataTimer);
  387. },
  388. onLoad(options) { this.$commonLoad.onload(options);
  389. let that = this;
  390. uni.getSystemInfo({
  391. success: function (res) {
  392. if(res.model.indexOf('iPhone X') > -1 || res.model.indexOf('iPhone 11') > -1 || res.model.indexOf('iPhone11') > -1 || res.model.indexOf('iPhone12') > -1) {
  393. that.iphone_x = true;
  394. }
  395. }
  396. })
  397. var myDate = new Date();
  398. let year = myDate.getFullYear();
  399. let month = myDate.getMonth() + 1;
  400. if (month >= 1 && month <= 9) {
  401. month = "0" + month;
  402. }
  403. let now = myDate.getDate();
  404. if (now >= 1 && now <= 9) {
  405. now = "0" + now;
  406. }
  407. this.today = year + "/" + month + "/" + now;
  408. this.id = options.id;
  409. this.end_time = options.end;
  410. this.expire_day = options.expire_day ? options.expire_day : 0;
  411. that.getSetting(options.id);
  412. }
  413. }
  414. </script>
  415. <style scoped lang="scss">
  416. .head-card {
  417. height: #{344rpx};
  418. position: relative;
  419. .card-bottom {
  420. position: absolute;
  421. bottom: 0;
  422. left: 0;
  423. height: #{80rpx};
  424. width: 100%;
  425. }
  426. }
  427. .list {
  428. width: #{702rpx};
  429. margin: 0 auto;
  430. position: relative;
  431. margin-top: #{-284rpx};
  432. z-index: 5;
  433. background-color: #fff;
  434. border-radius: #{15rpx};
  435. padding-bottom: #{40rpx};
  436. box-shadow: 0 0 #{8rpx} rgb(239, 239, 239);
  437. .title {
  438. width: 100%;
  439. padding-top: #{40rpx};
  440. margin-bottom: #{20rpx};
  441. .title-text {
  442. margin: 0 #{20rpx};
  443. font-size: #{32rpx};
  444. color: #342e25;
  445. }
  446. image {
  447. width: #{60rpx};
  448. height: #{19rpx};
  449. }
  450. }
  451. .item {
  452. min-height: #{120rpx};
  453. border-top: #{2rpx} solid #e2e2e2;
  454. padding: #{40rpx} 0;
  455. width: #{630rpx};
  456. margin: 0 auto;
  457. font-size: #{28rpx};
  458. color: #342e25;
  459. .label {
  460. font-size: #{28rpx};
  461. width: #{260rpx};
  462. text-align: right;
  463. margin-right: #{30rpx};
  464. color: #999999;
  465. }
  466. .content {
  467. width: #{340rpx};
  468. view {
  469. margin-top: #{20rpx};
  470. }
  471. view:first-of-type {
  472. margin-top: #{2rpx};
  473. }
  474. .about {
  475. font-size: #{20rpx};
  476. color: #999999;
  477. }
  478. .to-detail {
  479. font-size: #{24 rpx};
  480. margin-top: 0;
  481. color: #999999;
  482. width: 30%;
  483. height: 100%;
  484. view {
  485. margin-top: 0;
  486. }
  487. image {
  488. width: #{12rpx};
  489. height: #{22rpx};
  490. margin-left: #{12rpx};
  491. }
  492. }
  493. }
  494. }
  495. }
  496. .bottom-place {
  497. height: #{160rpx};
  498. }
  499. .bottom-place.iphone_x {
  500. height: #{210rpx};
  501. }
  502. .foot {
  503. position: fixed;
  504. z-index: 997;
  505. bottom: 0;
  506. left: 0;
  507. width: 100%;
  508. height: #{160rpx};
  509. background-color: #F7F7F7;
  510. .foot-button {
  511. width: #{702rpx};
  512. margin: #{40rpx} auto;
  513. height: #{80rpx};
  514. line-height: #{80rpx};
  515. font-size: #{32rpx};
  516. text-align: center;
  517. border-radius: #{40rpx};
  518. color: #342e25;
  519. background-color: #F3BE94;
  520. }
  521. }
  522. .foot.iphone_x {
  523. height: #{210rpx};
  524. padding-bottom: #{50rpx};
  525. }
  526. .dialog {
  527. position: fixed;
  528. top: 0;
  529. left: 0;
  530. width: 100%;
  531. height: 100%;
  532. background-color: rgba(0,0,0,.3);
  533. z-index: 998;
  534. .gift {
  535. max-height: #{1059rpx};
  536. width: #{668rpx};
  537. .gift-bg {
  538. height: #{332rpx};
  539. width: #{668rpx};
  540. }
  541. .gift-list {
  542. width: #{668rpx};
  543. background-color: #fff;
  544. padding-bottom: #{55rpx};
  545. padding-top: #{40rpx};
  546. border-bottom-left-radius: #{20rpx};
  547. border-bottom-right-radius: #{20rpx};
  548. margin-top: #{-18rpx};
  549. .dialog-btn {
  550. width: #{253rpx};
  551. height: #{89rpx};
  552. line-height: #{89rpx};
  553. margin: #{30rpx} auto 0;
  554. border-radius: #{45rpx};
  555. text-align: center;
  556. background: linear-gradient(to right,#fbdec7,#f3bf95);
  557. color: #fcfcfc;
  558. }
  559. .gift-item {
  560. position: relative;
  561. color: #666666;
  562. font-size: #{30rpx};
  563. text-align: center;
  564. height: #{112rpx};
  565. line-height: #{112rpx};
  566. width: #{532rpx};
  567. border-radius: #{15rpx};
  568. border: #{2rpx} solid #e2e2e2;
  569. margin: 0 auto #{20rpx};
  570. image {
  571. position: absolute;
  572. bottom: #{44rpx};
  573. right: #{20rpx};
  574. width: #{12rpx};
  575. height: #{22rpx};
  576. }
  577. .gift-icon {
  578. height: #{80rpx};
  579. width: #{80rpx};
  580. position: absolute;
  581. left: #{30rpx};
  582. top: #{15rpx};
  583. }
  584. }
  585. }
  586. }
  587. }
  588. .buy-form {
  589. border-radius: 16upx;
  590. overflow: hidden;
  591. box-shadow: 0 0 5upx rgba(0,0,0,0.025);
  592. margin: 20upx 24upx 0 24upx;
  593. }
  594. </style>