feat(user): 添加用户修改密码功能
- 在前端 HomePage 组件中添加修改密码对话框 - 在 API 中添加 updatePassword 接口 - 在后端 UserController 中添加密码更新接口 - 在 UserService 中添加 updatePassword 方法 - 实现密码更新逻辑,包括旧密码验证和新密码加密
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
package com.test.bijihoudaun.bo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "更新密码业务对象")
|
||||||
|
public class UpdatePasswordBo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "旧密码", name = "oldPassword", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String oldPassword;
|
||||||
|
|
||||||
|
@Schema(description = "新密码", name = "newPassword", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private String newPassword;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.test.bijihoudaun.common.exception;
|
||||||
|
|
||||||
|
public class BusinessException extends RuntimeException {
|
||||||
|
|
||||||
|
public BusinessException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BusinessException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.test.bijihoudaun.controller;
|
package com.test.bijihoudaun.controller;
|
||||||
|
|
||||||
|
import com.test.bijihoudaun.bo.UpdatePasswordBo;
|
||||||
import com.test.bijihoudaun.common.response.R;
|
import com.test.bijihoudaun.common.response.R;
|
||||||
import com.test.bijihoudaun.entity.User;
|
import com.test.bijihoudaun.entity.User;
|
||||||
import com.test.bijihoudaun.service.RegistrationCodeService;
|
import com.test.bijihoudaun.service.RegistrationCodeService;
|
||||||
@@ -10,11 +11,9 @@ import io.swagger.v3.oas.annotations.Parameter;
|
|||||||
import io.swagger.v3.oas.annotations.Parameters;
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -79,4 +78,13 @@ public class UserController {
|
|||||||
return R.success("Token is valid");
|
return R.success("Token is valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "更新用户密码")
|
||||||
|
@PutMapping("/password")
|
||||||
|
public R<String> updatePassword(@RequestBody UpdatePasswordBo updatePasswordBo) {
|
||||||
|
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
String username = userDetails.getUsername();
|
||||||
|
User user = userService.getOne(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<User>().eq("username", username));
|
||||||
|
userService.updatePassword(user.getId(), updatePasswordBo);
|
||||||
|
return R.success("密码更新成功");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.test.bijihoudaun.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.test.bijihoudaun.entity.User;
|
import com.test.bijihoudaun.entity.User;
|
||||||
|
|
||||||
|
import com.test.bijihoudaun.bo.UpdatePasswordBo;
|
||||||
|
|
||||||
public interface UserService extends IService<User> {
|
public interface UserService extends IService<User> {
|
||||||
/**
|
/**
|
||||||
* 用户注册
|
* 用户注册
|
||||||
@@ -33,4 +35,11 @@ public interface UserService extends IService<User> {
|
|||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
Boolean isTokenExpired(Long id,String token);
|
Boolean isTokenExpired(Long id,String token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户密码
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param updatePasswordBo 包含新旧密码的对象
|
||||||
|
*/
|
||||||
|
void updatePassword(Long userId, UpdatePasswordBo updatePasswordBo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.test.bijihoudaun.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.test.bijihoudaun.bo.UpdatePasswordBo;
|
||||||
|
import com.test.bijihoudaun.common.exception.BusinessException;
|
||||||
import com.test.bijihoudaun.common.exception.RegistrationException;
|
import com.test.bijihoudaun.common.exception.RegistrationException;
|
||||||
import com.test.bijihoudaun.entity.User;
|
import com.test.bijihoudaun.entity.User;
|
||||||
import com.test.bijihoudaun.mapper.UserMapper;
|
import com.test.bijihoudaun.mapper.UserMapper;
|
||||||
@@ -83,4 +85,18 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||||||
// 修改过期检查逻辑
|
// 修改过期检查逻辑
|
||||||
return user != null && new Date().before(user.getTokenEnddata());
|
return user != null && new Date().before(user.getTokenEnddata());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePassword(Long userId, UpdatePasswordBo updatePasswordBo) {
|
||||||
|
User user = getById(userId);
|
||||||
|
if (user == null) {
|
||||||
|
throw new BusinessException("用户不存在");
|
||||||
|
}
|
||||||
|
if (!PasswordUtils.verify(updatePasswordBo.getOldPassword(), user.getPassword())) {
|
||||||
|
throw new BusinessException("旧密码不正确");
|
||||||
|
}
|
||||||
|
String newPassword = PasswordUtils.encrypt(updatePasswordBo.getNewPassword());
|
||||||
|
user.setPassword(newPassword);
|
||||||
|
updateById(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -150,3 +150,8 @@ export const toggleRegistration = (enabled) => {
|
|||||||
export const generateRegistrationCode = () => {
|
export const generateRegistrationCode = () => {
|
||||||
return axiosApi.post('/system/registration/generate-code');
|
return axiosApi.post('/system/registration/generate-code');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 更新密码
|
||||||
|
export const updatePassword = (data) => {
|
||||||
|
return axiosApi.put('/api/user/password', data);
|
||||||
|
};
|
||||||
|
|||||||
@@ -88,6 +88,7 @@
|
|||||||
<div v-if="userStore.isLoggedIn" class="user-actions">
|
<div v-if="userStore.isLoggedIn" class="user-actions">
|
||||||
<span class="welcome-text">欢迎, {{ userStore.userInfo?.username }}</span>
|
<span class="welcome-text">欢迎, {{ userStore.userInfo?.username }}</span>
|
||||||
<el-button type="danger" @click="handleLogout">退出</el-button>
|
<el-button type="danger" @click="handleLogout">退出</el-button>
|
||||||
|
<el-button type="primary" @click="showUpdatePasswordDialog = true">修改密码</el-button>
|
||||||
<el-button type="warning" @click="showSystemSettingsDialog = true">系统管理</el-button>
|
<el-button type="warning" @click="showSystemSettingsDialog = true">系统管理</el-button>
|
||||||
<el-button type="primary" @click="showCreateNoteDialog = true">新建笔记</el-button>
|
<el-button type="primary" @click="showCreateNoteDialog = true">新建笔记</el-button>
|
||||||
<el-upload
|
<el-upload
|
||||||
@@ -226,6 +227,25 @@
|
|||||||
<el-button @click="showSystemSettingsDialog = false">关闭</el-button>
|
<el-button @click="showSystemSettingsDialog = false">关闭</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 修改密码对话框 -->
|
||||||
|
<el-dialog v-model="showUpdatePasswordDialog" title="修改密码" width="400px" @close="resetUpdatePasswordForm">
|
||||||
|
<el-form :model="updatePasswordForm" :rules="updatePasswordFormRules" ref="updatePasswordFormRef" label-width="100px">
|
||||||
|
<el-form-item label="旧密码" prop="oldPassword">
|
||||||
|
<el-input v-model="updatePasswordForm.oldPassword" type="password" show-password autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码" prop="newPassword">
|
||||||
|
<el-input v-model="updatePasswordForm.newPassword" type="password" show-password autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认新密码" prop="confirmPassword">
|
||||||
|
<el-input v-model="updatePasswordForm.confirmPassword" type="password" show-password autocomplete="off"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showUpdatePasswordDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleUpdatePassword">确定</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
</el-container>
|
</el-container>
|
||||||
@@ -251,7 +271,8 @@ import {
|
|||||||
validateToken,
|
validateToken,
|
||||||
getRegistrationStatus,
|
getRegistrationStatus,
|
||||||
toggleRegistration,
|
toggleRegistration,
|
||||||
generateRegistrationCode
|
generateRegistrationCode,
|
||||||
|
updatePassword
|
||||||
} from '@/api/CommonApi.js'
|
} from '@/api/CommonApi.js'
|
||||||
import { Plus, Fold, Expand, Folder, Document, Search, Edit, Delete, ArrowDown, Clock } from "@element-plus/icons-vue";
|
import { Plus, Fold, Expand, Folder, Document, Search, Edit, Delete, ArrowDown, Clock } from "@element-plus/icons-vue";
|
||||||
import { useUserStore } from '../stores/user';
|
import { useUserStore } from '../stores/user';
|
||||||
@@ -282,6 +303,7 @@ const currentGroupName = ref('');
|
|||||||
const showSystemSettingsDialog = ref(false);
|
const showSystemSettingsDialog = ref(false);
|
||||||
const isRegistrationEnabled = ref(true);
|
const isRegistrationEnabled = ref(true);
|
||||||
const generatedCode = ref('');
|
const generatedCode = ref('');
|
||||||
|
const showUpdatePasswordDialog = ref(false);
|
||||||
|
|
||||||
const groupFormRef = ref(null);
|
const groupFormRef = ref(null);
|
||||||
const newGroupForm = ref({ name: '', parentId: null });
|
const newGroupForm = ref({ name: '', parentId: null });
|
||||||
@@ -302,6 +324,27 @@ const noteFormRules = ref({
|
|||||||
groupingId: [{ required: true, message: '请选择分类', trigger: 'change' }],
|
groupingId: [{ required: true, message: '请选择分类', trigger: 'change' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatePasswordFormRef = ref(null);
|
||||||
|
const updatePasswordForm = ref({
|
||||||
|
oldPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
confirmPassword: ''
|
||||||
|
});
|
||||||
|
const validateConfirmPassword = (rule, value, callback) => {
|
||||||
|
if (value === '') {
|
||||||
|
callback(new Error('请再次输入新密码'));
|
||||||
|
} else if (value !== updatePasswordForm.value.newPassword) {
|
||||||
|
callback(new Error("两次输入的新密码不一致"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const updatePasswordFormRules = ref({
|
||||||
|
oldPassword: [{ required: true, message: '请输入旧密码', trigger: 'blur' }],
|
||||||
|
newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' }, { min: 6, message: '密码长度不能少于6位', trigger: 'blur' }],
|
||||||
|
confirmPassword: [{ required: true, validator: validateConfirmPassword, trigger: 'blur' }]
|
||||||
|
});
|
||||||
|
|
||||||
const editData=ref(null)
|
const editData=ref(null)
|
||||||
const imageUrls = ref([]);
|
const imageUrls = ref([]);
|
||||||
const originalImages = ref([]);
|
const originalImages = ref([]);
|
||||||
@@ -987,6 +1030,32 @@ onMounted(async () => {
|
|||||||
console.error("Failed to fetch registration status:", error);
|
console.error("Failed to fetch registration status:", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const handleUpdatePassword = async () => {
|
||||||
|
if (!updatePasswordFormRef.value) return;
|
||||||
|
await updatePasswordFormRef.value.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
try {
|
||||||
|
await updatePassword({
|
||||||
|
oldPassword: updatePasswordForm.value.oldPassword,
|
||||||
|
newPassword: updatePasswordForm.value.newPassword
|
||||||
|
});
|
||||||
|
ElMessage.success('密码修改成功,请重新登录');
|
||||||
|
showUpdatePasswordDialog.value = false;
|
||||||
|
await handleLogout();
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('密码修改失败: ' + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetUpdatePasswordForm = () => {
|
||||||
|
updatePasswordForm.value = { oldPassword: '', newPassword: '', confirmPassword: '' };
|
||||||
|
if (updatePasswordFormRef.value) {
|
||||||
|
updatePasswordFormRef.value.resetFields();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
BIN
mydatabase.db
BIN
mydatabase.db
Binary file not shown.
Reference in New Issue
Block a user