day109:MoFang:好友列表显示&添加好友页面初始化&添加好友后端接口
目录
1.好友列表
1.在用户中心页面添加好友列表点击入口
html/user.html,用户中心添加好友列表点击入口,代码:

<div class="menu">
<div class="item" @click="open_friend_list">
<span class="title">我的好友</span>
<span class="value">查看</span>
</div>
<div class="item">
<span class="title">我的主页</span>
<span class="value">查看</span>
</div>
<div class="item">
<span class="title">任务列表</span>
<span class="value">75%</span>
</div>
<div class="item">
<span class="title">收益明细</span>
<span class="value">查看</span>
</div>
<div class="item">
<span class="title">实名认证</span>
<span class="value">未认证</span>
</div>
</ul>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
nickname:"",
avatar:"",
prev:{name:"",url:"",params:{}},
current:{name:"user",url:"user.html",params:{}},
}
},
created(){
this.get_user_info();
this.change_avatar();
},
methods:{
open_friend_list(){
// ***进入好友列表***
this.game.goFrame("friends","friends.html", this.current,{},{},true);
}
}
});
}
</script>
</body>
</html>
在用户中心页面添加好友列表点击入口
2.好友列表主页面初始化:friends.html
html/friends.html,好友列表主页面,代码:

<!DOCTYPE html>
<html>
<head>
<title>用户中心</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/friends_bg.png">
</div>
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="add_friend_btn" @click="add_friend">
<img src="../static/images/add_friend.png" alt="">
</div>
<div class="friends_list">
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
friends:[],
prev:{name:"",url:"",params:{}},
current:{name:"friends",url:"friends.html",params:{}},
}
},
methods:{
add_friend(){
// 添加好友 },
goto_home(){
// 退出当前页面
this.game.outFrame("friends","friends.html", this.current);
},
}
});
}
</script>
</body>
</html>
好友列表主页面初始化:friends.html
3.好友列表主页面CSS样式
css/main.css,样式代码:

.add_friend_btn {
position: absolute;
top: 12rem;
left: 3.6rem;
width: 26rem;
height: 6rem;
}
.add_friend_btn img{
box-shadow: 2px 2px 5px rgba(9,9,9,0.1);
}
好友列表主页面CSS样式
4.在打开好友列表页面的同时,也打开好友列表数据页面
1.user.html
在user.html设置在打开好友列表页面的同时,也打开好友列表数据页面
methods:{
open_friend_list(){
// 进入好友列表
this.game.goFrame("friends","friends.html", this.current,{},{},true);
this.game.goFrame("friend_list","friend_list.html", this.current,{
x: 0,
y: 194,
w: 'auto',
h: 'auto',
});
}
}
});
}
2.好友数据列表页面初始化:friend_list.html
接下来,添加html/friend_list.html,页面代码:

<!DOCTYPE html>
<html>
<head>
<title>用户中心</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="friends_list">
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="fruit">果子:9,999.00</p>
</div>
<div class="behavior pick">摘</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="fruit">果子:9,999.00</p>
</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="fruit">果子:9,999.00</p>
</div>
<div class="behavior protect">护</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="fruit">果子:9,999.00</p>
</div>
<div class="behavior pick">摘</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="fruit">果子:9,999.00</p>
</div>
<div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
friends:[],
page: 1,
prev:{name:"",url:"",params:{}},
current:{name:"friend_list",url:"friend_list.html",params:{}},
}
},
created(){
this.get_friends();
},
methods:{
get_friends(){ },
goto_home(){
// 退出当前页面
this.game.outFrame("friend_list","friend_list.html", this.current);
},
}
});
}
</script>
</body>
</html>
好友数据列表页面初始化:friend_list.html
3.好友数据列表页面CSS样式
css/main.css,样式代码:

.friends_list .avatar{
width: 6.39rem;
height: 6.39rem;
position: relative;
}
.friends_list .avatar_bf{
position: absolute;
z-index: 1;
margin: auto;
width: 4.56rem;
height: 4.56rem;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.friends_list .user_avatar{
position: absolute;
z-index: 1;
width: 4.56rem;
height: 4.56rem;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
border-radius: 1rem;
}
.friends_list .avatar_border{
position: absolute;
z-index: 1;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 6.1rem;
height: 6.1rem;
}
.friends_list{
position: absolute;
top: 0rem;
left: 3.6rem;
}
.friends_list .item{
position: relative;
background-color: rgba(196,81,9,0.1);
border-radius: 4px;
height: 7rem;
width: 25.8rem;
margin-bottom: 1rem;
box-shadow: 2px 2px 5px rgba(9,9,9,0.1);
}
.friends_list .item .avatar{
position: absolute;
left: 1rem;
top: 0;
bottom: 0;
margin: auto;
}
.friends_list .item .info{
position: absolute;
left: 8rem;
top: 2rem;
color: #fff;
width: 10rem;
}
.friends_list .item .behavior{
position: absolute;
left: 16rem;
font-size: 1.5rem;
text-align: center;
line-height: 4rem;
height: 4rem;
width: 4rem;
color: #fff;
top: 0;
bottom: 0;
margin: auto;
box-shadow: 2px 2px 5px #333333;
}
.friends_list .item .pick{
background: #336633;
border-radius: 50%;
}
.friends_list .item .protect{
background: #990000;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 30px;
border-bottom-right-radius: 30px;
}
.friends_list .item .goto{
position: absolute;
left: 23rem;
top: 0;
bottom: 0;
margin: auto;
width: 0.96rem;
height: 1.8rem;
}
好友数据列表页面CSS样式
4.为好友数据列表页面添加下拉效果
添加下拉新效果,html/friend_list.html,代码:
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
friends:[],
page: 1,
prev:{name:"",url:"",params:{}},
current:{name:"friend_list",url:"friend_list.html",params:{}},
}
},
created(){
this.get_friends();
},
methods:{
get_friends(){
// ***通过下拉请求获取当前用户的好友列表***
api.setRefreshHeaderInfo({
loadingImg: 'widget://image/refresh.png',
bgColor: null,
textColor: '#fff',
textDown: '下拉刷新...',
textUp: '松开刷新...'
}, (ret, err)=>{
//在这里从服务器加载数据,加载完成后调用api.refreshHeaderLoadDone()方法恢复组件到默认状态
api.refreshHeaderLoadDone();
});
}, }
});
}
</script>
</body>
</html>
5.关闭好友列表页的时候,同时关闭好友数据列表页面
关闭好友列表页时,需要同时关闭2个frame页面。所以需要在html/friends.html关闭时,通知friend_list.html关闭。
1.friends.html发起退出通知
html/friends.html代码:

<!DOCTYPE html>
<html>
<head>
<title>好友列表</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/friends_bg.png">
</div>
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="add_friend_btn" @click="add_friend">
<img src="../static/images/add_friends.png" alt="">
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
friends:[],
prev:{name:"",url:"",params:{}},
current:{name:"friends",url:"friends.html",params:{}},
}
},
created(){
// 打开好友列表数据页面
this.game.goFrame("friend_list","friend_list.html",this.current,{
x: 0,
y: 190,
w: 'auto',
h: 'auto',
},null,true);
},
methods:{
add_friend(){
// 添加好友 },
goto_home(){
// ***好友列表主页面friends.html发起通知,告知friend_list.html退出***
api.sendEvent({
name: 'out_page_to_user',
extra: {
key1: 'user',
key2: 'user.html'
}
}); // ***退出当前页面***
setTimeout(()=>{
this.game.outFrame("friends","friends.html", this.current);
},100);
},
}
});
}
</script>
</body>
</html>
friends.html发起退出通知
2.friend_list.html监听通知
html/friend_list.html,代码:

<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
friends:[],
page: 1,
prev:{name:"",url:"",params:{}},
current:{name:"friend_list",url:"friend_list.html",params:{}},
}
},
created(){
this.get_friends();
this.page_out_listener();
},
methods:{
page_out_listener(){
// ****监听什么时候需要退出当前页面****
api.addEventListener({
name: 'out_page_to_user'
}, (ret, err)=>{
this.goto_home();
});
},
goto_home(){
// 退出当前页面
this.game.outFrame("friend_list","friend_list.html", this.current);
},
}
});
}
</script>
</body>
</html>
friend_list.html监听通知
2.添加好友-前端
1.点击添加好友按钮,跳转到添加好友界面
html/friends.html,代码:

<script>
new Vue({
el:"#app",
data(){
return {
friends:[],
prev:{name:"",url:"",params:{}},
current:{name:"friends",url:"friends.html",params:{}},
}
},
methods:{
add_friend(){
// ***添加好友***
this.game.goFrame("add_friend","add_friend.html", this.current,null,{
type:"push", //动画类型(详见动画类型常量)
subType:"from_top", //动画子类型(详见动画子类型常量)
duration:300 //动画过渡时间,默认300毫秒
});
},
goto_home(){
// 退出当前页面
api.sendEvent({
name: 'friends_out_page',
extra: {
name: 'user',
url: 'user.html'
}
});
this.game.outFrame("friends","friends.html", this.current);
},
}
});
}
</script>
</body>
</html>
点击添加按钮,跳转到添加好友界面
2.添加好友页面初始化页面:add_friend.html
html/add_friend.html,添加好友,页面代码:

<!DOCTYPE html>
<html>
<head>
<title>添加好友</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar update_nickname add_friend" id="app">
<div class="box">
<p class="title">添加好友</p>
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<input class="nickname" type="text" v-model="account" placeholder="输入昵称/手机/邮箱/魔方账号....">
</div>
<div class="friends_list">
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="time">刚刚搜索</p>
</div>
<div class="status">添加</div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="time">3小时前</p>
</div>
<div class="status" @click="change_status">等待通过</div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="time">1天前</p>
</div>
<div class="status">已通过</div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="time">7天前</p>
</div>
<div class="status">已超时</div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="time">7天前</p>
</div>
<div class="status">已拒绝</div>
</div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
account:"",
prev:{name:"",url:"",params:{}},
current:{name:"add_friend",url:"add_friend.html",params:{}},
}
},
methods:{
close_frame(){
this.game.outFrame("add_friend");
},
add_friend_commit(){
// 提交搜索信息 },
change_status(){
// 状态修改
}
}
});
}
</script>
</body>
</html>
添加好友页面初始化:add_friend.html
3.添加好友界面CSS样式
css/main.css,代码:

input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder{
color: #fff;
}
.add_friend .box{
top: 4rem;
height: 55.56rem;
background: url("../images/long_bg1.png") no-repeat 0 0;
background-size: 100%;
}
.add_friend .nickname{
margin: 4rem 4.6rem 2rem;
width: 19rem;
height: 4rem;
line-height: 4rem;
background-color: #cc9966;
outline: none;
border: 1px solid #330000;
text-align: center;
font-size: 1rem;
color: #ffffcc;
} .add_friend .friends_list{
position: absolute;
top: 15rem;
left: 3.6rem;
}
.add_friend .friends_list .item{
position: relative;
margin-left: 1rem;
background-color: rgba(196,81,9,0.1);
border-radius: 4px;
height: 4rem;
width: 19rem;
margin-bottom: 1rem;
box-shadow: 2px 2px 5px rgba(9,9,9,0.1);
}
.add_friend .friends_list .avatar{
width: 3.84rem;
height: 3.84rem;
position: absolute;
left: 1rem;
} .add_friend .friends_list .avatar_bf{
position: absolute;
z-index: 1;
margin: auto;
width: 2.74rem;
height: 2.74rem;
top: 0;
bottom: 0;
left: 0;
right: 0;
} .add_friend .friends_list .user_avatar{
position: absolute;
z-index: 1;
width: 2.74rem;
height: 2.74rem;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
border-radius: 1rem;
}
.add_friend .friends_list .avatar_border{
position: absolute;
z-index: 1;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 3.66rem;
height: 3.66rem;
}
.add_friend .friends_list .item .info{
top: 0.6rem;
left: 6rem;
}
.add_friend .friends_list .item .time{
font-size: 0.6rem;
}
.friends_list .item .status{
position: absolute;
left: 12rem;
top: 1.2rem;
width: 8rem;
text-align: center;
height: 2rem;
color: #fff;
}
添加好友页面CSS样式
3.服务端提供添加好友的后端接口
1.模型创建
user/models.py,代码:
class UserRelation(BaseModel):
"""用户关系"""
__tablename__ = "mf_user_relation"
relration_chioce = (
(1,"已申请"),
(2,"已通过"),
(3,"已超时"),
(4,"已拒绝"),
(5,"已取消"),
(6,"已关注"),
(7,"取消关注"),
(8,"拉黑"), # 正向拉黑
(9,"拉黑"), # 反向拉黑
(10,"取消拉黑")
)
send_user = db.Column(db.Integer, comment="用户ID1") # 主动构建关系的用户
receive_user = db.Column(db.Integer, comment="用户ID2") # 接受关系请求的用户
'''
创建方式的类型
查找 1.手机 2.账号 3.邮箱 3.昵称
社交 3.群聊
推荐 4.同城推荐 5. 二维码邀请注册
'''
relation_type = db.Column(db.Integer, default=0, comment="构建关系类型")
# 关系的状态 status = db.Column(db.Integer, default=0, comment="关系状态") def __repr__(self):
return "用户%s通过%s对%s进行了%s操作" % (self.send_user,self.relation_type, self.receive_user,self.status)
2.前端在输入框输入信息:触发搜索用户信息事件:search_user()

<!DOCTYPE html>
<html>
<head>
<title>添加好友</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar update_nickname add_friend" id="app">
<div class="box">
<p class="title">添加好友</p>
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<!-- v-model=account -->
<input class="nickname" type="text" v-model="account" placeholder="输入昵称/手机/邮箱/魔方账号....">
</div>
<div class="friends_list">
<div class="item" v-for="user in search_user_list">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" :src="avatar_url(user.avatar)" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">{{user.nickname}}</p>
<p class="time">刚刚搜索</p>
</div>
<div class="status">添加</div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">陈二狗子</p>
<p class="time">3小时前</p>
</div>
<div class="status" @click="change_status">等待通过</div>
</div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
search_user_list:[], // 搜索出的用户列表
search_timer:"", // 输入框内容不变的持续时间
account:"", // 用户在输入框输入的内容
prev:{name:"",url:"",params:{}},
current:{name:"add_friend",url:"add_friend.html",params:{}},
}
},
watch:{
// ***监听输入框的内容***
account(){
clearTimeout(this.search_timer);
if(this.account.length>0){
this.search_timer = setTimeout(()=>{
// 2s内内容不发生改变,触发search_user方法
this.search_user();
},2000);
}else{
// 如果用户没有在输入框输入任何内容,那搜索用户列表为空
this.search_user_list = [];
}
}
},
methods:{
// 获取用户头像对应的前端url
avatar_url(avatar){
var token = this.game.get("access_token") || this.game.fget("access_token");
return `${this.settings.avatar_url}?sign=${avatar}&token=${token}`;
},
search_user(){
// ***搜索用户**
var token = this.game.get("access_token") || this.game.fget("access_token");
// 查看token是否存在
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
// 查看token是否过期
this.game.checkout(this, token, (new_access_token)=>{
if(!new_access_token){
this.game.print(new_access_token);
return ;
}
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.user.relation",
"params": {
"account": this.account, // ***将输入内容发送给后端***
}
},{
headers:{
Authorization: "jwt " + new_access_token,
}
}).then(response=>{
this.game.print(response.data.result);
if(parseInt(response.data.result.errno)==1000){
this.search_user_list = response.data.result.user_list;
}else if(parseInt(response.data.result.errno) == 1008){
this.search_user_list = [];
}else{
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
}); });
},
close_frame(){
this.game.outFrame("add_friend");
},
add_friend_commit(){
// 提交搜索信息 },
change_status(){
// 状态修改
}
}
});
}
</script>
</body>
</html>
前端在输入框输入信息,触发搜索用户信息事件:search_user()
3.搜索用户信息后端接口:User.user.relation
服务端提供用户搜索功能的视图代码,user/views.py:
from sqlalchemy import or_
from .marshmallow import UserSearchInfoSchema as usis
@jsonrpc.method("User.user.relation")
@jwt_required # 验证jwt
def user_relation(account):
"""搜索用户信息""" # 1.判断用户是否存在.
current_user_id = get_jwt_identity()
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
} # 2. 识别搜索用户
'''根据手机号/用户名/昵称/邮箱 搜索用户'''
receive_user_list = User.query.filter( or_(
User.mobile == account,
User.name == account,
User.nickname.contains(account),
User.email==account
) ).all() # 3.如果搜索不到任何用户,则提示搜索的用户不存在
if len(receive_user_list) < 1:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.receive_user_not_exists,
}
# 4.对用户搜索信息进行序列化
marshmallow = usis(many=True)
user_list = marshmallow.dump(receive_user_list) return {
"errno": status.CODE_OK,
"errmsg": message.ok,
"user_list": user_list
}
4.用户搜索信息序列化器
marshmallow.py,代码:
class UserSearchInfoSchema(SQLAlchemyAutoSchema):
"""用户搜索信息返回"""
id = auto_field()
nickname = auto_field()
avatar = auto_field() class Meta:
model = User
include_fk = True
include_relationships = True
fields = ["id","nickname","avatar"]
sql_session = db.session
在上面服务端接口提供的数据中,增加双方关系状态信息.
users/marshmallow.py,代码:
from sqlalchemy import or_,and_
from .models import UserRelation
class UserSearchInfoSchema(SQLAlchemyAutoSchema):
"""用户搜索信息返回"""
id = auto_field()
nickname = auto_field()
avatar = auto_field()
status = fields.String(dump_only=True) # 在序列化器中添加双方状态信息 @post_dump()
def status_relation(self, data, **kwargs):
# ***查询主动用户和被动用户存在的关系***
relaionship = UserRelation.query.filter(
or_(
and_(UserRelation.send_user==self.context["user_id"], UserRelation.receive_user==data["id"]),
and_(UserRelation.receive_user==self.context["user_id"], UserRelation.send_user==data["id"]),
)
).first()
print(relaionship) # 用户3通过None对4进行了1操作 # ***如果二者之间存在关系***
if relaionship is not None:
tuple_data = UserRelation.relration_chioce[relaionship.status-1]
list_data = list(tuple_data)
list_data.append(relaionship.send_user)
print(list_data)
data["status"] = list_data
else:
data["status"] = (0,"添加",self.context["user_id"])
return data class Meta:
model = User
include_fk = True
include_relationships = True
fields = ["id","nickname","avatar","status"]
sql_session = db.session
5.前端根据不同的关系状态,提供对应的操作菜单
客户端根据不同的关系状态,提供对应的操作菜单,add_friend.html代码:

<!DOCTYPE html>
<html>
<head>
<title>添加好友</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar update_nickname add_friend" id="app">
<div class="box">
<p class="title">添加好友</p>
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<input class="nickname" type="text" v-model="account" placeholder="输入昵称/手机/邮箱/魔方账号....">
</div>
<div class="friends_list">
<div class="item" v-if="user.status[0]!=9" v-for="user in search_user_list">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" :src="avatar_url(user.avatar)" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">{{user.nickname}}</p>
<p class="time">刚刚搜索</p>
</div>
<div class="status" @click="change_relation(user.id,user.status)">{{user.status[1]}}</div>
</div>
<div class="item">
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<div class="info">
<p class="username">长昵称都很好</p>
<p class="time">3小时前</p>
</div>
<div class="status">等待通过</div>
</div> </div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
user_id: "", // 当前登陆用户Id
search_user_list:[],
search_timer:"",
account:"",
prev:{name:"",url:"",params:{}},
current:{name:"add_friend",url:"add_friend.html",params:{}},
}
},
watch:{
account(){
clearTimeout(this.search_timer);
if(this.account.length>0){
this.search_timer = setTimeout(()=>{
this.search_user();
},2000);
}else{
this.search_user_list = [];
}
}
},
created(){
this.user_id = this.game.get("user_id") || this.game.fget("user_id");
},
methods:{
avatar_url(avatar){
var token = this.game.get("access_token") || this.game.fget("access_token");
return `${this.settings.avatar_url}?sign=${avatar}&token=${token}`;
},
search_user(){
// 搜素用户
var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
this.game.checkout(this, token, (new_access_token)=>{
if(!new_access_token){
this.game.print(new_access_token);
return ;
}
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.user.relation",
"params": {
"account": this.account,
}
},{
headers:{
Authorization: "jwt " + new_access_token,
}
}).then(response=>{
this.game.print(response.data.result);
if(parseInt(response.data.result.errno)==1000){
this.search_user_list = response.data.result.user_list;
}else if(parseInt(response.data.result.errno) == 1008){
this.search_user_list = [];
}else{
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
}); });
},
close_frame(){
this.game.outFrame("add_friend");
},
add_friend_commit(){
// 提交搜索信息 },
change_relation(user_id,status){
// ***状态修改***
this.game.print(user_id);
todo = [];
if(status[0] == 0){
// 未添加
todo.push("添加对方为好友");
}else if(status[0]==1){
// 已添加
todo.push("撤回添加好友操作");
}else if(status[0]==2){
// 好友关系
return;
}else if(status[0]==3){
// 已超时
todo.push("重新发起申请好友");
}else if(status[0]==4){
// 已拒绝
todo.push("重新发起申请好友");
}else if(status[0]==5){
// 已取消
todo.push("重新发起申请好友");
} if(status[0]==6){
// 已关注
todo.push("发起申请好友");
todo.push("取消关注");
}else if(status[0]==7){
todo.push("发起申请好友");
todo.push("关注");
}else{
todo.push("关注");
} if(status[0]==8){
// 已拉黑
todo.push("取消拉黑");
}else{
todo.push("拉黑");
} api.actionSheet({
title: '操作',
buttons: todo
}, (ret, err)=>{
if(status[0] == 0 && ret.buttonIndex == 1 ){
// 申请添加好友
this.game.print(status[0]);
this.game.print(ret.buttonIndex);
}
}); }
}
});
}
</script>
</body>
</html>
根据不同的关系状态提供对应的操作菜单
day109:MoFang:好友列表显示&添加好友页面初始化&添加好友后端接口的更多相关文章
- day105:Mofang:设置页面初始化&更新头像/上传头像&设置页面显示用户基本信息
目录 1.设置页面初始化 2.更新头像 1.点击头像进入更新头像界面 2.更新头像页面初始化 3.更新头像页面CSS样式 4.头像上传来源选择:相册/相机 5.调用api提供的本地接口从相册/相机提取 ...
- 小强的HTML5移动开发之路(50)——jquerymobile页面初始化过程
为了方便说明和更加直观的展示jquerymobile的页面初始化过程以及各个事件的触发过程,我绘制了一幅流程图: 图中用红色框圈起来的是界面中的事件,測试代码例如以下: <!DOCTYPE ht ...
- angluarjs中页面初始化的时候会出现语法{{}}在页面中问题
angluarjs中页面初始化的时候会出现语法{{}}在页面中问题,也即是页面闪烁问题.出现这个的原因是:由于页面或者组件需要渲染加载数据,浏览器和angluarjs渲染页面需要消耗一定的时间,虽然这 ...
- 页面初始化的js函数要放在最最最最最最最前边!否则没效果
简单说一下这个情况,html的页面的各部分都是动态渲染的,所以头部的某些个样式调用函数需要在页面初始化的时候被加载,这个我也是知道的,结果后边代码敲着敲着,就把这个事儿给忘了,然后启动项目的时候,页面 ...
- ios 上浏览器返回上一页不会刷新页面问题,页面初始化的方法不执行
https://blog.csdn.net/yang450712123/article/details/79276102 https://blog.csdn.net/Chengbin_Huang/ar ...
- Sword框架解析——知识采集流程页面初始化
Sword框架解析——知识采集流程页面初始化 Sword框架解析知识采集流程页面初始化 问题解答流程采集新增页面初始化 1后台t_xt_gnzy表和BLH类 2BLH类的写法前台目录树代码 3登录系统 ...
- 解决页面初始化vue加载代码问题
<style type="text/css"> /* 解决页面初始化vue加载代码问题 */ [v-cloak] { display: none; } </sty ...
- 十二、js去掉空格_比较字符长度_中英文判断_页面初始化_简体字与繁字体判断
1.去掉字符串前后所有空格 function trimBlank(str){ return str.replace(/(^\s*)|(\s*$)/g, ""); } 2.字符串长度 ...
- vue页面初始化
HTML: <div id="app"> <input type="" class="app" v-model=" ...
随机推荐
- 新鲜出炉!春招-面试-阿里钉钉、头条广告,美团面经分享,看我如何拿下offer!
之前给大家分享了一个朋友在字节面试的面试经历和拿到offer的过程,过程也算是比较精彩了,感兴趣的朋友可以去翻翻之前的那篇文章.话不多说重点来啦,一直有人发私信问我有没有其他大厂的面经分享啊,我也是联 ...
- linux常见目录
- CentOS7.X 下安装MySQL8.0(附文件)
这是64位的安装包.如果需要32位的可以去官网下载哦.步骤一样 1 获取安装资源包 mysql-8.0.18-1.el7.x86_64.rpm-bundle.tar 链接: https://pan.b ...
- IPSec传输模式/隧道模式下ESP报文的装包与拆包过程
IPSec协议:IPsec将IP数据包的内容先加密再传输,即便中途被截获,由于缺乏解密数据包所必要的密钥,攻击者也无法获取里面的内容. 传输模式和隧道模式:IPsec对数据进行加密的方式有两种:传输模 ...
- JDK阅读之Enum
JDK学习之Enum enum的使用 在没有enum之前如果想要定义一些常量,就会采用如下的方式 假设要定义四个常量表示不同的季节 public class SeasonWithoutEnum { p ...
- Android自带图标库
Java Usage example: myMenuItem.setIcon(android.R.drawable.ic_menu_save); Resource Usage example: and ...
- 使用 Zuul 聚合多个微服务的 Swagger 文档
在 Spring Boot 中集成 Swagger 可参考之前的文章:Spring Boot 2 集成 Swagger, 在各个微服务中的配置与之相同:本文仅介绍在 Zuul 中的配置 在 Zuul ...
- day6(短信验证接口)
1.注册容联云账号 1.1注册账号 https://www.yuntongxun.com/user/login 1.2登录即可看到开发者账号信息 1.3 添加测试账号 2.使用容联云发送代码测试 ' ...
- 大厂是如何用DevCloud流水线实现自动化部署Web应用的?
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师. 官方网站:devui.design Ng组件库:ng-devui(欢 ...
- 第7.7节 案例详解:Python类继承机制
本节实现一个类继承的小程序,下面一边结合代码一边介绍相关继承的知识.例子以车.汽车为例,车为父类.汽车为子类. 一. 定义父类Vehicle class Vehicle(): def __ ...