article-long.vue 8.08 KB
<template>
  <div class="article-detail-long">
    <ArticleDetailHeader ref="header" :step="headerAnimateStep" :title-step="headerTitleAnimateStep">
      <div class="title-main">
        <div class="title-info" :style="`transform: translate3d(0, ${titleTranslateY}, 0)`">
          <ArticleItemHeader class="title-info-author" :share="share" :data="authorData" :lazy="lazy" :more="showMoreOpt" @on-follow="onFollow"></ArticleItemHeader>
          <div class="title-info-rec">{{listTitle}}</div>
        </div>
      </div>
    </ArticleDetailHeader>
    <div ref="coverFigure" class="cover-figure">
      <img class="cover-img" :src="coverImage.src" :style="`transform: translate3d(0, ${coverTranslateY}px, 0)`">
    </div>
    <div ref="authorBlock" class="author-block">
      <ArticleItemHeader :share="share" :data="authorData" :lazy="lazy" :more="showMoreOpt" @on-follow="onFollow"></ArticleItemHeader>
    </div>
    <div class="main-detail">
      <div class="article-context" style="height: 1000px;background: #ccc;">

      </div>
      <ArticleItemTopics class="topics-wrap" :data="data" :share="share"></ArticleItemTopics>
      <LayoutTitle class="rec-goods-title">推荐商品</LayoutTitle>
      <ProductGroup :data="recomendProduct" model="2"></ProductGroup>
      <LayoutTitle class="rec-article-title">{{listTitle}}</LayoutTitle>
    </div>
    <ArticleDetailFooter class="detail-fixed-footer" @on-comment-click="onComment">
      <template v-slot:after>
        <div class="article-goods">文中商品</div>
      </template>
    </ArticleDetailFooter>
  </div>
</template>

<script>
import {get} from 'lodash';
import ArticleItemHeader from '../article/article-item-header';
import ArticleItemTopics from '../article/article-item-topics';
import ArticleDetailFooter from './article-footer';
import ArticleDetailHeader from './article-header';
import {mapState} from 'vuex';

export default {
  name: 'ArticleDetailLong',
  props: {
    data: {
      type: Object,
      default() {
        return {};
      }
    },
    listTitle: String,
    scrollTop: Number,
    share: Boolean,
  },
  data() {
    return {
      coverHeight: 0,
      downgrade: false,
      showMoreOpt: false,
      authorBlock: {},
      recomendProduct: [{
        "id": 230,
        "marketPrice": 390,
        "orderBy": 0,
        "productId": 142427,
        "productImage": "http://img10.static.yhbimg.com/goodsimg/2019/01/16/16/0123e8e8c7243ca83e37e6a11d4a431777.png?imageView2/{mode}/w/{width}/h/{height}",
        "productName": "Timberland 插肩印花短袖T恤",
        "productSkn": 51085719,
        "productType": 1,
        "salesPrice": 11
      }, {
        "id": 232,
        "marketPrice": 1290,
        "orderBy": 1,
        "productId": 142447,
        "productImage": "http://img13.static.yhbimg.com/goodsimg/2015/02/13/08/024becd3478789516c2749d5bc0e4e48cc.jpg?imageView2/{mode}/w/{width}/h/{height}",
        "productName": "Timberland 女士经典无里衬帆船鞋",
        "productSkn": 51085694,
        "productType": 1,
        "salesPrice": 11
      }, {
        "id": 234,
        "marketPrice": 444,
        "orderBy": 2,
        "productId": 508376,
        "productImage": "http://img13.static.yhbimg.com/goodsimg/2017/03/31/17/021204a24a95b6a5c258e7469e7bbbd22f.jpg?imageView2/{mode}/w/{width}/h/{height}",
        "productName": "bigrabbit男手套",
        "productSkn": 512587700,
        "productType": 1,
        "salesPrice": 444
      }, {
        "id": 236,
        "marketPrice": 790,
        "orderBy": 3,
        "productId": 142413,
        "productImage": "http://img10.static.yhbimg.com/goodsimg/2019/01/17/10/01d10b02308ecbfb42176cbf965478181a.jpg?imageView2/{mode}/w/{width}/h/{height}",
        "productName": "Timberland 男士休闲短裤116",
        "productSkn": 51085737,
        "productType": 1,
        "salesPrice": 11
      }, {
        "id": 238,
        "marketPrice": 429,
        "orderBy": 4,
        "productId": 69792,
        "productImage": "http://img13.static.yhbimg.com/goodsimg/2014/05/14/03/02e5b2050d3fd73584dd786cadc4eaf68d.jpg?imageView2/{mode}/w/{width}/h/{height}",
        "productName": "izzue 碎花拼接T恤",
        "productSkn": 51041119,
        "productType": 1,
        "salesPrice": 11
      }],
    };
  },
  mounted() {
    let {clientHeight, clientWidth} = document.documentElement;

    if (!this.$yoho.isiOS && (clientHeight / clientWidth) < 1.8) {
      this.downgrade = true;
    }
  },
  computed: {
    ...mapState(['yoho']),
    coverImage() {
      this.$nextTick(() => {
        if (this.$refs.coverFigure) {
          this.coverHeight = this.$refs.coverFigure.offsetHeight;
        }

        if (this.$refs.authorBlock) {
          this.authorBlock = {
            height: this.$refs.authorBlock.offsetHeight,
            top: this.$refs.authorBlock.offsetTop
          };
        }
      });

      return {
        src: '//flv01.static.yhbimg.com/grassImg/2019/05/07/12/03a620a29bb8b3a4f508dc8f86f6974a7a.jpg'
      };
    },
    coverTranslateY() {
      let top = this.scrollTop > 0 ? this.scrollTop : 0;

      if (top && !this.downgrade && this.coverHeight && top < this.coverHeight) {
        return top / 2;
      } else {
        return 0;
      }
    },
    headerAnimateStep() {
      if (this.scrollTop > this.coverHeight) {
        return 100;
      } else if (this.scrollTop > 0) {
        let step = Math.round(this.scrollTop - 10 / (this.coverHeight - 10) * 100);

        return Math.max(Math.min(step, 100), 0);
      } else {
        return 0;
      }
    },
    headerTitleAnimateStep() {
      let {height, top} = this.authorBlock;
      let scrollTop = this.scrollTop;

      if (this.$refs && this.$refs.header) {
        scrollTop += this.$refs.header.$el.offsetHeight;
      }

      if (top && height) {
       if (scrollTop >= top + height) {
          return 100;
        } else if (scrollTop > top) {
          let step = Math.round((scrollTop - top) / height * 100);

          return Math.max(Math.min(step, 100), 0);
        }
      }

      return 0;
    },
    titleTranslateY() {
      let scrollTop = this.scrollTop;

      if (this.$refs && this.$refs.header) {
        scrollTop += this.$refs.header.$el.offsetHeight;
        return scrollTop > this.$el.offsetHeight ? '-50%' : 0;
      } else {
        return 0;
      }
    },
    authorData() {
      return {
        authorName: this.data.authorName,
        authorUid: this.data.authorUid,
        authorType: this.data.authorType,
        authorHeadIco: this.data.authorHeadIco,
        hasAttention: this.data.hasAttention,
        isAuthor: this.data.isAuthor
      };
    },
    lazy() {
      return this.data.lazy;
    }
  },
  methods: {
    onClick() {
      if (this.share) {
        return this.$links.toDownloadApp();
      }
    },
    onFollow(follow) {
      this.$emit('on-follow', follow);
    },
    onComment() {

    }
  },
  components: {
    ArticleDetailHeader,
    ArticleItemHeader,
    ArticleItemTopics,
    ArticleDetailFooter
  }
};
</script>

<style scoped>
.title-main {
  height: 100%;
  color: #444;
  overflow: hidden;

  .title-info {
    height: 200%;
    transition: all 300ms;

    > * {
      height: 50%;
      background: none;
    }

    .title-info-rec {
      font-size: 32px;
      line-height: 1.2;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }

  /deep/ .avatar {
    padding-left: 0;
  }

  /deep/ .opts {
    padding-right: 10px;
  }
}

.cover-img {
  width: 100%;
  display: block;
  position: relative;
  z-index: 0;
}

.author-block,
.main-detail {
  position: relative;
  z-index: 1;
}

.article-context {
  padding: 30px;
}

.topics-wrap {
  padding-left: 30px;
  margin-bottom: 36px;
}

.rec-goods-title {
  margin-bottom: -32px;
}

/deep/ .product-item:first-child {
  margin-left: 30px;
}

/deep/ .product-item:last-child {
  margin-right: 30px;
}

.rec-article-title {
  margin-top: -6px;
}

.detail-fixed-footer {
  width: 100%;
  position: fixed;
  bottom: 0;
  z-index: 10;

  .article-goods {
    width: 200px;
    color: white;
    font-size: 32px;
    line-height: 100px;
    font-weight: 300;
    background-color: #d0021b;
    text-align: center;
  }
}
</style>