point-mall.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <template>
  2. <view class="index">
  3. <user-point />
  4. <view class="index-head">
  5. <scroll-view scroll-x class="list-scroll-content" :scroll-left="currentLeft" scroll-with-animation>
  6. <view class="index-head-navs">
  7. <view class="index-head-nav" v-for="(ele, index) in categoryIndexData" :key="index" :class="{ 'index-head-nav-active': tabIndex == index }" @click="setCat(index)">
  8. {{ ele.name }}
  9. </view>
  10. </view>
  11. </scroll-view>
  12. </view>
  13. <swiper :current="tabIndex" class="swiper-box" @change="ontabchange" duration="300">
  14. <swiper-item v-for="(nav, index) in categoryIndexData" :key="index" class="swiper-item">
  15. <scroll-view class="scroll-v" enableBackToTop="true" scroll-with-animation scroll-y @scrolltolower="loadMore">
  16. <view class="index-items">
  17. <view class="index-item" v-for="(item, key) in nav.goods" :key="key" @click="toGoods(item)">
  18. <view class="index-item-img">
  19. <u-image :src="item.goodsSku.thumbnail" mode="aspectFill">
  20. <u-loading slot="loading"></u-loading>
  21. </u-image>
  22. <view class="index-item-title">{{ item.goodsSku.goodsName }}</view>
  23. <view class="index-item-price">
  24. {{ item.points | unitPrice }}积分
  25. <span class="tipsMkt">¥{{ item.goodsSku.price | unitPrice }}</span>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. <uni-load-more :status="nav.loadStatus"></uni-load-more>
  31. </scroll-view>
  32. </swiper-item>
  33. </swiper>
  34. </view>
  35. </template>
  36. <script>
  37. import { getPointsCategory, getPointsGoods } from "@/api/promotions.js";
  38. import userPoint from "./user";
  39. export default {
  40. components: {
  41. "user-point": userPoint,
  42. },
  43. data() {
  44. return {
  45. headOffSetTop: "0",
  46. tabIndex: 0,
  47. categoryIndexData: [
  48. {
  49. categoryId: 0,
  50. name: "全部",
  51. loadStatus: "more",
  52. goods: [],
  53. params: {
  54. pageNumber: 1,
  55. pageSize: 10,
  56. pointsGoodsCategoryId: "",
  57. },
  58. },
  59. ],
  60. currentLeft: 0,
  61. pageParams: {
  62. pageNumber: 1,
  63. pageSize: 10,
  64. pointsGoodsCategoryId: 0,
  65. },
  66. flag: true,
  67. };
  68. },
  69. onLoad() {},
  70. async onPullDownRefresh() {
  71. this.categoryIndexData[this.tabIndex].goods = [];
  72. this.categoryIndexData[this.tabIndex].params.pageNumber = 1;
  73. this.categoryIndexData[this.tabIndex].loadStatus = "more";
  74. this.loadGoods();
  75. },
  76. onPageScroll(e) {
  77. if (e.scrollTop < -40 && this.flag) {
  78. this.flag = false;
  79. this.categoryIndexData[this.tabIndex].goods = [];
  80. this.categoryIndexData[this.tabIndex].params.pageNumber = 1;
  81. this.categoryIndexData[this.tabIndex].loadStatus = "more";
  82. uni.startPullDownRefresh();
  83. this.loadGoods();
  84. }
  85. },
  86. watch: {
  87. tabIndex(val) {
  88. if (
  89. this.categoryIndexData[this.tabIndex].goods.length == 0 &&
  90. this.categoryIndexData[this.tabIndex].params.pageNumber == 1
  91. ) {
  92. this.loadGoods();
  93. }
  94. },
  95. },
  96. async onShow() {
  97. //获取顶级分类
  98. let response = await getPointsCategory();
  99. if (response.data.success) {
  100. let navData = response.data.result.records;
  101. navData.forEach((item) => {
  102. this.categoryIndexData.push({
  103. categoryId: item.id,
  104. goods: [],
  105. loadStatus: "more",
  106. name: item.name,
  107. params: {
  108. pageNumber: 1,
  109. pageSize: 10,
  110. pointsGoodsCategoryId: item.id,
  111. },
  112. });
  113. });
  114. }
  115. this.loadGoods();
  116. },
  117. methods: {
  118. // 跳转
  119. navigateTo(url) {
  120. uni.navigateTo({
  121. url,
  122. });
  123. },
  124. toGoods(item) {
  125. //跳转详情
  126. uni.navigateTo({
  127. url: `/pages/product/goods?id=${item.skuId}&goodsId=${item.id}&whetherPoint=1`,
  128. });
  129. },
  130. async loadGoods() {
  131. let index = this.tabIndex;
  132. //获取商品数据
  133. let response = await getPointsGoods(this.categoryIndexData[index].params);
  134. if (response.data.success) {
  135. this.categoryIndexData[index].goods.push(
  136. ...response.data.result.records
  137. );
  138. if (response.data.result.records.length < 10) {
  139. this.categoryIndexData[index].loadStatus = "noMore";
  140. }
  141. let _this = this;
  142. setTimeout(function () {
  143. _this.flag = true;
  144. }, 3000);
  145. }
  146. uni.stopPullDownRefresh();
  147. },
  148. setCat(type) {
  149. this.tabIndex = type;
  150. },
  151. ontabchange(e) {
  152. this.tabIndex = e.detail.current;
  153. if (e.detail.current > 3) {
  154. this.currentLeft = (e.detail.current - 3) * 70;
  155. } else {
  156. this.currentLeft = 0;
  157. }
  158. },
  159. loadMore() {
  160. if (this.categoryIndexData[this.tabIndex].loadStatus == "more") {
  161. this.categoryIndexData[this.tabIndex].params.pageNumber++;
  162. this.loadGoods();
  163. }
  164. },
  165. },
  166. };
  167. </script>
  168. <style lang="scss" scoped>
  169. page {
  170. height: 100%;
  171. }
  172. .tipsMkt {
  173. float: right;
  174. color: #c0c4cc;
  175. font-size: 24rpx;
  176. text-decoration: line-through;
  177. margin-right: 20rpx;
  178. }
  179. .header {
  180. background: $light-color;
  181. position: relative;
  182. color: #fff;
  183. display: flex;
  184. height: 80rpx;
  185. align-items: center;
  186. justify-content: center;
  187. font-size: 26rpx;
  188. font-size: 34rpx;
  189. .left,
  190. .right {
  191. position: absolute;
  192. width: max-content;
  193. height: max-content;
  194. top: 0;
  195. bottom: 0;
  196. margin: auto;
  197. }
  198. .left {
  199. float: left;
  200. top: 0;
  201. bottom: 0;
  202. left: 20rpx;
  203. }
  204. .right {
  205. float: right;
  206. right: 20rpx;
  207. }
  208. }
  209. .index {
  210. height: 100vh;
  211. // #ifdef H5
  212. height: calc(100vh - 44px);
  213. // #endif
  214. width: 100%;
  215. overflow: hidden;
  216. }
  217. .index-head {
  218. background: #fff;
  219. }
  220. .list-scroll-content {
  221. white-space: nowrap;
  222. width: 100%;
  223. height: 100rpx;
  224. color: #333;
  225. }
  226. .index-head-navs {
  227. width: 100%;
  228. height: 92rpx;
  229. display: -webkit-box;
  230. display: -webkit-flex;
  231. display: flex;
  232. align-items: center;
  233. }
  234. .index-head-nav {
  235. width: 100rpx;
  236. padding-bottom: 8rpx;
  237. margin: 20rpx;
  238. text-align: center;
  239. box-sizing: border-box;
  240. white-space: nowrap;
  241. font-size: 30rpx;
  242. color: #333;
  243. display: -webkit-box;
  244. display: -webkit-flex;
  245. display: flex;
  246. justify-content: center;
  247. align-items: center;
  248. &-active {
  249. border-bottom: 4rpx solid $light-color;
  250. }
  251. }
  252. .swiper-box {
  253. // #ifdef H5
  254. height: calc(100vh - 294px);
  255. // #endif
  256. // #ifndef H5
  257. height: calc(100vh - 200px);
  258. // #endif
  259. .scroll-v {
  260. height: 100%;
  261. }
  262. }
  263. .index-items {
  264. padding-top: 10rpx;
  265. margin-top: 20rpx;
  266. padding-left: 20rpx;
  267. background-color: #f7f7f7;
  268. display: -webkit-box;
  269. display: -webkit-flex;
  270. display: flex;
  271. align-items: center;
  272. flex-wrap: wrap;
  273. }
  274. .index-item {
  275. width: 346rpx;
  276. // height: 2100rpx;
  277. background-color: #fff;
  278. margin: 0 18rpx 20rpx 0;
  279. border-radius: 16rpx;
  280. box-sizing: border-box;
  281. overflow: hidden;
  282. height: auto;
  283. padding-bottom: 20rpx;
  284. }
  285. .index-item-img {
  286. /deep/ .u-image {
  287. width: 346rpx !important;
  288. height: 320rpx !important;
  289. border-radius: 10rpx !important;
  290. }
  291. }
  292. .index-item-title {
  293. font-size: 26rpx;
  294. color: #333333;
  295. padding: 0 20rpx;
  296. height: 80rpx;
  297. box-sizing: border-box;
  298. max-height: 3em;
  299. overflow: hidden;
  300. }
  301. .index-item-title-desc {
  302. font-size: 25rpx;
  303. color: #999999;
  304. margin-top: 10rpx;
  305. }
  306. .index-item-price {
  307. font-size: 28rpx;
  308. color: #ff5a10;
  309. padding: 20rpx 0 0 20rpx;
  310. }
  311. </style>