wallet.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. <template>
  2. <view class="wallet-page">
  3. <!-- 余额卡片 -->
  4. <view class="balance-card">
  5. <view class="card-header">
  6. <text>我的余额</text>
  7. <view class="detail-link" @click="handleWithdrawDetail">
  8. 提现明细
  9. <u-icon name="arrow-right" color="#FFFFFF" size="26" top="4rpx"></u-icon>
  10. </view>
  11. </view>
  12. <view class="amount flex-c">
  13. <text class="number">¥ {{ restMoney }}</text>
  14. </view>
  15. <view class="balance-info flex-c">
  16. (可用余额¥{{ canUseMoney }} 提现中¥{{ freezeMoney }})
  17. </view>
  18. <view class="flex-c">
  19. <view class="withdraw-btn" @click="handleWithdraw">
  20. 提现
  21. </view>
  22. </view>
  23. </view>
  24. <!-- <view class="withdraw-tips">
  25. <view class="tip-line">温馨提示:因腾讯系统升级,平台审核通过后需要再次点击“确认收款”,才会到账哦</view>
  26. <view class="tip-line">快捷入口:商家审核后会在“我的”页面有“提现确认”浮窗,点击“确认立即到账”即可到账。</view>
  27. </view> -->
  28. <!-- 余额明细列表 -->
  29. <view class="detail-section">
  30. <view class="section-header">
  31. <text>余额明细</text>
  32. <view class="filter" @click="toggleFilter">
  33. 分类
  34. <u-icon name="arrow-down" color="#333" size="26"></u-icon>
  35. </view>
  36. </view>
  37. <page-scroll @updateList="handleUpdateList" ref="pageRef" slotEmpty url="/token/user/accountChangeList"
  38. :immediate="false" bgColor="#ffffff" :height="height">
  39. <view class="detail-list">
  40. <view class="detail-item" v-for="(item, index) in detailList" :key="index"
  41. @click="goToDetail(item)">
  42. <view class="item-left">
  43. <text class="title">{{ item.title }}</text>
  44. <text class="time">{{ item.createTime }}</text>
  45. </view>
  46. <view class="item-right">
  47. <text :class="['amount', item.changeMoney > 0 ? 'income' : 'expense']">
  48. {{ item.changeMoney }}
  49. </text>
  50. <text class="status" v-if="item.desc">{{ item.desc }}</text>
  51. </view>
  52. </view>
  53. </view>
  54. </page-scroll>
  55. </view>
  56. <!-- 分类选择弹窗 -->
  57. <category-popup :show.sync="showCategoryPopup" @confirm="onCategoryConfirm"></category-popup>
  58. </view>
  59. </template>
  60. <script>
  61. import CategoryPopup from '../components/category-popup.vue'
  62. import pageScroll from '@/components/pageScroll/index.vue'
  63. export default {
  64. components: {
  65. CategoryPopup,
  66. pageScroll
  67. },
  68. data() {
  69. return {
  70. showCategoryPopup: false,
  71. restMoney: '0.00',
  72. freezeMoney: '0.00',
  73. canUseMoney: '0.00',
  74. detailList: [],
  75. otherParams: {
  76. queryTypes: ''
  77. },
  78. height: 'calc(100vh - 540rpx)'
  79. }
  80. },
  81. // #ifdef MP-ALIPAY
  82. onPullDownRefresh() {
  83. this.$refs.pageRef?.loadData(true)
  84. },
  85. // #endif
  86. onLoad() {
  87. this.getWithdrawInfo()
  88. this.$nextTick(() => {
  89. this.$refs.pageRef.loadData(true, { queryTypes: '' })
  90. })
  91. },
  92. methods: {
  93. async getWithdrawInfo() {
  94. try {
  95. const res = await uni.$u.http.get('/token/user/accountInfo')
  96. if (res.code === 200) {
  97. const { userId, restMoney, freezeMoney, canUseMoney } = res.data
  98. this.restMoney = restMoney
  99. this.freezeMoney = freezeMoney
  100. this.canUseMoney = canUseMoney
  101. }
  102. } catch (e) {
  103. console.error('获取提现信息失败:', e)
  104. }
  105. },
  106. // 分类选择
  107. onCategoryConfirm(selectedCategories) {
  108. console.log('选中的分类:', selectedCategories)
  109. this.otherParams.queryTypes = selectedCategories.join(',')
  110. this.$refs.pageRef.loadData(true, this.otherParams)
  111. },
  112. goToDetail(item) {
  113. if (item.desc == '待确认收款') {
  114. uni.$u.http.post('/token/user/withdrawConfirm', {
  115. orderNo: item.orderNo
  116. }).then(res => {
  117. if (res.code === 200) {
  118. this.handleConfirmReceipt(res.data)
  119. }
  120. }).catch(err => {
  121. uni.showToast({
  122. title: err.message || '确认失败',
  123. icon: 'none'
  124. });
  125. });
  126. }
  127. },
  128. handleWithdraw() {
  129. uni.navigateTo({
  130. url: '/pages-mine/pages/withdraw'
  131. })
  132. },
  133. handleWithdrawDetail() {
  134. uni.navigateTo({
  135. url: '/pages-mine/pages/withdraw-detail'
  136. })
  137. },
  138. toggleFilter() {
  139. // 实现筛选功能
  140. this.showCategoryPopup = !this.showCategoryPopup
  141. },
  142. // 更新列表
  143. handleUpdateList(data) {
  144. this.detailList = data
  145. },
  146. //执行微信确认收款操作
  147. handleConfirmReceipt(data) {
  148. if (wx.canIUse('requestMerchantTransfer')) {
  149. wx.requestMerchantTransfer({
  150. mchId: data.mchId,
  151. appId: data.appId,
  152. package: data.packageStr,
  153. success: (res) => {
  154. // res.err_msg将在页面展示成功后返回应用时返回ok,并不代表付款成功
  155. uni.showToast({
  156. title: '确认收款成功',
  157. icon: 'none'
  158. })
  159. // 刷新列表和余额信息
  160. this.getWithdrawInfo();
  161. this.$refs.pageRef.loadData(true, this.otherParams);
  162. },
  163. fail: (res) => {
  164. console.log('fail:', res);
  165. },
  166. });
  167. } else {
  168. wx.showModal({
  169. content: '你的微信版本过低,请更新至最新版本。',
  170. showCancel: false,
  171. });
  172. }
  173. },
  174. }
  175. }
  176. </script>
  177. <style lang="scss" scoped>
  178. .wallet-page {
  179. height: 100vh;
  180. background: #F5F5F5;
  181. padding: 10rpx 30rpx;
  182. box-sizing: border-box;
  183. overflow: hidden;
  184. .balance-card {
  185. background: #38C148;
  186. border-radius: 20rpx;
  187. padding: 30rpx 40rpx;
  188. color: #FFFFFF;
  189. z-index: 9;
  190. position: sticky;
  191. top: 10rpx;
  192. .card-header {
  193. display: flex;
  194. justify-content: space-between;
  195. align-items: center;
  196. font-size: 28rpx;
  197. .detail-link {
  198. display: flex;
  199. align-items: center;
  200. opacity: 0.9;
  201. }
  202. }
  203. .amount {
  204. margin: 40rpx 0 20rpx;
  205. .symbol {
  206. font-size: 40rpx;
  207. margin-right: 8rpx;
  208. }
  209. .number {
  210. font-size: 80rpx;
  211. font-weight: 500;
  212. }
  213. }
  214. .balance-info {
  215. font-size: 26rpx;
  216. opacity: 0.9;
  217. }
  218. .withdraw-btn {
  219. margin-top: 40rpx;
  220. height: 60rpx;
  221. line-height: 60rpx;
  222. text-align: center;
  223. background: rgba(255, 255, 255, 0.2);
  224. border-radius: 14rpx;
  225. font-size: 28rpx;
  226. width: 200rpx;
  227. }
  228. }
  229. .withdraw-tips {
  230. margin-top: 20rpx;
  231. padding: 16rpx 20rpx;
  232. background: #fff;
  233. border-radius: 16rpx;
  234. .tip-line {
  235. font-size: 24rpx;
  236. line-height: 36rpx;
  237. color: #E64545;
  238. & + .tip-line {
  239. margin-top: 8rpx;
  240. }
  241. }
  242. }
  243. .detail-section {
  244. background: #FFFFFF;
  245. border-radius: 20rpx;
  246. margin-top: 20rpx;
  247. padding: 0 30rpx;
  248. height: calc(100vh - 400rpx);
  249. overflow-y: auto;
  250. .section-header {
  251. display: flex;
  252. justify-content: space-between;
  253. align-items: center;
  254. height: 100rpx;
  255. font-size: 30rpx;
  256. color: #333;
  257. border-bottom: 1px solid #EEEEEE;
  258. .filter {
  259. display: flex;
  260. align-items: center;
  261. color: #666;
  262. font-size: 28rpx;
  263. margin-right: 8rpx;
  264. }
  265. }
  266. .detail-list {
  267. .detail-item {
  268. display: flex;
  269. justify-content: space-between;
  270. align-items: center;
  271. padding: 30rpx 0;
  272. border-bottom: 1px solid #EEEEEE;
  273. &:last-child {
  274. border-bottom: none;
  275. }
  276. .item-left {
  277. .title {
  278. font-size: 28rpx;
  279. color: #333;
  280. margin-bottom: 10rpx;
  281. display: block;
  282. }
  283. .time {
  284. font-size: 24rpx;
  285. color: #999;
  286. }
  287. }
  288. .item-right {
  289. text-align: right;
  290. .amount {
  291. display: block;
  292. font-size: 32rpx;
  293. margin-bottom: 10rpx;
  294. font-weight: 500;
  295. &.income {
  296. color: #FF5B5B;
  297. }
  298. &.expense {
  299. color: #38C148;
  300. }
  301. }
  302. .status {
  303. font-size: 24rpx;
  304. color: #999;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }
  311. </style>