<template> <div class="author-page"> <LayoutHeader class="fix-header" theme="white"> <div ref="headerAuthor" class="header-author"> <div class="h-name flex">{{baseData.nickName}}</div> <div class="h-more"> <div class="flex"> <WidgetAvatar v-if="baseData.headIco" class="h-headico" :src="baseData.headIco" :width="100" :height="100"></WidgetAvatar> </div> <div v-if="!isOwner" class="h-follow flex"> <WidgetFollow class="widget-follow" :author-uid="autherInfo.authorUid" :follow="isAttention" @on-follow="follow => onFollow(follow)"></WidgetFollow> </div> </div> </div> </LayoutHeader> <div class="fixed-tab" :class="`${tabFixed ? '' : 'hide'}`"> <FavTabBlock :tabs-num="tabsNum" :active-index="activeIndex" @change="changeTab"></FavTabBlock> </div> <div ref="mainContent" class="main-content"> <div ref="authorProfile" class="author-profile"> <span class="avatar-box"> <WidgetAvatar v-if="baseData.headIco" :src="baseData.headIco" :width="100" :height="100"></WidgetAvatar> </span> <div class="author-section"> <ul class="author-fans"> <li v-for="(item, key) in fansList" :key="key"> <span class="num">{{baseData[key] || 0}}</span> <p class="name"><span>{{item}}</span></p> </li> </ul> <div class="operate-wrap"> <router-link v-if="isOwner" class="operate-btn btn-user-edit" to="//m.yohobuy.com/home/mydetails?openby:yohobuy={'action':'go.mineinfo'}">编辑个人资料</router-link> <WidgetFollow v-else class="operate-btn" :author-uid="autherInfo.authorUid" :follow="isAttention" @on-follow="follow => onFollow(follow)"></WidgetFollow> </div> </div> </div> <p v-if="baseData.signature" class="author-desc">{{baseData.signature}}</p> <FavTabBlock :tabs-num="tabsNum" :active-index="activeIndex" @change="changeTab"></FavTabBlock> <div class="contant-list"> <WaterFall class="pannel-wrap" :list="list" :pos="scrollY" :query="linkQueryString"></WaterFall> </div> <div v-if="loadStatus" class="loading"> <Loading v-if="loadStatus === 1" class="load-icon" :size="20"></Loading> <p v-else class="load-text">没有更多了</p> </div> </div> </div> </template> <script> import {assign, get} from 'lodash'; import {Scroll, Sticky, Loading} from 'cube-ui'; import CubeStickyEle from 'cube-ui/src/components/sticky/sticky-ele.vue'; import FavTabBlock from './components/fav-tab-block'; import WaterFall from './components/scroll-reveal'; import {createNamespacedHelpers} from 'vuex'; const {mapActions} = createNamespacedHelpers('user'); export default { name: 'userpage', data() { return { autherInfo: {}, tabFixed: false, scrollEvents: ['scroll'], scrollY: 0, fansList: { attCount: '关注', fansCount: '粉丝', praiseAndfavorite: '获赞与收藏' }, baseData: {}, isAttention: false, isOwner: false, tabsNum: [0, 0], activeIndex: 0, fetchInfo: {}, loadStatus: '' } }, mounted() { let $dom = this.$refs.headerAuthor; if (!this.$route.params.id) { try { this.$sdk.getUser().then(res => { if (get(res, 'uid') > 0) { this.$route.params.id = res.uid; this.autherInfo = assign({}, this.autherInfo, { authorUid: res.uid }); } else { this.$sdk.goLogin(); } }); } catch(e){ console.log(e); } } if ($dom.offsetHeight) { this._animeDuration = 300; import('animejs').then(({default: anime}) => { this._animeEl = anime({ targets: $dom, translateY: -$dom.offsetHeight, easing: 'easeInOutSine', duration: this._animeDuration, autoplay: false }); }); } this.$el.onscroll = (e) => { console.log(this.$el.scrollTop); this.scrollHandler(this.$el.scrollTop); } }, activated() { if (this.$route.params.id !== this.autherInfo.authorUid) { this.init(this.$route.params); } }, beforeRouteUpdate(to, from, next) { if (this.$route.params.id !== to.params.labelId) { this.init(to.params); } next(); }, computed: { list() { return get(this.fetchInfo, `${this.activeIndex}.list`) || []; }, linkQueryString() { return assign({}, this.autherInfo, { type: ['publish', 'fav'][this.activeIndex] }) }, linkTpl() { return `/grass/article/{articleId}?authorUid=${this.autherInfo.authorUid}&authorType=${this.autherInfo.authorType}&type=${['publish', 'fav'][this.activeIndex]}`; }, waterFallType() { return ['publish', 'fav'][this.activeIndex]; } }, methods: { ...mapActions(['autherBaseInfo', 'autherAritcleNum', 'autherPubList', 'autherFavList', 'autherMineBaseInfo', 'autherMineAritcleNum', 'autherMinePubList', 'autherMineFavList']), init(params) { params = params || {}; this._apiNamePre = 'auther'; if (!params.id) { this._apiNamePre += 'Mine'; } this.autherInfo = { authorUid: params.id, authorType: params.type || 1 }; this.fetchBaseInfo(); this.fetchList(); }, scrollHandler(y) { this.scrollY = y; this.calcAnimate(y); if (this.scrollY + 1000 > this.$refs.mainContent.offsetHeight) { this._listTimer && clearTimeout(this._listTimer); this._listTimer = setTimeout(() => { this.fetchList(); }, 200); } }, calcAnimate(top) { let animePlayed = false; if (top > this.$refs.authorProfile.offsetHeight) { animePlayed = true; } if (!this._animePlayed === !animePlayed) { return; } this.tabFixed = animePlayed; let start; let self = this; function step(timestamp) { if (!start) { start = timestamp }; let progress = Math.floor(timestamp - start); self._animeEl.seek(animePlayed ? progress : self._animeDuration - progress); if (progress < self._animeDuration) { window.requestAnimationFrame(step); } }; window.requestAnimationFrame(step); this._animePlayed = animePlayed; }, changeTab(index) { if (this.activeIndex !== index) { this.activeIndex = index; let info = this.fetchInfo[index] || {}; info.page = 1; info.lastedTime = ''; this.$refs.mainContent.scrollTop = this.$refs.authorProfile.offsetHeight; this.fetchList(); } }, fetchBaseInfo() { this[this._apiNamePre + 'BaseInfo'](this.autherInfo).then(res => { if (res.code === 200) { this.baseData = res.data; this.isOwner = +res.data.userType === 1; this.isAttention = res.data.hasAttention === 'Y'; } }); this[this._apiNamePre + 'AritcleNum'](this.autherInfo).then(res => { this.tabsNum = [get(res, 'data.articleCount'), get(res, 'data.favoriteCount')]; }); }, async fetchList() { this.fetchInfo = this.fetchInfo || []; if (this.syncing) { return; } let info = this.fetchInfo[this.activeIndex] || {}; let result; info.page = info.page || 1; if (info.page > info.totalPage) { return; } let syncServiceName; if (this.activeIndex === 1) { syncServiceName = this._apiNamePre + 'FavList'; } else { syncServiceName = this._apiNamePre + 'PubList'; } if (this[syncServiceName]) { this.syncing = true; result = await this[syncServiceName](assign({ limit: 20, page: info.page, lastedTime: info.lastedTime || '' }, this.autherInfo)); this.syncing = false; } if (result.code === 200) { info.list = (info.list || []).concat(result.data.list || []); info.page++; info.totalPage = result.data.totalPage; info.lastedTime = result.data.lastedTime; if (info.list.length) { info.list[0]._type = `${info.list[0].articleId}_${this.activeIndex}`; } } if (info.page > info.totalPage) { this.loadStatus = 2; } else { this.loadStatus = 1; } this.fetchInfo[this.activeIndex] = info; this.fetchInfo = {...this.fetchInfo}; }, goUserInfoEdit() { if (this.$yoho.isYohoBuy) { this.$yoho.goMineInfo(); } }, onFollow(follow) { this.isAttention = follow; } }, components: { CubeScroll: Scroll, CubeSticky: Sticky, CubeStickyEle, Loading, FavTabBlock, WaterFall } }; </script> <style lang="scss"> .author-page { width: 100%; height: 100%; overflow: hidden; position: absolute; top: 0; left: 0; right: 0; bottom: 0; box-sizing: border-box; color: #4a4a4a; padding-top: 44PX; overflow: scroll; } .fix-header { position: fixed; top: 0; z-index: 2; } .hide { display: none; } .fixed-tab { width: 100%; position: fixed; z-index: 2; } .header-author { position: absolute; left: 0; right: 0; top: 0; bottom: 0; .flex { height: 100%; display: flex; align-items: center; justify-content: center; } .h-name { font-size: 36px; font-weight: 500; } .h-more { width: 100%; height: 100%; position: absolute; top: 100%; left: 0; } .h-headico { width: 60px; height: 60px; } .h-follow { position: absolute; top: 0; right: -130px; } } .header-share { margin-right: 26px; color: #222; font-weight: bold; } .author-profile { padding: 24px 30px; display: flex; justify-content: space-between; overflow: hidden; .avatar-box { width: 150px; height: 150px; overflow: hidden; border-radius: 50%; > img { width: 100%; height: 100%; display: block; } } } .author-section { display: flex; flex-direction: column; justify-content: space-between; } .author-fans { display: flex; justify-content: flex-end; padding-top: 4px; padding-right: 54px; li { margin-left: 140px; position: relative; &:first-child { margin-left: 0; } .num { font-size: 28px; font-weight: 500; padding-bottom: 6px; display: block; } .name { position: absolute; font-size: 20px; font-weight: 300; color: #9b9b9b; margin-left: 50%; word-break: keep-all; white-space: nowrap; > * { position: relative; left: -50%; } } } } .operate-wrap { text-align: right; .operate-btn { width: calc(100% - 20px); font-size: 23px; line-height: 48px; display: inline-block; } .btn-user-edit { color: #222; border: 1px solid #4a4a4a; border-radius: 8px; text-align: center; } } .author-desc { margin: 20px 30px; font-size: 24px; font-weight: 300; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .loading { padding: 20px 0; .load-icon > span { margin: auto; } .load-text { text-align: center; } } </style>