recharge.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <uv-navbar leftIcon="arrow-left" @leftClick="handleLeftClick" title="充值" bg-color="#C6171E" color="white"></uv-navbar>
  3. <view class="container">
  4. <view class="title">请选择充值金额</view>
  5. <view class="amount-list">
  6. <view
  7. v-for="(item, index) in state.configList"
  8. :key="index"
  9. :class="['amount-item', { 'active': state.chosenIdx === index }]"
  10. @click="handleRechargeClick(item,index)"
  11. >
  12. <view class="amount-text">{{ (item.rechargeAmount/100).toFixed(0) }}元</view>
  13. <view v-if="item.grantsAmount > 0" class="gift-tag">
  14. <uv-icon name="gift" size="12"></uv-icon>
  15. {{ (item.grantsAmount/100).toFixed(0) }}元
  16. </view>
  17. </view>
  18. </view>
  19. <view class="selected-info" v-if="state.chosenIdx > -1">
  20. <view class="selected-text">已选择:<span class="selected-amount">¥{{ (state.configList[state.chosenIdx].rechargeAmount/100).toFixed(2) }}</span></view>
  21. <view v-if="state.rechargeItem.grantsAmount>0" class="gift-info">
  22. <uv-icon name="gift" size="18"></uv-icon>
  23. <span class="gift-amount">赠送¥{{(state.rechargeItem.grantsAmount/100).toFixed(2)}}</span>
  24. </view>
  25. </view>
  26. <view class="recharge-pay">
  27. <uv-button type="primary" shape="circle" iconColor="white" color="#C6171E" text="立即充值" @click="debounceConfirm" :disabled="state.chosenIdx < 0"></uv-button>
  28. </view>
  29. </view>
  30. </template>
  31. <script setup lang="ts">
  32. import {reactive, ref} from "vue";
  33. import {onHide, onLoad, onShow} from "@dcloudio/uni-app";
  34. import {debounce} from "@/utils/common";
  35. import {get, post,body} from "@/utils/https";
  36. // <uv-navbar leftIcon="arrow-left" title="充值" @leftClick="handleLeftClick"></uv-navbar>
  37. //
  38. const initState = () => ({
  39. configList: [],
  40. chosenIdx: -1,
  41. stationId:'000',
  42. rechargeItem:{
  43. grantsAmount:0
  44. }
  45. })
  46. const state = reactive(initState())
  47. onLoad((options:any)=>{
  48. if(options.stationId){
  49. state.stationId = options.stationId;
  50. }
  51. })
  52. onShow(() => {
  53. loadRechargeConfig();
  54. })
  55. onHide(() => {
  56. Object.assign(state, initState());
  57. })
  58. const handleLeftClick = () => {
  59. uni.navigateBack()
  60. }
  61. const handleRechargeClick = (recharge: any, idx: number) => {
  62. state.chosenIdx = idx;
  63. state.rechargeItem = state.configList[idx]
  64. }
  65. const loadRechargeConfig = () => {
  66. get(`/common/rechargeConfig`).then((res: any) => {
  67. state.configList = res;
  68. })
  69. }
  70. const debounceConfirm = debounce(() => {
  71. confirm();
  72. }, 500)
  73. const confirm = () => {
  74. if (state.chosenIdx < 0) {
  75. return;
  76. }
  77. uni.showLoading({
  78. title: "",
  79. });
  80. let recharge = state.configList[state.chosenIdx]
  81. get("/payment/wxPay", {rechargeConfigId:recharge.id,stationId:state.stationId}).then((res: any) => {
  82. // #ifdef MP-WEIXIN
  83. wx.requestPayment({
  84. timeStamp: `${res.timeStamp}`,
  85. nonceStr: res.nonceStr,
  86. package: res.packageVal,
  87. signType: res.signType,
  88. paySign: res.paySign,
  89. success:function (res: any) {
  90. uni.showToast({
  91. title:'充值完成',
  92. icon:'success'
  93. })
  94. getApp<any>().globalData.refresh =true;
  95. setTimeout(()=>{
  96. uni.switchTab({
  97. url:'/pages/user/index'
  98. })
  99. },500)
  100. },
  101. fail: function (e) {
  102. },
  103. });
  104. // #endif
  105. // #ifndef MP-WEIXIN
  106. uni.showToast({title: '目前仅支持微信支付'})
  107. // #endif
  108. });
  109. }
  110. </script>
  111. <style scoped lang="scss">
  112. .container {
  113. padding: 40rpx 20rpx;
  114. margin-top: 90px;
  115. display: flex;
  116. flex-direction: column;
  117. min-height: calc(100vh - 90px);
  118. background-color: $uni-bg-color-page;
  119. box-sizing: border-box;
  120. }
  121. .title {
  122. font-size: 28rpx;
  123. text-align: center;
  124. margin-bottom: 40rpx;
  125. font-weight: 600;
  126. color: $uni-text-color;
  127. }
  128. .amount-list {
  129. display: grid;
  130. grid-template-columns: repeat(3, 1fr);
  131. gap: 20rpx;
  132. margin-bottom: 40rpx;
  133. width: 100%;
  134. box-sizing: border-box;
  135. }
  136. .amount-item {
  137. background-color: white;
  138. padding: 32rpx 0;
  139. text-align: center;
  140. border: 2px solid $uni-border-color;
  141. border-radius: 14rpx;
  142. font-size: 30rpx;
  143. font-weight: 600;
  144. color: $uni-text-color;
  145. position: relative;
  146. transition: all 0.15s ease;
  147. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  148. height: 120rpx;
  149. display: flex;
  150. align-items: center;
  151. justify-content: center;
  152. box-sizing: border-box;
  153. }
  154. .amount-item:active {
  155. transform: scale(0.95);
  156. }
  157. .amount-item.active {
  158. background-color: #C6171E;
  159. color: white;
  160. border-color: #C6171E;
  161. box-shadow: 0 4rpx 12rpx rgba(198, 23, 30, 0.3);
  162. }
  163. .amount-text {
  164. font-size: 28rpx;
  165. font-weight: 600;
  166. }
  167. .gift-tag {
  168. position: absolute;
  169. top: -10rpx;
  170. right: -10rpx;
  171. background-color: #E84545;
  172. color: white;
  173. font-size: 18rpx;
  174. padding: 4rpx 12rpx;
  175. border-radius: 12rpx;
  176. display: flex;
  177. align-items: center;
  178. gap: 4rpx;
  179. animation: giftPulse 2s infinite;
  180. box-shadow: 0 2rpx 6rpx rgba(232, 69, 69, 0.3);
  181. }
  182. @keyframes giftPulse {
  183. 0% {
  184. transform: scale(1);
  185. }
  186. 50% {
  187. transform: scale(1.05);
  188. }
  189. 100% {
  190. transform: scale(1);
  191. }
  192. }
  193. .selected-info {
  194. background-color: white;
  195. padding: 30rpx;
  196. border-radius: 12rpx;
  197. margin-bottom: 40rpx;
  198. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  199. }
  200. .selected-text {
  201. font-size: 26rpx;
  202. color: $uni-text-color-secondary;
  203. margin-bottom: 10rpx;
  204. }
  205. .selected-amount {
  206. font-size: 32rpx;
  207. font-weight: 600;
  208. color: #C6171E;
  209. }
  210. .gift-info {
  211. display: flex;
  212. align-items: center;
  213. gap: 10rpx;
  214. font-size: 24rpx;
  215. color: #E84545;
  216. }
  217. .gift-amount {
  218. font-weight: 600;
  219. }
  220. .recharge-pay {
  221. width: calc(100vw - 60rpx);
  222. position: fixed;
  223. bottom: 40rpx;
  224. left: 30rpx;
  225. }
  226. </style>