|
|
<template>
|
|
|
<Layout class="article-detail">
|
|
|
<ArticleDetailHeader ref="header" class="article-detail-header" :data="articleInfo" :step="headerAnimateStep" :title-step="headerTitleAnimateStep">
|
|
|
<div v-if="articleInfo.articleId && !articleInfo.empty" class="title-main">
|
|
|
<div class="title-info" :style="`transform: translate3d(0, ${viewMoreArticles ? '-50%' : '0'}, 0)`">
|
|
|
<ArticleItemHeader class="title-info-author" :share="share" :data="authorData" :more="false" @on-follow="onFollowAuthor"></ArticleItemHeader>
|
|
|
<div class="title-info-rec">{{listTitle}}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</ArticleDetailHeader>
|
|
|
<RecycleScrollReveal :size="10" ref="scroll" :class="{'preview-page': previewPage}" @scroll="onScroll" :offset="2000" :on-fetch="onFetch" :manual-init="true">
|
|
|
<template v-slot:eternalTop>
|
|
|
<ArticleDeatilLong
|
...
|
...
|
@@ -24,7 +32,8 @@ |
|
|
:share="share"
|
|
|
:pos-id="posId"
|
|
|
@on-show-more="onShowMore"
|
|
|
@on-follow="onFollowAuthor">
|
|
|
@on-follow="onFollowAuthor"
|
|
|
@on-praise="onPraise">
|
|
|
</ArticleDeatilNote>
|
|
|
</template>
|
|
|
<template class="article-item" #item="{ data }">
|
...
|
...
|
@@ -43,6 +52,30 @@ |
|
|
</template>
|
|
|
</RecycleScrollReveal>
|
|
|
|
|
|
<ArticleDetailFooter ref="footer" v-show="!articleInfo.thumb" class="detail-fixed-footer" :style="`transform: translate3d(0, ${viewMoreArticles ? '100%' : '0'}, 0)`" v-bind="footerData" @on-comment-click="onComment">
|
|
|
<template v-if="articleInfo.sort != 2" v-slot:before>
|
|
|
<div class="footer-comment">
|
|
|
<CommentPlaceholder
|
|
|
ref="commentInput"
|
|
|
:share="share"
|
|
|
class="comment-input hover-opacity"
|
|
|
:dest-id="articleInfo.articleId"
|
|
|
:add-type="0"
|
|
|
:article-id="articleInfo.articleId"
|
|
|
:pos-id="posId"
|
|
|
:column-type="1001"
|
|
|
:autoUpdate="false"
|
|
|
@on-comment="onCommentInput">
|
|
|
添加评论...
|
|
|
</CommentPlaceholder>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template v-slot:after>
|
|
|
<div v-if="articleProducts.length" class="article-goods">文中商品</div>
|
|
|
<div v-else></div>
|
|
|
</template>
|
|
|
</ArticleDetailFooter>
|
|
|
|
|
|
<MoreActionSheet transfer ref="moreAction" @on-follow="onFollowAuthor" @on-delete="onDelete" @on-edit="onEdit"></MoreActionSheet>
|
|
|
</Layout>
|
|
|
</template>
|
...
|
...
|
@@ -51,11 +84,14 @@ |
|
|
import {get} from 'lodash';
|
|
|
|
|
|
import YAS from 'utils/yas-constants';
|
|
|
import ArticleDetailHeader from './components/detail/article-header';
|
|
|
import ArticleItemHeader from './components/article/article-item-header';
|
|
|
import ArticleDeatilLong from './components/detail/article-long';
|
|
|
import ArticleDeatilNote from './components/detail/article-note';
|
|
|
import ArticleItem2 from './components/article/article-item2';
|
|
|
import ArticleDetailFooter from './components/detail/article-footer';
|
|
|
import MoreActionSheet from './components/detail/more-action-sheet';
|
|
|
import {mapState as mapYohoState, createNamespacedHelpers} from 'vuex';
|
|
|
import {mapState as mapYohoState, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex';
|
|
|
const {mapState, mapActions, mapMutations} = createNamespacedHelpers('article');
|
|
|
|
|
|
export default {
|
...
|
...
|
@@ -72,7 +108,8 @@ export default { |
|
|
listTitle: '',
|
|
|
colWidthForTwo: 370,
|
|
|
posId: YAS.scene.newsDetail,
|
|
|
previewPage: false
|
|
|
previewPage: false,
|
|
|
articleProducts: []
|
|
|
};
|
|
|
},
|
|
|
created() {
|
...
|
...
|
@@ -109,14 +146,94 @@ export default { |
|
|
},
|
|
|
computed: {
|
|
|
...mapYohoState(['yoho']),
|
|
|
...mapState(['articleSingleDetail']),
|
|
|
...mapState(['articleSingleDetail', 'articleStates', 'authorStates']),
|
|
|
articleInfo() {
|
|
|
return this.articleSingleDetail[this.id || this.$route.params.id] || {};
|
|
|
}
|
|
|
},
|
|
|
articleState() {
|
|
|
const articleState = this.articleStates[this.articleInfo.articleId] || this.articleInfo;
|
|
|
const authorState = this.authorStates[`${this.articleInfo.authorUid}-${this.articleInfo.authorType}`] || this.articleInfo;
|
|
|
|
|
|
return Object.assign({...articleState}, {hasAttention: authorState.hasAttention});
|
|
|
},
|
|
|
headerAnimateStep() {
|
|
|
if (this.articleInfo.sort !== 2 || this.scrollTop > this.coverHeight) {
|
|
|
return 100;
|
|
|
} else if (this.scrollTop > 0) {
|
|
|
let coverHeight = get(this.$refs, 'detailLong.coverHeight', 0);
|
|
|
let step = Math.round((this.scrollTop - 10) / (coverHeight - 90) * 100);
|
|
|
|
|
|
step = Math.max(Math.min(step, 100), 0);
|
|
|
this.SET_STATUS_BAR_COLOR({
|
|
|
color: step > 55 ? 'black' : 'white'
|
|
|
});
|
|
|
|
|
|
return step;
|
|
|
} else {
|
|
|
this.SET_STATUS_BAR_COLOR({
|
|
|
color: 'white'
|
|
|
});
|
|
|
return 0;
|
|
|
}
|
|
|
},
|
|
|
headerTitleAnimateStep() {
|
|
|
if (this.articleInfo.sort === 2) {
|
|
|
let {height, top} = get(this.$refs, 'detailLong.authorBlock', {});;
|
|
|
let scrollTop = this.scrollTop + get(this.$refs, 'header.$el.offsetHeight', 0);
|
|
|
|
|
|
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;
|
|
|
} else {
|
|
|
return 100;
|
|
|
}
|
|
|
},
|
|
|
viewMoreArticles() {
|
|
|
let scrollTop = this.scrollTop;
|
|
|
|
|
|
if (this.$refs && this.$refs.header) {
|
|
|
scrollTop += this.$refs.header.$el.offsetHeight;
|
|
|
|
|
|
return scrollTop > get(this.$refs, `${this.articleInfo.sort === 2 ? 'detailLong' : 'detailNote'}.$el.offsetHeight`);
|
|
|
} else {
|
|
|
return false;
|
|
|
}
|
|
|
},
|
|
|
authorData() {
|
|
|
return {
|
|
|
authorName: this.articleInfo.authorName,
|
|
|
authorUid: this.articleInfo.authorUid,
|
|
|
authorType: this.articleInfo.authorType,
|
|
|
authorHeadIco: this.articleInfo.authorHeadIco,
|
|
|
authGroupId: this.articleInfo.authGroupId,
|
|
|
hasAttention: this.articleState.hasAttention,
|
|
|
isAuthor: this.articleInfo.isAuthor
|
|
|
};
|
|
|
},
|
|
|
footerData() {
|
|
|
return {
|
|
|
favoriteCount: this.articleState.favoriteCount,
|
|
|
praiseCount: this.articleState.praiseCount,
|
|
|
commentCount: this.articleState.commentCount,
|
|
|
hasFavor: this.articleState.hasFavor,
|
|
|
hasPraise: this.articleState.hasPraise,
|
|
|
articleId: this.articleInfo.articleId,
|
|
|
share: this.share
|
|
|
};
|
|
|
},
|
|
|
},
|
|
|
methods: {
|
|
|
...mapActions(['fetchArticleList', 'fetchDetailRecommendAricles']),
|
|
|
...mapMutations(['CHANGE_AUTHOR_FOLLOW']),
|
|
|
...mapYohoMutations(['SET_STATUS_BAR_COLOR']),
|
|
|
init() {
|
|
|
this.recommendArticles = {};
|
|
|
this.fetching = true;
|
...
|
...
|
@@ -125,7 +242,7 @@ export default { |
|
|
pageVisibileEvent() {
|
|
|
if (this.articleOnEdit) {
|
|
|
this.articleOnEdit = false;
|
|
|
this.syncServiceArticleDetail();
|
|
|
this.syncServiceArticleDetail(true);
|
|
|
}
|
|
|
},
|
|
|
loadPreData(articleId) {
|
...
|
...
|
@@ -147,7 +264,7 @@ export default { |
|
|
this.scrolling = false;
|
|
|
}, 200);
|
|
|
},
|
|
|
syncServiceArticleDetail() {
|
|
|
syncServiceArticleDetail(withoutList) {
|
|
|
const articleId = parseInt(this.id, 10);
|
|
|
|
|
|
return this.fetchArticleList({
|
...
|
...
|
@@ -155,7 +272,7 @@ export default { |
|
|
fromPlatform: this.previewPage ? 'Y' : 'N',
|
|
|
singleDetail: 'Y'
|
|
|
}).then((res) => {
|
|
|
if (this.$refs.scroll) {
|
|
|
if (this.$refs.scroll && !withoutList) {
|
|
|
this.listTitle = '';
|
|
|
this.fetching = false;
|
|
|
this.$refs.scroll.init();
|
...
|
...
|
@@ -228,6 +345,23 @@ export default { |
|
|
onEdit() {
|
|
|
this.articleOnEdit = true;
|
|
|
},
|
|
|
onPraise() {
|
|
|
this.$refs.footer.onPraise();
|
|
|
},
|
|
|
onComment() {
|
|
|
if (this.articleInfo.sort === 2) {
|
|
|
this.$refs.detailLong.onComment();
|
|
|
} else if (this.articleState.commentCount) {
|
|
|
this.$refs.detailNote.toCommentList();
|
|
|
} else {
|
|
|
this.$refs.commentInput.$el.click();
|
|
|
}
|
|
|
},
|
|
|
onCommentInput(comment) {
|
|
|
if (get(this.$refs, 'detailNote.onComment')) {
|
|
|
this.$refs.detailNote.onComment(comment);
|
|
|
}
|
|
|
},
|
|
|
reportArticleShow(items) {
|
|
|
if (!items || !items.length) {
|
|
|
return;
|
...
|
...
|
@@ -305,10 +439,13 @@ export default { |
|
|
}
|
|
|
},
|
|
|
components: {
|
|
|
ArticleDetailHeader,
|
|
|
ArticleItemHeader,
|
|
|
ArticleDeatilLong,
|
|
|
ArticleDeatilNote,
|
|
|
ArticleItem2,
|
|
|
MoreActionSheet
|
|
|
MoreActionSheet,
|
|
|
ArticleDetailFooter
|
|
|
}
|
|
|
};
|
|
|
</script>
|
...
|
...
|
@@ -356,4 +493,75 @@ export default { |
|
|
}
|
|
|
}
|
|
|
|
|
|
.title-main {
|
|
|
height: 100%;
|
|
|
color: #444;
|
|
|
overflow: hidden;
|
|
|
|
|
|
.title-info {
|
|
|
height: 200%;
|
|
|
transition: all 200ms;
|
|
|
|
|
|
> * {
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.detail-fixed-footer {
|
|
|
width: 100%;
|
|
|
position: absolute!important;
|
|
|
bottom: 0;
|
|
|
z-index: 10;
|
|
|
transition: all 300ms;
|
|
|
|
|
|
.footer-comment {
|
|
|
width: 312px;
|
|
|
margin-left: 30px;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
|
|
|
.comment-input {
|
|
|
width: 100%;
|
|
|
height: 68px;
|
|
|
line-height: 68px;
|
|
|
font-size: 28px;
|
|
|
color: #b0b0b0;
|
|
|
background: #f0f0f0;
|
|
|
padding: 0 20px;
|
|
|
border-radius: 35px;
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.article-goods {
|
|
|
width: 200px;
|
|
|
color: white;
|
|
|
font-size: 32px;
|
|
|
line-height: 100px;
|
|
|
font-weight: 300;
|
|
|
background-color: #d0021b;
|
|
|
text-align: center;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
</style> |
...
|
...
|
|