article.vue 4.52 KB
<template>
  <Layout class="article">
    <LayoutHeader theme="white" slot='header' :title="title" :share="shareData" :opacity="currentAuthor.opacity">
      <template v-if="showHeader">
        <WidgetAvatar class="widget-avatar" :src="currentAuthor.authorHeadIco" :width="70" :height="70"></WidgetAvatar>
        <span class="user-name">{{currentAuthor.authorName}}</span>
      </template>
      <template v-if="showHeader" v-slot:opts>
        <WidgetFollow class="widget-follow" :author-uid="currentAuthor.authorUid" :follow="currentAuthor.hasAttention === 'Y'" @on-follow="follow => onFollow(currentAuthor, follow)"></WidgetFollow>
      </template>
    </LayoutHeader>
    <LayoutRecycleList v-if="isMounted" ref="scroll" @scroll="onScroll" :offset="1000" :on-fetch="onFetch">
      <template class="article-item" v-slot:item="{ data }">
        <ArticleItem
          :id="`item${data.index}`"
          :data="data"
          :data-id="data.articleId"
          @on-resize="onResize(data)"
          @on-resizeing="onResizeing(data)"
          @on-follow="follow => onFollow(data, follow)"
          @on-expand="onExpand"></ArticleItem>
        <div :id="`ph${data.index}`"></div>
      </template>
    </LayoutRecycleList>
    <slot name="thumb" v-else></slot>

    <ArticleActionSheet ref="actionSheet"></ArticleActionSheet>
  </Layout>
</template>

<script>
import ArticleItem from './article-item';
import ArticleActionSheet from '../detail/article-action-sheet';

export default {
  name: 'Article',
  props: {
    title: {
      type: String,
      default: '逛'
    },
    onFetch: Function
  },
  mounted() {
    this.isMounted = true;
  },
  data() {
    return {
      shareData: {},
      inx: 0,
      scrollTop: 0,
      showHeader: false,
      isMounted: false,
      currentAuthor: {
        authorUid: 0,
        authorName: '',
        authorHeadIco: '',
        hasAttention: 'N',
        opacity: 1,
        isShare: false
      }
    };
  },
  activated() {
    if (this.scrollTop > 0) {
      this.$refs.scroll.$el.scrollTo(0, this.scrollTop);
    }
  },
  methods: {
    onScroll({item, scrollTop}) {
      this.scrollTop = scrollTop;
      if (scrollTop === 0) {
        this.currentAuthor.opacity = 1;
        this.showHeader = false;
      } else if (item) {
        this.currentAuthor.authorUid = item.data.authorUid;
        this.currentAuthor.authorName = item.data.authorName;
        this.currentAuthor.authorHeadIco = item.data.authorHeadIco;
        this.currentAuthor.hasAttention = item.data.hasAttention;
        this.showHeader = true;
        const offsetTop = scrollTop - item.top;

        if (offsetTop < 50) {
          this.currentAuthor.opacity = parseInt((offsetTop / 50) * 100, 10) / 100;
        } else if (offsetTop - item.height >= -60 && offsetTop - item.height < -10) {
          this.currentAuthor.opacity = parseInt(((Math.abs(offsetTop - item.height + 10)) / 50) * 100, 10) / 100;
        } else if (offsetTop - item.height >= -10 && offsetTop - item.height < 0) {
          this.currentAuthor.opacity = 0;
        } else {
          this.currentAuthor.opacity = 1;
        }
      }
    },
    init() {
      this.$refs.scroll.$el.scrollTo(0, 0);
      this.$refs.scroll.init();
    },
    onResize(data) {
      const $phItem = document.getElementById(`ph${data.index}`);

      $phItem.innerHTML = '';
      $phItem.status = 0;
      this.$refs.scroll.resize();
    },
    onResizeing(data) {
      const $phItem = document.getElementById(`ph${data.index}`);

      if ($phItem.status === 1) {
        return;
      }

      const $nextItem = document.getElementById(`item${data.index + 1}`);
      const html = $nextItem.outerHTML;

      $phItem.innerHTML = html;
      $phItem.style.zIndex = 999;
      $phItem.status = 1;
    },
    onFollow(data, follow) {
      this.$emit('on-follow', {authorUid: data.authorUid, follow});
      if (data.authorUid === this.currentAuthor.authorUid) {
        this.currentAuthor.hasAttention = follow ? 'Y' : 'N';
      }
    },
    onExpand(params) {
      const toast = this.$createToast({
        time: 0,
        txt: '加载中',
        mask: true,
        type: 'loading'
      });

      toast.show();

      this.$refs.actionSheet.show(params).then(() => {
        toast.hide();
      });
    }
  },
  components: {
    ArticleItem,
    ArticleActionSheet
  }
};
</script>

<style lang="scss" scoped>
.article {
  background-color: #f0f0f0;
}

.widget-avatar {
  width: 52px;
  height: 52px;
}

.widget-follow {
  margin-right: 30px;
}

.user-name {
  margin-left: 10px;
  font-size: 12px;
  color: #000;
}
</style>