collect.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <view class="collect-container">
  3. <view class="collect-container__head bg-white" :style="{ height: headHeight + 'px' }">
  4. <view :style="{ height: headHeight + 'px', paddingTop: headTop + 'px' }">
  5. <view class="navigater flex align-center justify-between">
  6. <view class="back" :style="{height: headHeight + 'px', lineHeight: headHeight + 'px'}"
  7. @tap="handleBack">
  8. <text class="wlIcon-fanhui1"></text>
  9. </view>
  10. <scroll-view scroll-x class="nav text-center">
  11. <view v-for="(item, index) in navList" :key="index" class="cu-item flex-sub"
  12. :class="currentItemId === item.type ? 'text-orange cur' : ''"
  13. @tap="handleSelect(item.type, index)">
  14. <text class="text-30">{{item.type_text}}</text>
  15. </view>
  16. </scroll-view>
  17. </view>
  18. </view>
  19. </view>
  20. <!-- 主体 -->
  21. <swiper class="collect-container__main" :current-item-id="currentItemId"
  22. :style="{ height: windowHeight + 'px' }" @change="changeCurrent" @animationfinish="animationFinish">
  23. <swiper-item v-for="(data, keys) in navList" :key="keys" :item-id="data.type">
  24. <wanl-empty :text="$t('collect.empty')" src="collect_default3x" v-if="data.dataList.length === 0 && data.loaded" />
  25. <scroll-view class="content" scroll-y @scrolltolower="loadData">
  26. <view class="item margin-bj padding-sm bg-white radius-bock" v-for="(item, index) in data.dataList"
  27. :key="index" @click="handleGoods(item.id)">
  28. <view class="cu-avatar margin-right-bj radius"
  29. :style="{backgroundImage: `url(${$appKit.oss(item.image, 88, 88)})`}"></view>
  30. <view class="subject">
  31. <view class="text-sm wanl-gray-dark text-cut-2">
  32. <view v-if="currentItemId === 'groups'" class="cu-tag sm bg-gradual-red radius margin-right-xs">
  33. {{ item.is_ladder === 1 ? $t('collect.ladder') : $t('collect.groupTag', [item.people_num]) }}
  34. </view>
  35. {{item.title}}
  36. </view>
  37. <view class="text-price text-red text-df"> {{item.price}} </view>
  38. <view class="menu">
  39. <view class="wanl-gray-light text-sm">
  40. <text class="margin-right-sm">{{ $t('collect.likes', [item.like]) }}</text>
  41. <text v-if="currentItemId === 'goods'">{{ $t('collect.payment', [item.payment]) }}</text>
  42. <text v-if="currentItemId === 'groups'">{{ $t('collect.grouped', [0]) }}</text>
  43. </view>
  44. <view class="button text-bold text-30">
  45. <text class="wlIcon-lajitong" @click.stop="loadFollow(item.id, index)"></text>
  46. <text class="wlIcon-dianpu1" @click.stop="onShop(item.shop_id)"></text>
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. <uni-load-more :status="data.loadingType" :content-text="contentText" />
  52. </scroll-view>
  53. </swiper-item>
  54. </swiper>
  55. </view>
  56. </template>
  57. <script>
  58. import { pullCollectList, postCollectFollow } from '@/features/mall/mall-gateway'
  59. export default {
  60. data() {
  61. return {
  62. headHeight: 0,
  63. windowHeight: 0,
  64. headTop: 0,
  65. currentId: 0,
  66. currentItemId: 'goods',
  67. navList: [],
  68. contentText: {
  69. contentdown: ' ',
  70. contentrefresh: '',
  71. contentnomore: ''
  72. }
  73. }
  74. },
  75. onLoad() {
  76. const sysInfo = uni.getSystemInfoSync()
  77. const statusBarHeight = sysInfo.statusBarHeight || 0
  78. this.headTop = statusBarHeight
  79. this.headHeight = statusBarHeight + uni.upx2px(90)
  80. this.windowHeight = sysInfo.windowHeight - uni.upx2px(90)
  81. this.navList = [{
  82. type: 'goods',
  83. type_text: this.$t('collect.goods'),
  84. dataList: [],
  85. loadingType: 'more',
  86. current_page: 1
  87. }, {
  88. type: 'groups',
  89. type_text: this.$t('collect.groups'),
  90. dataList: [],
  91. loadingType: 'more',
  92. current_page: 1
  93. }]
  94. this.contentText.contentrefresh = this.$t('collect.loading')
  95. this.loadData()
  96. },
  97. methods: {
  98. async loadData(source) {
  99. let navItem = this.navList[this.currentId]
  100. if (!navItem) return
  101. if (navItem.loadingType == 'noMore') return
  102. if (source === 'tabChange' && navItem.loaded === true) return
  103. if (navItem.loadingType === 'loading') return
  104. navItem.loadingType = 'loading'
  105. try {
  106. const res = await pullCollectList({
  107. type: navItem.type,
  108. page: navItem.current_page
  109. })
  110. navItem.current_page = res.current_page
  111. if (res.last_page === res.current_page) {
  112. navItem.loadingType = 'noMore'
  113. } else {
  114. navItem.loadingType = 'more'
  115. navItem.current_page++
  116. }
  117. res.data.forEach(item => {
  118. navItem.dataList.push(item.goods)
  119. })
  120. this.$set(navItem, 'loaded', true)
  121. } catch (e) {
  122. navItem.loadingType = 'more'
  123. console.error('[collect] load failed:', e)
  124. }
  125. },
  126. async loadFollow(id, index) {
  127. try {
  128. await postCollectFollow({
  129. type: this.currentItemId,
  130. id: id
  131. })
  132. this.$delete(this.navList[this.currentId].dataList, index)
  133. this.$store.commit('statistics/dynamic', {
  134. collection: this.$store.state.statistics.dynamic.collection - 1
  135. })
  136. } catch (e) {
  137. console.error('[collect] unfollow failed:', e)
  138. }
  139. },
  140. handleSelect(id, index) {
  141. this.currentItemId = id
  142. this.currentId = index
  143. },
  144. animationFinish(e) {
  145. this.changeCurrent(e)
  146. },
  147. changeCurrent(e) {
  148. this.currentItemId = e.detail.currentItemId
  149. this.currentId = e.detail.current
  150. this.loadData('tabChange')
  151. },
  152. handleBack() {
  153. uni.navigateBack({ delta: 1 })
  154. },
  155. handleGoods(id) {
  156. if (this.currentItemId === 'goods') {
  157. uni.navigateTo({ url: `/pages/product/goods?id=${id}` })
  158. } else if (this.currentItemId === 'groups') {
  159. uni.navigateTo({ url: `/pages/apps/groups/goods?id=${id}` })
  160. }
  161. },
  162. onShop(shop_id) {
  163. if (shop_id) {
  164. uni.navigateTo({ url: `/pages/shop/index?id=${shop_id}` })
  165. }
  166. }
  167. }
  168. }
  169. </script>
  170. <style lang="scss">
  171. .collect-container {
  172. &__head {
  173. .navigater {
  174. position: relative;
  175. .back {
  176. position: absolute;
  177. left: 25rpx;
  178. z-index: 9999;
  179. text {
  180. font-size: 36rpx;
  181. font-weight: bold;
  182. }
  183. }
  184. }
  185. }
  186. &__main {
  187. position: relative;
  188. z-index: 99;
  189. .content {
  190. height: 100%;
  191. .item {
  192. display: flex;
  193. .cu-avatar {
  194. height: 160rpx;
  195. width: 160rpx;
  196. flex-shrink: 0;
  197. }
  198. .subject {
  199. display: flex;
  200. flex: 1;
  201. flex-wrap: wrap;
  202. align-content: space-between;
  203. &>view {
  204. width: 100%;
  205. }
  206. .menu {
  207. display: flex;
  208. justify-content: space-between;
  209. .button {
  210. &>text + text{
  211. margin-left: 60rpx;
  212. margin-right: 10rpx;
  213. }
  214. }
  215. }
  216. }
  217. }
  218. }
  219. }
  220. }
  221. </style>