index.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <template>
  2. <view>
  3. <navbar :iSimmersive="false" titleColor="#000000" :placeholder="true" :isPrev="false" title="商品分类"></navbar>
  4. <view v-if="!isLoading && isError == false">
  5. <view class="search-wrap">
  6. <view @click="onSearch" class="iconfont search-box">请输入关键字</view>
  7. </view>
  8. <scroll-view
  9. class="menu"
  10. style="overflow: hidden;"
  11. :style="{'height': wHeight+'px'}"
  12. scroll-with-animation="true"
  13. scroll-y="true"
  14. :scroll-top="menuTop"
  15. :scroll-into-view="menuIndex"
  16. >
  17. <view
  18. v-for="(data,i) in category"
  19. :key="i"
  20. class="menu-item"
  21. :class="{active:currentIndex==i}"
  22. @click="onMenu(i)"
  23. :id="'menu-'+i"
  24. ref="cat"
  25. >
  26. {{ data.title }}
  27. </view>
  28. </scroll-view>
  29. <view class="content" style="overflow: hidden;" :style="{'height': wHeight+'px'}">
  30. <scroll-view
  31. :scroll-into-view="tabindex"
  32. scroll-with-animation="true"
  33. scroll-y="true"
  34. :style="{'height': wHeight+'px'}"
  35. @scroll="onScroll"
  36. >
  37. <view
  38. v-for="(data,i) in category" :key="i"
  39. class="s-list goods-item"
  40. :id="'item-'+i"
  41. ref="item"
  42. >
  43. <text class="s-item">{{data.title}}</text>
  44. <view class="t-list">
  45. <view
  46. class="t-item"
  47. v-for="(children, index) in data.children"
  48. :key="index"
  49. >
  50. <navigator :url="'../goods/list?id='+children.id" hover-class="none">
  51. <image :src="children.thumb_img"></image>
  52. <view class="children-text"><text>{{children.name}}</text></view>
  53. </navigator>
  54. </view>
  55. </view>
  56. </view>
  57. </scroll-view>
  58. </view>
  59. </view>
  60. <loading v-if="isLoading"></loading>
  61. <empty-box type="service" v-if="isError && isLoading == false" @onEvents="onJump"></empty-box>
  62. </view>
  63. </template>
  64. <script>
  65. import loading from '../../components/tool/loading'
  66. export default {
  67. components: {
  68. loading
  69. },
  70. data() {
  71. return {
  72. isLoading:true,
  73. isError: false,
  74. currentIndex: 0,
  75. wHeight:0,
  76. menuTop: 0,
  77. scrollTop: 0,
  78. tabindex:'item-0',
  79. menuIndex:'menu-0',
  80. selectId: "",
  81. goodsHeight: [],
  82. menuHeight: [],
  83. category: []
  84. }
  85. },
  86. mounted() {
  87. let menuClientRect = { height: 35, searchHeight: 0 };
  88. let systemInfoSync = uni.getSystemInfoSync();
  89. let statusBar = 0;
  90. // #ifdef MP || APP-PLUS
  91. statusBar = systemInfoSync.statusBarHeight;
  92. // #endif
  93. // #ifdef MP
  94. menuClientRect = uni.getMenuButtonBoundingClientRect();
  95. // #endif
  96. // #ifdef APP-PLUS || MP
  97. menuClientRect.height += 10;
  98. // #endif
  99. let navHeight = menuClientRect.height + statusBar;
  100. // #ifdef H5
  101. this.wHeight = (systemInfoSync.screenHeight - navHeight - systemInfoSync.windowBottom) - 46;
  102. // #endif
  103. // #ifdef APP-PLUS
  104. this.wHeight = (systemInfoSync.windowHeight - navHeight - systemInfoSync.windowBottom) - 46;
  105. // #endif
  106. // #ifdef MP
  107. this.wHeight = (systemInfoSync.windowHeight - navHeight) - 46;
  108. // #endif
  109. this.onLoadData();
  110. },
  111. onShow() {
  112. // #ifdef APP-PLUS
  113. setTimeout(()=>{
  114. plus.navigator.setStatusBarStyle("dark");
  115. },230);
  116. // #endif
  117. },
  118. methods: {
  119. onLoadData(){
  120. this.$http.getCategoryList().then((result)=>{
  121. if(result.status){
  122. this.isLoading = false;
  123. this.category = result.data;
  124. this.$nextTick(()=>{
  125. setTimeout(()=>{
  126. this.setScrollHeight();
  127. },1500);
  128. });
  129. this.isLoading = false;
  130. this.isError = false;
  131. }else{
  132. this.isLoading = false;
  133. this.isError = true;
  134. }
  135. }).catch(err=>{
  136. this.isLoading = false;
  137. this.isError = true;
  138. });
  139. },
  140. onJump(){
  141. this.onLoadData();
  142. },
  143. onSearch(){
  144. uni.navigateTo({
  145. url:"../search/index"
  146. })
  147. },
  148. onMenu(i){
  149. this.currentIndex = i;
  150. this.tabindex = 'item-'+i;
  151. },
  152. onScroll(event){
  153. if (this.goodsHeight.length == 0) {
  154. return;
  155. }
  156. let scrollTop = event.detail.scrollTop;
  157. let current = this.currentIndex;
  158. if (scrollTop >= this.scrollTop) {
  159. if (current + 1 < this.goodsHeight.length && scrollTop >= this.goodsHeight[current]) {
  160. this.currentIndex = current + 1;
  161. }
  162. } else {
  163. if (current - 1 >= 0 && scrollTop < this.goodsHeight[current - 1]) {
  164. this.currentIndex = current - 1;
  165. }
  166. }
  167. this.menuIndex = 'menu-'+this.currentIndex;
  168. this.scrollTop = scrollTop;
  169. },
  170. setScrollHeight(){
  171. let h = 0;
  172. const query = uni.createSelectorQuery();
  173. query.selectAll('.goods-item').boundingClientRect().exec((res)=>{
  174. res[0].forEach((item) => {
  175. h += item.height;
  176. this.goodsHeight.push(h);
  177. })
  178. });
  179. this.menuHeight = [];
  180. let m = 0;
  181. query.select(".menu-item").boundingClientRect().exec((res) => {
  182. res[0].forEach((item) => {
  183. m += item.height;
  184. this.menuHeight.push(m);
  185. })
  186. });
  187. }
  188. }
  189. }
  190. </script>
  191. <style lang='scss' scoped>
  192. page { background-color: #fff; }
  193. .search-wrap{
  194. width: 100%;
  195. height: 90rpx;
  196. border-top: 1px solid #ddd;
  197. background: #fafafa;
  198. .search-box{
  199. width: 92%;
  200. margin: 0 auto;
  201. height: 64rpx;
  202. line-height: 64rpx;
  203. border:1px solid #bfbfbf;
  204. border-radius: 15rpx;
  205. background-color: #fff;
  206. background-size: 34rpx 33rpx;
  207. background-position: 20rpx center;
  208. position: relative;
  209. top: 12rpx;
  210. text-indent: 70rpx;
  211. font-size: 26rpx;
  212. color: #333;
  213. &::before {
  214. position: absolute;
  215. content: "\e629";
  216. left: -55rpx;
  217. top: -1rpx;
  218. font-size: 38rpx;
  219. color: #aaa;
  220. }
  221. }
  222. }
  223. .menu{
  224. width: 178rpx;
  225. float: left;
  226. background: #f3f4f6;
  227. view{
  228. width: 100%;
  229. text-align: center;
  230. height: 100rpx;
  231. line-height: 100rpx;
  232. background: #f3f4f6;
  233. font-size: 27rpx;
  234. color: #333;
  235. border-bottom: 1px solid #dadbdd;
  236. }
  237. view.active{
  238. background: #fff;
  239. }
  240. }
  241. .content{
  242. float: right;
  243. width: 552rpx;
  244. padding: 0 10rpx;
  245. .s-item{
  246. display: flex;
  247. align-items: center;
  248. height: 70rpx;
  249. padding-top: 8rpx;
  250. font-size: 28rpx;
  251. color: #333;
  252. }
  253. .goods-item {
  254. &:last-child { padding-bottom: 100rpx; }
  255. }
  256. .t-list{
  257. display: flex;
  258. flex-wrap: wrap;
  259. width: 100%;
  260. background: #fff;
  261. padding-top: 12rpx;
  262. &:after{
  263. content: '';
  264. flex: 99;
  265. height: 0;
  266. }
  267. }
  268. .t-item{
  269. flex-shrink: 0;
  270. display: flex;
  271. justify-content: center;
  272. align-items: center;
  273. flex-direction: column;
  274. width: 176rpx;
  275. font-size: 26rpx;
  276. color: #666;
  277. padding-bottom: 20rpx;
  278. .children-text{
  279. text-align: center;
  280. }
  281. image{
  282. width: 140rpx;
  283. height: 140rpx;
  284. }
  285. }
  286. }
  287. </style>