Authored by yyq

Merge remote-tracking branch 'origin/release/6.8.7' into feature/grassV2

Showing 36 changed files with 522 additions and 107 deletions
import axios from 'axios';
import config from 'config';
import {get} from 'lodash';
axios.defaults.baseURL = config.axiosBaseUrl;
axios.defaults.responseType = config.axiosResponseType;
... ... @@ -8,12 +9,22 @@ axios.defaults.headers = {
};
const errHandle = (error) => {
let res = error.response;
console.log(error);
if (+res.status === 510) {
if (get(res, 'data.data.refer')) {
return window.location.href = get(res, 'data.data.refer');
}
}
return Promise.reject({
code: 500,
message: '服务器开小差了~'
});
};
const request = (options, store) => {
return axios(options).then((res) => {
if (res.data.code === 401) {
... ...
... ... @@ -17,6 +17,8 @@
<CommentPlaceholder
class="comment-cont"
:dest-id="parentComment.id"
:pos-id="posId"
:article-id="articleId"
:add-type="1"
:user="parentComment.userName"
:column-type="columnType"
... ... @@ -65,7 +67,9 @@ export default {
columnType: {
type: Number,
default: 1001
}
},
posId: Number,
articleId: Number
},
data() {
return {
... ...
... ... @@ -9,6 +9,8 @@
:parent-comment="comment.parentComment"
:children-comments="comment.childrenComments"
:column-type="columnType"
:pos-id="posId"
:article-id="articleId"
@on-reply="onReply">
</CommentItem>
</Scroll>
... ... @@ -18,6 +20,8 @@
<CommentPlaceholder
class="comment-input"
:dest-id="destId"
:pos-id="posId"
:article-id="articleId"
:add-type="0"
:column-type="columnType"
@on-comment="onComment">
... ... @@ -41,7 +45,9 @@ export default {
columnType: {
type: Number,
default: 1001
}
},
posId: Number,
articleId: Number
},
data() {
return {
... ...
import {createNamespacedHelpers} from 'vuex';
const {mapActions} = createNamespacedHelpers('comment');
import YAS from 'utils/yas-constants';
const {mapActions: articleMapActions} = createNamespacedHelpers('article');
export default {
... ... @@ -16,7 +17,9 @@ export default {
type: String,
default: ''
},
share: Boolean
share: Boolean,
posId: Number,
articleId: Number
},
data() {
return {
... ... @@ -80,6 +83,8 @@ export default {
addType: this.addType,
columnType: this.columnType
});
this.reportComment(this.destId);
} else {
this.$createToast({
txt: result.message || '服务器开小差了',
... ... @@ -87,6 +92,18 @@ export default {
time: 1000
}).show();
}
},
reportComment(comId) {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.comment,
param: {
POS_ID: this.posId,
ARTICLE_ID: this.articleId,
COM_ID: this.addType === 1 ? comId : void 0
}
}
});
}
},
render(h) {
... ...
... ... @@ -6,7 +6,7 @@
<i class="iconfont icon-close icon" @touchend.prevent="onClose"></i>
</template>
</LayoutHeader>
<CommentList ref="commentList" :dest-id="destId" :column-type="1001" @on-page-change="onPageChange" @on-comment="onComment" @on-page-ready="onPageReady"></CommentList>
<CommentList ref="commentList" :dest-id="destId" :pos-id="posId" :article-id="articleId" :column-type="1001" @on-page-change="onPageChange" @on-comment="onComment" @on-page-ready="onPageReady"></CommentList>
</Layout>
</template>
... ... @@ -20,7 +20,9 @@ export default {
popup: {
type: Boolean,
default: false
}
},
posId: Number,
articleId: Number
},
data() {
return {
... ...
... ... @@ -20,6 +20,7 @@
<script>
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapActions} = createNamespacedHelpers('product');
export default {
... ... @@ -29,7 +30,10 @@ export default {
lazy: Boolean,
product: Object,
share: Boolean,
thumb: Boolean
thumb: Boolean,
posId: Number,
articleId: [String, Number],
index: Number
},
data() {
return {
... ... @@ -78,6 +82,7 @@ export default {
if (result.code === 200) {
if (favorite) {
this.reportFavProduct(this.product.productSkn, this.product.productType);
this.prompt = this.$grassPrompt({
img: this.product.productImage,
title: '收藏成功',
... ... @@ -118,11 +123,41 @@ export default {
if (!skn) {
return;
}
if (this.product.productType === 1) {
this.$yoho.goProductDetail(skn);
} else if (this.product.productType === 2) {
this.$yoho.goUfoProductDetail(skn);
}
this.reportProduct(skn, this.product.productType);
},
reportProduct(skn, type) {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.productClick,
param: {
POS_ID: this.posId,
ARTICLE_ID: this.articleId,
PRD_SKN: skn,
PRD_TYPE: type
}
}
});
},
reportFavProduct(skn, type) {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.productFav,
param: {
POS_ID: this.posId,
ARTICLE_ID: this.articleId,
PRD_SKN: skn,
PRD_TYPE: type,
I_INDEX: this.index
}
}
});
}
}
};
... ...
... ... @@ -6,8 +6,12 @@
:thumb="thumb"
:single="single"
:product="product"
:article-id="articleId"
:pos-id="posId"
:lazy="lazy"
:key="inx"></ProductGroupItem>
:index="index"
:key="inx">
</ProductGroupItem>
</div>
</template>
... ... @@ -28,8 +32,13 @@ export default {
type: Boolean,
default: true
},
articleId: {
type: [String, Number],
},
share: Boolean,
thumb: Boolean
thumb: Boolean,
posId: Number,
index: Number
},
computed: {
single() {
... ...
<template>
<WidgetIconBtn type="fav" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option"></WidgetIconBtn>
<WidgetIconBtn type="fav" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option" :pos-id="posId"></WidgetIconBtn>
</template>
<script>
... ... @@ -8,6 +8,7 @@ export default {
props: {
num: [String, Number],
articleId: Number,
posId: Number,
commentId: Number,
option: Object,
share: Boolean
... ...
... ... @@ -6,6 +6,7 @@
<script>
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapActions} = createNamespacedHelpers('user');
export default {
... ... @@ -17,7 +18,8 @@ export default {
type: [Number, String],
default: 1
},
share: Boolean
share: Boolean,
posId: Number
},
data() {
return {
... ... @@ -60,6 +62,9 @@ export default {
this.loading = false;
if (result.code === 200) {
this.followStatus = !this.followStatus;
if (this.followStatus) {
this.reportFellow();
}
this.$emit('on-follow', this.followStatus);
} else {
this.$createToast && this.$createToast({
... ... @@ -68,6 +73,17 @@ export default {
time: 1000
}).show();
}
},
reportFellow() {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.fellow,
param: {
AUTH_ID: this.authorUid,
POS_ID: this.posId
}
}
});
}
}
};
... ...
... ... @@ -15,6 +15,7 @@ import {createNamespacedHelpers} from 'vuex';
const {mapActions} = createNamespacedHelpers('user');
const {mapActions: articleMapActions} = createNamespacedHelpers('article');
import cookie from 'yoho-cookie';
import YAS from 'utils/yas-constants';
const classMap = {
fav: {
... ... @@ -63,6 +64,7 @@ export default {
}
},
articleId: Number,
posId: Number,
commentId: Number,
option: {
type: Object,
... ... @@ -96,6 +98,17 @@ export default {
return 'praiseComment';
}
},
syncReportName() {
if (this.articleId) {
if (this.type === 'fav') {
return 'reportFav';
} else if (this.type === 'star') {
return 'reportStar';
}
}
return '';
},
isAuth() {
return !!this.syncFnName;
},
... ... @@ -141,7 +154,7 @@ export default {
placText() {
if (!isNaN(Number(this.text)) && this.viewText.length) {
return fill(Array(this.viewText.length), 0).join('');
} else {
} else {
return `${this.text}`;
}
}
... ... @@ -243,6 +256,8 @@ export default {
this.fetchArticleUpdate({articleId: this.articleId});
}
}
this[this.syncReportName] && this[this.syncReportName]();
};
this.syncing = true;
... ... @@ -256,6 +271,32 @@ export default {
}
this.viewOption.emitName && this.$emit(this.viewOption.emitName, evt);
},
reportFav() {
if (this.viewOption.selected) {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.fav,
param: {
POS_ID: this.posId,
ARTICLE_ID: this.articleId
}
}
});
}
},
reportStar() {
if (this.viewOption.selected) {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.star,
param: {
POS_ID: this.posId,
ARTICLE_ID: this.articleId
}
}
});
}
}
},
};
... ...
<template>
<WidgetIconBtn type="star" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option"></WidgetIconBtn>
<WidgetIconBtn type="star" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option" :pos-id="posId"></WidgetIconBtn>
</template>
<script>
... ... @@ -9,6 +9,7 @@ export default {
num: [String, Number],
articleId: Number,
commentId: Number,
posId: Number,
option: Object,
share: Boolean
}
... ...
<template>
<Comment ref="comment" :dest-id="articleId"></Comment>
<Comment ref="comment" :dest-id="articleId" :pos-id="sceneId" :articleId="articleId"></Comment>
</template>
<script>
import YAS from 'utils/yas-constants';
export default {
name: 'ArticleComment',
data() {
return {
size: 0,
articleId: 0
articleId: 0,
sceneId: YAS.scene.newsDetail
};
},
mounted() {
... ...
... ... @@ -3,7 +3,9 @@
ref="article"
type="article"
:thumbs="articleThumbList"
:on-fetch="onFetch">
:on-fetch="onFetch"
:pos-id="sceneId"
>
</Article>
</template>
... ... @@ -12,6 +14,7 @@ import {get} from 'lodash';
import Article from './components/article/article';
import ArticleItem from './components/article/article-item';
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapState, mapActions} = createNamespacedHelpers('article');
export default {
... ... @@ -20,6 +23,7 @@ export default {
return {
page: 1,
id: 0,
sceneId: YAS.scene.list
};
},
created() {
... ...
... ... @@ -7,6 +7,8 @@
v-for="(comment, inx) in data.comments"
:key="inx"
:dest-id="comment.id"
:pos-id="posId"
:article-id="articleId"
:add-type="1"
:column-type="comment.columnType"
:user="comment.userName">
... ... @@ -19,6 +21,8 @@
class="comment-input hover-opacity"
:dest-id="data.articleId"
:add-type="0"
:article-id="articleId"
:pos-id="posId"
:column-type="1001"
@on-comment="onComment">
添加评论
... ... @@ -46,7 +50,9 @@ export default {
},
type: String,
share: Boolean,
thumb: Boolean
thumb: Boolean,
posId: Number,
articleId: [Number, String]
},
computed: {
...mapState(['articleStates']),
... ...
... ... @@ -12,6 +12,8 @@
</template>
<script>
import YAS from 'utils/yas-constants';
export default {
name: 'ArticleItemHeader',
props: {
... ... @@ -27,7 +29,8 @@ export default {
},
type: String,
share: Boolean,
thumb: Boolean
thumb: Boolean,
posId: Number
},
computed: {
invisibleClass() {
... ... @@ -44,6 +47,7 @@ export default {
if (this.share) {
return this.$links.toDownloadApp();
}
this.$router.push({
name: 'author',
params: {
... ... @@ -51,9 +55,22 @@ export default {
id: this.data.authorUid
}
});
this.reportClickAvatar();
},
onFollow(follow) {
this.$emit('on-follow', follow);
},
reportClickAvatar() {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.avatar,
param: {
AUTH_ID: this.data.authorUid,
POS_ID: this.posId
}
}
});
}
}
};
... ...
... ... @@ -20,8 +20,8 @@
<WidgetShare :share="share" @click.native="onShare"></WidgetShare>
</div>
<div class="opts">
<WidgetFav :class="invisibleClass" :share="share" :num="articleState.praiseCount" :article-id="data.articleId" :option="praiseOption"></WidgetFav>
<WidgetLike :class="invisibleClass" :share="share" :num="articleState.favoriteCount" :article-id="data.articleId" :option="favoriteOption"></WidgetLike>
<WidgetFav :class="invisibleClass" :share="share" :num="articleState.praiseCount" :article-id="data.articleId" :option="praiseOption" :pos-id="posId"></WidgetFav>
<WidgetLike :class="invisibleClass" :share="share" :num="articleState.favoriteCount" :article-id="data.articleId" :option="favoriteOption" :pos-id="posId"></WidgetLike>
<WidgetComment :class="invisibleClass" :share="share" :num="articleState.commentCount" @click.native="onShowComment"></WidgetComment>
</div>
</div>
... ... @@ -31,6 +31,7 @@
<script>
import {get} from 'lodash';
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapMutations, mapState} = createNamespacedHelpers('article');
export default {
... ... @@ -44,7 +45,8 @@ export default {
},
type: String,
share: Boolean,
thumb: Boolean
thumb: Boolean,
posId: Number
},
data() {
return {
... ... @@ -134,6 +136,7 @@ export default {
if (this.data.articleType === 5) {
return;
}
this.$router.push({
name: 'topic',
params: {
... ... @@ -141,6 +144,8 @@ export default {
labelName: labelName
}
});
this.reportLabel(labelId);
},
onShare() {
let title = `@${this.data.authorName} 在有货逛上发了一篇笔记,快点开看看!`;
... ... @@ -179,6 +184,17 @@ export default {
if (this.articleState.commentCount) {
this.$emit('on-show-comment');
}
},
reportLabel(id) {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.labelClick,
param: {
AUTH_ID: id,
POS_ID: this.posId
}
}
});
}
}
};
... ...
<template>
<div class="article-item">
<ArticleItemHeader :type="type" :thumb="thumb" :share="share" :data="headerData" :lazy="lazy" @on-follow="onFollow" @on-show-more="onShowMore"></ArticleItemHeader>
<ArticleItemHeader :pos-id="posId" :type="type" :thumb="thumb" :share="share" :data="headerData" :lazy="lazy" @on-follow="onFollow" @on-show-more="onShowMore"></ArticleItemHeader>
<ArticleItemSlide :type="type" :thumb="thumb" :share="share" :data="slideData" :slide-index="data.blockIndex" :lazy="lazy"></ArticleItemSlide>
<ProductGroup :thumb="thumb" v-if="productListData.length" :share="share" :data="productListData" :lazy="lazy"></ProductGroup>
<ArticleItemIntro :thumb="thumb" :type="type" :share="share" :data="introData" @on-expand="onExpand" @on-expanding="onExpanding" @on-show-guang="onShowGuang" @on-show-comment="onShowComment"></ArticleItemIntro>
<ArticleItemComment :thumb="thumb" :type="type" :share="share" :data="commentData" @on-show-comment="onShowComment" @on-resize="onResize"></ArticleItemComment>
<ProductGroup :article-id="data.articleId" :pos-id="posId" :index="index" :thumb="thumb" v-if="productListData.length" :share="share" :data="productListData" :lazy="lazy"></ProductGroup>
<ArticleItemIntro :thumb="thumb" :type="type" :share="share" :data="introData" @on-expand="onExpand" @on-expanding="onExpanding" @on-show-guang="onShowGuang" @on-show-comment="onShowComment"
:article-id="articleId" :pos-id="posId">
</ArticleItemIntro>
<ArticleItemComment :thumb="thumb" :type="type" :share="share" :data="commentData" @on-show-comment="onShowComment" @on-resize="onResize" :pos-id="posId" :article-id="articleId" ></ArticleItemComment>
<div class="line"></div>
</div>
</template>
... ... @@ -15,6 +17,7 @@ import ArticleItemHeader from './article-item-header';
import ArticleItemSlide from './article-item-slide';
import ArticleItemIntro from './article-item-intro';
import ArticleItemComment from './article-item-comment';
import YAS from 'utils/yas-constants';
import dayjs from 'dayjs';
export default {
... ... @@ -29,7 +32,9 @@ export default {
index: Number,
share: Boolean,
type: String,
thumb: Boolean
thumb: Boolean,
posId: Number,
articleId: Number
},
computed: {
articleState() {
... ... @@ -101,18 +106,45 @@ export default {
this.changeResolve = r;
})
});
this.reportClickArticle();
},
onFollow(follow) {
this.$emit('on-follow', follow);
},
onShowGuang() {
this.$emit('on-show-guang', {articleId: this.data.relateId, grassId: this.data.articleId});
this.reportOpenGuang();
},
onShowComment() {
this.$emit('on-show-comment', {articleId: this.data.articleId, index: this.index});
},
onShowMore() {
this.$emit('on-show-more', {article: this.data, index: this.index});
},
reportOpenGuang() {
this.$store.dispatch('reportYas', {
params: {
appop: 'YB_H5_PAGE_OPEN_L',
param: {
F_URL: `${location.origin}/news/${this.articleId}`,
PAGE_URL: '',
PAGE_NAME: 'news'
}
}
});
},
reportClickArticle() {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.articleExpand,
param: {
I_INDEX: this.index,
ARTICLE_ID: this.articleId,
PRD_SKN: this.productListData.map(i => i.productSkn).join(','),
POS_ID: this.posId
}
}
});
}
},
components: {ArticleItemHeader, ArticleItemSlide, ArticleItemIntro, ArticleItemComment}
... ...
... ... @@ -9,7 +9,7 @@
</div>
</template>
<template v-if="showHeader" v-slot:opts>
<WidgetFollow :share="share" class="widget-follow" :author-uid="currentAuthor.authorUid" :follow="currentAuthor.hasAttention === 'Y'" @on-follow="follow => onFollow(currentAuthor, follow)"></WidgetFollow>
<WidgetFollow :share="share" class="widget-follow" :author-uid="currentAuthor.authorUid" :follow="currentAuthor.hasAttention === 'Y'" @on-follow="follow => onFollow(currentAuthor, follow)" :pos-id="posId"></WidgetFollow>
</template>
</LayoutHeader>
<LayoutRecycleList :size="10" :thumbs="thumbs" ref="scroll" @scroll="onScroll" :offset="2000" :on-fetch="onFetch">
... ... @@ -19,6 +19,8 @@
:index="data.index"
:data="data.data"
:share="share"
:article-id="data.articleId"
:pos-id="posId"
@on-follow="follow => onFollow(data.data, follow)"
@on-resize="onResize"
@on-unlock-height="onUnlockHeight"
... ... @@ -33,6 +35,8 @@
<Comment ref="comment"
:destId="articleId"
:popup="true"
:article-id="articleId"
:pos-id="posId"
@on-close="onClose"
@on-comment="onActionComment"
@on-page-ready="onPageReady"></Comment>
... ... @@ -43,6 +47,7 @@
<script>
import {throttle} from 'lodash';
import YAS from 'utils/yas-constants';
import ArticleItem from './article-item';
import ArticleActionSheet from '../detail/article-action-sheet';
import MoreActionSheet from '../detail/more-action-sheet';
... ... @@ -65,10 +70,12 @@ export default {
default() {
return [];
}
}
},
posId: Number
},
mounted() {
this.scrollEvent = throttle(this.onDounceScroll.bind(this), 100);
this.reportShow = this.startReportShow();
},
data() {
return {
... ... @@ -106,6 +113,7 @@ export default {
if (this.share) {
return this.$links.toDownloadApp();
}
this.$router.push({
name: 'author',
params: {
... ... @@ -113,6 +121,8 @@ export default {
id: this.currentAuthor.authorUid
}
});
this.reportClickAvatar();
},
onShowComment({articleId, index}) {
this.articleId = articleId;
... ... @@ -161,7 +171,7 @@ export default {
onScroll(params) {
this.scrollEvent(params);
},
onDounceScroll({item, scrollTop}) {
onDounceScroll({item, scrollTop, startIndex}) {
this.scrollTop = scrollTop;
if (scrollTop === 0) {
this.showHeader = false;
... ... @@ -177,6 +187,8 @@ export default {
this.currentAuthor.authorType = item.data.authorType;
this.showHeader = true;
this.reportShow(startIndex, item);
}
},
init() {
... ... @@ -199,6 +211,42 @@ export default {
this.$nextTick(() => {
this.$refs.actionSheet.show(params);
});
},
reportClickAvatar() {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.avatar,
param: {
AUTH_ID: this.currentAuthor.authorUid,
POS_ID: this.posId
}
}
});
},
startReportShow() {
let preview = null;
return (index, item) => {
if (preview === item.data.articleId) {
return;
}
preview = item.data.articleId;
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.show,
param: {
P_NAME: this.$route.name,
P_PARAM: this.$route.params,
I_INDEX: index,
ARTICLE_ID: preview,
PRD_SKN: (item.data.productList || []).map(i => i.productSkn).join(','),
POS_ID: this.posId
}
}
});
};
}
},
components: {
... ...
<template>
<div class="article-item-header">
<router-link class="avatar" :to="`/grass/author/${data.authorType}/${data.authorUid}`">
<div class="avatar" @click="goAuthor">
<WidgetAvatar class="widget-avatar" :src="data.avatar" :width="70" :height="70"></WidgetAvatar>
<span class="name">{{data.name}}</span>
</router-link>
</div>
<div class="opts">
<WidgetFollow v-bind="data"></WidgetFollow>
</div>
... ... @@ -11,6 +11,9 @@
</template>
<script>
import YAS from 'utils/yas-constants';
export default {
name: 'ArticleAuthor',
props: {
... ... @@ -19,9 +22,32 @@ export default {
default() {
return {};
}
}
},
posId: Number
},
methods: {
goAuthor() {
this.$router.push({
name: 'author',
params: {
type: this.data.authorType,
id: this.data.authorUid
}
});
this.reportClickAvatar();
},
reportClickAvatar() {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.avatar,
param: {
AUTH_ID: this.data.authorUid,
POS_ID: this.posId
}
}
});
}
}
};
</script>
... ...
<template>
<div class="scroll-wrapper">
<Author :data="articleDetail.getAuthor"></Author>
<Author :data="articleDetail.getAuthor" :pos-id="sceneId"></Author>
<div class="post-content" v-if="articleDetail && articleDetail.getArticleContent">
<template v-for="item in articleDetail.getArticleContent">
<template v-if="item.text">
... ... @@ -23,7 +23,7 @@
</template>
<template v-if="item.relatedReco">
<div class="products">
<ProductGroup v-for="(p,index) in item.relatedReco.goods" :data="[p]" :key="index"></ProductGroup>
<ProductGroup :pos-id="sceneId" :article-id="articleId" v-for="(p,index) in item.relatedReco.goods" :data="[p]" :key="index"></ProductGroup>
</div>
</template>
</template>
... ... @@ -44,11 +44,13 @@ import Author from './article-author';
import ZanBar from './zan-bar';
import TagBar from './tag-bar';
import { createNamespacedHelpers } from 'vuex';
import YAS from 'utils/yas-constants';
const { mapState } = createNamespacedHelpers('article');
export default {
name: 'ArticleBody',
props: ['articleId'],
components: {
RecommendProductList,
Recommend,
... ... @@ -61,7 +63,8 @@ export default {
scrollOpts: {
eventPassthrough: 'horizontal',
bounce: false
}
},
sceneId: YAS.scene.newsDetail
};
},
computed: {
... ...
... ... @@ -5,7 +5,7 @@
<div class="body" v-if="fetchStatus">
<Loading class="loading"></Loading>
</div>
<ArticleBody v-else ref="body" class="body"></ArticleBody>
<ArticleBody v-else ref="body" :articleId="grassId" class="body"></ArticleBody>
<ArticleFooter class="footer"
v-if="articleDetail"
... ... @@ -23,6 +23,7 @@ import ArticleFooter from './article-footer';
import ArticleBody from './article-body';
import * as sleep from '../../../../utils/sleep';
import { createNamespacedHelpers } from 'vuex';
import YAS from 'utils/yas-constants';
import { Loading } from 'cube-ui';
const { mapActions, mapState, mapMutations } = createNamespacedHelpers('article');
... ... @@ -38,7 +39,8 @@ export default {
data() {
return {
articleId: 0,
grassId: 0
grassId: 0,
posId: YAS.scene.newsDetail
};
},
mounted() {
... ... @@ -52,9 +54,10 @@ export default {
}
});
},
...mapActions(['getDetail']),
...mapActions(['getDetail', 'fetchProductFav']),
...mapMutations({
fetchArticleDetail: 'FETCH_GUANG_SUCCESS'
fetchArticleDetail: 'FETCH_GUANG_SUCCESS',
fetchArticleProductList: 'GUANG_DETAIL_PRODUCT_LIST'
}),
fetch(params) {
this.articleId = params.articleId;
... ... @@ -63,6 +66,12 @@ export default {
return this.getDetail({
article_id: params.articleId,
grass_id: params.grassId
}).then(() => {
this.$sdk.getUser().then(user => {
if (user && user.uid) {
this.fetchProductFav();
}
});
});
},
onClose() {
... ... @@ -72,6 +81,7 @@ export default {
async reset() {
await sleep.sleep(200);
this.fetchArticleDetail({});
this.fetchArticleProductList([]);
}
},
computed: {
... ...
<template>
<div class="article-footer-wrapper">
<div class="tool-bar">
<WidgetIconBtn class="item" type="fav" :text="praiseCount" :articleId="articleId" :option="optionPraise"></WidgetIconBtn>
<WidgetIconBtn class="item" type="star" :text="favoriteCount" :articleId="articleId" :option="optionFav" ></WidgetIconBtn>
<WidgetIconBtn class="item" type="fav" :pos-id="sceneId" :text="praiseCount" :articleId="articleId" :option="optionPraise"></WidgetIconBtn>
<WidgetIconBtn class="item" type="star" :pos-id="sceneId" :text="favoriteCount" :articleId="articleId" :option="optionFav" ></WidgetIconBtn>
<WidgetIconBtn class="item" type="msg" :text="commentCount" :option="optionComment" @click="onComment"></WidgetIconBtn>
</div>
<div class="close ml20" @click="onClose">收起</div>
... ... @@ -11,6 +11,8 @@
<script>
import YAS from 'utils/yas-constants';
export default {
name: 'ArticleFooter',
props: ['favoriteCount', 'praiseCount', 'commentCount', 'hasFavor', 'hasPraise', 'articleId'],
... ... @@ -26,6 +28,7 @@ export default {
emitName: 'click',
canSelect: false
},
sceneId: YAS.scene.newsDetail
};
},
computed: {
... ...
... ... @@ -3,7 +3,9 @@
ref="article"
:title="labelName"
type="topic"
:on-fetch="onFetch">
:on-fetch="onFetch"
:pos-id="sceneId"
>
</Article>
</template>
... ... @@ -12,6 +14,7 @@ import {get} from 'lodash';
import Article from './components/article/article';
import ArticleItem from './components/article/article-item';
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapActions} = createNamespacedHelpers('article');
export default {
... ... @@ -22,6 +25,7 @@ export default {
labelId: 0,
reload: true,
labelName: '',
sceneId: YAS.scene.topicList
};
},
created() {
... ...
... ... @@ -4,7 +4,8 @@
:title="userName"
type="userArticle"
:thumbs="articleUserThumbList"
:on-fetch="onFetch">
:on-fetch="onFetch"
:pos-id="sceneId">
</Article>
</template>
... ... @@ -13,6 +14,7 @@ import {get} from 'lodash';
import Article from './components/article/article';
import ArticleItem from './components/article/article-item';
import {createNamespacedHelpers} from 'vuex';
import YAS from 'utils/yas-constants';
const {mapState, mapActions} = createNamespacedHelpers('article');
export default {
... ... @@ -24,7 +26,8 @@ export default {
authorUid: 0,
authorType: 0,
type: '',
userName: ''
userName: '',
sceneId: YAS.scene.authorList
};
},
created() {
... ...
... ... @@ -11,7 +11,7 @@
<WidgetAvatar class="h-headico" :src="authorBaseData.headIco" :width="100" :height="100"></WidgetAvatar>
</div>
<div v-if="!isOwner" class="h-follow flex">
<WidgetFollow class="widget-follow" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)"></WidgetFollow>
<WidgetFollow class="widget-follow" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
</div>
</div>
</div>
... ... @@ -42,7 +42,7 @@
</ul>
<div class="operate-wrap">
<a v-if="isOwner" class="operate-btn btn-user-edit" :href="mineInfoUrl">编辑个人资料</a>
<WidgetFollow v-if="!isOwner && authorBaseData.hasAttention" class="operate-btn" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)"></WidgetFollow>
<WidgetFollow v-if="!isOwner && authorBaseData.hasAttention" class="operate-btn" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
</div>
</div>
</div>
... ... @@ -52,7 +52,7 @@
</div>
<div ref="contantList" class="contant-list" :style="`min-height: ${listMinHeight}px;`">
<p v-if="emptyTip" class="empty-tip">{{emptyTip}}</p>
<WaterFall class="pannel-wrap" :list="list" :params="params"></WaterFall>
<WaterFall class="pannel-wrap" :list="list" :params="params" :tab="activeIndex"></WaterFall>
<div v-if="loadStatus && !emptyTip" class="loading">
<Loading v-if="loadStatus === 1" class="load-icon" :size="20"></Loading>
<p v-else class="load-text">没有更多了</p>
... ... @@ -69,6 +69,7 @@ import {assign, get} from 'lodash';
import {Scroll, Loading} from 'cube-ui';
import FavTabBlock from './components/fav-tab-block';
import WaterFall from './components/scroll-reveal';
import YAS from 'utils/yas-constants';
import {createNamespacedHelpers} from 'vuex';
const {mapState, mapActions, mapMutations} = createNamespacedHelpers('user');
... ... @@ -96,7 +97,8 @@ export default {
emptyTip: '',
scrollOpts: {
bounce: false,
}
},
sceneId: YAS.scene.author
};
},
created() {
... ...
... ... @@ -18,7 +18,7 @@
</div>
<div class="fav">
<WidgetFav :articleId="data.articleId" :num="data.praiseCount" :option="favOption"></WidgetFav>
<WidgetFav :articleId="data.articleId" :num="data.praiseCount" :option="favOption" :pos-id="sceneId"></WidgetFav>
</div>
</div>
</div>
... ... @@ -27,11 +27,13 @@
<script>
import YAS from 'utils/yas-constants';
export default {
data() {
return {
imgWidth: 350
}
imgWidth: 350,
sceneId: YAS.scene.author
};
},
props: {
data: {
... ... @@ -43,7 +45,9 @@ export default {
temporary: {
type: Boolean,
default: false
}
},
index: Number,
tab: Number
},
computed: {
favOption() {
... ... @@ -52,13 +56,28 @@ export default {
iconBold: true,
iconFontSize: 26,
textAlign: 'normal'
}
};
}
},
methods: {
onClick(type) {
if (type === 'article') {
this.reportClickArticle();
}
this.$emit('click', {data: this.data, type});
}
},
reportClickArticle() {
this.$store.dispatch('reportYas', {
params: {
appop: YAS.eventName.articleExpand,
param: {
I_INDEX: this.index,
ARTICLE_ID: this.data.articleId,
POS_ID: this.posId
}
}
});
},
}
};
</script>
... ...
... ... @@ -2,9 +2,9 @@
<div class="sr-list">
<div class="sr-col" v-for="(col, index) in colsList" :key="index" :style="`width:${100/cols}%`">
<template v-if="col.length">
<ArticleItem v-for="item in col" :key="item.articleId" class="sr-item" :data="item" @click="onClick"></ArticleItem>
<ArticleItem v-for="(item, index) in col" :key="item.articleId" class="sr-item" :data="item" :index="index" @click="onClick" :tab="tab"></ArticleItem>
</template>
<ArticleItem class="sr-temp" :temporary="true"></ArticleItem>
<ArticleItem class="sr-temp" :temporary="true" :index="0" :tab="tab"></ArticleItem>
</div>
</div>
</template>
... ... @@ -32,7 +32,8 @@ export default {
type: Number,
default: 2
},
params: Object
params: Object,
tab: Number
},
created() {
this.reset();
... ... @@ -140,7 +141,7 @@ export default {
},
onClick({data, type}) {
if (type === 'author') {
this.toAuthor(data)
this.toAuthor(data);
} else {
this.toArticle(data);
}
... ... @@ -176,7 +177,7 @@ export default {
this.$router.push(router);
}
});
} catch(e){
} catch (e) {
console.log(e);
}
} else {
... ...
... ... @@ -170,33 +170,28 @@ export default {
await sleep.sleep(200);
commit(Types.GUANG_ARTICLE_CONTENT, processContents.finalDetail);
commit(Types.GUANG_DETAIL_PRODUCT_LIST, processContents.allgoods);
//再处理其他信息
const [goodsList, favsList, zan, article] = await Promise.all([
const [goodsList, zan, article] = await Promise.all([
this.$api.post('/api/guang/article/queryGoods', {
query: processContents.allgoods.skn.join(','),
order: 's_t_desc',
limit: processContents.allgoods.skn.length || 1
}),
this.$api.post('/api/favorite/batchCheckIsFavorite', {
favIds: processContents.allgoods.id.join(','),
type: 'product'
}),
this.$api.post('/api/guang/article/zan', { articleId: grass_id }),
this.$api.get('/api/guang/article/detail', { article_id })
]).then(([res1, res2, res3, res4]) => {
]).then(([res1, res2, res3]) => {
return [
get(res1, 'data.product_list', []),
get(res2, 'data', []),
get(res3, 'data', false),
get(res4, 'data', false)
get(res2, 'data', false),
get(res3, 'data', false)
];
});
result.getArticleContent = guangProcess.pushGoodsInfo(
processContents.finalDetail,
goodsList,
favsList
goodsList
);
result.getRecommendProducts = processContents.recommends;
... ... @@ -222,10 +217,21 @@ export default {
}
// 等待动画完成后,提交数据
commit(Types.FETCH_GUANG_SUCCESS, result);
},
async fetchProductFav({ commit, state }) {
if (!state.articleProductList.id.length) {
return;
}
const favsList = await this.$api.post('/api/favorite/batchCheckIsFavorite', {
favIds: state.articleProductList.id.join(','),
type: 'product'
}).then(result => {
return get(result, 'data', []);
});
commit(Types.GUANG_CHANGE_PRODUCT_FAV, favsList);
},
async reportArticle(actions, {articleId}) {
const result = await this.$api.post('/api/grass/reportIllegalArticle', {articleId});
... ...
... ... @@ -237,8 +237,8 @@ export function processArticleDetail(articleContent) {
/**
* 商品搜索商品数据处理
*/
function processProductList(list, favsList) {
const pruductList = [];
function processProductList(list) {
const productList = [];
forEach(list, (product) => {
if (!product) {
... ... @@ -269,7 +269,7 @@ function processProductList(list, favsList) {
product.data.shopUrl = '//m.yohobuy.com/product/shop?domain=' + product.data.shop_domain;
}
pruductList.push(product);
productList.push(product);
}
return;
... ... @@ -286,6 +286,7 @@ function processProductList(list, favsList) {
product.salesPrice = product.sales_price;
product.productName = product.product_name;
product.productId = product.product_id;
product.productSkn = product.product_skn;
product.is_soon_sold_out = product.is_soon_sold_out === 'Y';
... ... @@ -293,12 +294,9 @@ function processProductList(list, favsList) {
product.cn_alphabet = productNameProcess(product.cn_alphabet);
}
// fav
const fav = favsList.find(i => `${i.id}` === `${product.product_id}`);
product.id = product.product_id;
product.productType = 1;
product.favorite = get(fav, 'favorite', false);
product.favorite = false;
/**
* 全球购商品标记
... ... @@ -320,10 +318,10 @@ function processProductList(list, favsList) {
product.url = productUrl(product.product_skn);
}
pruductList.push(product);
productList.push(product);
});
return pruductList;
return productList;
}
const _goodsArrayToObj = (goodsArray) => {
... ... @@ -335,8 +333,8 @@ const _goodsArrayToObj = (goodsArray) => {
/**
* 重新获取商品数据
*/
export function pushGoodsInfo(finalDetail, goodsList, favsList) {
let goodsObj = _goodsArrayToObj(processProductList(goodsList, favsList));
export function pushGoodsInfo(finalDetail, goodsList) {
let goodsObj = _goodsArrayToObj(processProductList(goodsList));
finalDetail = cloneDeep(finalDetail);
... ...
... ... @@ -15,6 +15,7 @@ export default function() {
articleUserThumbList: [],
fetchArticleDetail: false,
articleDetail: {},
articleProductList: [],
articleLastedTimeByTopic: 0,
articleStates: {}
},
... ...
... ... @@ -194,5 +194,19 @@ export default {
[Types.FETCH_GUANG_SUCCESS](state, data) {
state.fetchArticleDetail = false;
state.articleDetail = data;
},
[Types.GUANG_DETAIL_PRODUCT_LIST](state, data) {
state.articleProductList = data;
},
[Types.GUANG_CHANGE_PRODUCT_FAV](state, favsList) {
get(state.articleDetail, 'getArticleContent', []).forEach(c => {
const products = get(c, 'relatedReco.goods', []);
products.forEach(p => {
const fav = favsList.find(i => `${i.id}` === `${p.product_id}`);
p.favorite = get(fav, 'favorite', false);
});
});
}
};
... ...
... ... @@ -18,6 +18,8 @@ export const FETCH_GUANG_SUCCESS = 'FETCH_GUANG_SUCCESS';
export const FETCH_FAV_SUCCESS = 'FETCH_FAV_SUCCESS';
export const FETCH_ZAN_SUCCESS = 'FETCH_ZAN_SUCCESS';
export const GUANG_ARTICLE_CONTENT = 'GUANG_ARTICLE_CONTENT';
export const GUANG_CHANGE_PRODUCT_FAV = 'GUANG_CHANGE_PRODUCT_FAV';
export const GUANG_DETAIL_PRODUCT_LIST = 'GUANG_DETAIL_PRODUCT_LIST';
export const CHANGE_AUTHOR_FOLLOW = 'CHANGE_AUTHOR_FOLLOW';
export const CHANGE_ARTICLE_LIST_SLIDE = 'CHANGE_ARTICLE_LIST_SLIDE';
... ...
... ... @@ -84,26 +84,30 @@ export default function() {
},
actions: {
reportYas(params, {params: {appop, param}, asyncindx = false}) {
document.addEventListener('deviceready', () => {
setTimeout(() => {
if (window._yas && window._yas.sendAppLogs) {
param = param || {};
try {
document.addEventListener('deviceready', () => {
setTimeout(() => {
if (window._yas && window._yas.sendAppLogs) {
param = param || {};
if (!param.C_ID) {
const channel = {
men: 1,
women: 2
}[cookie.get('_Channel') || 'men'];
if (!param.C_ID) {
const channel = {
men: 1,
women: 2
}[cookie.get('_Channel') || 'men'];
param.C_ID = channel;
param.C_ID = channel;
}
window._yas.sendAppLogs({
appop,
param: param ? JSON.stringify(param) : '{}'
}, asyncindx);
}
window._yas.sendAppLogs({
appop,
param: param ? JSON.stringify(param) : '{}'
}, asyncindx);
}
}, 300);
});
}, 300);
});
} catch (e) {
// pass
}
}
}
};
... ...
export default {
scene: {
index: 101,
list: 102,
author: 103,
authorList: 104,
topicList: 105,
newsDetail: 106
},
eventName: {
show: 'YB_SHOW_EVENT',
fav: 'YB_STROLL_ATC_LIKE_C',
star: 'YB_STROLL_ATC_COL_C',
avatar: 'YB_STROLL_ACT_AUTH_C',
fellow: 'YB_STROLL_AUTH_ATT_C',
articleExpand: 'YB_STROLL_LIST_ACT_C',
comment: 'YB_STROLL_ATC_COM_C',
productClick: 'YB_STROLL_ARC_RLT_PRD_C',
productFav: 'YB_STROLL_ARC_RLT_PRD_COL_C',
labelClick: 'YB_STROLL_ACT_LBL_C'
}
};
... ...
const _ = require('lodash');
const logger = global.yoho.logger;
const cache = global.yoho.cache.master;
const helpers = global.yoho.helpers;
const appName = 'h5'; // 与H5共用
const LIMITER_IP_TIME = 3600; // 超出访问限制ip限制访问1小时
const replaceKey = '__refer__';
const checkRefer = helpers.urlFormat('/3party/check', {refer: replaceKey});
/**
* 服务器错误
* @return {[type]}
*/
exports.serverError = (err, req, res, next) => { // eslint-disable-line
exports.serverError = (err = {}, req, res, next) => { // eslint-disable-line
logger.error(`error at path: ${req.url}`);
logger.error(`${req.url},${typeof err === 'object' ? JSON.stringify(err) : err}`);
if (err.apiRisk) { // 接口风控
let remoteIp = req.yoho.clientIp;
if (_.get(req.app.locals, 'wap.open.apmrisk', false)) {
cache.setAsync(`${appName}:limit2:${remoteIp}`, 1, LIMITER_IP_TIME);
} else {
cache.setAsync(`${appName}:limiter:${remoteIp}`, 1, LIMITER_IP_TIME);
}
req.session.apiRiskValidate = true;
if (req.xhr) {
return res.status(510).json({
code: err.code,
data: {refer: checkRefer.replace(replaceKey, req.get('Referer') || '')}
});
}
return res.redirect(checkRefer.replace(replaceKey, req.protocol + '://' + req.get('host') + req.originalUrl));
}
res.status(err.code || 500);
if (req.xhr) {
return res.json({
code: 500,
message: '服务器错误!'
code: err.code || 500,
message: err.message || '服务器错误'
});
}
... ...
... ... @@ -3,6 +3,7 @@ const ufoAPI = global.yoho.UfoAPI;
const logger = global.yoho.logger;
const checkParams = require('../../utils/check-params');
const apiMaps = require('../../config/api-map');
const errorHandler = require('./error-handler');
module.exports = async(req, res, next) => {
res.set({
... ... @@ -76,10 +77,6 @@ module.exports = async(req, res, next) => {
code: 400
});
} catch (error) {
logger.error(error);
return res.json({
code: error.code || 500,
message: error.message || '服务器错误'
});
return errorHandler.serverError(error, req, res, next);
}
};
... ...