目录
一、个人成果总结
这段时间我主要负责并完成了注册、个人信息等界面的前后端+mysql数据库设计和实现,同时实现了头像上传、数据格式限制等功能。
二、主要功能点实现
1.注册
界面展示:
数据库设计:
其中设置用户名username唯一。
后端接口逻辑:
@ApiOperation("输入用户名密码邮箱和用户类型注册")
@PostMapping("/register")
public Result register(@RequestBody UserDTO userDTO) {
String username = userDTO.getUsername();
String password = userDTO.getPassword();
String email = userDTO.getEmail();
//判断参数格式
if (StrUtil.isBlank(username) || StrUtil.isBlank(password) || StrUtil.isBlank(email)) {
return Result.error(Constants.CODE_400, "参数错误,部分参数为空");
}
if (!StringUtil.checkEmail(email)){
return Result.error(Constants.CODE_600,"邮箱格式错误");
}
if ( !StringUtil.checkPassword(password) ) {
// 密码格式校验
return Result.error(Constants.CODE_400,"密码格式为:长度为6-18,只有数字和字母且至少包含1个字母");
}
return Result.success(userService.register(userDTO));
}
前端界面设计:
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 8, message: '长度在 3 到 8 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 18, message: '长度为6-18,只有数字和字母且至少包含1个字母', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{ min: 6, max: 18, message: '长度为6-18,只有数字和字母且至少包含1个字母', trigger: 'blur' }
],
email: [
{required: true, message: '请输入邮箱', trigger: 'blur'},
{min: 6, max: 20, message: '请输入正确的邮箱格式', trigger: 'blur'}
]
}
为了让系统有更好的交互性,这里做了详细的提示信息,同时通过设计“确认密码”的方式,进一步加强了用户信息的安全性。
2.个人信息
界面展示:
采用element-plus提供的el-form框架,
通过右上角下拉框“个人信息”进入个人信息界面,路由:
{
path: '/person',
name: 'Person',
component: () => import("@/views/Person"),
meta: { isStu: true, title:'主页' },
},
在数据库表中加入以下字段:
后端分页查找某个用户的信息:
@ApiOperation("(分页查询)(有改动)根据username查找某个学生信息")
@GetMapping("/page")
public Result findStudentByStudentNumOrStudentName(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(defaultValue = "") String studentname
) {
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
if (StrUtil.isNotBlank(studentname)) {
queryWrapper.like("studentname", studentname);
}
queryWrapper.orderByAsc("id");
return Result.success(studentService.page(new Page<>(pageNum, pageSize), queryWrapper));
}
由于前面将username设为主键,所以这里直接根据它进行搜索即可;
保存用户信息:
@PostMapping//保存一个用户的信息
public Result save(@RequestBody Student student) {
if (student.getPhoneNumber()!=null){
if (!StringUtil.checkPhone(student.getPhoneNumber())){
return Result.error(Constants.CODE_400,"电话号码格式错误");
}
}
if(student.getBirthday()!=null){
String birthday = student.getBirthday();
DateTime datetime = DateUtil.parse(birthday);
student.setBirthday(datetime.toDateStr());
}
studentService.saveOrUpdate(student);
return Result.success();
}
这里对手机号码的格式进行了限制,同时将前端返回的生日设成数据库所需格式。
3.个人头像上传
前端上传用户头像:
<!--上传头像 -->
<el-upload
class="avatar-uploader"
:action="'/api/file/uploadphoto'"
:show-file-list="false"
:on-success="handleAvatarSuccess"
>
<img v-if="user.headPortrait" :src="user.headPortrait" class="avatar">
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
这里设置一个上传头像的“钩子”,上传后便会调用后端接口,同时通过handleAvatarSuccess函数更新用户头像的url:
handleAvatarSuccess(res) {
console.log(res)
//调用user/id接口存头像url
if(res.code==='400'){
this.$message.error(res.msg)
} else{
this.user.headPortrait=res.data;
}
}
后端接口设计:
这里对上传文件的类型进行了限制,后续可能会继续对图片进行大小限制/压缩处理,减轻存储压力;除此之外,通过查询数据库判断图片是否已存储,若已存储则返回对应文件md5,反之保存在相应的绝对路径下。
@PostMapping("/uploadphoto")
public Result uploadphoto(@RequestParam MultipartFile file) throws IOException {
//得到文件原始名
String originalFilename = file.getOriginalFilename();
//文件类型
String type = FileUtil.extName(originalFilename);
//判断文件类型是否合法
String[] photo_type = {"bmp", "jpg", "png", "tif", "gif", "fpx", "svg", "psd", "webp", "jpeg"};
boolean is_legal_type = false;
for (String ps : photo_type) {
if (ps.matches(type)) is_legal_type = true;
// System.out.println(ps);
}
if (!is_legal_type) {
return Result.error(Constants.CODE_400, "错误图片格式");
}
//文件大小要不要设置图片最大规格???/压缩图片???
long size = file.getSize();
// 定义一个文件唯一的标识码 唯一性ID生成器:UUID
// 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID DOT“.”
String fileUUID = IdUtil.fastSimpleUUID() + StrUtil.DOT + type;
File uploadFile = new File(fileUploadPath + fileUUID);
// 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录
File parentFile = uploadFile.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
String url;
// 获取文件的md5
String md5 = SecureUtil.md5(file.getInputStream());
// 从数据库查询是否存在相同的记录
Files dbFiles = getFileByMd5(md5);
if (dbFiles != null) {
url = dbFiles.getUrl();
} else {
// 上传文件到磁盘
file.transferTo(uploadFile);
// 数据库若不存在重复文件,则不删除刚才上传的文件
url = "http://" + serverIp + ":8088/file/" + fileUUID;//
// 存储file数据库
Files saveFile = new Files();
saveFile.setName(originalFilename);
saveFile.setType(type);
saveFile.setSize(size / 1024); // 单位 kb
saveFile.setUrl(url);
saveFile.setMd5(md5);
fileMapper.insert(saveFile);
}
4.邮箱格式限制
/**
* 邮箱校验
*
* @param email 邮箱
* @return true or false
*/
public static boolean checkEmail(String email) {
String check = "^([a-zA-Z]|[0-9])(\\w|\\-)+@[a-zA-Z0-9]+\\.([a-zA-Z]{2,4})$";
Pattern regex = Pattern.compile(check);
Matcher matcher = regex.matcher(email);
return matcher.matches();
}
这里还对邮箱的格式加了限制,控制邮箱格式为“××@××.××”,这是为了引导用户输入真实的邮箱,从而在密码丢失后以便找回账号;
5.密码限制
/**
* 密码校验(长度 6-18,至少包含1个字母)
* @param password
* @return
*
*/
public static boolean checkPassword(String password) {
String check = "(?=.*[a-zA-Z])[a-zA-Z0-9]{6,18}";
// String check = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,18}$";
Pattern regex = Pattern.compile(check);
Matcher matcher = regex.matcher(password);
return matcher.matches();
}
同时用正则表达式的防止,限制密码长度为6~18位、只含字母/数字、至少含1个字母。
6.前端友好提示
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 8, message: '长度在 3 到 8 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 18, message: '长度为6-18,只有数字和字母且至少包含1个字母', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{ min: 6, max: 18, message: '长度为6-18,只有数字和字母且至少包含1个字母', trigger: 'blur' }
],
email: [
{required: true, message: '请输入邮箱', trigger: 'blur'},
{min: 6, max: 20, message: '请输入正确的邮箱格式', trigger: 'blur'}
]
}
为了让系统有更好的交互性,这里做了详细的提示信息,同时通过设计“确认密码”的方式,进一步加强了用户信息的安全性。
三、后续任务
接下来的时间,我将完成日志相关的操作,包括发表日志、编辑日志、删除日志、查找日志、以及与日志编辑器有关的用操作,如添加表情、上传本地图片、设置导航栏等。