index.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <template>
  2. <mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" @up="upCallback">
  3. <!-- 分类列表tab -->
  4. <view class="tabs-wrapper">
  5. <scroll-view class="scroll-view" scroll-x>
  6. <view class="tab-item" :class="{ active: curId == 0 }" @click="onSwitchTab(0)">
  7. <view class="value"><text>全部</text></view>
  8. </view>
  9. <!-- 分类列表 -->
  10. <view class="tab-item" :class="{ active: curId == item.id }" @click="onSwitchTab(item.id)"
  11. v-for="(item, index) in categoryList" :key="index">
  12. <view class="value"><text>{{ item.name }}</text></view>
  13. </view>
  14. </scroll-view>
  15. </view>
  16. <!-- 会员列表 -->
  17. <view class="member-list">
  18. <view class="member-item" v-for="(item, index) in memberList.content" :key="index" @click="onTargetDetail(item.id)">
  19. <block>
  20. <view class="left flex-box">
  21. <image class="image" :src="item.avatar"></image>
  22. </view>
  23. <view class="right">
  24. <view class="base">
  25. <text class="name">{{ item.name }}</text>
  26. <text class="grade">{{ item.gradeName ? item.gradeName : '' }}</text>
  27. </view>
  28. <view class="amount">
  29. <view class="balance">余额:¥{{ item.balance.toFixed(2) }}</view>
  30. <view class="point">积分:{{ item.point }}</view>
  31. </view>
  32. <view class="footer">
  33. <text class="member-views f-24 col-8">{{ item.lastLoginTime }}活跃</text>
  34. </view>
  35. </view>
  36. </block>
  37. </view>
  38. </view>
  39. </mescroll-body>
  40. </template>
  41. <script>
  42. import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue'
  43. import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins'
  44. import * as MemberApi from '@/api/merchant/member'
  45. import { getEmptyPaginateObj, getMoreListData } from '@/utils/app'
  46. const pageSize = 15
  47. export default {
  48. components: {
  49. MescrollBody
  50. },
  51. mixins: [MescrollMixin],
  52. data() {
  53. return {
  54. // 分类列表
  55. categoryList: [{ name : '今日活跃', id: 'todayActive' }, { name : '今日注册', id: 'todayRegister' }],
  56. // 会员列表
  57. memberList: getEmptyPaginateObj(),
  58. // 当前选中的分类id (all则代表全部)
  59. curId: 'all',
  60. // 上拉加载配置
  61. upOption: {
  62. // 首次自动执行
  63. auto: true,
  64. // 每页数据的数量; 默认20
  65. page: { size: pageSize },
  66. // 数量要大于12条才显示无更多数据
  67. noMoreSize: 12,
  68. }
  69. }
  70. },
  71. /**
  72. * 生命周期函数--监听页面加载
  73. */
  74. onLoad(options) {
  75. const app = this
  76. if (options.dataType) {
  77. app.curId = options.dataType
  78. }
  79. },
  80. methods: {
  81. /**
  82. * 上拉加载的回调 (页面初始化时也会执行一次)
  83. * 其中page.num:当前页 从1开始, page.size:每页数据条数,默认20
  84. * @param {Object} page
  85. */
  86. upCallback(page) {
  87. const app = this
  88. // 设置列表数据
  89. app.getMemberList(page.num)
  90. .then(list => {
  91. const curPageLen = list.content.length;
  92. const totalSize = list.totalElements;
  93. app.mescroll.endBySize(curPageLen, totalSize);
  94. })
  95. .catch(() => app.mescroll.endErr())
  96. },
  97. /**
  98. * 获取会员列表
  99. * @param {Number} pageNo 页码
  100. */
  101. getMemberList(pageNo = 1) {
  102. const app = this;
  103. return new Promise((resolve, reject) => {
  104. MemberApi.list({ dataType: app.curId, page: pageNo }, { load: false })
  105. .then(result => {
  106. // 合并新数据
  107. const newList = result.data.paginationResponse;
  108. app.memberList.content = getMoreListData(newList, app.memberList, pageNo);
  109. resolve(newList);
  110. })
  111. .catch(result => reject())
  112. })
  113. },
  114. // 切换选择的分类
  115. onSwitchTab(dataType = 'all') {
  116. const app = this;
  117. // 切换当前的分类ID
  118. app.curId = dataType;
  119. // 刷新列表数据
  120. app.mescroll.resetUpScroll();
  121. },
  122. // 跳转会员详情页
  123. onTargetDetail(memberId) {
  124. this.$navTo('pages/merchant/member/detail', { memberId })
  125. },
  126. // 刷新列表
  127. onRefreshList() {
  128. this.list = getEmptyPaginateObj()
  129. setTimeout(() => {
  130. this.mescroll.resetUpScroll()
  131. }, 120)
  132. },
  133. }
  134. }
  135. </script>
  136. <style lang="scss" scoped>
  137. /* 顶部选项卡 */
  138. .container {
  139. min-height: 100vh;
  140. }
  141. .tabs-wrapper {
  142. position: sticky;
  143. top: var(--window-top);
  144. display: flex;
  145. width: 100%;
  146. height: 88rpx;
  147. color: #333;
  148. font-size: 28rpx;
  149. background: #fff;
  150. border-bottom: 1rpx solid #e4e4e4;
  151. z-index: 100;
  152. overflow: hidden;
  153. white-space: nowrap;
  154. }
  155. .tab-item {
  156. display: inline-block;
  157. padding: 0 15rpx;
  158. text-align: center;
  159. min-width: 20%;
  160. height: 87rpx;
  161. line-height: 88rpx;
  162. box-sizing: border-box;
  163. .value {
  164. height: 100%;
  165. }
  166. &.active .value {
  167. color: #fd4a5f;
  168. border-bottom: 4rpx solid #fd4a5f;
  169. }
  170. }
  171. /* 会员列表 */
  172. .member-list {
  173. padding-top: 20rpx;
  174. line-height: 1;
  175. background: #f7f7f7;
  176. }
  177. .member-item {
  178. margin-bottom: 10rpx;
  179. padding: 30rpx;
  180. background: #fff;
  181. border: #f5f5f5 solid 1rpx;
  182. height: 188rpx;
  183. &:last-child {
  184. margin-bottom: 0;
  185. }
  186. .left {
  187. width: 320rxp;
  188. float: left;
  189. .image {
  190. display: block;
  191. width: 120rpx;
  192. height: 120rpx;
  193. border-radius: 120rpx;
  194. border: solid 1rpx #cccccc;
  195. }
  196. }
  197. .right {
  198. margin-left: 140rpx;
  199. height: 180rpx;
  200. .base {
  201. .name {
  202. font-weight: bold;
  203. max-height: 80rpx;
  204. font-size: 30rpx;
  205. color: #333;
  206. }
  207. .grade {
  208. margin-left: 20rpx;
  209. float: right;
  210. }
  211. }
  212. .amount {
  213. margin-top: 10rpx;
  214. .balance {
  215. margin-top: 15rpx;
  216. }
  217. .point {
  218. margin-top: 10rpx;
  219. }
  220. }
  221. .footer {
  222. margin-top: 20rpx;
  223. .member-views {
  224. float: right;
  225. }
  226. }
  227. }
  228. }
  229. </style>