category.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <template>
  2. <view class="content">
  3. <scroll-view scroll-y class="left-aside">
  4. <view v-for="(item,index) in flist" :key="item.id" class="f-item b-b" :class="{ active: index === currentId }" @click="tabtap(item,index)">{{ item.cate_name }}</view>
  5. </scroll-view>
  6. <scroll-view :scroll-with-animation="scrollAnimation" scroll-y class="right-aside" :scroll-top="tabScrollTop" @scrolltolower="getProductsList(flist[currentId])">
  7. <view class="t-list">
  8. <view @click="navToList(flist[currentId].id, titem.id)" class="t-item" v-for="titem in flist[currentId].list" :key="titem.id">
  9. <view class=""><image :src="titem.pic"></image></view>
  10. <view class="titem-right">
  11. <text class="clamp">{{ titem.store_name }}</text>
  12. <view class="titem-right-d">
  13. <view class="price">¥{{ titem.price }}</view>
  14. <view class="button">马上购</view>
  15. </view>
  16. </view>
  17. </view>
  18. </view>
  19. </scroll-view>
  20. </view>
  21. </template>
  22. <script>
  23. import { getCategoryList, getProducts } from '@/api/product.js';
  24. export default {
  25. data() {
  26. return {
  27. sizeCalcState: false,
  28. tabScrollTop: 0,
  29. currentId: 0,
  30. flist: ['list'],
  31. scrollAnimation: true //是否开启动画
  32. };
  33. },
  34. onLoad() {
  35. this.loadData();
  36. },
  37. // 监听导航栏输入框点击事件
  38. onNavigationBarSearchInputClicked(e) {
  39. uni.navigateTo({
  40. url: '/pages/product/search'
  41. });
  42. },
  43. methods: {
  44. // 载入数据
  45. loadData() {
  46. let obj = this;
  47. getCategoryList({})
  48. .then(({ data }) => {
  49. console.log(data);
  50. obj.flist = data.map(function(s) {
  51. s.list = []; //用于保存当前分类下商品对象的数据
  52. s.loadingType = 'more'; //判断当前商品分类数据是否已经加载完毕
  53. s.page = 1; //当前商品分类加载的商品页数
  54. s.limit = 10; //每次家在数据加载的数据条数
  55. return s;
  56. });
  57. // console.log(obj.flist,"123456789")
  58. obj.currentId = 0;
  59. obj.getProductsList(obj.flist[0]);
  60. })
  61. .catch(err => {
  62. console.log(err);
  63. });
  64. },
  65. getProductsList(item, type = 'add') {
  66. if (type === 'tabChange' && item.loaded === true) {
  67. //tab切换只有第一次需要加载数据
  68. return;
  69. }
  70. if (item.loadingType === 'noMore' || item.loadingType === 'loading') {
  71. //防止重复加载
  72. return;
  73. }
  74. item.loadingType = 'loading';
  75. const obj = this;
  76. const requestData = {
  77. page: item.page,
  78. limit: item.limit,
  79. cid: item.id
  80. };
  81. return new Promise((ok, erro) => {
  82. getProducts(requestData)
  83. .then(({ data }) => {
  84. item.list = item.list.concat(data);
  85. item.page ++
  86. if(item.limit != data.length){
  87. item.loadingType = 'noMore'
  88. }else {
  89. item.loadingType = 'more'
  90. }
  91. this.$set(item, 'loaded', true);
  92. obj.$nextTick(e => {
  93. // 重新开启动画效果
  94. uni.hideLoading();
  95. // 数据加载完成后重新计算高度
  96. obj.scrollAnimation = true;
  97. });
  98. ok(data);
  99. })
  100. .catch(err => {
  101. erro(err);
  102. console.log(err);
  103. });
  104. });
  105. },
  106. //一级分类点击
  107. tabtap(item,index) {
  108. let obj = this;
  109. // 获取当前点击的id
  110. this.currentId = index;
  111. obj.getProductsList(item);
  112. },
  113. //右侧栏滚动
  114. // asideScroll(e) {
  115. // // 判断有没有初始化页面高度对象数据
  116. // if (!this.sizeCalcState) {
  117. // this.calcSize();
  118. // }
  119. // let scrollTop = e.detail.scrollTop;
  120. // let box = 0; //列表包裹框高度初始化
  121. // let bottom = 10; //距离页面底部多少像素左侧列表切换到最后一个一级分类
  122. // // 查询当前页面对象
  123. // let view = uni.createSelectorQuery().select('.content');
  124. // view.fields(
  125. // {
  126. // id: true,
  127. // dataset: true,
  128. // rect: true,
  129. // size: true,
  130. // scrollOffset: true
  131. // },
  132. // function(e) {
  133. // // 保存包裹框高度
  134. // box = e.height;
  135. // }
  136. // ).exec();
  137. // // 获取所有距离顶部大于滚轮距离页面高度的所有分类
  138. // let tabs = this.flist.filter(item =>( item.top-10) <= scrollTop).reverse();
  139. // if (tabs.length > 0) {
  140. // // 判断是否已经到达滚轮底部
  141. // if (box + scrollTop + bottom >= e.detail.scrollHeight) {
  142. // this.currentId = this.flist[this.flist.length - 1].id;
  143. // } else {
  144. // this.currentId = tabs[0].id;
  145. // }
  146. // }
  147. // },
  148. navToList(sid, tid) {
  149. // 点击导航跳转到详细页面
  150. uni.navigateTo({
  151. url: '/pages/product/product?fid=' + this.currentId + '&sid=' + sid + '&id=' + tid
  152. });
  153. }
  154. }
  155. };
  156. </script>
  157. <style lang="scss">
  158. page,
  159. .content {
  160. height: 100%;
  161. background-color: #f8f8f8;
  162. }
  163. .content {
  164. display: flex;
  165. }
  166. .left-aside {
  167. flex-shrink: 0;
  168. width: 200rpx;
  169. height: 100%;
  170. background-color: #f2f2f2;
  171. }
  172. .f-item {
  173. display: flex;
  174. align-items: center;
  175. justify-content: center;
  176. width: 100%;
  177. height: 100rpx;
  178. font-size: 28rpx;
  179. color: $font-color-base;
  180. position: relative;
  181. &.active {
  182. color: #000;
  183. font-weight: bold;
  184. background: #fff;
  185. &:before {
  186. content: '';
  187. position: absolute;
  188. left: 0;
  189. top: 50%;
  190. transform: translateY(-50%);
  191. height: 100%;
  192. width: 4rpx;
  193. background-color: #1075ff;
  194. border-radius: 0 4px 4px 0;
  195. opacity: 0.8;
  196. }
  197. }
  198. }
  199. .right-aside {
  200. // flex: 1;
  201. background-color: #fff;
  202. overflow: hidden;
  203. .s-list {
  204. margin-top: 2rpx;
  205. // padding: 5rpx;
  206. margin: 25rpx;
  207. }
  208. }
  209. .s-item {
  210. display: flex;
  211. // align-items: center;
  212. height: 70rpx;
  213. padding: 30rpx;
  214. padding-top: 20rpx;
  215. font-size: 28rpx;
  216. color: $font-color-dark;
  217. }
  218. .t-list {
  219. // display: flex;
  220. // flex-wrap: wrap;
  221. border-radius: 15rpx;
  222. width: 100%;
  223. background: #fff;
  224. padding-top: 12rpx;
  225. &:after {
  226. content: '';
  227. flex: 99;
  228. height: 0;
  229. }
  230. }
  231. .t-item {
  232. margin-top: 20rpx;
  233. flex-shrink: 0;
  234. display: flex;
  235. border-bottom: solid 1rpx #f2f2f2;
  236. // justify-content: center;
  237. // align-items: center;
  238. // flex-direction: column;
  239. // padding: 30rpx;
  240. width: 100%;
  241. font-size: 26rpx;
  242. color: #666;
  243. padding-bottom: 20rpx;
  244. image {
  245. width: 180rpx;
  246. height: 180rpx;
  247. margin: 0 20rpx;
  248. border-radius: 10rpx;
  249. }
  250. .titem-right {
  251. width: 100%;
  252. display: grid;
  253. align-content: space-between;
  254. text:nth-child(1) {
  255. width: 100%;
  256. color: #333333;
  257. font-size: 32rpx;
  258. }
  259. text:nth-child(2) {
  260. color: #666666;
  261. font-size: 28rpx;
  262. }
  263. .titem-right-d {
  264. display: flex;
  265. justify-content: space-between;
  266. padding-right: 20rpx;
  267. .price {
  268. color: #fb3a2f;
  269. font-size: 32rpx;
  270. }
  271. .button {
  272. background: linear-gradient(90deg, #438bed 0%, #44bfec 100%);
  273. background-color: #438bed;
  274. height: 50rpx;
  275. line-height: 50rpx;
  276. border-radius: 25rpx;
  277. padding: 0 30rpx;
  278. color: #fff;
  279. font-size: 25rpx;
  280. }
  281. }
  282. }
  283. }
  284. </style>