Authored by 陈峰

Merge branch 'feature/recommendArticle' into 'master'

Feature/recommend article



See merge request !95
... ... @@ -33,12 +33,15 @@ export default {
}
},
mounted() {
this.$yoho.getNavStatus('', res => {
if (res === 'N') {
this.SET_STATUS_BAR_STATUS({status: false});
}
this.$yoho.ready(() => {
this.$yoho.getNavStatus('', res => {
if (res === 'N') {
this.SET_STATUS_BAR_STATUS({status: false});
}
});
});
const barColor = get(this.$route, 'meta.statusBarColor');
if (barColor) {
... ... @@ -62,8 +65,6 @@ export default {
this.$yoho.setStatusBar({statusBarColor});
}
}
});
if (process.env.NODE_ENV === 'development') {
... ...
... ... @@ -591,17 +591,24 @@ const yoho = {
},
// 跳商品详情页
goProductDetail({skn, name, articleId}) {
goProductDetail({skn, name, articleId, collageActivityId}) {
var url = window.location.protocol + '//m.yohobuy.com/';
if (this.isYohoBuy && window.yohoInterface) {
let params = {
product_skn: skn,
from_page_name: name,
from_page_param: articleId
};
if (collageActivityId) {
params.activity_id = collageActivityId;
params.activity_type = 'groupPurchase';
}
url = url + '?openby:yohobuy=' + JSON.stringify({
action: 'go.productDetail',
params: {
product_skn: skn,
from_page_name: name,
from_page_param: articleId
}
params
});
if ($appLink) {
... ... @@ -616,7 +623,7 @@ const yoho = {
// 跳UFO商品详情页
goUfoProductDetail({skn, name, articleId = 0}) {
var url = window.location.protocol + '//m.yohobuy.com/';
var url = window.location.protocol + '//2.yohobuy.com';
if (this.isYohoBuy && window.yohoInterface) {
url = url + '?openby:yohobuy=' + JSON.stringify({
... ... @@ -634,7 +641,7 @@ const yoho = {
$appLink.click();
}
} else {
url = url + 'product/' + skn + '.html';
url = url + '/html/h5Share/goodsDetail.html?id=' + skn;
window.open(url);
}
},
... ...
... ... @@ -14,7 +14,8 @@
<WidgetFav
class="comment-fav"
:comment-id="parentComment.id"
:num="parentComment.praiseTotal"
:num="praiseTotal"
:share="share"
:option="favOption"></WidgetFav>
</div>
</div>
... ... @@ -102,6 +103,15 @@ export default {
},
replyMoreText() {
return this.isShowAllReply ? '收起' : `查看${this.moreReplyNum}条回复`;
},
praiseTotal() {
let praiseTotal = this.parentComment.praiseTotal || 0;
if (praiseTotal > 999) {
return Math.floor(praiseTotal / 1000) + 'k';
}
return praiseTotal;
}
},
methods: {
... ... @@ -191,9 +201,13 @@ export default {
}
.comment-nav-right {
width: 90px;
display: flex;
align-items: center;
padding-right: 20px;
.comment-fav {
position: absolute;
}
}
.comment-cont {
... ...
... ... @@ -384,6 +384,7 @@ export default {
overflow: hidden
margin: 10px auto
height: 20px
line-height: 1.2;
text-align: center
</style>
... ...
... ... @@ -108,7 +108,7 @@ export default {
let name = this.$yoho.isiOS ? 'iFP_ArticleDetail' : 'aFP_ArticleDetail';
if (this.product.productType === 1) {
this.$yoho.goProductDetail({skn, name, articleId: this.articleId});
this.$yoho.goProductDetail({skn, name, articleId: this.articleId, collageActivityId: this.product.collage_activity_id});
} else if (this.product.productType === 2) {
this.$yoho.goUfoProductDetail({skn, name, articleId: this.articleId});
}
... ...
... ... @@ -63,7 +63,7 @@ export default {
break;
}
return `${className}${this.small ? '-small' : ''}`;
return className ? `${className}${this.small ? '-small' : ''}` : '';
}
},
watch: {
... ...
... ... @@ -7,7 +7,7 @@
</div>
</i>
<p v-if="viewText" class="icon-btn-text" :style="textStyle">
<span class="view-text">{{Number(viewText) > 0 ? viewText : ''}}</span>
<span class="view-text">{{viewText}}</span>
<span class="placeholder-text">{{placText}}</span>
</p>
</div>
... ... @@ -153,7 +153,13 @@ export default {
return style;
},
viewText() {
return `${(this.editText === null ? this.text : this.editText)}`;
let text = (this.editText === null ? this.text : this.editText);
if (!isNaN(Number(text))) {
text = text > 0 ? text : '';
}
return text;
},
placText() {
if (!isNaN(Number(this.text)) && this.viewText.length) {
... ...
<template>
<Article
ref="article"
type="niceGoods"
:title="title"
:thumbs="articleNiceThumbList"
:on-fetch="onFetch"
:pos-id="sceneId">
</Article>
</template>
<script>
import {get} from 'lodash';
import Article from './components/article/article';
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapState, mapActions} = createNamespacedHelpers('article');
export default {
name: 'ArticleNicePage',
data() {
return {
title: '发现好货',
sceneId: YAS.scene.list
};
},
async serverPrefetch() {
return this.fetchFindNiceGoodsArticles({
page: 1,
limit: 3,
thumb: true
});
},
computed: {
...mapState(['articleNiceThumbList'])
},
methods: {
...mapActions(['fetchFindNiceGoodsArticles']),
init() {
this.page = 1;
this.$refs.article.init();
},
async onFetch() {
if (this.fetching) {
return [];
}
this.fetching = true;
this.page = this.page || 1;
const result = await this.fetchFindNiceGoodsArticles({
page: this.page
});
let list = [];
let end = false;
if (result.code === 200) {
this.page++;
if (get(result, 'data.detailList'|| []).length) {
list = result.data.detailList;
}
if (this.page > get(result, 'data.totalPage')) {
end = true;
}
} else {
this.$createToast && this.$createToast({
txt: result.message || '服务器开小差了',
type: 'warn',
time: 1000
}).show();
}
this.fetching = false;
return end ? false : list;
}
},
components: {
Article
}
};
</script>
<style lang="scss" scoped>
.article-page {
background-color: #f0f0f0;
}
</style>
... ...
... ... @@ -165,8 +165,6 @@ export default {
name: 'topic',
params: {
topicId,
},
query: {
topicName
}
});
... ...
... ... @@ -43,8 +43,6 @@ export default {
name: 'topic',
params: {
topicId,
},
query: {
topicName
}
});
... ...
... ... @@ -78,7 +78,7 @@ export default {
praiseCount: this.articleState.praiseCount,
favoriteCount: this.articleState.favoriteCount,
articleId: this.data.articleId,
shareImage: get(first(this.slideData.blockList), 'contentData', '').replace('{mode}', 2).replace('{width}', 200).replace('{height}', 200)
blockList: this.data.blockList
};
},
commentData() {
... ...
... ... @@ -224,15 +224,14 @@ export default {
}
.avatar {
width: 40px;
height: 40px;
width: 20PX;
height: 20PX;
margin-right: 12px;
display: block;
}
.name {
max-width: 170px;
display: inline-block;
vertical-align: middle;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
... ...
... ... @@ -9,7 +9,7 @@
</div>
</ArticleDetailHeader>
<div class="header-cover"></div>
<ArticleItemSlideImage ref="coverFigure" :data="coverImage" :thumb-size="coverSize" :style="`transform: translate3d(0, ${coverTranslateY}px, 0)`">
<ArticleItemSlideImage ref="coverFigure" class="cover-figure" :data="coverImage" :thumb-size="coverSize" :style="`transform: translate3d(0, ${coverTranslateY}px, 0)`">
</ArticleItemSlideImage>
<div ref="authorBlock" class="author-block">
<ArticleItemHeader :share="share" :data="authorData" :lazy="lazy" :more="showMoreOpt" @on-follow="onFollowAuthor"></ArticleItemHeader>
... ... @@ -267,6 +267,10 @@ export default {
}
}
.cover-figure {
opacity: 1!important;
}
.title-main {
height: 100%;
color: #444;
... ...
... ... @@ -31,6 +31,14 @@ export default [{
keepAlive: true
}
}, {
path: '/article/nice/list',
name: 'articlelist.nice',
alias: '/article/nice/list',
component: () => import(/* webpackChunkName: "article-list" */ './article-nice'),
meta: {
keepAlive: true
}
}, {
path: '/article/detail/:id',
name: 'article.detail',
alias: '/article/detail/:id',
... ... @@ -55,8 +63,8 @@ export default [{
keepAlive: true
}
}, {
path: '/topic/:topicId',
alias: '/topic/:topicId',
path: '/topic/:topicId/:topicName',
alias: '/topic/:topicId/:topicName',
name: 'topic',
component: () => import(/* webpackChunkName: "topic" */ './topic'),
meta: {
... ...
... ... @@ -56,7 +56,7 @@ import ArticleActionSheet from './components/detail/article-action-sheet';
import MoreActionSheet from './components/detail/more-action-sheet';
import TopicHeader from './components/topic/header';
import TopicBanner from './components/topic/banner';
import {mapState as mapYohoState, mapActions as mapYohoActions, createNamespacedHelpers} from 'vuex';
import {mapState as mapYohoState, mapActions as mapYohoActions, mapMutations as mapYohoMutations, createNamespacedHelpers} from 'vuex';
const {mapMutations, mapActions} = createNamespacedHelpers('article');
const throttleTime = 40;
... ... @@ -85,7 +85,7 @@ export default {
};
},
created() {
this.topicName = this.$route.query.topicName;
this.topicName = this.$route.params.topicName;
},
activated() {
if (this.scrollTop && this.yoho.direction === 'back') {
... ... @@ -94,7 +94,7 @@ export default {
if (+this.$route.params.topicId !== this.topicId) {
this.topicId = +this.$route.params.topicId;
this.topicName = this.$route.query.topicName;
this.topicName = this.$route.params.topicName;
this.reload = true;
this.init();
}
... ... @@ -118,6 +118,10 @@ export default {
this.scrollEvent = throttle(this.onDounceScroll.bind(this), throttleTime);
this.colWidthForTwo = Math.floor(this.$el.offsetWidth / 2);
this.SET_STATUS_BAR_COLOR({
color: 'white'
});
},
computed: {
...mapYohoState(['yoho']),
... ... @@ -133,6 +137,7 @@ export default {
},
methods: {
...mapYohoActions(['fetchUserProfile']),
...mapYohoMutations(['SET_STATUS_BAR_COLOR']),
...mapActions(['fetchTopicSimpleInfo', 'fetchTopicRelatedArticles', 'fetchArticleProductFavs']),
...mapMutations(['ASYNC_ARTICLE_COMMENT', 'CHANGE_AUTHOR_FOLLOW']),
onShowComment({articleId, index}) {
... ...
... ... @@ -173,22 +173,21 @@ export default {
padding: 20px;
}
.avatar {
width: 40px;
height: 40px;
display: inline-block;
vertical-align: middle;
.auther {
display: flex;
align-items: center;
}
> img {
width: 100%;
height: 100%;
}
.avatar {
width: 20PX;
height: 20PX;
margin-right: 10px;
display: block;
}
.name {
max-width: 170px;
display: inline-block;
vertical-align: middle;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
... ...
... ... @@ -459,7 +459,7 @@ export default {
};
</script>
<style lang="scss">
<style lang="scss" scoped>
.author-page {
box-sizing: border-box;
color: #4a4a4a;
... ... @@ -695,11 +695,10 @@ export default {
background-color: #f7f7f7;
}
.loading {
padding: 20px 0;
.load-icon > span {
/deep/ .cube-loading-spinners {
margin: auto;
}
... ...
... ... @@ -282,7 +282,7 @@ export default {
return result;
},
async fetchTopicSimpleInfo({ commit, state }, {topicId}) {
if (state.fetchTopicInfo || get(state.topicInfo, 'topicId') === topicId) {
if (state.fetchTopicInfo) {
return Promise.resolve({});
}
... ... @@ -335,5 +335,28 @@ export default {
}
return result;
},
async fetchFindNiceGoodsArticles({ commit, state }, { page, limit, thumb}) {
commit(Types.FETCH_NICE_GOODS_REQUEST, { page });
const result = await this.$api.post('/api/grass/findGoodsList', {
page,
limit: limit || 6,
lastedTime: state.articleLastedTimeByNice || void 0
});
if (result && result.code === 200) {
if (!result.data.detailList) {
result.data.detailList = [];
}
commit(Types.FETCH_NICE_GOODS_SUCCESS, {
data: result.data,
page,
thumb
});
} else {
commit(Types.FETCH_NICE_GOODS_FAILD);
}
return result;
}
};
... ...
... ... @@ -24,7 +24,11 @@ export default function() {
fetchTopicArticles: false,
articleSingleDetail: {},
fetchArticleSingleDetail: false,
fetchDetailRecommendArticles: false
fetchDetailRecommendArticles: false,
articleNiceList: [],
articleNiceThumbList: [],
articleLastedTimeByNice: 0,
fetchArticleNiceList: false,
},
actions,
mutations
... ...
... ... @@ -10,6 +10,8 @@ function articlefield(type, thumb) {
return `article${thumb ? 'Thumb' : ''}ListByTopic`;
} else if (type === 'userArticle') {
return `articleUser${thumb ? 'Thumb' : ''}List`;
} else if (type === 'niceGoods') {
return `articleNice${thumb ? 'Thumb' : ''}List`;
}
return '';
}
... ... @@ -373,4 +375,19 @@ export default {
[Types.FETCH_DETAIL_RECOMMEND_FAILD](state) {
state.fetchDetailRecommendArticles = false;
},
[Types.FETCH_NICE_GOODS_REQUEST](state, {page}) {
state.fetchArticleNiceList = true;
if (page === 1) {
state.articleLastedTimeByNice = 0;
state.articleNiceList = [];
}
},
[Types.FETCH_NICE_GOODS_SUCCESS](state, {data, thumb}) {
state.fetchArticleNiceList = false;
state.articleLastedTimeByNice = data.lastedTime;
setArticleList(state, data.detailList || [], 'niceGoods', thumb);
},
[Types.FETCH_NICE_GOODS_FAILD](state) {
state.fetchArticleNiceList = false;
},
};
... ...
... ... @@ -42,3 +42,7 @@ export const FETCH_ARTICLE_SINGLE_DETAIL_SUCCESS = 'FETCH_ARTICLE_SINGLE_DETAIL_
export const FETCH_DETAIL_RECOMMEND_REQUEST = 'FETCH_DETAIL_RECOMMEND_REQUEST';
export const FETCH_DETAIL_RECOMMEND_FAILD = 'FETCH_DETAIL_RECOMMEND_FAILD';
export const FETCH_DETAIL_RECOMMEND_SUCCESS = 'FETCH_DETAIL_RECOMMEND_SUCCESS';
export const FETCH_NICE_GOODS_REQUEST = 'FETCH_NICE_GOODS_REQUEST';
export const FETCH_NICE_GOODS_FAILD = 'FETCH_NICE_GOODS_FAILD';
export const FETCH_NICE_GOODS_SUCCESS = 'FETCH_NICE_GOODS_SUCCESS';
... ...
... ... @@ -25,7 +25,7 @@ export function processImage(src, mode, width, height, webp) {
const imgName = splits[0] || '';
let query = splits[1] || '';
if (src.indexOf('{width}') < 0) {
if (!src || src.indexOf('{width}') < 0) {
return src;
}
... ...
... ... @@ -32,7 +32,7 @@ const getDetailShareData = (article) => {
}
return {
title: `@${article.authorName} 在有货社区上发了一篇笔记,快点开看看!`,
title: `@${article.authorName} 在有货社区上发了一篇内容,快点开看看!`,
imgUrl: handleProtocol(get(shareImage.split('?'), '[0]') || DEFAULT_SHARE_IMAGE),
link: handleProtocol(`${window ? window.location.origin : ''}/grass/article/share/${article.articleId}`),
desc,
... ...
... ... @@ -46,6 +46,16 @@ module.exports = {
articleId: {type: Number, require: false}
}
},
'/api/grass/findGoodsList': {
api: 'app.grass.findGoodsList',
cache: true,
auth: true,
params: {
page: {type: Number},
limit: {type: Number},
lastedTime: {type: Number}
}
},
'/api/grass/updateAttention': {
api: 'app.grass.updateAttention',
auth: true,
... ...
... ... @@ -57,5 +57,10 @@ module.exports = [
route: /grass\/mine\/fans/,
cacheTime: 900,
cache: true
},
{
route: /grass\/article\/nice\/list/,
cacheTime: 900,
cache: true
}
];
... ...
... ... @@ -93,7 +93,7 @@ const getCacheKey = (req, route) => {
ck += `?${qks.map(qk => `${qk}=${req.query && req.query[qk] || ''}`).join('&')}`;
}
ck += `|${isIos ? 'ios' : 'android'}|${config.appVersion}`;
ck += `|${isIos ? 'ios' : 'android'}|${pkg.version}`;
return md5(ck);
};
... ...
{
"name": "yoho-community-web",
"version": "6.9.5-14",
"version": "6.9.5-18",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ...