channel.vue 7.92 KB
<template>
  <LayoutApp class="yohoufo-channel-page" :show-back="true" :hide-header="hideHeader">
      <div class="fixed-nav scroll-nav-wrap" v-if="isShow && navList.length">
        <ScrollNav :list="navList" :current="active" @transfer="getIndex"></ScrollNav>
      </div>
      <Scroll
        ref="scroll"
        :scroll-events="scrollEvents"
        @scroll="scrollHandler"
        :options="options"
        @pulling-up="onPullingUp"
        @pulling-down="onPullingDown"
        :data="productList.list">
        <div class="channel-body" ref="body">
          <div ref="topSource" class="channel-html">
            <template v-for="(item, index) in channelList.list">
              <Swiper :list="item.data" :key="index" v-if="item.template_name == 'threePicture'"/>
              <Hot :list="item.data" :key="index" v-if="item.template_name == 'image_list'"/>
              <Banner :list="item.data" :key="index" v-if="item.template_name == 'single_image'"/>
              <TwoBanner :list="item.data" :key="index" v-if="item.template_name == 'twoPicture'"/>
            </template>
          </div>
          <div ref="scrollNav" class="scroll-nav-wrap" v-if="navList.length">
            <ScrollNav :list="navList" :current="active" @transfer="getIndex"></ScrollNav>
          </div>
          <div class="list-wrap" :style="{minHeight: total + 'px'}">
            <ProductList :list="productList.list" v-if="productList.list.length > 0"></ProductList>
            <UfoNoItem :tip="`暂无数据`" v-else></UfoNoItem>
          </div>
        </div>
      </Scroll>
  </LayoutApp>
</template>

<script>
import { get, find } from 'lodash';
import { Style, Scroll, Sticky } from 'cube-ui';
import { createNamespacedHelpers } from 'vuex';
import queryString from 'query-string';
import Swiper from './components/swiper';
import Banner from './components/banner';
import TwoBanner from './components/twoBanner';
import Hot from './components/hot';
import ScrollNav from './components/scrollNav';
import ProductList from '../../list/components/productList';
import { setTimeout } from 'timers';
import UfoNoItem from '../../../components/ufo-no-item';

const { mapState, mapActions } = createNamespacedHelpers('home/channel');
const { mapState: mapStateList, mapActions: mapActionsList } = createNamespacedHelpers('list');

export default {
  props: ['hideHeader'],
  data() {
    return {
      options: {
        // bounce: {
        //   top: false
        // },
        scrollbar: true,
        pullUpLoad: true,
        pullDownRefresh: true,
        pullDownRefresh: {
          txt: '刷新成功',
        }
      },
      scrollEvents: ['scroll'],
      scrollY: 0,
      navTop: 0,
      navHeight: 0,
      isShow: false,
      total: 0,
      active: 0,
      listBaseParams: {
        isHome: true,
      },

      productList: {
        showErrorPage: false,
        isFetching: false,
        error: null,
        page: 0, // 当前页
        page_size: 10, // 每页数量
        page_total: 0, // 总共多少页
        total: 0, // 总共多少条
        endReached: false, // 到达底部
        list: [], // 商品列表
        isEmpty: false,
      },
      searchParams: {
        type: 0, // type:0,推荐;1,热销;2,即将发售; 3,品类; 4,品牌;5,系列;6,搜索 7, 收藏
        order: '', // 指定排序
        productPool: null, // 商品池id
        sort: null, // 品类id
        brand: null, // 品牌id
        series: null, // 系列id
        gender: null, // 性别
        size: null, // 尺码id
        isSoonSale: null, // 是否是即将售卖
        query: null, // 搜索词
        limit: null, // 每页记录数
        page: null, // 当前页号
        coupon_token: null, // 优惠券token
      },
    };
  },
  computed: {
    ...mapState(['channelList']),
    navList() {
      return get(find(this.channelList.list, ['template_name', 'guessLike']), 'data') || [];
    }
  },
  watch: {
    'channelList.list': function() {
      this.init();
    }
  },
  activated() {
    if (!this.channelList.list || !this.channelList.list.length) {
      this.fetchChannelList();
    }
  },
  async serverPrefetch() {
    return this.fetchChannelList();
  },
  mounted() {
    this.init();
  },
  methods: {
    ...mapActions(['fetchChannelList']),
    ...mapActionsList(['fetchProductList']),
    init() {
      this.$nextTick(() => {
        this.navTop = this.$refs.topSource.offsetHeight;
        this.navHeight = get(this.$refs, 'scrollNav.offsetHeight') || 0;
        this.total = this.$refs.scroll.$el.offsetHeight - this.navHeight;
        this.refreshProductList(this.active);
      });
    },
    getIndex(index) {
      this.active = Number(index);
    },
    scrollHandler({ y }) {
      if (this.navTop) {
        let scrollY = -y;

        if (scrollY >= this.navTop) {
          this.isShow = true;
        } else {
          this.isShow = false;
        }
      }
    },
    refreshProductList(index) {
      let str = get(get(this.navList, `[${index}].url`, '').split('?'), '[1]', '');

      this.searchParams = Object.assign({}, queryString.parse(str), this.listBaseParams);
      this.fetchList(this.searchParams);
    },

    async onPullingUp() {
      await this.fetchList();
    },

    // 查询商品列表
    fetchList: async function(params) {
      let searchParams = this.searchParams;
      let list = this.productList;
      let pageSize = list.page_size;
      let isReset = false;

      if (params && params.isReset) {
        isReset = true;
        delete params.isReset;
      }

      if (!isReset && (list.endReached || (!list.endReached && list.page_total === 1))) {
        return;
      }
      if (typeof params === 'object' && Object.keys(params)) {
        searchParams ={...params};
        this.searchParams = searchParams;
      }

      let page = isReset ? 1 : (list.page + 1);

      for (let key in searchParams) {
        if (!searchParams[key]) {
          delete searchParams[key];
        }
      }
      let result = await this.fetchProductList({
        ...searchParams,
        page,
        pageSize
      });
      let {data} = result;

      if (result.code === 200) {

        data.endReached = (data.page === data.page_total) && (data.page_size !== 1);
      }

      if (typeof data === 'object' && Object.keys(data).length) {
        for (let key in data) {
          if (key === 'product_list') {
            list.list = data.page > 1 ? list.list.concat(data.product_list) : data.product_list;
          } else {
            list[key] = data[key];
          }
        }
        this.productList = list;
      }
    },

    onPullingDown() {
      let params = this.searchParams;

      params.isReset = true;
      this.fetchList(params);
    },
  },
  components: {
    Swiper,
    Banner,
    TwoBanner,
    Hot,
    ScrollNav,
    Style,
    Scroll,
    Sticky,
    cubeSticky: Sticky,
    cubeStickyEle: Sticky.Ele,
    ProductList,
    UfoNoItem
  }
};
</script>

<style lang="scss" scoped>
.yohoufo-channel-page {
  background-color: #fefefe;
}

.scroll-nav-wrap {
  position: relative;

  &:after {
    content: "";
    position: absolute;
    width: 100%;
    height: 0;
    box-shadow: 0 0 120px 100px #f2f2f2;
  }

  &.fixed-nav {
    width: 100%;
    position: absolute;
    z-index: 10;
    background-color: #fefefe;
    overflow: hidden;
  }
}

.channel-body {
  height: 100%;
  position: relative;

  &:before {
    content: "";
    width: 100%;
    height: 330px;
    background: #08304B;
    position: absolute;
    top: 0;
    z-index: -1;
  }
}

.channel-html {
  padding: 20px 24px 0;

  &:before {
    content: "";
    width: 520px;
    height: 28px;
    background-image: url("~statics/image/channel/server.png");
    background-size: 100% 100%;
    margin: 0 auto 20px;
    display: block;
  }

  &:after {
    content: "";
    width: 100%;
    height: 1px;
    display: block;
  }

  > * {
    margin-top: 20px;
  }
}

.list-wrap {
  background: #f2f2f2;

  /deep/ .item {
    position: relative;
    z-index: 1;
  }
}
</style>