心链5---修改用户消息+登录界面(种cookie)

心链 — 伙伴匹配系统

后端用户个人信息修改接口

控制层新增用户信息更新接口
UserController

/**
     *      用户信息更新
     * @param user
     * @param request
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Integer> updateUser(@RequestBody User user , HttpServletRequest request) {
        //验证参数是否为空
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //鉴权
        User loginUser = userService.getLogininUser(request);
        int result = userService.updateUser(user,loginUser);
        return ResultUtils.success(result);
    }

service层提供用户信息修改方法,并提取了获取当前用户信息和是否为管理员的方法。
UserService

    /**
     *  用户信息修改
     * @param user
     * @return
     */
    int updateUser(User user,User loginUser);

    /**
     *  获取当前用户信息
     * @param request
     * @return
     */
    User getLogininUser(HttpServletRequest request);

    /**
     * 是否为管理员
     *
     * @param request
     * @return
     */
    boolean isAdmin(HttpServletRequest request);

    /**
     * 是否为管理员
     *
     * @param loginUser
     * @return
     */
     boolean isAdmin(User loginUser);

serviceImpl层进行实现。
UserSercviceImpl


    /**
     *  用户信息修改
     * @param user
     * @return
     */
    @Override
    public int updateUser(User user,User loginUser) {
        long userId = user.getId();
        if (userId <= 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //如果是管理员,允许更新任意用户
        //如果不是管理员,只允许更新自己的信息
        if (!isAdmin(loginUser) && userId != loginUser.getId()){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        User userold = userMapper.selectById(userId);
        if (userold == null){
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        return userMapper.updateById(user);
    }
     /**
     * 是否为管理员
     *
     * @param request
     * @return
     */
    public boolean isAdmin(HttpServletRequest request) {
        // 仅管理员可查询
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user = (User) userObj;
        return user != null && user.getUserRole() == ADMIN_ROLE;
    }

    /**
     * 是否为管理员
     *
     * @param loginUser
     * @return
     */
    public boolean isAdmin(User loginUser) {
        return loginUser != null && loginUser.getUserRole() == ADMIN_ROLE;
    }

    /**
     *  获取当前用户信息
     * @param request
     * @return
     */
    @Override
    public User getLogininUser(HttpServletRequest request) {
        if (request == null){
            return null;
        }
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        if (userObj == null){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        return (User) userObj;
    }

image.png

前端对接

登录

我这里不能使用Toast.success() ,进行提示,看文档说使用showSuccessToast、showFailToast进行提示

<template>
  <van-form @submit="onSubmit">
    <van-cell-group inset>
      <van-field
          v-model="userAccout"
          name="userAccout"
          label="账户"
          placeholder="账户"
          :rules="[{ required: true, message: '请填写账户' }]"
      />
      <van-field
          v-model="userPassword"
          type="password"
          name="userPassword"
          label="密码"
          placeholder="密码"
          :rules="[{ required: true, message: '请填写密码' }]"
      />
    </van-cell-group>
    <div style="margin: 16px;">
      <van-button round block type="primary" native-type="submit">
        提交
      </van-button>
    </div>
  </van-form>
</template>
<script setup lang="ts">

import {useRouter} from "vue-router";
import {ref} from "vue";
import myAxios from "../plugins/myAxios";
import {Toast} from "vant";

const router = useRouter();

const userAccout = ref('');
const userPassword = ref('');

const onSubmit = async () => {
  const res = await myAxios.post('/user/login',{
    userAccount: userAccout.value,
    userPassword: userPassword.value,
  })
  console.log(res,'用户登录');
  if (res.code == 0 && res.data){
    Toast.success('登录成功');
    router.replace('/')
  } else {
    Toast.fail('登录失败')
  }
};

</script>

<style scoped>

</style>

在路由里面引入

import UserLoginPage from "../pages/UserLoginPage.vue"; 

{ path: '/user/login', component: UserLoginPage },

这里需要我们在myAxios.ts里把响应改成data,如下图:
image.png
http://localhost:5173/#/user/login
运行 ,输入数据,成功登录并跳转的主页,显示如下:
image.png
image.png

用户信息获取

在用户个人信息页面上调取后端接口获取用户的信息。

import myAxios from "../plugins/myAxios.ts";
import {showFailToast,showSuccessToast} from "vant/lib/vant.es";

const user = ref();

onMounted(async ()=>{
    const res = await myAxios.get('/user/current');
    if (res.code === 0){
      user.value =res.data;
      showSuccessToast('获取用户信息成功');
    }else {
      showFailToast('获取用户信息成功');
    }
})

但是登录不会种下cookie,意味着后端不能获取登录用户信息,就不能动态展示用户信息

种cookie

在myAxios.ts中添加以下代码:(注意要在定义的变量,即myAxios之后粘贴)

myAxios.defaults.withCredentials = true; // 允许携带 cookie

这里遇到了新的坑,给后端接口添加允许携带 cookie 的配置,才能把cookie种下

在这里插入图片描述

后端设置 cookie 的作用域
在这里插入图片描述

再尝试就ok了
image.png



<template>
  <template v-if="user">
    <van-cell title="昵称" is-link to="/user/edit" :value="user.username" @click="toEdit('username','昵称',user.username)"/>
    <van-cell title="账户" :value="user.userAccount"
              @click="toEdit('userAccount','账户',user.userAccount)"/>
    <van-cell title="头像" is-link to="/user/edit" :value="user.avatarUrl" @click="toEdit('avatarUrl','头像',user.avatarUrl)">
      <img style="height: 48px" :src="user.avatarUrl">
    </van-cell>
    <van-cell title="性别" is-link to="/user/edit" :value="user.gender" @click="toEdit('gender','性别',user.gender)" />
    <van-cell title="电话" is-link to="/user/edit" :value="user.phone" @click="toEdit('phone','电话',user.phone)"/>
    <van-cell title="邮箱" is-link to="/user/edit" :value="user.email" @click="toEdit('email','邮箱',user.email)"/>
    <van-cell title="星球编号" :value="user.planetCode" />
    <van-cell title="注册时间" :value="user.createTime"  />
  </template>
</template>
<script setup lang="ts">
import {useRouter} from "vue-router";
import {onMounted, ref} from "vue";
import myAxios from "../plugins/myAxios.ts";
import {showFailToast, showSuccessToast} from "vant";

const user = ref();
// const user = {
//   id: 1,
//   username: '阿尼亚',
//   userAccount: 'Aniya',
//   avatarUrl: 'https://raw.githubusercontent.com/RockIvy/images/master/img/avatar42.jpg',
//   gender: '男',
//   phone: '12131133313',
//   email: '23432444@qq.com',
//   planetCode: '2220',
//   createTime: new Date(),
// };

const router = useRouter()
const toEdit = (editKey: String, editName: String, currentValue: String) => {
  router.push({
    path: 'user/edit',
    query: {
      editKey,
      editName,
      currentValue,
    }
  })
}

onMounted(async () => {
  const res = await myAxios.get('/user/current');
  if (res.code === 0) {
    user.value = res.data;
    showSuccessToast('获取用户信息成功');
  } else {
    showFailToast('获取用户信息成功');
  }
})

</script>

<style scoped>

</style>

完善修改用户信息

发现每个页面都要获取当前的用户信息,所以我们把这个方法提取出来 在src目录下建立services包,并创建user.ts编写代码

import myAxios from "../plugins/myAxios";
import {getCurrentUserState, setCurrentUserState} from "../states/user";

/**
 * 获取用户信息
 * @returns {Promise<null|any>}
 */
export const getCurrentUser = async () => {
    const user = getCurrentUserState();
    if (user) {
        return user;
    }
    //从远程处获取用户信息
    const res = await myAxios.get("/user/current");
    if (res.code == 0 ) {
        // setCurrentUserState(res.data);
        return res.data;
    }
    return null;
}

同时在src目录下建立states包,并创建user.ts编写代码(定义两个方法)

import {UserType} from "../models/user";

let currentUser: UserType;

const setCurrentUserState = (user:UserType) =>{
    currentUser =user;
}

const getCurrentUserState = (): UserType =>{
    return currentUser;
}

export {
    setCurrentUserState,
    getCurrentUserState,
}

由于提取了获取用户信息的代码,所以用户页原来编写的代码需要修改为下图
image.png

最后就是要编写用户修改页面了,发送修改用户信息请求。 UserEditPage.vue完整代码如下

<template>
  <van-form @submit="onSubmit">
    <van-field
        v-model="editUser.currentValue"
        :name="editUser.editKey"
        :label="editUser.editName"
        :placeholder="`请输入${editUser.editName}`"
    />
    <div style="margin: 16px;">
      <van-button round block type="primary" native-type="submit">
        提交
      </van-button>
    </div>
  </van-form>
</template>

<script setup lang="ts">
import {useRoute, useRouter} from "vue-router";
import {ref} from "vue";
import myAxios from "../plugins/myAxios";
import {showSuccessToast,showFailToast} from "vant/lib/vant.es";
import {getCurrentUser} from "../services/user";

const route = useRoute();
const router =useRouter();

const editUser = ref({
  editKey: route.query.editKey,
  currentValue: route.query.currentValue,
  editName: route.query.editName,
})

// 不可以写在外面,否则页面不显示内容,还没有报错信息,原因未知
// const currentUser = await getCurrentUser();

const onSubmit = async () => {
  // 异步方法必须添加 await 才可以拿到数据, 否则拿到的是 promise 对象
  const currentUser = await getCurrentUser();
  console.log("-------UserEditPage", currentUser);
  const res = await myAxios.post("/user/update", {
    "id": currentUser.id,
    [editUser.value.editKey]: editUser.value.currentValue // 动态取值
  })
  console.log("修改用户信息", res);
  if (res.code === 0 && res.data > 0) {
    showSuccessToast('修改成功')
    router.back()
  }else {
    showFailToast('修改失败');
  }
};

</script>

<style scoped>

</style>

image.png
**注意踩坑处:**语法糖是支持写在外面的,但是这里面运用就不显示页面
image.png
关于调用缓存去获取当前用户信息的问题
image.png
建议:在小系统(用户少)中尽量不要使用缓存,可以使用路由守卫,从远程获取踩坑处:如果前端在用户页的信息中并未设定editKey的话,就无法修改信息(更新内容为空),这需要我们在后端去控制、筛选前端所传入的参数 后端会有类似以下报错
image.png

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值