commission.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <template>
  2. <view class="container">
  3. <!-- 头部总览 -->
  4. <view class="header-card">
  5. <view class="header-row">
  6. <view class="header-item">
  7. <text class="header-label">累计佣金</text>
  8. <text class="header-value orange">¥{{ summary.totalCommission || '0.00' }}</text>
  9. </view>
  10. <view class="header-item">
  11. <text class="header-label">可提现</text>
  12. <text class="header-value blue">¥{{ summary.availableAmount || '0.00' }}</text>
  13. </view>
  14. </view>
  15. </view>
  16. <!-- 佣金列表 -->
  17. <view class="list-section">
  18. <view class="list-item" v-for="item in list" :key="item.id">
  19. <view class="item-left">
  20. <text :class="['type-tag', item.commissionType === 'member' ? 'tag-orange' : 'tag-blue']">
  21. {{ item.commissionType === 'member' ? '会员佣金' : '利润佣金' }}
  22. </text>
  23. <text class="item-desc">{{ getOrderDesc(item) }}</text>
  24. </view>
  25. <view class="item-right">
  26. <text class="item-amount">+¥{{ item.commissionAmount || '0.00' }}</text>
  27. <text class="item-time">{{ formatTime(item.createdAt) }}</text>
  28. </view>
  29. </view>
  30. <view class="empty-state" v-if="!loading && list.length === 0">
  31. <text>暂无佣金记录</text>
  32. </view>
  33. <view class="loading-state" v-if="loading">
  34. <text>加载中...</text>
  35. </view>
  36. </view>
  37. </view>
  38. </template>
  39. <script>
  40. import { getCommissionList, getCommissionSummary } from '../../utils/api.js'
  41. export default {
  42. data() {
  43. return {
  44. list: [],
  45. summary: {},
  46. page: 1,
  47. hasMore: true,
  48. loading: false
  49. }
  50. },
  51. onLoad() {
  52. this.loadSummary()
  53. this.loadList()
  54. },
  55. onReachBottom() {
  56. if (this.hasMore && !this.loading) {
  57. this.page++
  58. this.loadList()
  59. }
  60. },
  61. methods: {
  62. async loadSummary() {
  63. try {
  64. const res = await getCommissionSummary()
  65. if (res.data) {
  66. this.summary = res.data
  67. }
  68. } catch (e) {
  69. console.error('获取佣金总览失败', e)
  70. }
  71. },
  72. async loadList() {
  73. this.loading = true
  74. try {
  75. const res = await getCommissionList(this.page)
  76. if (res.data && res.data.records) {
  77. this.list = this.page === 1 ? res.data.records : [...this.list, ...res.data.records]
  78. this.hasMore = res.data.records.length >= 20
  79. } else {
  80. this.hasMore = false
  81. }
  82. } catch (e) {
  83. console.error('获取佣金明细失败', e)
  84. }
  85. this.loading = false
  86. },
  87. getOrderDesc(item) {
  88. const typeMap = {
  89. membership: '会员',
  90. product: '商品',
  91. assessment: '测评',
  92. package: '套餐'
  93. }
  94. return (typeMap[item.orderType] || item.orderType) + '订单 #' + item.orderId
  95. },
  96. formatTime(time) {
  97. if (!time) return ''
  98. const t = new Date(time)
  99. return t.getFullYear() + '-' + String(t.getMonth()+1).padStart(2,'0') + '-' + String(t.getDate()).padStart(2,'0')
  100. }
  101. }
  102. }
  103. </script>
  104. <style scoped>
  105. .container {
  106. padding: 30rpx;
  107. min-height: 100vh;
  108. background: #f5f7fa;
  109. }
  110. .header-card {
  111. background: #fff;
  112. border-radius: 20rpx;
  113. padding: 40rpx;
  114. margin-bottom: 30rpx;
  115. box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.05);
  116. }
  117. .header-row {
  118. display: flex;
  119. }
  120. .header-item {
  121. flex: 1;
  122. text-align: center;
  123. }
  124. .header-label {
  125. font-size: 26rpx;
  126. color: #999;
  127. display: block;
  128. margin-bottom: 12rpx;
  129. }
  130. .header-value {
  131. font-size: 40rpx;
  132. font-weight: bold;
  133. }
  134. .header-value.orange { color: #F97316; }
  135. .header-value.blue { color: #3A7CC4; }
  136. .list-section {
  137. background: #fff;
  138. border-radius: 20rpx;
  139. overflow: hidden;
  140. }
  141. .list-item {
  142. display: flex;
  143. justify-content: space-between;
  144. padding: 30rpx;
  145. border-bottom: 1rpx solid #f0f0f0;
  146. }
  147. .item-left {
  148. flex: 1;
  149. }
  150. .type-tag {
  151. font-size: 22rpx;
  152. padding: 4rpx 12rpx;
  153. border-radius: 6rpx;
  154. display: inline-block;
  155. margin-bottom: 8rpx;
  156. }
  157. .tag-orange {
  158. background: #FEF3E2;
  159. color: #F97316;
  160. }
  161. .tag-blue {
  162. background: #E8F0FE;
  163. color: #3A7CC4;
  164. }
  165. .item-desc {
  166. font-size: 26rpx;
  167. color: #666;
  168. display: block;
  169. }
  170. .item-right {
  171. text-align: right;
  172. }
  173. .item-amount {
  174. font-size: 32rpx;
  175. font-weight: bold;
  176. color: #F97316;
  177. display: block;
  178. }
  179. .item-time {
  180. font-size: 22rpx;
  181. color: #999;
  182. display: block;
  183. margin-top: 6rpx;
  184. }
  185. .empty-state, .loading-state {
  186. text-align: center;
  187. padding: 60rpx;
  188. color: #999;
  189. font-size: 28rpx;
  190. }
  191. </style>