Authored by yyq

follow and fans list

<template>
<Layout class="author-fans-page">
<LayoutHeader slot='header' theme="white" class="author-page-header">{{isMine ? '我的' : 'TA'}}粉丝</LayoutHeader>
<UserList :follow-name="isMine ? '回粉' : '关注'" :on-fetch="onFetch"></UserList>
</Layout>
</template>
<script>
import {assign, get} from 'lodash';
import {Scroll, Loading} from 'cube-ui';
import UserList from './components/user-list';
import {createNamespacedHelpers} from 'vuex';
const {mapActions} = createNamespacedHelpers('user');
export default {
name: 'authorFans',
data() {
return {
isMine: false
};
},
created() {
this.isMine = !this.$route.params.id;
this._baseParams = {
authorType: this.$route.params.type || 1,
limit: 20,
};
if (!this.isMine) {
this._baseParams.authorUid = this.$route.params.id;
}
},
methods: {
...mapActions(['authorFansList', 'authorMineFansList']),
onFetch({page, lastedTime}) {
let params = Object.assign({page, lastedTime}, this._baseParams);
return this.isMine ? this.authorMineFansList(params) : this.authorFansList(params);
}
},
components: {
UserList
}
}
</script>
<style lang="scss">
</style>
... ...
<template>
<Layout class="author-follow-page">
<LayoutHeader slot='header' theme="white" class="author-page-header">{{isMine ? '我的' : 'TA'}}关注</LayoutHeader>
<UserList :on-fetch="onFetch"></UserList>
</Layout>
</template>
<script>
import {assign, get} from 'lodash';
import {Scroll, Loading} from 'cube-ui';
import UserList from './components/user-list';
import {createNamespacedHelpers} from 'vuex';
const {mapActions} = createNamespacedHelpers('user');
export default {
name: 'authorFollow',
data() {
return {
isMine: false
};
},
created() {
this.isMine = !this.$route.params.id;
this._baseParams = {
authorType: this.$route.params.type || 1,
limit: 20,
};
if (!this.isMine) {
this._baseParams.authorUid = this.$route.params.id;
}
},
methods: {
...mapActions(['authorAttentionList', 'authorMineAttentionList']),
onFetch({page, lastedTime}) {
let params = Object.assign({page, lastedTime}, this._baseParams);
return this.isMine ? this.authorMineAttentionList(params) : this.authorAttentionList(params);
}
},
components: {
UserList
}
}
</script>
<style lang="scss">
</style>
... ...
... ... @@ -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.isAttention" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
<WidgetFollow class="widget-follow" :author-uid="authorInfo.authorUid" :author-type="authorInfo.authorType" :follow="authorBaseData.isAttention" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
</div>
</div>
</div>
... ... @@ -35,14 +35,15 @@
</span>
<div class="author-section">
<ul class="author-fans">
<li v-for="(item, key) in fansList" :key="key">
<span class="num">{{authorBaseData[key] || 0}}</span>
<p class="name"><span>{{item}}</span></p>
<li v-for="item in fansList" :key="item.key">
<div class="click-wrap" @click="toPage(item.type)"></div>
<span class="num">{{authorBaseData[item.key] || 0}}</span>
<p class="name"><span>{{item.name}}</span></p>
</li>
</ul>
<div class="operate-wrap">
<a v-if="isOwner" class="operate-btn btn-user-edit" :href="mineInfoUrl">编辑个人资料</a>
<WidgetFollow v-if="!isOwner" class="operate-btn" :author-uid="autherInfo.authorUid" :follow="authorBaseData.isAttention" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
<WidgetFollow v-if="!isOwner" class="operate-btn" :author-uid="authorInfo.authorUid" :author-type="authorInfo.authorType" :follow="authorBaseData.isAttention" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
</div>
</div>
</div>
... ... @@ -82,12 +83,12 @@ export default {
scrolling: false,
mineInfoUrl: '//m.yohobuy.com/home/mydetails?openby:yohobuy={"action":"go.mineinfo"}',
publishUrl: '?openby:yohobuy={"action":"go.grasspublish"}',
autherInfo: {},
fansList: {
attCount: '关注',
fansCount: '粉丝',
praiseAndfavorite: '获赞与收藏'
},
authorInfo: {},
fansList: [
{name: '关注', key: 'attCount', type: 'follow'},
{name: '粉丝', key: 'fansCount', type: 'fans'},
{name: '获赞与收藏', key: 'praiseAndfavorite'}
],
tabFixed: false,
tabsNum: [0, 0],
activeIndex: 0,
... ... @@ -125,7 +126,7 @@ export default {
}
},
activated() {
if (this.$route.params.id && +this.$route.params.id !== this.autherInfo.authorUid) {
if (this.$route.params.id && +this.$route.params.id !== this.authorInfo.authorUid) {
this.init(this.$route.params);
}
},
... ... @@ -144,8 +145,8 @@ export default {
return {
params: {
type: this.waterFallType,
authorType: this.autherInfo.authorType,
authorUid: this.autherInfo.authorUid,
authorType: this.authorInfo.authorType,
authorUid: this.authorInfo.authorUid,
},
query: {
userName: this.authorBaseData.nickName
... ... @@ -158,11 +159,11 @@ export default {
},
methods: {
...mapMutations(['CHANGE_AUTHOR_OWNER_STATUS', 'CHANGE_AUTHOR_ATTENTION_STATUS']),
...mapActions(['autherBaseInfo', 'autherAritcleNum', 'autherPubList', 'autherFavList', 'autherMineBaseInfo', 'autherMineAritcleNum', 'autherMinePubList', 'autherMineFavList']),
...mapActions(['authorBaseInfo', 'authorAritcleNum', 'authorPubList', 'authorFavList', 'authorMineBaseInfo', 'authorMineAritcleNum', 'authorMinePubList', 'authorMineFavList']),
init(params) {
params = params || {};
this._apiNamePre = 'auther';
this._apiNamePre = 'author';
this.CHANGE_AUTHOR_OWNER_STATUS(!this.$route.params.id);
this.tabFixed = false;
... ... @@ -191,7 +192,7 @@ export default {
}
},
fetchData(authorUid, authorType, noBase) {
this.autherInfo = {authorUid, authorType};
this.authorInfo = {authorUid, authorType};
this.fetchBaseInfo();
this.fetchList(true);
... ... @@ -276,9 +277,9 @@ export default {
}
},
fetchBaseInfo() {
this[this._apiNamePre + 'BaseInfo'](this.autherInfo);
this[this._apiNamePre + 'BaseInfo'](this.authorInfo);
this[this._apiNamePre + 'AritcleNum'](this.autherInfo).then(res => {
this[this._apiNamePre + 'AritcleNum'](this.authorInfo).then(res => {
this.tabsNum = [get(res, 'data.articleCount'), get(res, 'data.favoriteCount')];
});
},
... ... @@ -315,7 +316,7 @@ export default {
limit: 20,
page: info.page,
lastedTime: info.lastedTime || ''
}, this.autherInfo));
}, this.authorInfo));
this.syncing = false;
}
... ... @@ -369,6 +370,24 @@ export default {
},
onFollow(follow) {
this.CHANGE_AUTHOR_ATTENTION_STATUS(follow);
},
toPage(type) {
let routerName = '';
let params = {};
if (type) {
routerName = `${this.isOwner ? 'mine' : 'author'}.${type}`;
if (!this.isOwner) {
params.id = this.authorInfo.authorUid;
params.type = this.authorInfo.authorType;
}
this.$router.push({
name: routerName,
params
});
}
}
},
components: {
... ... @@ -501,11 +520,21 @@ export default {
li {
margin-left: 140px;
position: relative;
z-index: 1;
&:first-child {
margin-left: 0;
}
.click-wrap {
position: absolute;
left: -50px;
right: -50px;
top: -14px;
bottom: -50px;
z-index: 10;
}
.num {
min-width: 30px;
font-size: 28px;
... ...
<template>
<CubeScroll
class="main-container"
ref="scroll"
:options="scrollOpts"
:scroll-events="['scroll-end']"
@scroll-end="fetchList">
<div class="user-list">
<div v-for="(item, index) in list" :key="index" class="user-item">
<WidgetAvatar class="head-ico" :src="item.headIcon" :width="100" :height="100" @click="toUserPage(item)"></WidgetAvatar>
<div class="user-info" @click="toUserPage(item)">
<p class="name">{{item.nickName}}</p>
<p v-if="item.articleCount || item.fansCount" class="extra">
<span v-if="item.publishNum">笔记·{{item.publishNum}}</span>
<span v-if="item.fansCount">粉丝·{{item.fansCount}}</span>
</p>
</div>
<div class="option-btn" :class="{'follow': item.isAttention}">
<WidgetFollow class="click-wrap" :author-uid="item.authorUid" :author-type="item.authorType" :follow="item.isAttention" @on-follow="follow => onFollow(follow, index)"></WidgetFollow>
{{item.isAttention ? '取消关注' : followName}}
</div>
</div>
</div>
<div class="loading">
<p v-if="noMore" class="load-text">没有更多了</p>
<Loading v-else class="load-icon" :size="20"></Loading>
</div>
</CubeScroll>
</template>
<script>
import {get} from 'lodash';
import {Scroll, Loading} from 'cube-ui';
export default {
props: {
followName: {
type: String,
default: '关注'
},
onFetch: {
type: Function,
required: true
}
},
data() {
return {
scrollOpts: {
bounce: false,
},
list: [],
noMore: false
};
},
mounted() {
this.fetchList();
},
methods: {
fetchList() {
let page = this._page || 1;
if (this._fetching || page > this._totalPage) {
return;
}
this._fetching = true;
setTimeout(() => {
this._fetching = false;
}, 800)
this.onFetch({
page: this._page || 1,
lastedTime: this._lastedTime
}).then(res => {
if (res.code !== 200) {
return;
}
let list = get(res, 'data.list', []);
list.forEach(val => {
val.isAttention = val.hasAttention === 'Y';
});
this.list = this.list.concat(list);
this._totalPage = res.data.totalPage;
this._lastedTime = res.data.lastedTime;
this._page = ++page;
if (page > this._totalPage) {
this.noMore = true;
}
})
},
onFollow(follow, index) {
this.list[index].isAttention = follow;
},
toUserPage(item) {
this.$router.push({
name: 'author',
params: {
id: item.userId,
type: item.userType || 1
}
});
},
},
components: {
CubeScroll: Scroll,
Loading
}
};
</script>
<style>
.user-list {
padding-left: 30px;
}
.user-item {
height: 154px;
display: flex;
align-items: center;
border-bottom: 1px solid #e0e0e0;
.head-ico {
width: 100px;
height: 100px;
margin-right: 20px;
}
.user-info {
flex-grow: 1;
overflow: hidden;
}
.name {
font-size: 28px;
line-height: 1.4;
}
.extra {
font-size: 0;
line-height: 1.4;
margin-top: 16px;
color: #b0b0b0;
> span {
font-size: 24px;
display: inline-block;
padding: 0 12px;
position: relative;
&:before {
width: 2px;
content: "";
position: absolute;
top: 4px;
bottom: 4px;
left: -1px;
background-color: #b0b0b0;
}
&:first-child {
margin-left: -12px;
}
}
}
.option-btn {
min-width: 110px;
line-height: 50px;
letter-spacing: 3px;
text-align: center;
border: 1px solid #444;
border-radius: 26px;
padding: 0 18px;
margin-right: 28px;
box-sizing: border-box;
position: relative;
z-index: 1;
&.follow {
color: #b0b0b0;
border-color: #b0b0b0;
}
.click-wrap {
width: 140%;
height: 180%;
position: absolute;
left: -20%;
top: -38%;
z-index: 10;
background: none;
font-size: 0;
opacity: 0;
}
}
}
.loading {
padding: 20px 0;
.load-icon > span {
margin: auto;
}
.load-text {
text-align: center;
}
}
</style>
... ...
... ... @@ -15,4 +15,28 @@ export default [{
meta: {
keepAlive: true
},
},
{
path: '/author/follow/:type/:id',
alias: '/author/follow/:type/:id',
name: 'author.follow',
component: () => import(/* webpackChunkName: "authorFollow" */ './author-follow'),
},
{
path: '/author/fans/:type/:id',
alias: '/author/fans/:type/:id',
name: 'author.fans',
component: () => import(/* webpackChunkName: "authorFans" */ './author-fans'),
},
{
path: '/mine/follow',
alias: '/mine/follow',
name: 'mine.follow',
component: () => import(/* webpackChunkName: "authorFollow" */ './author-follow'),
},
{
path: '/mine/fans',
alias: '/mine/fans',
name: 'mine.fans',
component: () => import(/* webpackChunkName: "authorFans" */ './author-fans'),
}];
... ...
... ... @@ -44,7 +44,7 @@ export default {
return result;
},
async autherBaseInfo({commit}, {authorUid, authorType}) {
async authorBaseInfo({commit}, {authorUid, authorType}) {
commit(Types.FETCH_AUTHOR_INFO_REQUEST);
const result = await this.$api.get('/api/grass/getGrassUserBaseInfo', {
authorUid,
... ... @@ -62,7 +62,7 @@ export default {
return result;
},
async autherAritcleNum(actions, {authorUid, authorType}) {
async authorAritcleNum(actions, {authorUid, authorType}) {
const result = await this.$api.get('/api/grass/getGrassPubAndFavorNum', {
authorUid,
authorType
... ... @@ -70,7 +70,7 @@ export default {
return result;
},
async autherPubList(actions, {authorUid, authorType, limit, page, lastedTime}) {
async authorPubList(actions, {authorUid, authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/userPublishedArticleList', {
authorUid,
authorType,
... ... @@ -81,7 +81,7 @@ export default {
return result;
},
async autherFavList(actions, {authorUid, authorType, limit, page, lastedTime}) {
async authorFavList(actions, {authorUid, authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/userFavouriteArticleList', {
authorUid,
authorType,
... ... @@ -92,7 +92,7 @@ export default {
return result;
},
async autherMineBaseInfo({commit}, {authorType}) {
async authorMineBaseInfo({commit}, {authorType}) {
commit(Types.FETCH_AUTHOR_INFO_REQUEST);
const result = await this.$api.get('/api/grass/getMineGrassBaseInfo', {
authorType
... ... @@ -109,14 +109,14 @@ export default {
return result;
},
async autherMineAritcleNum(actions, {authorType}) {
async authorMineAritcleNum(actions, {authorType}) {
const result = await this.$api.get('/api/grass/getMineGrassPubAndFavorNum', {
authorType
});
return result;
},
async autherMinePubList(actions, {authorType, limit, page, lastedTime}) {
async authorMinePubList(actions, {authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/minePublishedArticleList', {
authorType,
limit,
... ... @@ -126,7 +126,7 @@ export default {
return result;
},
async autherMineFavList(actions, {authorType, limit, page, lastedTime}) {
async authorMineFavList(actions, {authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/mineFavouriteArticleList', {
authorType,
limit,
... ... @@ -136,4 +136,46 @@ export default {
return result;
},
async authorAttentionList(actions, {authorUid, authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/userAttentionList', {
authorUid,
authorType,
limit,
page,
lastedTime
});
return result;
},
async authorFansList(actions, {authorUid, authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/userFansList', {
authorUid,
authorType,
limit,
page,
lastedTime
});
return result;
},
async authorMineAttentionList(actions, {authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/mineAttentionList', {
authorType,
limit,
page,
lastedTime
});
return result;
},
async authorMineFansList(actions, {authorType, limit, page, lastedTime}) {
const result = await this.$api.get('/api/grass/mineFansList', {
authorType,
limit,
page,
lastedTime
});
return result;
},
};
... ...
... ... @@ -75,5 +75,49 @@ module.exports = {
lastedTime: {type: Number}
}
},
'/api/grass/userAttentionList': {
api: 'app.grass.userAttentionList',
auth: true,
params: {
authorUid: {type: Number, require: true},
authorType: {type: Number, require: true},
limit: {type: Number},
page: {type: Number},
lastedTime: {type: Number}
}
},
'/api/grass/userFansList': {
api: 'app.grass.userFansList',
auth: true,
params: {
authorUid: {type: Number, require: true},
authorType: {type: Number, require: true},
limit: {type: Number},
page: {type: Number},
lastedTime: {type: Number}
}
},
'/api/grass/mineAttentionList': {
api: 'app.grass.userAttentionList',
auth: true,
params: {
authorUid: {type: Number, require: true, alias: 'uid'},
authorType: {type: Number, require: true},
limit: {type: Number},
page: {type: Number},
lastedTime: {type: Number}
}
},
'/api/grass/mineFansList': {
api: 'app.grass.userFansList',
auth: true,
params: {
authorUid: {type: Number, require: true, alias: 'uid'},
authorType: {type: Number, require: true},
limit: {type: Number},
page: {type: Number},
lastedTime: {type: Number}
}
},
}
... ...