Cashier.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <window-size>
  3. <payment-countdown @onFinish="countdownFinished = true"></payment-countdown>
  4. <div class="to-be-paid-wrapper">
  5. <div class="label">
  6. 收款单位:<span>长沙泰和医院</span>
  7. </div>
  8. <div class="label">
  9. 缴费类别:<span>{{ createOrderRequest.body }}</span>
  10. </div>
  11. <div class="label money-box">
  12. 待缴金额:
  13. <span class="money">{{ psnCashpayAmt }}</span>
  14. <div class="detail-box">
  15. <div>
  16. <div>
  17. 总计金额:{{makeMoneyStyle(createOrderRequest.totalFee)}}
  18. </div>
  19. <div>
  20. 医保报销:{{makeMoneyStyle(createOrderRequest.fundpayAmt)}}
  21. </div>
  22. <div>
  23. 个账支付:{{makeMoneyStyle(createOrderRequest.acctpayAmt)}}
  24. </div>
  25. <div>
  26. 卡券优惠:{{makeMoneyStyle(createOrderRequest.couponAmt)}}
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. </div>
  32. <div style="margin: 0 12px">
  33. <van-coupon-cell
  34. :coupons="usableCoupons"
  35. :chosen-coupon="chosenCouponIndex"
  36. @click="showCouponList = true"
  37. />
  38. <van-popup
  39. v-model:show="showCouponList"
  40. round
  41. position="bottom"
  42. style="height: 90%; padding-top: 4px;"
  43. >
  44. <van-coupon-list
  45. :coupons="usableCoupons"
  46. :chosen-coupon="chosenCouponIndex"
  47. :disabled-coupons="unusableCoupons"
  48. @change="onCouponChange"
  49. :show-exchange-bar="false"
  50. />
  51. </van-popup>
  52. <div style="margin-top: 32px">
  53. <van-button block type="success" @click="weChatPay" :disabled="countdownFinished">微信支付</van-button>
  54. </div>
  55. </div>
  56. </window-size>
  57. </template>
  58. <script setup>
  59. import store from "../../store";
  60. import {computed, onMounted, ref} from "vue";
  61. import {getMyCoupons} from "../../api/coupon";
  62. import {createPayOrder, queryOrderState} from "../../api/wx-jsapi";
  63. import router from "../../router";
  64. import PaymentCountdown from '../../components/countdown-for-payment/index.vue'
  65. const countdownFinished = ref(false)
  66. const createOrderRequest = store.getters.getCreateOrderRequest
  67. const psnCashpayAmt = computed(() => {
  68. let cashpayAmt = createOrderRequest.totalFee - createOrderRequest.fundpayAmt -
  69. createOrderRequest.acctpayAmt - createOrderRequest.couponAmt
  70. cashpayAmt = cashpayAmt < 0 ? 0 : cashpayAmt
  71. createOrderRequest.cashpayAmt = cashpayAmt.toFixed(2)
  72. return makeMoneyStyle(cashpayAmt)
  73. })
  74. const showCouponList = ref(false);
  75. const chosenCouponIndex = ref(-1);
  76. const usableCoupons = ref([])
  77. const unusableCoupons = ref([])
  78. const onCouponChange = (index) => {
  79. showCouponList.value = false;
  80. chosenCouponIndex.value = index;
  81. if (index === -1) {
  82. createOrderRequest.couponId = null
  83. createOrderRequest.couponAmt = 0
  84. } else {
  85. const coupon = usableCoupons.value[index]
  86. createOrderRequest.couponId = coupon.id
  87. createOrderRequest.couponAmt = coupon.value / 100
  88. }
  89. }
  90. function makeMoneyStyle(m) {
  91. return '¥' + m.toFixed(2)
  92. }
  93. function weChatPay() {
  94. createPayOrder(createOrderRequest).then((order) => {
  95. createOrderRequest.tradeNo = order.tradeNo
  96. store.commit('SET_YJREQNO', null)
  97. if (createOrderRequest.cashpayAmt === 0) {
  98. queryOrderTradeState(order.tradeNo)
  99. } else {
  100. executePaymentAction(order)
  101. }
  102. })
  103. }
  104. function executePaymentAction(order) {
  105. WeixinJSBridge.invoke('getBrandWCPayRequest', {
  106. appId: order.appId,
  107. timeStamp: order.timeStamp,
  108. nonceStr: order.serialNo,
  109. package: order.prepayId,
  110. signType: order.signType,
  111. paySign: order.paySign,
  112. totalFee: order.cashpayAmt
  113. }, () => {
  114. queryOrderTradeState(order.tradeNo)
  115. })
  116. }
  117. function queryOrderTradeState(tradeNo) {
  118. queryOrderState(tradeNo).then((response) => {
  119. createOrderRequest.payTime = response
  120. store.dispatch({
  121. type: 'storeCreateOrderRequest',
  122. createOrderRequest
  123. }).then(() => {
  124. router.push('/paymentSuccess');
  125. })
  126. })
  127. }
  128. onMounted(() => {
  129. const hisOrdNum = createOrderRequest.hisOrdNum || 'NONE'
  130. getMyCoupons(hisOrdNum).then(res => {
  131. usableCoupons.value = res.usableCoupons
  132. unusableCoupons.value = res.unusableCoupons
  133. })
  134. })
  135. </script>
  136. <style scoped>
  137. .to-be-paid-wrapper {
  138. padding: 6px 12px 12px 12px;
  139. border-radius: 8px;
  140. box-shadow: #777777 1px 0 3px 0;
  141. margin: 12px;
  142. background-color: white;
  143. }
  144. .to-be-paid-wrapper > .label {
  145. font-size: 14px;
  146. color: #7a7a7a;
  147. padding: 16px 0;
  148. border-bottom: 1px solid #e1e1e1;
  149. }
  150. .label > span {
  151. color: #333333;
  152. }
  153. .to-be-paid-wrapper .money {
  154. margin-top: 8px;
  155. font-size: 26px;
  156. font-weight: bold;
  157. color: orangered;
  158. }
  159. .money-box {
  160. border: none!important;
  161. position: relative;
  162. }
  163. .detail-box{
  164. font-size: 10px;
  165. position: absolute;
  166. right: 0;
  167. top: 0;
  168. height: 100%;
  169. display: flex;
  170. align-items: center;
  171. }
  172. </style>