zoukankan      html  css  js  c++  java
  • day109:MoFang:好友列表显示&添加好友页面初始化&添加好友后端接口

    目录

    1.好友列表

    2.添加好友-前端

    3.服务端提供添加好友的后端接口

    今日内容流程图

    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>
    根据不同的关系状态提供对应的操作菜单
  • 相关阅读:
    cpp 二进制文件读写
    中文词频统计
    文件方式实现完整的英文词频统计实例
    组合数据类型练习,英文词频统计实例上
    英文词频统计预备,组合数据类型练习
    凯撒密码、GDP格式化输出、99乘法表
    字符串基本操作
    条件、循环、函数定义 练习
    turtle库基础练习
    Python基础练习
  • 原文地址:https://www.cnblogs.com/libolun/p/14148400.html
Copyright © 2011-2022 走看看