如下是我测试的截图
前台
/pages/find/moments/moments.vue
<template>
<view>
<free-transparent-bar :scrollTop="scrollTop" @clickRight="clickRight"></free-transparent-bar>
<view class="position-relative" style="height: 620rpx;">
<image src="https://douyinzcmcss.oss-cn-shenzhen.aliyuncs.com/shengchengqi/datapic/1.jpg" mode="aspectFill" style="height: 590rpx;" class="bg-secondary w-100"></image>
<image :src="avatar" style="width: 120rpx;height:120rpx;right: 30rpx;" mode="" class="bg-secondary rounded position-absolute bottom-0"></image>
<text class="text-white font-md position-absolute" style="bottom: 45rpx;right: 160rpx">{{nickname}}</text>
</view>
<!-- 朋友圈列表样式 -->
<free-moment-list v-for="(item,index) in list" :key='index' :item="item" :index="index" @action="doAction" @reply="replyEvent"></free-moment-list>
<!-- 评论框 -->
<free-popup ref="action" bottom transformOrigin="center bottom">
<view style="height: 105rpx;" class="bg-light border-top flex align-center">
<textarea fixed class="bg-white rounded p-2 font-md" style="height: 45rpx;width: 420rpx;" value="" placeholder="" v-model="content" :focus="true"/>
<free-icon-button @click="changeFaceModeal"><text class="iconfont font-lg"></text></free-icon-button>
<free-main-button name="发送" :disabled="content.length===0" @click="send"></free-main-button>
</view>
<!-- 表情包 -->
<scroll-view v-if="faceModal" scroll-y="true" style="height: 350rpx;" class="bg-light">
<view class="flex flex-wrap">
<view class="flex align-center justify-center" hover-class="bg-white" style="width:107rpx;height:107rpx;" v-for="(item,index) in faceList" :key="index" @click="addFace(item)">
<text>{{item}}</text>
</view>
</view>
</scroll-view>
</free-popup>
<!-- 上拉加载 -->
<view class="flex align-center justify-center py-5 bg-light" v-if="list.length >= 10">
<text class="text-muted font">{{loadmore}}</text>
</view>
</view>
</template>
<script>
import freeTransparentBar from '@/components/free-ui/free-transparent-bar.vue';
import freeMomentList from '@/components/free-ui/free-moment-list.vue';
import freePopup from '@/components/free-ui/free-popup.vue';
import freeIconButton from '@/components/free-ui/free-icon-button.vue';
import freeMainButton from '@/components/free-ui/free-main-button.vue';
import $H from '@/common/free-lib/request.js';
import { mapState } from 'vuex';
export default {
components:{
freeTransparentBar,
freeMomentList,
freePopup,
freeIconButton,
freeMainButton
},
data() {
return {
content:'',
scrollTop:0,
faceModal:false,
faceList:["😀","😁","😂","😃","😄","😅","😆","😉","😊","😋","😎","😍","😘","😗","😙","😚","😇","😐","😑","😶","😏","😣","😥","😮","😯","😪","😫","😴","😌","😛","😜","😝","😒","😓","😔","😕","😲","😷","😖","😞","😟","😤","😢","😭","😦","😧","😨","😬","😰","😱","😳","😵","😡","😠"],
commentIndex:-1,
page:1,
loadmore:'上拉加载更多',
key:'moment_timeline',
list:[],
params:'',
reply_user:false
}
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
onReachBottom() {
if(this.loadmore !== '上拉加载更多'){
return;
}
this.page += 1;
this.loadmore = '加载中...';
this.getData().catch(err=>{
this.page -= 1;
uni.showToast({
title:'加载失败',
icon:'none'
});
this.loadmore = '上拉加载更多';
})
},
onLoad(e) {
if(e.key){
this.key = e.key;
}
if(e.params){
this.params = JSON.parse(decodeURIComponent(e.params));
}
this.page = 1;
this.getData();
uni.$on('momentNotice',this.momentNotice)
},
destroyed() {
uni.$off('momentNotice',this.momentNotice)
},
onPullDownRefresh() {
this.page = 1;
this.getData().then(res=>{
uni.showToast({
title:'刷新成功',
icon:'none'
});
uni.stopPullDownRefresh();
}).catch(err=>{
uni.showToast({
title:'刷新失败',
icon:'none'
});
uni.stopPullDownRefresh();
});
},
computed:{
...mapState({
user:state=>state.user.user
}),
nickname(){
if(!this.params){
return user.nickname || user.username;
}
return this.params.name;
},
avatar(){
let avatar = '';
if(!this.params){
avatar = this.user.avatar;
}else{
avatar = this.params.avatar
}
return avatar || '/static/images/demo/demo6.jpg';
}
},
methods: {
momentNotice(e){
this.page = 1;
this.getData().then(res=>{
uni.showToast({
title:'刷新成功',
icon:'none'
});
});
},
// 点击操作菜单
doAction(e){
uni.showActionSheet({
itemList: ['点赞','评论'],
success: res => {
if(res.tapIndex === 0){
// 点赞
this.doSupport(e)
}else{
this.content='';
this.faceModal=false;
this.commentIndex = e.index;
this.reply_user = false;
this.$refs.action.show();
// this.doComment(e)
}
}
});
},
// 获取数据
getData(){
return new Promise((result,reject)=>{
let page = this.page;
let params = this.key === '';
if(this.params && this.key == 'moment'){
params = '?user_id='+this.params.id;
}
$H.get(`/${this.key}/${this.page}${params}`).then(res=>{
this.list = page === 1 ? res : [...this.list,...res];
this.loadmore = this.list.length === (page * 10) ? '上拉加载更多' : '没有更多了'
result(res);
}).catch(err=>{
reject(err);
})
})
},
// 点赞
doSupport(e){
$H.post('/moment/like',{id:e.item.moment_id}).then(res=>{
let i = e.item.likes.findIndex(item=>item.id === this.user.id);
if(i !== -1){
// 取消点赞
e.item.likes.splice(i,1);
}else{
// 点赞
e.item.likes.push({
id:this.user.id,
name:this.user.nickname || this.user.username
})
}
uni.showToast({
title:i !== -1 ? '取消点赞成功' : '点赞成功',
icon:'none'
});
})
},
// 添加表情
addFace(item){
this.content += item;
},
// 开启关闭表情包面板
changeFaceModeal(){
uni.hideKeyboard();
setTimeout(()=>{
this.faceModal = !this.faceModal;
},100);
},
// 发送
send(){
console.log(this.reply_user);
let item = this.list[this.commentIndex];
$H.post('/moment/comment',{
id:item.moment_id,
content:this.content,
reply_id:this.reply_user ? this.reply_user.id : 0
}).then(res=>{
item.comments.push({
content:this.content,
user:{
id:this.user.id,
name:this.user.nickname || this.user.username
},
replay:this.reply_user ? this.reply : null
})
uni.showToast({
title:'评论成功',
icon:'none'
})
})
this.$refs.action.hide();
},
replyEvent(e){
this.content = '';
this.faceModal = false,
this.commentIndex = e.index,
this.reply_user = e.reply;
this.$refs.action.show();
},
// 选择发表朋友圈类型
clickRight(){
let list = [{
name:'图文',
key:'image'
},
{
name:'视频',
key:'video'
},
{
name:'文字',
key:'content'
}];
uni.showActionSheet({
itemList:list.map(v=>v.name),
success:res=>{
uni.navigateTo({
url: '../add-moment/add-moment?type='+list[res.tapIndex].key,
});
}
})
}
},
}
</script>
<style>
</style>
/pages/mail/user-base/user-base.vue
<template>
<view class="page">
<!-- 导航栏 -->
<free-nav-bar showBack :showRight="detail.friend" bgColor="bg-white">
<view slot="right">
<free-icon-button v-if="detail.friend"><text class="iconfont font-md"
@click="openAction"></text></free-icon-button>
</view>
</free-nav-bar>
<view class="px-3 py-4 flex align-center bg-white border-bottom">
<free-avatar :src="detail.avatar" size="120"></free-avatar>
<view class="flex flex-column ml-3 flex-1">
<view class="font-lg font-weight-bold flex justify-between">
<text class="font-lg font-weight-bold mb-1">{{detail.nickname}}</text>
<image v-if="detail.star" src="/static/images/star.png" style="width: 40rpx;height: 40rpx;"></image>
</view>
<text class="font-md text-light-muted mb-1">账号:{{detail.username}}</text>
<!-- <text class="font-md text-light-muted">地区:广东广州</text> -->
</view>
</view>
<free-list-item v-if="detail.friend" showRight :showLeftIcon="false" @click="navigate(tagPath)">
<view class="flex align-center">
<text class="font-md text-dark mr-3">标签</text>
<text class="font-md text-light-muted mr-2" v-for="(item,index) in detail.tags"
:key="index">{{item}}</text>
</view>
</free-list-item>
<free-divider></free-divider>
<free-list-item v-if="detail.friend" showRight :showLeftIcon="false" @click="openMoments">
<view class="flex align-center">
<text class="font-md text-dark mr-3">朋友圈</text>
<image src="/static/images/demo/cate_01.png" style="width: 90rpx; height: 90rpx;" class=" mr-2"></image>
<image src="/static/images/demo/cate_01.png" style="width: 90rpx; height: 90rpx;" class=" mr-2"></image>
<image src="/static/images/demo/cate_01.png" style="width: 90rpx; height: 90rpx;" class=" mr-2"></image>
</view>
</free-list-item>
<free-list-item title="更多信息" showRight :showLeftIcon="false"></free-list-item>
<free-divider></free-divider>
<view v-if="detail.friend" class="py-3 flex align-center justify-center bg-white" hover-class="bg-light" @click="doEvent">
<text class="iconfont text-primary mr-1" v-if="!detail.isBlack"></text>
<text class="font-md text-primary">{{detail.isblack ? '移除黑名单' : '发信息'}}</text>
</view>
<view v-else class="py-3 flex align-center justify-center bg-white" hover-class="bg-light"
@click="navigate(addFriend())">
<text class="font-md text-primary">添加好友</text>
</view>
<!-- 扩展菜单 -->
<free-popup ref="action" bottom transformOrigin="center bottom" maskColor>
<scroll-view style="height: 580rpx;" scroll-y="true" class="bg-white" :show-scrollbar="false">
<free-list-item v-for="(item,index) in actions" :key="index" :title="item.title" :showRight="false"
:border="false" @click="popupEvent(item)">
<text slot="icon" class="iconfont font-lg py-1">{{item.icon}}</text>
</free-list-item>
</scroll-view>
</free-popup>
</view>
</template>
<script>
import freeNavBar from '@/components/free-ui/free-nav-bar.vue';
import freeIconButton from '@/components/free-ui/free-icon-button.vue';
import freeChatItem from '@/components/free-ui/free-chat-item.vue';
import freePopup from '@/components/free-ui/free-popup.vue';
import freeListItem from '@/components/free-ui/free-list-item.vue';
import freeDivider from '@/components/free-ui/free-divider.vue';
import freeAvatar from '@/components/free-ui/free-avatar.vue';
import auth from '@/common/mixin/auth.js';
import $H from '@/common/free-lib/request.js';
export default {
mixins: [auth],
components: {
freeNavBar,
freeIconButton,
freeChatItem,
freePopup,
freeListItem,
freeDivider,
freeAvatar
},
data() {
return {
detail: {
id: 0,
username: '',
nickname: '',
avatar: '',
sex: '',
sign: '',
area: '',
friend: false,
lookhim: 1,
lookme: 1,
star: 0,
isblack: 0,
tags: []
},
}
},
onShow() {
this.getData();
},
onLoad(e) {
uni.$on('saveRemarkTag', (e) => {
this.detail.tagList = e.detail.tagList
this.nickname = e.nickname;
})
if (!e.user_id) {
return this.backToast();
}
this.detail.id = e.user_id;
// 获取当前用户资料
this.getData();
},
beforeDestroy() {
this.$refs.action.hide();
uni.$off('saveRemarkTag')
},
computed: {
tagPath() {
return "mail/user-remark-tag/user-remark-tag?params="+JSON.stringify({
user_id:this.detail.id,
nickname:this.detail.nickname,
tags:this.detail.tags ? this.detail.tags.join(',') : ''
})
},
actions() {
return [{
icon: "\ue6b3",
title: "设置备注和标签",
type: "navigate",
path: "mail/user-remark-tag/user-remark-tag?params="+JSON.stringify({
user_id:this.detail.id,
nickname:this.detail.nickname,
tags:this.detail.tags ? this.detail.tags.join(',') : ''
})
}, {
icon: "\ue613",
title: "把他推荐给朋友",
type: "navigate",
path: "chat/chat-list/chat-list?params="+encodeURIComponent(JSON.stringify({
type: "card",
data: this.detail.nickname || this.detail.username,
options: {
avatar: this.detail.avatar,
id: this.detail.id
}
}))
}, {
icon: "\ue6b0",
title: this.detail.star ? '取消星标好友' : "设为星标朋友",
type: "event",
event: "setStar"
}, {
icon: "\ue667",
title: "设置朋友圈和动态权限",
type: "navigate",
path: "mail/user-moments-auth/user-moments-auth?user_id="+this.detail.id+"¶ms="+JSON.stringify({
lookme:this.detail.lookme,
lookhim:this.detail.lookhim,
})
}, {
icon: "\ue638",
title: this.detail.isblack ? '移出黑名单' : "加入黑名单",
type: "event",
event: "setBlack"
}, {
icon: "\ue61c",
title: "投诉",
type: "navigate",
path: "mail/user-report/user-report?params="+JSON.stringify({
user_id:this.detail.id,
type:'user'
})
}, {
icon: "\ue638",
title: "删除",
type: "event",
event: "deleteItem"
}]
}
},
methods: {
addFriend() {
let obj = {
friend_id: this.detail.id,
nickname: this.detail.nickname,
lookme: typeof this.detail.lookme === 'number' ? this.detail.lookme : 1,
lookhim: typeof this.detail.lookhim === 'number' ? this.detail.lookhim : 1,
};
return 'mail/add-friend/add-friend?params=' + JSON.stringify(obj);
},
getData() {
$H.get('/friend/read/' + this.detail.id).then(res => {
if (!res) {
return this.backToast('该用户不存在');
}
this.detail = res;
console.log(res);
});
},
openAction() {
this.$refs.action.show()
},
navigate(url) {
console.log(url);
uni.navigateTo({
url: '/pages/' + url,
});
},
openMoments(){
uni.navigateTo({
url: '../../find/moments/moments?key=moment¶ms='+encodeURIComponent(JSON.stringify({
id:this.detail.id,
name:this.detail.nickname || this.detail.username,
avatar:this.detail.avatar
})),
})
},
// 操作菜单事件
popupEvent(e) {
if (!e.type) {
return;
}
setTimeout(() => {
// 关闭弹出层
this.$refs.action.hide()
}, 300)
switch (e.type) {
case 'navigate':
this.navigate(e.path);
break;
case 'event':
this[e.event](e);
break;
}
},
// 删除好友
deleteItem(){
uni.showModal({
title: '是否要删除好友?',
success: res => {
if(res.confirm){
$H.post('/friend/destroy',{friend_id:this.detail.id}).then(res=>{
uni.showToast({
title:'删除好友成功',
icon:'none'
});
uni.reLaunch({
url:'/pages/tabbar/index/index'
})
})
}
},
fail: () => {},
complete: () => {}
});
},
// 设为星标
setStar(e) {
let star = this.detail.star == 0 ? 1 : 0;
$H.post('/friend/setstar/' + this.detail.id, {
star
}).then(res => {
this.detail.star = star;
e.title = this.detail.star ? '取消标星好友' : '设为标星好友';
});
},
// 加入黑名单
setBlack(e) {
let msg = this.detail.isblack ? '移出黑名单' : '加入黑名单';
uni.showModal({
content: '是否要' + msg,
success: (res) => {
if (res.confirm) {
let isblack = this.detail.isblack == 0 ? 1:0
$H.post('/friend/setblack/' + this.detail.id, {
isblack
}).then(res => {
this.detail.isblack = isblack;
});
// this.detail.isBlack = !this.detail.isBlack;
// e.title = this.isBlack ? '移出黑名单' : '加入黑名单';
uni.showToast({
title: msg + '成功',
icon: 'none'
})
}
}
})
},
// 发送消息
doEvent(e){
if(this.detail.isblack){
return this.setBlack();
}
uni.navigateTo({
url:'../../chat/chat/chat?params='+encodeURIComponent(JSON.stringify({
id:this.detail.id,
name:this.detail.nickname ? this.detail.nickname : this.detail.username,
avatar:this.detail.avatar,
chat_type:'user'
}))
})
}
}
}
</script>
<style>
</style>
后台
app/controller/moment.js
'use strict';
const Controller = require('egg').Controller;
class MomentController extends Controller {
// 发布朋友圈
async create() {
const { ctx, app } = this;
let current_user_id = ctx.authUser.id;
// 参数验证
ctx.validate({
content: {
type: 'string',
required: false,
desc: '内容'
},
image: {
type: 'string',
required: false,
desc: '图片'
},
video: {
type: 'string',
required: false,
desc: '视频'
},
type: {
type: 'string',
required: true,
range: {
in: ['content', 'image', 'video']
},
desc: '朋友圈类型'
},
location: {
type: 'string',
required: false,
desc: '位置'
},
remind: {
type: 'string',
required: false,
defValue: "",
desc: '提醒谁看'
},
see: {
type: 'string',
required: false,
defValue: "all",
desc: '谁可以看'
}
});
let { content, image, video, type, location, remind, see } = ctx.request.body;
if (!ctx.request.body[type]) {
return ctx.apiFail(`${type} 不能为空`);
}
let moment = await app.model.Moment.create({
content, image, video, location, remind, see,
user_id: current_user_id
});
if (!moment) {
return ctx.apiFail('发布失败');
}
// 推送到好友的时间轴
this.toTimeline(moment);
ctx.apiSuccess('ok');
}
// 推送到好友的时间轴
async toTimeline(moment) {
const { ctx, app } = this;
let current_user_id = ctx.authUser.id;
// 获取当前用户所有好友
let friends = await app.model.Friend.findAll({
where: {
user_id: current_user_id,
isblack: 0
},
attributes: ['friend_id']
});
// 谁可以看
/**
all 全部人可看
only:1,2,3 指定人可见
except:1,2,3 谁不可看
none 仅自己可见
*/
let sees = moment.see.split(':');
let o = {
only: [],
except: []
}
let oType = sees[0];
if ((sees[0] === 'only' || sees[0] === 'except') && sees[1]) {
o[sees[0]] = (sees[1].split(',')).map(v => parseInt(v));
}
let addData = friends.filter(item => {
return oType === 'all' || (oType === 'only' && o.only.includes(item.friend_id)) || (oType === 'except' && !o.except.includes(item.friend_id));
});
addData = addData.map(item => {
return {
user_id: item.friend_id,
moment_id: moment.id,
own: 0
}
});
addData.push({
user_id: current_user_id,
moment_id: moment.id,
own: 1
});
// 推送到时间轴当中
await app.model.MomentTimeline.bulkCreate(addData);
// 消息推送
let message = {
avatar: ctx.authUser.avatar,
user_id: current_user_id,
type: "new"
}
addData.forEach(item => {
ctx.sendAndSaveMessage(item.user_id, message, 'moment');
});
// 提醒用户
if (moment.remind) {
let arr = moment.remind.split(',');
arr.forEach(user_id => {
ctx.sendAndSaveMessage(user_id, {
avatar: ctx.authUser.avatar,
user_id: current_user_id,
type: "remind"
}, 'moment');
});
}
}
// 点赞
async like() {
const { ctx, app } = this;
let current_user_id = ctx.authUser.id;
ctx.validate({
id: {
type: "int",
required: true,
desc: "朋友圈id"
}
});
let { id } = ctx.request.body;
let MomentTimeline = await app.model.MomentTimeline.findOne({
where: {
user_id: current_user_id,
moment_id: id
},
include: [{
model: app.model.Moment,
attributes: ['user_id'],
include: [{
model: app.model.MomentLike,
attributes: ['user_id'],
}]
}]
});
if (!MomentTimeline) {
return ctx.apiFail('朋友圈消息不存在');
}
let like = await app.model.MomentLike.findOne({
where: {
user_id: current_user_id,
moment_id: id
}
});
let message = {
avatar: ctx.authUser.avatar,
user_id: current_user_id,
type: "like"
}
if (like) {
await like.destroy();
ctx.apiSuccess(MomentTimeline.moment.moment_likes);
} else {
await app.model.MomentLike.create({
user_id: current_user_id,
moment_id: id
});
ctx.apiSuccess(MomentTimeline.moment.moment_likes);
}
// 通知作者
if (MomentTimeline.moment.user_id && MomentTimeline.moment.user_id !== current_user_id) {
ctx.sendAndSaveMessage(MomentTimeline.moment.user_id, message, 'moment');
}
// 通知相关人
MomentTimeline.moment.moment_likes.forEach(item => {
if (item.user_id !== current_user_id) {
ctx.sendAndSaveMessage(item.user_id, message, 'moment');
}
});
}
// 朋友圈评论
async comment() {
const { ctx, app } = this;
let current_user_id = ctx.authUser.id;
ctx.validate({
id: {
type: "int",
required: true,
desc: "朋友圈id"
},
content: {
type: "string",
required: true,
desc: "评论内容"
},
reply_id: {
type: "int",
required: true,
defValue: 0,
desc: "回复id"
}
});
let { id, content, reply_id } = ctx.request.body;
let MomentTimeline = await app.model.MomentTimeline.findOne({
where: {
user_id: current_user_id,
moment_id: id
},
include: [{
model: app.model.Moment,
attributes: ['user_id'],
include: [{
model: app.model.MomentLike,
attributes: ['user_id']
}]
}]
});
if (!MomentTimeline) {
return ctx.apiFail('朋友圈消息不存在');
}
let comment = await app.model.MomentComment.create({
user_id: current_user_id,
moment_id: id,
content,
reply_id
});
ctx.apiSuccess(comment);
let message = {
avatar: ctx.authUser.avatar,
user_id: current_user_id,
type: "comment"
}
// 通知作者
if (MomentTimeline.moment.user_id && MomentTimeline.moment.user_id !== current_user_id) {
ctx.sendAndSaveMessage(MomentTimeline.moment.user_id, message, 'moment');
}
// 通知相关人
MomentTimeline.moment.moment_likes.forEach(item => {
if (item.user_id !== current_user_id) {
ctx.sendAndSaveMessage(item.user_id, message, 'moment');
}
});
// 通知被回复人
if (reply_id > 0) {
let index = MomentTimeline.moment.moment_likes.findIndex(item => {
return item.user_id === reply_id
});
if (index === -1) {
ctx.sendAndSaveMessage(reply_id, message, 'moment');
}
}
}
// 朋友圈列表
async timeline() {
const { ctx, app } = this;
let current_user_id = ctx.authUser.id;
let page = ctx.params.page ? parseInt(ctx.params.page) : 1;
let limit = ctx.query.limit ? parseInt(ctx.query.limit) : 10;
let offset = (page - 1) * limit;
let rows = await app.model.MomentTimeline.findAll({
where: {
user_id: current_user_id
},
include: [{
model: app.model.Moment,
include: [{
model: app.model.User,
attributes: ['id', 'nickname', 'username', 'avatar']
}, {
model: app.model.MomentComment,
attributes: {
exclude: ['created_at', 'updated_at']
},
include: [{
model: app.model.User,
as: "momentCommentUser",
attributes: ['id', 'nickname', 'username']
}, {
model: app.model.User,
as: "momentCommentReply",
attributes: ['id', 'nickname', 'username']
}]
}, {
model: app.model.MomentLike,
attributes: ['user_id', 'moment_id'],
include: [{
model: app.model.User,
attributes: ['id', 'nickname', 'username']
}]
}]
}],
offset,
limit,
order: [
['id', 'DESC']
]
});
let friends = await app.model.Friend.findAll({
where: {
user_id: current_user_id,
lookhim: 1
},
attributes: ['friend_id']
});
console.log(friends);
let bfriends = await app.model.Friend.findAll({
where: {
friend_id: current_user_id,
lookme: 1
},
attributes: ['user_id']
});
friends = friends.map(item => item.friend_id);
bfriends = bfriends.map(item => item.user_id);
friends = friends.filter(item => bfriends.includes(item));
let res = [];
rows.forEach(item => {
if (friends.includes(item.moment.user_id) || item.moment.user_id === current_user_id) {
let comments = [];
item.moment.moment_comments.forEach(v => {
if (friends.includes(v.momentCommentUser.id) || v.momentCommentUser.id === current_user_id) {
comments.push({
content: v.content,
user: {
id: v.momentCommentUser.id,
name: v.momentCommentUser.nickname || v.momentCommentUser.username
},
reply: v.momentCommentReply ? {
id: v.momentCommentReply.id,
name: v.momentCommentReply.nickname || v.momentCommentReply.username
} : null
});
}
});
let likes = [];
item.moment.moment_likes.forEach(v => {
if (friends.includes(v.user.id) || v.user.id === current_user_id) {
likes.push({
id: v.user.id,
name: v.user.nickname || v.user.username
});
}
});
res.push({
id: item.id,
user_id: item.moment.user_id,
user_name: item.moment.user.nickname || item.moment.user.username,
avatar: item.moment.user.avatar,
moment_id: item.moment_id,
content: item.moment.content,
image: item.moment.image ? item.moment.image.split(',') : [],
video: item.moment.video ? JSON.parse(item.moment.video) : null,
location: item.moment.location,
own: item.own,
created_at: item.created_at,
comments,
likes
});
}
});
ctx.apiSuccess(res);
}
// 某个用户的朋友圈列表
async list() {
const { ctx, app } = this;
let current_user_id = ctx.authUser.id;
let page = ctx.params.page ? parseInt(ctx.params.page) : 1;
let limit = ctx.query.limit ? parseInt(ctx.query.limit) : 10;
let offset = (page - 1) * limit;
let user_id = ctx.query.user_id ? parseInt(ctx.query.user_id) : 0;
// ctx.validate({
// user_id: {
// type: "int",
// required: false,
// defValue: current_user_id,
// desc: "用户id"
// }
// });
let lookIds = [];
if (!user_id) {
// 本人
user_id = current_user_id;
lookIds = false;
} else {
// 验证我是否具备权限 是否是朋友,是否拉黑,是否删除
let f = await app.model.User.findOne({
where: {
id: user_id,
status: 1
},
attributes: ['id', 'nickname', 'username', 'avatar'],
include: [{
model: app.model.Friend,
as: "bfriends",
where: {
user_id: current_user_id
},
attributes: ['lookhim', 'isblack']
}, {
model: app.model.Friend,
as: "friends",
where: {
friend_id: current_user_id
},
attributes: ['lookme', 'isblack']
}]
});
// 用户是否存在
if (!f) {
return ctx.apiFail('用户不存在或已被禁用');
}
// 是否是好友关系
if (!f.bfriends.length || !f.friends.length) {
return ctx.apiSuccess([]);
}
// 不可见
if (f.bfriends[0].isblack || f.friends[0].isblack || !f.bfriends[0].lookhim || !f.friends[0].lookme) {
return ctx.apiSuccess([]);
}
// 获取当前用户所有好友(查找共同好友)
let friends = await app.model.Friend.findAll({
where: {
user_id: current_user_id,
isblack: 0
},
attributes: ['friend_id']
});
lookIds = friends.map(item => item.friend_id);
}
let rows = await app.model.Moment.findAll({
where: {
user_id
},
include: [{
model: app.model.User,
attributes: ['id', 'nickname', 'username', 'avatar']
}, {
model: app.model.MomentComment,
attributes: {
exclude: ['created_at', 'updated_at']
},
include: [{
model: app.model.User,
as: "momentCommentUser",
attributes: ['id', 'nickname', 'username']
}, {
model: app.model.User,
as: "momentCommentReply",
attributes: ['id', 'nickname', 'username']
}]
}, {
model: app.model.MomentLike,
attributes: ['user_id', 'moment_id'],
include: [{
model: app.model.User,
attributes: ['id', 'nickname', 'username']
}]
}],
offset,
limit,
order: [
['id', 'DESC']
]
});
let res = [];
rows.forEach(item => {
let comments = [];
item.moment_comments.forEach(v => {
if (!lookIds || lookIds.includes(v.momentCommentUser.id) || v.momentCommentUser.id === current_user_id) {
comments.push({
content: v.content,
user: {
id: v.momentCommentUser.id,
name: v.momentCommentUser.nickname || v.momentCommentUser.username
},
reply: v.momentCommentReply ? {
id: v.momentCommentReply.id,
name: v.momentCommentReply.nickname || v.momentCommentReply.username
} : null
})
}
});
let likes = [];
item.moment_likes.forEach(v => {
if (!lookIds || lookIds.includes(v.user.id) || v.user.id === current_user_id) {
likes.push({
id: v.user.id,
name: v.user.nickname || v.user.username
});
}
});
res.push({
user_id: item.user_id,
user_name: item.user.nickname || item.user.username,
avatar: item.user.avatar,
moment_id: item.id,
content: item.content,
image: item.image ? item.image.split(',') : [],
video: item.video ? JSON.parse(item.video) : null,
location: item.location,
own: 1,
created_at: item.created_at,
comments,
likes
});
});
ctx.apiSuccess(res);
}
}
module.exports = MomentController;
感谢大家观看,我们下次见