index.html 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <!-- +---------------------------------------------------------------------- -->
  2. <!-- | CRMEB [ CRMEB赋能开发者,助力企业发展 ] -->
  3. <!-- +---------------------------------------------------------------------- -->
  4. <!-- | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved. -->
  5. <!-- +---------------------------------------------------------------------- -->
  6. <!-- | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 -->
  7. <!-- +---------------------------------------------------------------------- -->
  8. <!-- | Author: CRMEB Team <admin@crmeb.com> -->
  9. <!-- +---------------------------------------------------------------------- -->
  10. {extend name="public/container"}
  11. {block name="title"}商品列表{/block}
  12. {block name="head_top"}
  13. <style>
  14. .nothing {
  15. position: absolute;
  16. top: 50%;
  17. left: 50%;
  18. width: 4rem;
  19. height: 4rem;
  20. -webkit-transform: translate(-50%, -50%);
  21. transform: translate(-50%, -50%);
  22. }
  23. body {
  24. padding-bottom: 1.1rem;
  25. padding-bottom: calc(1.1rem + constant(safe-area-inset-bottom));
  26. padding-bottom: calc(1.1rem + env(safe-area-inset-bottom));
  27. }
  28. </style>
  29. {/block}
  30. {block name="content"}
  31. <div v-cloak id="app">
  32. <div class="store">
  33. <div v-if="banner.length" class="banner">
  34. <div id="swiper1" class="swiper-container" @click="swiper1Click">
  35. <div class="swiper-wrapper">
  36. <div v-for="(item, index) in banner" :key="index" :data-url="item.url" class="swiper-slide">
  37. <img :src="item.pic" :alt="item.title">
  38. </div>
  39. </div>
  40. </div>
  41. <div class="swiper-pagination"></div>
  42. </div>
  43. <div :style="{ height: isFixed ? offsetHeight + 'px' : 'auto' }">
  44. <div ref="tabs" id="tabs" :class="{ fixed: isFixed }" class="swiper-container tabs" @click="swiper2Click">
  45. <div class="swiper-wrapper">
  46. <div v-for="(item, index) in categoryList" :key="item.id" :class="{ on: clickedIndex === index }" class="swiper-slide">{{ item.cate_name }}</div>
  47. </div>
  48. </div>
  49. </div>
  50. <div class="goods-section">
  51. <div class="list">
  52. <a v-for="item in goodsList" :key="item.id" class="item" :href="'detail.html?id=' + item.id">
  53. <div class="image">
  54. <img class="img" :src="item.image" alt="">
  55. </div>
  56. <div class="text">
  57. <div class="title">{{ item.store_name }}</div>
  58. <div class="group">
  59. <div class="price">¥<span class="num">{{ item.price }}</span></div>
  60. <div class="sale">已售{{ item.sales }}件</div>
  61. </div>
  62. </div>
  63. </a>
  64. </div>
  65. <div v-if="goodsList.length && !loading" class="finished">{{ loadTitle }}</div>
  66. <div v-if="finished && !goodsList.length" class="empty">
  67. <img src="{__WAP_PATH}zsff/images/empty.png" alt="暂无商品">
  68. <div>暂无商品</div>
  69. </div>
  70. </div>
  71. </div>
  72. {include file="public/store_menu"}
  73. </div>
  74. <script>
  75. var banner = {$banner};
  76. require(['vue', 'store', 'helper', 'swiper'], function (Vue, api, $h, Swiper) {
  77. new Vue({
  78. el: '#app',
  79. data: {
  80. banner: banner ? banner : [],
  81. categoryList: [],
  82. goodsList: [],
  83. clickedIndex: 0,
  84. activeId: 0,
  85. loadTitle: '',
  86. page: 1,
  87. limit: 16,
  88. loading:false,
  89. finished:false,
  90. isFixed: false,
  91. offsetTop: 0,
  92. offsetHeight: 0
  93. },
  94. created: function () {
  95. var vm = this;
  96. this.getCateList();
  97. this.getGoodsList();
  98. window.onscroll
  99. window.addEventListener('scroll', function () {
  100. vm.isFixed = window.pageYOffset >= vm.offsetTop;
  101. });
  102. },
  103. mounted: function () {
  104. this.$nextTick(function () {
  105. this.swiper1 = new Swiper('#swiper1', {
  106. autoplay: true,
  107. loop: true,
  108. spaceBetween: 20,
  109. pagination: {
  110. el: '.swiper-pagination'
  111. }
  112. });
  113. $h.EventUtil.listenTouchDirection(document, function () {
  114. this.getGoodsList();
  115. }.bind(this));
  116. });
  117. },
  118. methods: {
  119. // 点击轮播图
  120. swiper1Click: function () {
  121. if (this.swiper1.clickedIndex === undefined) {
  122. return;
  123. }
  124. var url = this.banner[this.swiper1.realIndex].url;
  125. if (url.indexOf('http') === -1) {
  126. return;
  127. }
  128. window.location = url;
  129. },
  130. // 获取分类
  131. getCateList: function () {
  132. var vm = this;
  133. $h.loadFFF();
  134. api.baseGet($h.U({
  135. c: 'store',
  136. a: 'getcategory'
  137. }), function (res) {
  138. $h.loadClear();
  139. vm.categoryList = [
  140. {
  141. cate_name: '全部',
  142. id: 0
  143. }
  144. ].concat(res.data.data);
  145. vm.$nextTick(function () {
  146. vm.tabs = new Swiper('#tabs', {
  147. freeMode: true,
  148. slidesPerView: 'auto',
  149. observer: true,
  150. on: {
  151. init: function () {
  152. vm.offsetTop = vm.$refs.tabs.offsetTop;
  153. vm.offsetHeight = vm.$refs.tabs.offsetHeight;
  154. }
  155. }
  156. });
  157. });
  158. }, function () {
  159. $h.loadClear();
  160. });
  161. },
  162. // 获取商品列表
  163. getGoodsList: function (id) {
  164. if (this.loading || this.finished) {
  165. return;
  166. }
  167. this.loadTitle = '';
  168. this.loading = true;
  169. $h.loadFFF();
  170. api.baseGet($h.U({
  171. c: 'store',
  172. a: 'getproductlist',
  173. p: {
  174. cId: this.activeId,
  175. page: this.page++,
  176. limit: this.limit
  177. }
  178. }), function (res) {
  179. this.loading = false;
  180. $h.loadClear();
  181. var data = res.data.data;
  182. this.goodsList = this.goodsList.concat(data);
  183. this.finished = data.length < this.limit;
  184. this.loadTitle = this.finished ? '已全部加载完' : '上拉加载更多';
  185. }.bind(this), function () {
  186. $h.loadClear();
  187. this.loading = false;
  188. }.bind(this));
  189. },
  190. // 点击商品分类
  191. swiper2Click: function () {
  192. if (this.tabs.clickedIndex === undefined || this.loading) {
  193. return;
  194. }
  195. var swiperWidth = this.tabs.width;
  196. var wrapperWidth = this.tabs.$wrapperEl[0].scrollWidth;
  197. var clickedWidth = this.tabs.clickedSlide.offsetWidth;
  198. var clickedLeft = this.tabs.clickedSlide.offsetLeft;
  199. this.clickedIndex = this.tabs.clickedIndex;
  200. this.tabs.setTransition(300);
  201. if (clickedLeft < (swiperWidth - clickedWidth) / 2) {
  202. this.tabs.setTranslate(0);
  203. } else if (clickedLeft > wrapperWidth - (clickedWidth + swiperWidth) / 2) {
  204. this.tabs.setTranslate(swiperWidth - wrapperWidth);
  205. } else {
  206. this.tabs.setTranslate((swiperWidth - clickedWidth) / 2 - clickedLeft);
  207. }
  208. this.goodsList = [];
  209. this.page = 1;
  210. this.finished = false;
  211. this.activeId = this.categoryList[this.clickedIndex].id;
  212. this.getGoodsList();
  213. }
  214. }
  215. });
  216. });
  217. </script>
  218. {/block}