笔记
- 用户修改页面前端、后端开发和联调
一、后端修改用户信息接口
首先运行前后端,看看是否正常
1.在UserController里面添加更新用户信息接口
/**
* 更新用户信息
* @param user
* @param request
* @return
*/
@PostMapping("/update")
public BaseResponse<Integer> updateUser(@RequestBody User user, HttpServletRequest request) {
// 1. 校验参数是否为空
if (user == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User loginUser = userService.getCurrentUser(request);
int result = userService.updateUser(user, loginUser);
return ResultUtils.success(result);
}
由于项目中多次用户鉴权,所以我们在service层编写isAdmin方法(包括复写) UserService
/**
* 是否为管理员
* @param request
* @return
*/
boolean isAdmin(HttpServletRequest request);
/**
* 是否为管理员
* @param loginUser
* @return
*/
boolean isAdmin(User loginUser);
/**
* 获取当前用户
* @param request
* @return
*/
User getCurrentUser(HttpServletRequest request);
/**
* 更新用户信息
* @param user
* @param loginUser
* @return
*/
int updateUser(User user, User loginUser);
同时在UserServiceImpl里面实现上述方法
/**
* 更新用户信息
* @param user
* @param loginUser
* @return
*/
@Override
public int updateUser(User user, User loginUser) {
Long userId = user.getId();
if (userId <= 0) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
// 2. 校验权限
// 2.1 管理员可以更新任意信息
// 2.2 用户只能更新自己的信息
if (!isAdmin(loginUser) && userId != loginUser.getId()) {
throw new BusinessException(ErrorCode.NO_AUTH);
}
User oldUser = this.getById(user.getId());
if (oldUser == null) {
throw new BusinessException(ErrorCode.NULL_ERROR);
}
// 3. 触发更新
return this.baseMapper.updateById(user);
}
/**
* 是否为管理员
* @param request
* @return
*/
public boolean isAdmin(HttpServletRequest request) {
User user = (User) request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
if (user == null user.getUserRole() != UserConstant.ADMIN_ROLE) {
return false;
}
return true;
}
/**
* 是否为管理员
* @param loginUser
* @return
*/
@Override
public boolean isAdmin(User loginUser) {
return loginUser.getUserRole() == ADMIN_ROLE;
}
/**
* 获取当前用户
* @param request
* @return
*/
@Override
public User getCurrentUser(HttpServletRequest request) {
if (request == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User user = (User) request.getSession().getAttribute(USER_LOGIN_STATE);
if (user == null) {
throw new BusinessException(ErrorCode.NOT_LOGIN);
}
return user;
}
二、前端页面开发
1.现在pages包里新建一个登录页面UserLoginPage.vue
<template>
<van-form @submit="onSubmit">
<van-cell-group inset>
<van-field
v-model="userAccount"
name="userAccount"
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>
import myAxios from "../plugins/myAxios.ts";
import {Toast} from "vant";
import {ref} from "vue";
import {useRouter} from "vue-router";
const router = useRouter();
const userAccount = ref();
const userPassword = ref();
const onSubmit = async () => {
// console.log("用户登录");
const res = await myAxios.post("/user/login", {
userAccount: userAccount.value,
userPassword: userPassword.value
});
if (res.code == 0 && res.data != null) {
Toast.success("登录成功");
router.replace("/")
} else {
Toast.fail("登录失败");
}
};
</script>
<style scoped>
</style>
别忘了在路由里面引入
import UserLoginPage from "../pages/UserLoginPage.vue";
{ path: '/user/login', component: UserLoginPage },
这里需要我们在axios.ts里把响应改成data,如下图: 运行 ,输入数据,成功登录并跳转的主页,显示如下:
2.登录成功,现在就要去编写用户信息了(动态显示数据库里面的信息),原来是写死的
onMounted(async ()=>{
const res = await myAxios.get('/user/current');
if (res.code === 0){
user.value =res.data;
Toast.success('获取用户信息成功');
}else {
Toast.fail('获取用户信息成功');
}
})
但是登录不会种下cookie,意味着后端不能获取登录用户信息,就不能动态展示用户信息页 在myAxios.ts中添加以下代码:(注意要在定义的变量,即myAxios之后粘贴)
myAxios.defaults.withCredentials = true; // 允许携带 cookie
在后端接口添加允许携带 cookie 的配置 同时后端设置 cookie 的作用域
登录,再次点击个人,发现cookie已经带有了,只是页面还没有显示
查看操作台报错,发现是createTime的字符转变导致的,直接删去,后面再处理
再次刷新,页面成功的显示
3.完善修改用户信息
发现每个页面都要获取当前的用户信息,所以我们把这个方法提取出来 在src目录下建立services包,并创建user.ts编写代码
import myAxios from "../plugins/myAxios";
import {getCurrentUserState, setCurrentUserState} from "../states/user";
/**
* 获取用户信息
* @returns {Promise<nullany>}
*/
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,
}
由于提取了获取用户信息的代码,所以用户页原来编写的代码需要修改为下图 最后就是要编写用户修改页面了,发送修改用户信息请求。 完整代码如下
<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 {Toast} from "vant";
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) {
Toast.success("修改成功");
router.replace("/user");
} else {
Toast.fail("修改失败");
}
};
</script>
<style scoped>
</style>
4.测试如下:其中会有报错,好像大多是由于ts造成的,但是都不会影响代码的运行实现
注意踩坑处: 1.语法糖是支持写在外面的,但是这里面运用就不显示页面
5.关于调用缓存去获取当前用户信息的问题
这边就很玄学,鱼皮使用了缓存,结果获取不到最新的用户信息,而我这边可以。。。 建议:在小系统(用户少)中尽量不要使用缓存,可以使用路由守卫,从远程获取 踩坑处:如果前端在用户页的信息中并未设定editKey的话,就无法修改信息(更新内容为空),这需要我们在后端去控制、筛选前端所传入的参数 后端会有类似以下报错