Authored by yyq

detail

<template>
<Article
ref="article"
type="article"
:thumbs="articleThumbList"
:on-fetch="onFetch"
:pos-id="sceneId"
:user-uid="userUid"
>
</Article>
<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="articleSingleDetail.sort == 2" ref="detailLong" :data="articleSingleDetail" :scroll-top="scrollTop" :list-title="listTitle" :scroll-to="scrollTo" @on-show-more="onShowMore" @on-follow="onFollowAuthor"></ArticleDeatilLong>
<ArticleDeatilNote v-else :data="articleSingleDetail" :scroll-top="scrollTop" :list-title="listTitle" :scroll-to="scrollTo" @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"></MoreActionSheet>
</Layout>
</template>
<script>
import {get} from 'lodash';
import Article from './components/article/article';
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 {createNamespacedHelpers} from 'vuex';
const {mapState, mapActions} = createNamespacedHelpers('article');
const {mapState, mapActions, mapMutations} = createNamespacedHelpers('article');
export default {
name: 'ArticlePage',
name: 'ArticleDetailPage',
data() {
return {
page: 1,
id: 0,
sceneId: YAS.scene.list,
userUid: -1
scrollTop: 0,
scrolling: false,
share: false,
listTitle: '',
colWidthForTwo: 370,
posId: 0
};
},
activated() {
... ... @@ -33,54 +54,95 @@ export default {
this.init();
}
},
beforeRouteUpdate(to, from, next) {
if (+this.$route.params.id !== +to.params.id) {
this.id = +to.params.id;
this.init();
}
next();
},
async serverPrefetch() {
const articleId = parseInt(this.$route.params.id, 10);
if (articleId > 0) {
return this.fetchArticleList({
articleId,
singleDetail: 'Y',
thumb: true
});
}
return;
},
mounted() {
this.colWidthForTwo = Math.floor(this.$el.offsetWidth / 2);
},
computed: {
...mapState(['articleThumbList', 'articleStates']),
...mapState(['articleSingleDetail'])
},
methods: {
...mapActions(['fetchArticleList']),
...mapActions(['fetchArticleList', 'fetchDetailRecommendAricles']),
...mapMutations(['CHANGE_SINGLE_DETAIL_AUTHOR_FOLLOW']),
init() {
this.page = 1;
this.$refs.article.init();
if (this.$route.query.commentId) {
setTimeout(() => {
let articleState = this.articleStates[this.id] || {};
this.$refs.article.onShowComment({
articleId: this.id,
index: 0,
commentCount: articleState.commentCount,
commentId: +this.$route.query.commentId
});
}, 400);
}
this.recommendArticles = {};
this.syncServiceArticleDetail();
},
onScroll({scrollTop}) {
this.scrollTop = scrollTop;
this.scrolling = true;
this._scTimer && clearTimeout(this._scTimer);
this._scTimer = setTimeout(() => {
this.scrolling = false;
}, 400);
},
syncServiceArticleDetail() {
const articleId = parseInt(this.id, 10);
this.$sdk.getUser().then(user => {
if (user && user.uid) {
this.userUid = +user.uid;
this.fetchArticleList({
articleId,
singleDetail: 'Y'
}).then(res => {
if (this.$refs.scroll) {
this.$refs.scroll.$el.scrollTop = 0;
this.$refs.scroll.clear();
this.listTitle = '';
this.$nextTick(() => {
this.$refs.scroll.init();
});
}
});
},
async onFetch() {
const articleId = parseInt(this.id, 10);
if (!this.id || this.fetching) {
return [];
}
if (!articleId || this.page > 1) {
return;
// 推荐文章接口一次性提供,不支持分页
if (this.recommendArticles[this.id]) {
return false;
}
const result = await this.fetchArticleList({
articleId,
page: this.page,
limit: 1,
columnType: 1002
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) {
if (get(result, 'data.detailList', []).length) {
this.page++;
return Promise.resolve(result.data.detailList);
list = get(result, 'data', []);
if (!list || !list.length) {
list = false;
} else {
this.listTitle = '推荐阅读';
}
return Promise.resolve(false);
} else {
this.$createToast && this.$createToast({
txt: result.message || '服务器开小差了',
... ... @@ -88,16 +150,40 @@ export default {
time: 1000
}).show();
}
return list;
},
scrollTo({scrollTop}) {
this.$refs.scroll.$el.scrollTop = scrollTop;
this.scrollTop = scrollTop;
},
onShowMore() {
this.$refs.moreAction.show(this.articleSingleDetail);
},
onFollowAuthor(data, follow) {
console.log(data, follow);
this.CHANGE_SINGLE_DETAIL_AUTHOR_FOLLOW({authorUid: data.authorUid, follow});
},
onDelete() {
}
},
components: {
Article
ArticleDeatilLong,
ArticleDeatilNote,
ArticleItem2,
MoreActionSheet
}
};
</script>
<style lang="scss" scoped>
.article-page {
/deep/ .scroll-reveal-list {
padding: 6px;
background-color: #f0f0f0;
}
/deep/ .loading {
height: 100px;
visibility: hidden;
}
</style>
... ...
<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="articleSingleDetail.sort == 2" ref="detailLong" :data="articleSingleDetail" :scroll-top="scrollTop" :list-title="listTitle" :scroll-to="scrollTo" @on-show-more="onShowMore" @on-follow="onFollowAuthor"></ArticleDeatilLong>
<ArticleDeatilNote v-else :data="articleSingleDetail" :scroll-top="scrollTop" :list-title="listTitle" :scroll-to="scrollTo" @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"></MoreActionSheet>
</Layout>
</template>
<script>
import {get} from 'lodash';
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 {createNamespacedHelpers} from 'vuex';
const {mapState, mapActions, mapMutations} = createNamespacedHelpers('article');
export default {
name: 'ArticleDetailPage',
data() {
return {
id: 0,
scrollTop: 0,
scrolling: false,
share: false,
listTitle: '',
colWidthForTwo: 370,
posId: 0
};
},
activated() {
if (+this.$route.params.id !== this.id) {
this.id = +this.$route.params.id;
this.init();
}
},
beforeRouteUpdate(to, from, next) {
if (+this.$route.params.id !== +to.params.id) {
this.id = +to.params.id;
this.init();
}
next();
},
async serverPrefetch() {
const articleId = parseInt(this.$route.params.id, 10);
if (articleId > 0) {
return this.fetchArticleList({
articleId,
singleDetail: 'Y',
thumb: true
});
}
return;
},
mounted() {
this.colWidthForTwo = Math.floor(this.$el.offsetWidth / 2);
},
computed: {
...mapState(['articleSingleDetail'])
},
methods: {
...mapActions(['fetchArticleList', 'fetchDetailRecommendAricles']),
...mapMutations(['CHANGE_SINGLE_DETAIL_AUTHOR_FOLLOW']),
init() {
this.recommendArticles = {};
this.syncServiceArticleDetail();
},
onScroll({scrollTop}) {
this.scrollTop = scrollTop;
this.scrolling = true;
this._scTimer && clearTimeout(this._scTimer);
this._scTimer = setTimeout(() => {
this.scrolling = false;
}, 400);
},
syncServiceArticleDetail() {
const articleId = parseInt(this.id, 10);
this.fetchArticleList({
articleId,
singleDetail: 'Y'
}).then(res => {
if (this.$refs.scroll) {
this.$refs.scroll.$el.scrollTop = 0;
this.$refs.scroll.clear();
this.listTitle = '';
this.$nextTick(() => {
this.$refs.scroll.init();
});
}
});
},
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.articleSingleDetail);
},
onFollowAuthor(data, follow) {
console.log(data, follow);
this.CHANGE_SINGLE_DETAIL_AUTHOR_FOLLOW({authorUid: data.authorUid, follow});
},
onDelete() {
}
},
components: {
ArticleDeatilLong,
ArticleDeatilNote,
ArticleItem2,
MoreActionSheet
}
};
</script>
<style lang="scss" scoped>
/deep/ .scroll-reveal-list {
padding: 6px;
background-color: #f0f0f0;
}
/deep/ .loading {
height: 100px;
visibility: hidden;
}
</style>
... ... @@ -2,7 +2,7 @@ export default [{
path: '/article/:id',
name: 'article',
alias: '/article/:id',
component: () => import(/* webpackChunkName: "article" */ './article'),
component: () => import(/* webpackChunkName: "article" */ './article-detail'),
meta: {
keepAlive: true
}
... ... @@ -15,26 +15,10 @@ export default [{
keepAlive: true
}
}, {
path: '/article/detail2/:id',
name: 'article.detail2',
alias: '/article/detail2/:id',
component: () => import(/* webpackChunkName: "article" */ './article-detail'),
meta: {
keepAlive: true
}
}, {
path: '/article/:type/:id',
name: 'article.detail',
alias: '/article/:type/:id',
component: () => import(/* webpackChunkName: "article-detail" */ './article-detail2'),
meta: {
keepAlive: true
}
}, {
path: '/article/detail/:id',
name: 'article.detail',
alias: '/article/detail/:id',
component: () => import(/* webpackChunkName: "article-detail" */ './article-detail2'),
component: () => import(/* webpackChunkName: "article-detail" */ './article-detail'),
meta: {
keepAlive: true
}
... ...
... ... @@ -161,12 +161,10 @@ export default {
},
toArticle({articleId}) {
let router = {
name: 'article.user',
name: 'article',
params: {
id: articleId,
...this.params.params
},
query: this.params.query
id: articleId
}
};
if (!router.params.authorUid) {
... ...