feat: 完成登录和注册功能

backend/dev
Spark 6 months ago
parent 1e835ca9bd
commit 461d9fc87c

@ -0,0 +1,44 @@
package cc.aspark.controller;
import cc.aspark.domain.dto.UserLoginDTO;
import cc.aspark.domain.dto.UserRegisterDTO;
import cc.aspark.domain.vo.UserLoginVO;
import cc.aspark.result.Result;
import cc.aspark.service.AdminService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/admin")
@RequiredArgsConstructor
@Tag(name = "管理员表相关操作")
public class AdminController {
private final AdminService adminService;
@PostMapping("/login")
@Operation(summary = "用户登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
log.info("用户登录:{}", userLoginDTO);
UserLoginVO userLoginVO = adminService.login(userLoginDTO);
return Result.success(userLoginVO);
}
@PostMapping("/register")
@Operation(summary = "用户注册")
public Result register(@RequestBody UserRegisterDTO userRegisterDTO) {
log.info("用户注册:{}", userRegisterDTO);
adminService.register(userRegisterDTO);
return Result.success();
}
}

@ -0,0 +1,14 @@
package cc.aspark.mapper;
import cc.aspark.domain.entity.Admin;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author night
* @description admin()Mapper
* @createDate 2024-10-02 16:31:44
* @Entity generator.domain.TbAdmin
*/
public interface AdminMapper extends BaseMapper<Admin> {
}

@ -0,0 +1,19 @@
package cc.aspark.service;
import cc.aspark.domain.dto.UserLoginDTO;
import cc.aspark.domain.dto.UserRegisterDTO;
import cc.aspark.domain.entity.Admin;
import cc.aspark.domain.vo.UserLoginVO;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author night
* @description tb_admin()Service
* @createDate 2024-10-02 16:31:44
*/
public interface AdminService extends IService<Admin> {
UserLoginVO login(UserLoginDTO userLoginDTO);
void register(UserRegisterDTO userRegisterDTO);
}

@ -0,0 +1,87 @@
package cc.aspark.service.impl;
import cc.aspark.constant.MessageConstant;
import cc.aspark.domain.dto.UserLoginDTO;
import cc.aspark.domain.dto.UserRegisterDTO;
import cc.aspark.domain.entity.Admin;
import cc.aspark.domain.vo.UserLoginVO;
import cc.aspark.exception.AccountNotFoundException;
import cc.aspark.exception.LoginFailedException;
import cc.aspark.exception.PasswordErrorException;
import cc.aspark.mapper.AdminMapper;
import cc.aspark.properties.JwtProperties;
import cc.aspark.service.AdminService;
import cc.aspark.utils.JwtUtil;
import ch.qos.logback.core.util.StringUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author night
* @description admin()Service
* @createDate 2024-10-02 16:31:44
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin>
implements AdminService {
private final JwtProperties jwtProperties;
@Override
public UserLoginVO login(UserLoginDTO userLoginDTO) {
if (userLoginDTO == null || StringUtil.isNullOrEmpty(userLoginDTO.getUsername()) || StringUtil.isNullOrEmpty(userLoginDTO.getPassword())) {
throw new LoginFailedException(MessageConstant.INVALID_INPUT);
}
userLoginDTO.setPassword(SecureUtil.md5(userLoginDTO.getPassword()));
log.info(userLoginDTO.getPassword());
LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Admin::getUsername, userLoginDTO.getUsername());
Admin admin = baseMapper.selectOne(wrapper);
if (admin == null) {
throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
}
if (!admin.getPassword().equals(userLoginDTO.getPassword())) {
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
//登录成功后生成jwt令牌
Map<String, Object> claims = new HashMap<>();
claims.put("id", admin.getId());
claims.put("username", admin.getUsername());
String token = JwtUtil.createJWT(
jwtProperties.getSecretKey(),
jwtProperties.getTtl(),
claims);
UserLoginVO userLoginVO = BeanUtil.copyProperties(admin, UserLoginVO.class);
userLoginVO.setToken(token);
return userLoginVO;
}
@Override
public void register(UserRegisterDTO userRegisterDTO) {
Admin admin = BeanUtil.copyProperties(userRegisterDTO, Admin.class);
admin.setPassword(SecureUtil.md5(admin.getPassword()));
admin.setUpdateTime(LocalDateTime.now());
admin.setCreateTime(LocalDateTime.now());
baseMapper.insert(admin);
}
}

@ -0,0 +1,276 @@
package cc.aspark.service.impl;
import cc.aspark.constant.MessageConstant;
import cc.aspark.context.BaseContext;
import cc.aspark.domain.dto.PageQueryDTO;
import cc.aspark.domain.dto.StudentDTO;
import cc.aspark.domain.entity.Student;
import cc.aspark.exception.BaseException;
import cc.aspark.result.PageResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
/**
* @author night
* @description student()Service
* @createDate 2024-10-02 16:31:44
*/
@Service
@Slf4j
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student>
implements StudentService {
@Override
public void updateStu(StudentDTO studentDTO) {
Student student = BeanUtil.copyProperties(studentDTO, Student.class);
student.setUpdateTime(LocalDateTime.now());
baseMapper.updateById(student);
}
private void handleSort(LambdaQueryWrapper<Student> wrapper, String orderBy, String orderRule) {
if (orderBy == null || orderRule == null) {
wrapper.orderByAsc(Student::getNo);
return;
}
// 使用Map存储字段与对应的getter方法
Map<String, SFunction<Student, ?>> sortFieldMap = new HashMap<>();
sortFieldMap.put("no", Student::getNo);
sortFieldMap.put("name", Student::getName);
sortFieldMap.put("gender", Student::getGender);
sortFieldMap.put("className", Student::getClassName);
sortFieldMap.put("points", Student::getPoints);
sortFieldMap.put("createTime", Student::getCreateTime);
sortFieldMap.put("updateTime", Student::getUpdateTime);
SFunction<Student, ?> sortField = sortFieldMap.get(orderBy);
if (sortField == null) {
throw new BaseException(MessageConstant.INVALID_INPUT);
}
switch (orderRule.toUpperCase()) {
case "ASC" -> wrapper.orderByAsc(sortField);
case "DESC" -> wrapper.orderByDesc(sortField);
default -> throw new BaseException(MessageConstant.INVALID_INPUT);
}
}
@Override
public PageResult<Student> page(PageQueryDTO pageQueryDTO) {
int page = Math.max(1, pageQueryDTO.getPage());
int pageSize = Math.min(Math.max(1, pageQueryDTO.getPageSize()), 20);
Page<Student> pageStu = new Page<>(page, pageSize);
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
Boolean isExactQuery = pageQueryDTO.getExactQuery();
if (isExactQuery == null || !isExactQuery) {
wrapper .eq(Student::getCreator, BaseContext.getCurrentId())
.like(pageQueryDTO.getNo() != null, Student::getNo, pageQueryDTO.getNo())
.like(pageQueryDTO.getName() != null, Student::getName, pageQueryDTO.getName())
.eq(pageQueryDTO.getGender() != null, Student::getGender, pageQueryDTO.getGender())
.like(pageQueryDTO.getClassName() != null, Student::getClassName, pageQueryDTO.getClassName())
.between(pageQueryDTO.getCreateTimeStart() != null && pageQueryDTO.getCreateTimeEnd() != null,
Student::getCreateTime, pageQueryDTO.getCreateTimeStart(), pageQueryDTO.getCreateTimeEnd())
.between(pageQueryDTO.getUpdateTimeStart() != null && pageQueryDTO.getUpdateTimeEnd() != null,
Student::getUpdateTime, pageQueryDTO.getUpdateTimeStart(), pageQueryDTO.getUpdateTimeEnd());
} else {
wrapper .eq(Student::getCreator, BaseContext.getCurrentId())
.eq(pageQueryDTO.getNo() != null, Student::getNo, pageQueryDTO.getNo())
.eq(pageQueryDTO.getName() != null, Student::getName, pageQueryDTO.getName())
.eq(pageQueryDTO.getGender() != null, Student::getGender, pageQueryDTO.getGender())
.eq(pageQueryDTO.getClassName() != null, Student::getClassName, pageQueryDTO.getClassName())
.between(pageQueryDTO.getCreateTimeStart() != null && pageQueryDTO.getCreateTimeEnd() != null,
Student::getCreateTime, pageQueryDTO.getCreateTimeStart(), pageQueryDTO.getCreateTimeEnd())
.between(pageQueryDTO.getUpdateTimeStart() != null && pageQueryDTO.getUpdateTimeEnd() != null,
Student::getUpdateTime, pageQueryDTO.getUpdateTimeStart(), pageQueryDTO.getUpdateTimeEnd());
}
handleSort(wrapper, pageQueryDTO.getOrderBy(), pageQueryDTO.getOrderRule());
pageStu = baseMapper.selectPage(pageStu, wrapper);
return new PageResult<>(pageStu.getTotal(), pageStu.getRecords());
}
@Override
public void save(StudentDTO studentDTO) {
Student student = BeanUtil.copyProperties(studentDTO, Student.class);
student.setUpdateTime(LocalDateTime.now());
student.setCreateTime(LocalDateTime.now());
student.setCreator(Integer.valueOf(BaseContext.getCurrentId().toString()));
log.info("{}", student);
baseMapper.insert(student);
}
@Override
public Student rollCall() {
List<Student> studentList = this.list();
if (studentList.isEmpty()) {
throw new RuntimeException("学生列表为空");
}
// 找出最高积分,用于计算反向权重
final double maxPoints = studentList.stream()
.mapToDouble(Student::getPoints)
.max()
.orElse(0.0) + 1.0;
// 计算总的反向权重
double totalInverseWeights = studentList.stream()
.mapToDouble(student -> maxPoints - student.getPoints())
.sum();
// 生成一个0到总反向权重之间的随机数
Random random = new Random();
double randomValue = random.nextDouble() * totalInverseWeights;
// 使用累加器方法选择学生
double accumulatedWeight = 0;
for (Student student : studentList) {
// 计算该学生的反向权重
double inverseWeight = maxPoints - student.getPoints();
accumulatedWeight += inverseWeight;
if (accumulatedWeight >= randomValue) {
return student;
}
}
// 以防万一,返回最后一个学生
return studentList.get(studentList.size() - 1);
}
@Override
public void importStudentsByExcel(MultipartFile file) {
try {
ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
reader .addHeaderAlias("学号", "no")
.addHeaderAlias("姓名", "name")
.addHeaderAlias("性别", "gender")
.addHeaderAlias("班级", "className")
.addHeaderAlias("积分", "credits")
.addHeaderAlias("创建时间", "createTime")
.addHeaderAlias("最后操作时间", "updateTime");
List<Map<String, Object>> rows = reader.readAll();
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
List<Student> studentList = rows.stream().map(row -> {
Student student = new Student();
student.setNo(row.get("no").toString());
student.setName(row.get("name").toString());
student.setGender("男".equals(row.get("gender")) ? (short) 0 : (short) 1);
student.setClassName(row.get("className").toString());
student.setCreator(Integer.valueOf(BaseContext.getCurrentId().toString()));
if (row.get("credits") == null) {
student.setPoints(0.00);
} else {
student.setPoints(Double.valueOf(row.get("credits").toString()));
}
if (row.get("createTime") == null) {
student.setCreateTime(now);
} else {
String createTimeStr = row.get("createTime").toString();
student.setCreateTime(LocalDateTime.parse(createTimeStr, formatter));
}
if (row.get("updateTime") == null) {
student.setUpdateTime(now);
} else {
String updateTimeStr = row.get("updateTime").toString();
student.setUpdateTime(LocalDateTime.parse(updateTimeStr, formatter));
}
return student;
}).toList();
try {
baseMapper.insertOrUpdate(studentList);
} catch (Exception e) {
log.info(e.getMessage());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void exportStudentsToExcel(HttpServletResponse response) {
try {
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Student::getCreator, BaseContext.getCurrentId());
List<Student> studentList = baseMapper.selectList(wrapper);
// 创建一个Excel写入器
ExcelWriter writer = ExcelUtil.getWriter(true);
// 设置表头别名
writer.addHeaderAlias("no", "学号");
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("gender", "性别");
writer.addHeaderAlias("className", "班级");
writer.addHeaderAlias("points", "积分");
writer.addHeaderAlias("createTime", "创建时间");
writer.addHeaderAlias("updateTime", "最后操作时间");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 将性别的数字转换为文字
List<Map<String, Object>> rows = studentList.stream().map(student -> {
Map<String, Object> row = new HashMap<>();
row.put("no", student.getNo());
row.put("name", student.getName());
row.put("gender", student.getGender() == 0 ? "男" : "女");
row.put("className", student.getClassName());
row.put("points", student.getPoints());
row.put("createTime", student.getCreateTime().format(formatter));
row.put("updateTime", student.getUpdateTime().format(formatter));
return row;
}).collect(Collectors.toList());
// 写入数据
writer.write(rows, true);
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=students.xlsx");
// 输出Excel文件
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(out);
} catch (Exception e) {
log.error("导出Excel失败", e);
throw new BaseException(e.getMessage());
}
}
@Override
public void updatePoints(Integer id, Double points) {
Student student = baseMapper.selectById(id);
student.setPoints(student.getPoints() + points);
baseMapper.updateById(student);
}
}

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cc.aspark.mapper.AdminMapper">
<resultMap id="BaseResultMap" type="cc.aspark.domain.entity.Admin">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="password" column="password" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,username,password,
create_time,update_time
</sql>
</mapper>

@ -1,13 +0,0 @@
package cc.aspark;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class TestApplicationTests {
@Test
void contextLoads() {
}
}
Loading…
Cancel
Save