category.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. <template>
  2. <view class="content">
  3. <!-- 兼容小程序搜索 -->
  4. <!-- #ifdef MP -->
  5. <navigator url="/pages/product/search">
  6. <view class="input-box flex">
  7. <view class=" input-content flex">
  8. <view class="iconfont iconsearch"></view>
  9. <view class="input"><input disabled placeholder="请输入搜索内容" /></view>
  10. </view>
  11. </view>
  12. </navigator>
  13. <!-- #endif -->
  14. <!-- #ifdef H5 -->
  15. <!-- <view class="cate-bg"></view> -->
  16. <!-- #endif -->
  17. <div class="classBox">
  18. <scroll-view scroll-y class="left-aside">
  19. <view class="f-item b-b" :class="{ active: item.id === currentId }" v-for="(item, index) in flist" :key="item.id" @click="tabtap(item, index)">
  20. {{ item.cate_name }}
  21. </view>
  22. </scroll-view>
  23. <scroll-view scroll-with-animation scroll-y class="right-aside" :scroll-top="tabScrollTop" @scrolltolower="getListMore">
  24. <view class="t-list " v-if="flist.length > 0">
  25. <view @click="navToDetailPage(titem)" class="t-item" v-for="titem in flist[actionClassInd].list" :key="titem.id" id="'main-' + item.id">
  26. <image :src="titem.image" mode="scaleToFill" :lazy-load="true"></image>
  27. <view class="font">
  28. <view class="title">{{ titem.store_name }}</view>
  29. <view class="font-bottom">
  30. <view class="price">¥{{ titem.price }}</view>
  31. <view class="shop"><view class="shop-text">马上购</view></view>
  32. </view>
  33. </view>
  34. </view>
  35. <view class="text-center"><uni-load-more :status="flist[actionClassInd].loadingType"></uni-load-more></view>
  36. </view>
  37. <!-- </view> -->
  38. </scroll-view>
  39. </div>
  40. </view>
  41. </template>
  42. <script>
  43. import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
  44. import { getProducts, getCategoryList, newgetList } from '@/api/product.js';
  45. export default {
  46. components: {
  47. uniLoadMore
  48. },
  49. data() {
  50. return {
  51. sizeCalcState: false,
  52. tabScrollTop: 0,
  53. currentId: 5,
  54. flist: [],
  55. commodity: [], //商品列表
  56. current: 0,
  57. page: 1, //当前页数
  58. limit: 6, //每次加载数据条数
  59. loadingType: 'more', //加载更多状态
  60. actionClassInd: 0
  61. };
  62. },
  63. onLoad() {
  64. this.loadData();
  65. },
  66. //下拉刷新
  67. onPullDownRefresh() {
  68. this.loadData('refresh');
  69. },
  70. // 监听导航栏输入框点击事件
  71. onNavigationBarSearchInputClicked(e) {
  72. uni.navigateTo({
  73. url: '/pages/product/search'
  74. });
  75. },
  76. //监听页面是否滚动到底部加载更多
  77. onReachBottom() {
  78. this.loadData();
  79. },
  80. methods: {
  81. // 载入数据
  82. async loadData(type = 'add', loading) {
  83. let obj = this;
  84. let data = {
  85. page: obj.page,
  86. limit: obj.limit
  87. };
  88. //没有更多直接返回
  89. if (type === 'add') {
  90. if (obj.loadingType === 'nomore') {
  91. return;
  92. }
  93. obj.loadingType = 'loading';
  94. } else {
  95. obj.loadingType = 'more';
  96. }
  97. if (type === 'refresh') {
  98. // 清空数组
  99. obj.page = 1;
  100. }
  101. getCategoryList({})
  102. .then(({ data }) => {
  103. console.log('------', data);
  104. obj.flist = data.map(function(s) {
  105. s.list = []; //用于保存当前分类下商品对象的数据
  106. s.loadingType = 'more'; //判断当前商品分类数据是否已经加载完毕
  107. s.page = 1; //当前商品分类加载的商品页数
  108. s.limit = 10; //每次家在数据加载的数据条数
  109. return s;
  110. });
  111. console.log(obj.flist, '数据');
  112. obj.currentId = obj.flist[0].id;
  113. // 开始处理数据
  114. // for (var i = 0; i < obj.flist.length; i++) {
  115. // }
  116. obj.getProductsList(obj.flist[0]);
  117. })
  118. .catch(err => {
  119. console.log(err);
  120. });
  121. },
  122. //一级分类点击
  123. tabtap(item, index) {
  124. // 判断有没有初始化页面高度对象数据
  125. // if (!this.sizeCalcState) {
  126. // this.calcSize();
  127. // }
  128. // 获取当前点击的id
  129. this.currentId = item.id;
  130. //获取当前点击的下标
  131. this.actionClassInd = index;
  132. this.tabScrollTop = item.top;
  133. // 获取当前选中的对象
  134. let ls = this.flist[this.actionClassInd];
  135. // 判断当前数据是否已经加载完毕
  136. if (ls.loadingType == 'more') {
  137. this.getProductsList(ls);
  138. }
  139. },
  140. //右侧栏滚动
  141. // asideScroll(e) {
  142. // console.log('开始处理数据');
  143. // // 判断有没有初始化页面高度对象数据
  144. // // if (!this.sizeCalcState) {
  145. // // this.calcSize();
  146. // // }
  147. // // 获取当前滚轮高度
  148. // let scrollTop = e.detail.scrollTop;
  149. // let box = 0; //列表包裹框高度初始化
  150. // let bottom = 10; //距离页面底部多少像素左侧列表切换到最后一个一级分类
  151. // // 查询当前页面对象
  152. // let view = uni.createSelectorQuery().select('.content');
  153. // view.fields(
  154. // {
  155. // id: true,
  156. // dataset: true,
  157. // rect: true,
  158. // size: true,
  159. // scrollOffset: true
  160. // },
  161. // function(e) {
  162. // // 保存包裹框高度
  163. // box = e.height;
  164. // }
  165. // ).exec();
  166. // // 获取所有距离顶部大于滚轮距离页面高度的所有分类
  167. // let tabs = this.flist.filter(item => item.top - 10 <= scrollTop).reverse();
  168. // if (tabs.length > 0) {
  169. // // 判断是否已经到达滚轮底部
  170. // if (box + scrollTop + bottom >= e.detail.scrollHeight) {
  171. // this.currentId = this.flist[this.flist.length - 1].id;
  172. // } else {
  173. // this.currentId = tabs[0].id;
  174. // }
  175. // }
  176. // },
  177. //计算右侧栏每个tab的高度等信息
  178. // calcSize() {
  179. // let h = 0;
  180. // this.flist.forEach(item => {
  181. // let view = uni.createSelectorQuery().select('#main-' + item.id);
  182. // view.fields(
  183. // {
  184. // size: true
  185. // },
  186. // data => {
  187. // item.top = h;
  188. // h += data.height;
  189. // item.bottom = h;
  190. // }
  191. // ).exec();
  192. // });
  193. // this.sizeCalcState = true;
  194. // },
  195. // 加载分类下商品数据
  196. getProductsList(item, type = 'add') {
  197. console.log(item);
  198. const obj = this;
  199. const requestData = {
  200. page: item.page,
  201. limit: item.limit,
  202. cid: item.id
  203. };
  204. // 判断数据是否加载中
  205. if (item.loadingType == 'nomore' || item.loadingType == 'loading') {
  206. return;
  207. }
  208. // 判断是否重新加载数据
  209. if (type == 'refresh') {
  210. item.list = [];
  211. }
  212. // 设置数据加载中
  213. item.loadingType = 'loading';
  214. return new Promise((ok, erro) => {
  215. getProducts(requestData)
  216. .then(({ data }) => {
  217. // item.list = data.map((s,ind) => {
  218. // return s;
  219. // });
  220. data.forEach((sj, index) => {
  221. item.list.push(sj);
  222. });
  223. if (item.limit == data.length) {
  224. item.page++;
  225. item.loadingType = 'more';
  226. } else {
  227. item.loadingType = 'nomore';
  228. }
  229. if (type === 'refresh') {
  230. if (loading == 1) {
  231. uni.hideLoading();
  232. } else {
  233. uni.stopPullDownRefresh();
  234. }
  235. }
  236. })
  237. .catch(err => {
  238. console.log(err);
  239. });
  240. });
  241. },
  242. //下拉到底部后加载商品列表数据
  243. getListMore() {
  244. this.getProductsList(this.flist[this.actionClassInd]);
  245. },
  246. navToDetailPage(item) {
  247. // 点击导航跳转到详细页面
  248. uni.navigateTo({
  249. url: '/pages/product/product?id=' + item.id
  250. });
  251. }
  252. }
  253. };
  254. </script>
  255. <style lang="scss">
  256. .text-center {
  257. width: 100%;
  258. text-align: center;
  259. }
  260. /* #ifdef MP || APP-PLUS*/
  261. .input-box {
  262. padding: 25rpx;
  263. /* #ifdef APP-PLUS */
  264. margin-top: var(--status-bar-height);
  265. /* #endif */
  266. background-color: #fe8119;
  267. height: 44px;
  268. .iconsearch {
  269. font-size: 50rpx;
  270. }
  271. .input-content {
  272. border-radius: 99rpx;
  273. flex-grow: 1;
  274. padding: 5rpx 30rpx;
  275. // background-color: rgba(231, 231, 231, 0.7);
  276. background: #ffffff;
  277. .input {
  278. flex-grow: 1;
  279. input {
  280. font-size: $font-base;
  281. }
  282. }
  283. }
  284. .input-button {
  285. padding-left: 20rpx;
  286. font-size: $font-base;
  287. height: 100%;
  288. }
  289. }
  290. /* #endif */
  291. page,
  292. .content {
  293. height: 100%;
  294. background-color: #f8f8f8;
  295. }
  296. .content {
  297. .cate-bg {
  298. position: fixed;
  299. top: 0;
  300. width: 750rpx;
  301. height: 44px;
  302. z-index: 10;
  303. // background: linear-gradient(90deg, #FF8E00, #FE762F);
  304. background: #12ada9;
  305. }
  306. .classBox {
  307. // padding-top: 44px;
  308. display: flex;
  309. height: calc(100% - 44px);
  310. /* #ifdef APP-PLUS || MP */
  311. height: calc(100% - 88px);
  312. /* #endif */
  313. }
  314. }
  315. .left-aside {
  316. flex-shrink: 0;
  317. width: 180rpx;
  318. height: 100%;
  319. background-color: #fff;
  320. }
  321. .f-item {
  322. display: flex;
  323. align-items: center;
  324. justify-content: center;
  325. width: 100%;
  326. height: 100rpx;
  327. font-size: 28rpx;
  328. color: $font-color-base;
  329. position: relative;
  330. &.active {
  331. color: $base-color;
  332. background: #f8f8f8;
  333. &:before {
  334. content: '';
  335. position: absolute;
  336. left: 0;
  337. top: 50%;
  338. transform: translateY(-50%);
  339. height: 36rpx;
  340. width: 8rpx;
  341. background-color: $base-color;
  342. border-radius: 0 4px 4px 0;
  343. opacity: 0.8;
  344. }
  345. }
  346. }
  347. .right-aside {
  348. flex: 1;
  349. overflow: hidden;
  350. padding-left: 20rpx;
  351. padding-right: 20rpx;
  352. }
  353. .s-item {
  354. display: flex;
  355. align-items: center;
  356. font-weight: bold;
  357. height: 70rpx;
  358. padding-top: 8rpx;
  359. font-size: 35rpx;
  360. color: $font-color-dark;
  361. }
  362. .t-list {
  363. display: flex;
  364. flex-wrap: wrap;
  365. border-radius: 15rpx;
  366. width: 100%;
  367. background: #fff;
  368. padding-top: 12rpx;
  369. &:after {
  370. content: '';
  371. flex: 99;
  372. height: 0;
  373. }
  374. }
  375. .t-item {
  376. height: 220rpx;
  377. flex-shrink: 0;
  378. display: flex;
  379. justify-content: center;
  380. align-items: center;
  381. flex-direction: row;
  382. width: 500rpx;
  383. font-size: 26rpx;
  384. color: #666;
  385. padding-bottom: 20rpx;
  386. margin-right: 40rpx;
  387. &.active {
  388. display: none;
  389. }
  390. image {
  391. width: 200rpx;
  392. height: 200rpx;
  393. margin-top: 30rpx;
  394. margin-left: 20rpx;
  395. }
  396. .font {
  397. margin-left: 25rpx;
  398. margin-top: 30rpx;
  399. width: 500rpx;
  400. .title {
  401. font-weight: bold;
  402. font-size: $font-base;
  403. color: $font-color-dark;
  404. word-break: break-all;
  405. display: -webkit-box;
  406. -webkit-line-clamp: 2;
  407. -webkit-box-orient: vertical;
  408. overflow: hidden;
  409. }
  410. .font-bottom {
  411. height: 60rpx;
  412. width: 100%;
  413. display: flex;
  414. margin-top: 76rpx;
  415. justify-content: space-between;
  416. .shop {
  417. width: 137rpx;
  418. height: 52rpx;
  419. background: linear-gradient(270deg, #ff8149, #ff4e00);
  420. border-radius: 26rpx;
  421. .shop-text {
  422. font-size: 26rpx;
  423. font-family: PingFang SC;
  424. font-weight: 500;
  425. color: #ffffff;
  426. margin-left: 30rpx;
  427. margin-top: 10rpx;
  428. }
  429. }
  430. .price {
  431. margin-top: 14rpx;
  432. width: 88rpx;
  433. height: 26rpx;
  434. font-size: 34rpx;
  435. font-family: PingFang SC;
  436. font-weight: bold;
  437. color: #fb3a2f;
  438. line-height: 34rpx;
  439. }
  440. }
  441. }
  442. }
  443. </style>