article-detail.vue 8.42 KB
<template>
  <Layout class="article-detail">
    <RecycleScrollReveal :size="10" ref="scroll" @scroll="onScroll" :offset="2000" :on-fetch="onFetch" :manual-init="true">
      <template v-slot:eternalTop>
        <ArticleDeatilLong
          v-if="articleInfo.sort == 2"
          ref="detailLong"
          :data="articleInfo"
          :scroll-top="scrollTop"
          :list-title="listTitle"
          :scroll-to="scrollTo"
          :share="share"
          :pos-id="posId"
          @on-show-more="onShowMore"
          @on-follow="onFollowAuthor">
        </ArticleDeatilLong>
        <ArticleDeatilNote
          v-else
          ref="detailNote"
          :data="articleInfo"
          :scroll-top="scrollTop"
          :list-title="listTitle"
          :scroll-to="scrollTo"
          :share="share"
          :pos-id="posId"
          @on-show-more="onShowMore"
          @on-follow="onFollowAuthor">
        </ArticleDeatilNote>
      </template>
      <template class="article-item" #item="{ data }">
        <ArticleItem2
          type="topic"
          :index="data.index"
          :data="data.data"
          :width="colWidthForTwo"
          :share="share"
          :article-id="data.data.articleId"
          :pos-id="posId">
          <template v-if="data.data.dataType == 2">
            <ArticleResource :data="data.data"></ArticleResource>
          </template>
        </ArticleItem2>
      </template>
    </RecycleScrollReveal>

    <MoreActionSheet transfer ref="moreAction" @on-follow="onFollowAuthor" @on-delete="onDelete" @on-edit="onEdit"></MoreActionSheet>
  </Layout>
</template>

<script>
import {get} from 'lodash';

import YAS from 'utils/yas-constants';
import ArticleDeatilLong from './components/detail/article-long';
import ArticleDeatilNote from './components/detail/article-note';
import ArticleItem2 from './components/article/article-item2';
import MoreActionSheet from './components/detail/more-action-sheet';
import {mapState as mapYohoState, createNamespacedHelpers} from 'vuex';
const {mapState, mapActions, mapMutations} = createNamespacedHelpers('article');

export default {
  name: 'ArticleDetailPage',
  props: {
    share: Boolean,
    setShareData: Function
  },
  data() {
    return {
      id: 0,
      scrollTop: 0,
      scrolling: false,
      listTitle: '',
      colWidthForTwo: 370,
      posId: YAS.scene.newsDetail
    };
  },
  activated() {
    if (this.scrollTop && this.yoho.direction === 'back') {
      this.$refs.scroll.$el.scrollTop = this.scrollTop;
    }

    if (+this.$route.params.id !== this.id) {
      this.id = +this.$route.params.id;
      this.init();
    } else {
      this.reportProductShow(this.articleInfo);
    }
  },
  async serverPrefetch() {
    this.id = parseInt(this.$route.params.id, 10);

    if (this.id > 0) {
      return this.fetchArticleList({
        articleId: this.id,
        singleDetail: 'Y',
        thumb: true
      });
    }

    return;
  },
  mounted() {
    this.colWidthForTwo = Math.floor(this.$el.offsetWidth / 2);
    this.loadPreData(+this.$route.params.id);
  },
  computed: {
    ...mapYohoState(['yoho']),
    ...mapState(['articleSingleDetail']),
    articleInfo() {
      return this.articleSingleDetail[this.id || this.$route.params.id] || {};
    }
  },
  methods: {
    ...mapActions(['fetchArticleList', 'fetchDetailRecommendAricles']),
    ...mapMutations(['CHANGE_AUTHOR_FOLLOW']),
    init() {
      this.recommendArticles = {};
      this.fetching = true;
      this.syncServiceArticleDetail();
    },
    pageVisibileEvent() {
      if (this.articleOnEdit) {
        this.articleOnEdit = false;
        this.syncServiceArticleDetail();
      }
    },
    loadPreData(articleId) {
      if (!this.$isServer && this.$yoho.isLocal) {
        this.fetchArticleList({
          articleId,
          thumb: true,
          local: true,
          singleDetail: 'Y'
        });
      }
    },
    onScroll({scrollTop, items}) {
      this.scrollTop = scrollTop;

      this.scrolling = true;
      this._scTimer && clearTimeout(this._scTimer);
      this._scTimer = setTimeout(() => {
        this.scrolling = false;
      }, 200);
    },
    syncServiceArticleDetail() {
      const articleId = parseInt(this.id, 10);

      return this.fetchArticleList({
        articleId,
        singleDetail: 'Y'
      }).then((res) => {
        if (this.$refs.scroll) {
          this.listTitle = '';

          setTimeout(() => {
            this.fetching = false;
            this.$refs.scroll.init();
          }, 200);
        }

        const article = get(res, 'data.detailList[0]', this.articleInfo);

        this.reportProductShow(article);
        if (this.share && this.setShareData) {
          this.setShareData(article);
        }
      });
    },
    async onFetch() {
      if (!this.id || this.fetching) {
        return [];
      }

      // 推荐文章接口一次性提供,不支持分页
      if (this.recommendArticles[this.id]) {
        return false;
      }

      this.fetching = true;

      let list = [];
      const result = await this.fetchDetailRecommendAricles({
        articleId: this.id
      });

      this.fetching = false;
      this.recommendArticles[this.id] = true;

      if (result.code === 200) {
        list = get(result, 'data', []);

        if (!list || !list.length) {
          list = false;
        } else {
          this.listTitle = '推荐阅读';
        }
      } else {
        this.$createToast && this.$createToast({
          txt: result.message || '服务器开小差了',
          type: 'warn',
          time: 1000
        }).show();
      }

      return list;
    },
    scrollTo({scrollTop}) {
      this.$refs.scroll.$el.scrollTop = scrollTop;
      this.scrollTop = scrollTop;
    },
    onShowMore() {
      this.$refs.moreAction.show(this.articleInfo);
    },
    onFollowAuthor(data, follow) {
      this.CHANGE_AUTHOR_FOLLOW({authorUid: data.authorUid, authorType: data.authorType, follow});
    },
    onDelete() {
      let $detail = {$refs: {}};

      this.$refs.detailLong && ($detail = this.$refs.detailLong);
      this.$refs.detailNote && ($detail = this.$refs.detailNote);

      $detail.$refs.header && $detail.$refs.header.onBack();
    },
    onEdit() {
      this.articleOnEdit = true;
    },
    reportArticleShow(items) {
      if (!items || !items.length) {
        return;
      }

      this._preReportArticles = this._preReportArticles|| {};

      let reportArticles = {};
      let articles = [];

      items.forEach(val => {
        let item = val.data || {};

        reportArticles[item.articleId] = 1;

        if (item.articleId && !this._preReportArticles[item.articleId]) {
          articles.push(val);
        }
      });

      this._preReportArticles = reportArticles;

      if (articles.length) {
        let name = this.$yoho.isiOS ? 'iFP_ArticleList' : 'aFP_ArticleList';

        this.$store.dispatch('reportYas', {
          params: {
            appop: YAS.eventName.show,
            param: {
              DATA: [
                ...articles.map(a => {
                  return {
                    P_NAME: name,
                    P_PARAM: this.id,
                    I_INDEX: a.index,
                    ARTICLE_ID: a.data.articleId,
                    POS_ID: this.posId
                  };
                })
              ],
            }
          }
        });
      }
    },
    reportProductShow(article) {
      const productList = article.productList || [];

      if (!productList.length) {
        return;
      }

      let name = this.$yoho.isiOS ? 'iFP_ArticleList' : 'aFP_ArticleList';

      this.$store.dispatch('reportYas', {
        params: {
          appop: YAS.eventName.show,
          param: {
            DATA: [
              ...productList.map((p, i) => {
                return {
                  P_NAME: name,
                  P_PARAM: this.id,
                  I_INDEX: i,
                  ARTICLE_ID: this.id,
                  PRD_SKN: p.productSkn,
                  ATR_TYPE: article.sort == 2 ? 1 : 2,
                  PRD_TYPE: p.collage_activity_id ? 'collage_info' : ''
                };
              })
            ],
          }
        }
      });
    }
  },
  components: {
    ArticleDeatilLong,
    ArticleDeatilNote,
    ArticleItem2,
    MoreActionSheet
  }
};
</script>

<style lang="scss" scoped>
/deep/ .scroll-reveal-list {
  padding: 0 6px;
  background-color: #f0f0f0;

  .scroll-reveal-col {
    margin: 6px 0;
  }
}
/deep/ .loading {
  display: none;
}

/deep/ .cube-recycle-list-noMore {
  display: none;
}
</style>