Vue项目四 头部右侧下拉表单功能的实现

下拉菜单功能的实现

下拉表单主要实现的是修改密码和退出系统功能。



一、修改密码功能的实现

需求是用户在输入原密码后,在输入框失去焦点后,系统对密码的正确性进行校验。并且用户在输入新密码和确认密码时进行二次校验。
修改密码界面

1.1后台添加校验密码接口

校验密码是用来验证原密码的正确性。我们需要查找到用户密码和用户ID,由于要对数据进行处理,所以采用post方法。
router.js添加接口

//校验密码是否正确
router.post("/user/pwd",function (req,res) {
    var body = req.body;
    User.findOne({
       //由于数据存储的时_id所以这里使用_id
        _id:body.userId,
        password:body.password
    },function (err,data) {
        if(err){
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "server error"
            })
        }
        if(!data){
            return res.status(200).json({
                code: 4000,
                flag: false,
                message: "密码不正确"
            })
        }
        return res.status(200).json({
            "code": 2000,
            "flag": true,
            "message": "密码正确"
        })
    })
});

1.2后端添加修改密码接口

修改密码是查找用户ID,对查找到的用户data中的密码(password)进行修改。修改数据采用put。

//修改密码
router.put('/user/pwd',function (req,res) {
    var id = req.body.userId;
    console.log(req.body);
    User.findOne({
        _id:id
    },function (err,data) {
        if(err){
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "server error"
            })
        }
        if(!data){
            return res.status(200).json({
                code: 4000,
                flag: false,
                message: "密码不正确"
            })
        }
        data.password = req.body.password;
        User.findByIdAndUpdate(id,data,function (err) {
            if(err){
                return res.status(500).json({
                    code: 3000,
                    flag: false,
                    message: "修改密码失败"
                })
            }
            return res.status(200).json({
                "code": 2000,
                "flag": true,
                "message": "修改密码成功"
            })
        })
    })
});

1.3 前端api配置抵用接口

这里新建password.js文件用来发送前台请求和获取后台响应数据。
password.js

import request from "@/utils/request.js"
export default {
    checkPwd(userId,password){
        return request ({
            url :"/user/pwd",
            method: "post",
            data:{
                userId,
                password
            }
        })
    },
    // 修改密码请求
    updatePwd(userId,password){
        return request({
            url : "/user/pwd",
            method:"put",
            data:{
                userId,
                password
            }
        })
    }
}

二、实现前端密码组件布局

2.1 前端AppHeader组件页面的实现

自定义校验规则
对话框弹出
这里使用了对话框弹出和自定义校验两个组件库。

    <!-- 修改密码弹出框设置 -->
    <el-dialog title="修改密码" :visible.sync="dialogFormVisible" width="500px">
      <el-form
        :model="ruleForm"
        status-icon
        :rules="rules"
        ref="ruleForm"
        label-width="100px"
        style="width: 400px"
      >
        <el-form-item label="原密码" prop="oldPass">
          <el-input type="password" v-model="ruleForm.oldPass"></el-input>
        </el-form-item>
        <el-form-item label="新密码" prop="pass">
          <el-input type="password" v-model="ruleForm.pass"></el-input>
        </el-form-item>
        <el-form-item label="确认密码" prop="checkPass">
          <el-input type="password" v-model="ruleForm.checkPass"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm('ruleForm')"
            >提交</el-button
          >
          <el-button @click="$refs['ruleForm'].resetFields()">重置</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

2.1 密码校验和修改功能的实现

将我们新传入的数据在data函数中定义,然后定义方法。
在script中导入方法

import passwordApi from "@/api/password.js";

data中初始化数据,自定义规则

  data() {
    const validateOldPass = (rule, value, callback) => {
      passwordApi.checkPwd(this.user.id, value).then((response) => {
        const resp = response.data;
        if (resp.flag) {
          callback();
        } else {
          callback(new Error(resp.message));
        }
      });
    };
    const validatePass = (rule, value, callback) => {
      if (value != this.ruleForm.pass) {
        callback(new Error("两次输入密码不一致!"));
      } else {
        callback();
      }
    };
    return {
      user: JSON.parse(localStorage.getItem("msm-user")),
      dialogFormVisible: false,
      ruleForm: {
        oldPass: "",
        pass: "",
        checkPass: "",
      },
      rules: {
        oldPass: [
          { required: true, message: "旧密码不能为空", trigger: "blur" },
          { validator: validateOldPass, trigger: "blur" },
        ],
        pass: [{ required: true, message: "新密码不能为空", trigger: "blur" }],
        checkPass: [
          { required: true, message: "确认密码不能为空", trigger: "blur" },
          { validator: validatePass, trigger: "change" },
        ],
      },
    };
  },

定义方法,打开弹出框实现密码的修改

  methods: {
    handleCommand(command) {
      switch (command) {
        case "a":
          // 打开修改密码窗口
          this.handlePwd();
          break;
        case "b":
          // 退出系统
          break;
        default:
          break;
      }
    },
    handlePwd() {
      this.dialogFormVisible = true;
      this.$nextTick(() => {
        this.$refs["ruleForm"].resetFields();
      });
    },
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          passwordApi
            .updatePwd(this.user.id, this.ruleForm.checkPass)
            .then((response) => {
              const resp = response.data;
              this.$message({
                message: resp.message,
                type: resp.flag ? "success" : "warning",
              });
              if (resp.flag) {
                this.handleLogout();
                this.dialogFormVisible = false;
              }
            });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
  },

三、实现退出系统的功能

3.1 后台配置退出登录接口

// 退出登录
router.post("/user/logout", function (req, res) {
    var body = req.body;
    User.findOne({
        token: body.token
    }, function (err, data) {
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: '登录信息存在错误'
            })
        }
        if (!data) {
            return res.status(200).json({
                code: 4000,
                flag: false,
                message: '不存在'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '退出登录成功'
        })
    })
})

3.2 前端api调用接口

这里的接口写在login.js文件下

// 用户退出登录
export function logout(token){
    return request ({
        method:"post",
        url:'/user/logout',
        data:{
            token
        }
    })
}

3.2 AppHeader实现功能

这里我们要将admin动态绑定成用户昵称,所以将admin转换成 {{ user.nickname }}

    <!-- 头部右部用户标签设置 -->
    <el-dropdown @command="handleCommand">
      <span class="el-dropdown-link">
        {{ user.nickname }}<i class="el-icon-arrow-down el-icon--right"></i>
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item command="a">修改密码</el-dropdown-item>
        <el-dropdown-item command="b">退出登录</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>

退出功能的实现
在script中导入方法

import { logout } from "@/api/login.js";
 handleCommand(command) {
      switch (command) {
        case "a":
          // 打开修改密码窗口
          this.handlePwd();
          break;
        case "b":
          // 退出系统
          this.handleLogout();
          break;
        default:
          break;
      }
    },
    handleLogout() {
      logout(localStorage.getItem("msm-token")).then((response) => {
        const resp = response.data;
        if (resp.flag) {
          localStorage.removeItem("msm-token");
          localStorage.removeItem("msm-user");
          this.$router.push("/login");
        } else {
          this.$message({
            message: resp.message,
            type: "warning",
          });
        }
      });
    },
  },

四、全局权限校验

原因:当用户未登录时,用户不能够进入项目主体页面,当出现该情况时,用户应被退出项目到登录页,如果用户未登录就回到注册页面,完成注册–>登录–>项目主页。
在msm项目文件夹下新建permission.js文件
permission.js

import router from './router' //导入路由
import {getUserInfo} from '@/api/login.js' //获取用户信息,判断项目是否含有用户信息
//通过router路由前置钩子函数 beforeEach() ,在跳转路由前进行拦截判断是否已经登录,如果已登录,则进行路由跳转,如果没有则回到登录页。
router.beforeEach((to, from, next) => { 
	//用户登录以后创建出的token,通过token来判断用户信息是否存在
    const token = localStorage.getItem('msm-token')
    //用户登录信息不存在,没有产生token
    if (!token) {
    	//让用户前往登录页面,如果在登录页面继续操作
        if (to.path == '/login') {
            next();
            //没有登录信息就去注册页面,如果在注册页面,继续操作
        } else if (to.path === "/register") {
            next();
        } else {
        //如果当前页面都不处于上两个页面,默认去登陆页面
            next({
                path: '/login'
            })
        }
        //如果有token
    } else {
  		//当前所处页面为登录,继续操作  
        if (to.path === '/login') {
            next();
        //当前页面为注册,继续操作   
        } else if (to.path === "/register") {
            next();
            } else {
            //如果页面为项目页面,获取用户信息。
            const userInfo = localStorage.getItem('msm-user');
            //如果有用户信息,继续操作
            if (userInfo) {
                next();
            } else {
            //调用方法,获取用户信息
                getUserInfo(token).then((response) => {
                    const resp = response.data;
                    // console.log('prer', resp)
                    //如果resp响应为true,那么获取用户信息成功并存储
                    if (resp.flag) {
                        localStorage.setItem('msm-user', JSON.stringify(resp.data))
                    } else {
                        //如果失败,去登陆页面。
                        next({
                            path: '/login'
                        })
                    }
                })
            }
        }
    }
})

总结

本章主要实现的是头部组件右侧下拉菜单的实现,主要功能包括修改密码和退出系统的功能。最后在配置全局权限校验,防止用户在未登录的状态进入到项目主页中去。
router.js新增代码

// 退出登录
router.post("/user/logout", function (req, res) {
    var body = req.body;
    User.findOne({
        token: body.token
    }, function (err, data) {
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: '登录信息存在错误'
            })
        }
        if (!data) {
            return res.status(200).json({
                code: 4000,
                flag: false,
                message: '不存在'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '退出登录成功'
        })
    })
})
//校验密码是否正确
router.post("/user/pwd",function (req,res) {
    var body = req.body;
    console.log('post',body);
    User.findOne({
        _id:body.userId,
        password:body.password
    },function (err,data) {
        if(err){
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "server error"
            })
        }
        if(!data){
            return res.status(200).json({
                code: 4000,
                flag: false,
                message: "密码不正确"
            })
        }
        return res.json({
            "code": 2000,
            "flag": true,
            "message": "密码正确"
        })
    })
});

//修改密码
router.put('/user/pwd',function (req,res) {
    console.log('put',req.body);
    var id = req.body.userId;
    console.log(req.body);
    User.findOne({
        _id:id
    },function (err,data) {
        if(err){
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "server error"
            })
        }
        if(!data){
            return res.status(200).json({
                code: 4000,
                flag: false,
                message: "密码不正确"
            })
        }
        data.password = req.body.password;
        User.findByIdAndUpdate(id,data,function (err) {
            if(err){
                return res.status(500).json({
                    code: 3000,
                    flag: false,
                    message: "修改密码失败"
                })
            }
            return res.status(200).json({
                "code": 2000,
                "flag": true,
                "message": "修改密码成功"
            })
        })
    })
});

login.js

//用于发送ajax请求
import request from "@/utils/request.js";
// 注册
export function register(username,nickname,password){ //这里的参数都是形参
    return request({
        method:"post",
        url:"/user/register",
        data:{ //需要向后台传输的数据是req,后台又会响应回来一个数据是res
            username,
            nickname,
            password
        }
    })
}
// 登录
export function login(username,password){
    return request({
        method:"post",
        url:"/user/login",
        data:{
            username,
            password
        }
    })
}
//获取用户信息
export function getUserInfo(token){
    return request({
        method:"get",
        url:`/user/info?token=${token}`,
    })
}
// 用户退出登录
export function logout(token){
    return request ({
        method:"post",
        url:'/user/logout',
        data:{
            token
        }
    })
}

password.js

import request from "@/utils/request.js"

export default {
    checkPwd(userId,password){
        return request ({
            url :"/user/pwd",
            method: "post",
            data:{
                userId,
                password
            }
        })
    },
    // 修改密码请求
    updatePwd(userId,password){
        return request({
            url : "/user/pwd",
            method:"put",
            data:{
                userId,
                password
            }
        })
    }
}

AppHeader下的index.vue

<template>
  <div class="header">
    <a href="#">
      <img src="@/assets/logo.png" width="25px" class="logo" />
      <span class="title">学堂</span>
    </a>
    <!-- 头部右部用户标签设置 -->
    <el-dropdown @command="handleCommand">
      <span class="el-dropdown-link">
        {{ user.nickname }}<i class="el-icon-arrow-down el-icon--right"></i>
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item command="a">修改密码</el-dropdown-item>
        <el-dropdown-item command="b">退出登录</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
    <!-- 修改密码弹出框设置 -->
    <el-dialog title="修改密码" :visible.sync="dialogFormVisible" width="500px">
      <el-form
        :model="ruleForm"
        status-icon
        :rules="rules"
        ref="ruleForm"
        label-width="100px"
        style="width: 400px"
      >
        <el-form-item label="原密码" prop="oldPass">
          <el-input type="password" v-model="ruleForm.oldPass"></el-input>
        </el-form-item>
        <el-form-item label="新密码" prop="pass">
          <el-input type="password" v-model="ruleForm.pass"></el-input>
        </el-form-item>
        <el-form-item label="确认密码" prop="checkPass">
          <el-input type="password" v-model="ruleForm.checkPass"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm('ruleForm')"
            >提交</el-button
          >
          <el-button @click="$refs['ruleForm'].resetFields()">重置</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>
import { logout } from "@/api/login.js";
import passwordApi from "@/api/password.js";
export default {
  data() {
    const validateOldPass = (rule, value, callback) => {
      passwordApi.checkPwd(this.user.id, value).then((response) => {
        const resp = response.data;
        if (resp.flag) {
          callback();
        } else {
          callback(new Error(resp.message));
        }
      });
    };
    const validatePass = (rule, value, callback) => {
      if (value != this.ruleForm.pass) {
        callback(new Error("两次输入密码不一致!"));
      } else {
        callback();
      }
    };
    return {
      user: JSON.parse(localStorage.getItem("msm-user")),
      dialogFormVisible: false,
      ruleForm: {
        oldPass: "",
        pass: "",
        checkPass: "",
      },
      rules: {
        oldPass: [
          { required: true, message: "旧密码不能为空", trigger: "blur" },
          { validator: validateOldPass, trigger: "blur" },
        ],
        pass: [{ required: true, message: "新密码不能为空", trigger: "blur" }],
        checkPass: [
          { required: true, message: "确认密码不能为空", trigger: "blur" },
          { validator: validatePass, trigger: "change" },
        ],
      },
    };
  },
  components: {},
  methods: {
    handleCommand(command) {
      switch (command) {
        case "a":
          // 打开修改密码窗口
          this.handlePwd();
          break;
        case "b":
          // 退出系统
          this.handleLogout();
          break;
        default:
          break;
      }
    },
    handlePwd() {
      this.dialogFormVisible = true;
      this.$nextTick(() => {
        this.$refs["ruleForm"].resetFields();
      });
    },
    handleLogout() {
      logout(localStorage.getItem("msm-token")).then((response) => {
        const resp = response.data;
        if (resp.flag) {
          localStorage.removeItem("msm-token");
          localStorage.removeItem("msm-user");
          this.$router.push("/login");
        } else {
          this.$message({
            message: resp.message,
            type: "warning",
          });
        }
      });
    },
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          passwordApi
            .updatePwd(this.user.id, this.ruleForm.checkPass)
            .then((response) => {
              const resp = response.data;
              this.$message({
                message: resp.message,
                type: resp.flag ? "success" : "warning",
              });
              if (resp.flag) {
                this.handleLogout();
                this.dialogFormVisible = false;
              }
            });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
  },
};
</script>

<style scoped>
.logo {
  vertical-align: middle;
  padding: 0 10px 0 40px;
}
.title {
  color: white;
  position: absolute;
}
.el-dropdown {
  float: right;
  margin-right: 40px;
}
.el-dropdown-link {
  color: #409eff;
  cursor: pointer;
}
.date-weather{
   float: right;
   color: white;
   margin-right: 30px;
   font-size: 12px;
}
</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值