parent
							
								
									b122d6b1c6
								
							
						
					
					
						commit
						5e5fb9a07d
					
				
				 36 changed files with 1401 additions and 57 deletions
			
			
		@ -0,0 +1,15 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.annotation; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.annotation.ElementType; | 
				
			||||||
 | 
					import java.lang.annotation.Retention; | 
				
			||||||
 | 
					import java.lang.annotation.RetentionPolicy; | 
				
			||||||
 | 
					import java.lang.annotation.Target; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-04-02 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					@Target({ElementType.METHOD, ElementType.TYPE}) | 
				
			||||||
 | 
					@Retention(RetentionPolicy.RUNTIME) | 
				
			||||||
 | 
					public @interface SkinLogin { | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,92 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.config; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserLoginOutDO; | 
				
			||||||
 | 
					import org.apache.commons.lang3.StringUtils; | 
				
			||||||
 | 
					import org.springframework.stereotype.Component; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalDateTime; | 
				
			||||||
 | 
					import java.util.concurrent.ConcurrentHashMap; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component | 
				
			||||||
 | 
					public class UserLoginStatusBean { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private ConcurrentHashMap<String, UserLoginOutDO> loginStatusMap = new ConcurrentHashMap<>(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 缓存登录信息 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param token          token | 
				
			||||||
 | 
					     * @param loginOutStatus 登录信息 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    public void login(String token, UserLoginOutDO loginOutStatus) { | 
				
			||||||
 | 
					        loginStatusMap.put(token, loginOutStatus); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 从缓存读取登录信息 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param token token | 
				
			||||||
 | 
					     * @return {@link UserLoginOutDO} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    public UserLoginOutDO getStatus(String token) { | 
				
			||||||
 | 
					        UserLoginOutDO loginStatus = loginStatusMap.getOrDefault(token, null); | 
				
			||||||
 | 
					        if (loginStatus.getLapseTime() != null) { | 
				
			||||||
 | 
					            LocalDateTime now = LocalDateTime.now(); | 
				
			||||||
 | 
					            if (now.isAfter(loginStatus.getLapseTime())) { | 
				
			||||||
 | 
					                logout(token); | 
				
			||||||
 | 
					                return null; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return loginStatus; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 为key设置登出 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param token token | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    public Boolean logout(String token) { | 
				
			||||||
 | 
					        if (StringUtils.isNotBlank(token) && loginStatusMap.containsKey(token)) { | 
				
			||||||
 | 
					            UserLoginOutDO removedUser = loginStatusMap.remove(token); | 
				
			||||||
 | 
					            // 返回true表示成功登出,返回false表示未成功登出
 | 
				
			||||||
 | 
					            return removedUser != null; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return Boolean.TRUE; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Boolean logoutByUserId(String userId) { | 
				
			||||||
 | 
					        final String[] targetKey = {null}; | 
				
			||||||
 | 
					        loginStatusMap.forEach((k, v) -> { | 
				
			||||||
 | 
					            if (targetKey[0] == null && v.getUserId().equals(userId)) { | 
				
			||||||
 | 
					                targetKey[0] = k; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        }); | 
				
			||||||
 | 
					        return logout(targetKey[0]); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String getTokenByUsername(String username) { | 
				
			||||||
 | 
					        final String[] token = {null}; | 
				
			||||||
 | 
					        loginStatusMap.forEach((k, v) -> { | 
				
			||||||
 | 
					            if (token[0] == null && v.getUserName().equals(username)) { | 
				
			||||||
 | 
					                token[0] = k; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        }); | 
				
			||||||
 | 
					        return token[0]; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Boolean containsToken(String token) { | 
				
			||||||
 | 
					        if (StringUtils.isBlank(token)) { | 
				
			||||||
 | 
					            return Boolean.FALSE; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        UserLoginOutDO loginStatus = loginStatusMap.getOrDefault(token, null); | 
				
			||||||
 | 
					        if (loginStatus.getLapseTime() != null) { | 
				
			||||||
 | 
					            LocalDateTime now = LocalDateTime.now(); | 
				
			||||||
 | 
					            if (now.isAfter(loginStatus.getLapseTime())) { | 
				
			||||||
 | 
					                logout(token); | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return loginStatusMap.containsKey(token); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,24 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.config; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.interceptor.TokenInterceptor; | 
				
			||||||
 | 
					import org.springframework.context.annotation.Configuration; | 
				
			||||||
 | 
					import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | 
				
			||||||
 | 
					import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * 注册请求拦截器 | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-04-02 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Configuration | 
				
			||||||
 | 
					public class WebMvcConfig implements WebMvcConfigurer { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public void addInterceptors(InterceptorRegistry registry) { | 
				
			||||||
 | 
					        registry.addInterceptor(new TokenInterceptor()) | 
				
			||||||
 | 
					                // 拦截所有路径
 | 
				
			||||||
 | 
					                .addPathPatterns("/**"); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,32 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.controller; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.AnswerSubmitDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.service.IAnswerService; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.utils.base.BackUtils; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.vo.base.Back; | 
				
			||||||
 | 
					import lombok.extern.slf4j.Slf4j; | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||||
 | 
					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; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-27 13:24 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Slf4j | 
				
			||||||
 | 
					@RestController | 
				
			||||||
 | 
					@RequestMapping("/answer") | 
				
			||||||
 | 
					public class AnswerController { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private IAnswerService answerService; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("submit") | 
				
			||||||
 | 
					    public Back<Boolean> submit(@RequestBody AnswerSubmitDTO dto) { | 
				
			||||||
 | 
					        return BackUtils.success(answerService.handleSubmit(dto)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,47 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.controller; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.annotation.SkinLogin; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLogoutDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.service.IUserService; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.utils.base.BackUtils; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.vo.UserVO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.vo.base.Back; | 
				
			||||||
 | 
					import lombok.extern.slf4j.Slf4j; | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||||
 | 
					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; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-31 15:48 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Slf4j | 
				
			||||||
 | 
					@RestController | 
				
			||||||
 | 
					@RequestMapping("/user") | 
				
			||||||
 | 
					public class UserController { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private IUserService userService; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("login") | 
				
			||||||
 | 
					    @SkinLogin | 
				
			||||||
 | 
					    public Back<UserVO> login(@RequestBody UserLoginDTO dto) { | 
				
			||||||
 | 
					        return BackUtils.success(userService.login(dto)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("register") | 
				
			||||||
 | 
					    @SkinLogin | 
				
			||||||
 | 
					    public Back<UserVO> register(@RequestBody UserLoginDTO dto) { | 
				
			||||||
 | 
					        return BackUtils.success(userService.register(dto)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PostMapping("logout") | 
				
			||||||
 | 
					    public Back<Boolean> logout(@RequestBody UserLogoutDTO dto) { | 
				
			||||||
 | 
					        return BackUtils.success(userService.logout(dto)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,45 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-27 13:31 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class AnswerDetailDTO { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 回答内容(文字/选项id,多选时以,分隔) | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String content; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 得分 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer points; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 题目id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String subjectId; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 题目类型:0-单选;1-多选;2-文字 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer subjectType; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 题目分值 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer subjectPoints; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 权重 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Double weights; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,37 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-27 13:26 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class AnswerSubmitDTO { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 二维码id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String qrId; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 问卷Id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String qnId; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * openid, 即答卷人 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String openid; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 答题内容 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private List<AnswerDetailDTO> details; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,30 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 21:55 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class UserLoginDTO { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * userName | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String username; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * password | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String password; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 密码错误次数(暂未使用) | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer pswErrorCount; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,21 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.base.PageParams; | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 21:50 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class UserLoginOutPageDTO extends PageParams { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * userId | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String userId; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,25 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 21:56 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class UserLogoutDTO { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * userName | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String username; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * token | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String token; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,37 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.base.PageParams; | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalDateTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 20:50 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class UserPageDTO extends PageParams { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String id; | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户名 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String username; | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 状态;0(默认):正常;4:封号;9:异常; | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer status; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 注册时间 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private LocalDateTime startTime; | 
				
			||||||
 | 
					    private LocalDateTime endTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,45 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.dto; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 20:50 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class UserSaveDTO { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String id; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户名 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String username; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 密码 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String password; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 状态;0(默认):正常;4:封号;9:异常; | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer status; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 权限等级,默认200 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer authorityLevel; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 密码修改次数 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer pswChange; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,93 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.entity; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.annotation.*; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.extension.activerecord.Model; | 
				
			||||||
 | 
					import lombok.Getter; | 
				
			||||||
 | 
					import lombok.Setter; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Serializable; | 
				
			||||||
 | 
					import java.time.LocalDateTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户表 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-30 14:34:13 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					@Getter | 
				
			||||||
 | 
					@Setter | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					@TableName("tb_user") | 
				
			||||||
 | 
					public class UserDO extends Model<UserDO> { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final long serialVersionUID = 1L; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableId(value = "id", type = IdType.ASSIGN_UUID) | 
				
			||||||
 | 
					    private String id; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户名 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("username") | 
				
			||||||
 | 
					    private String username; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 密码 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("password") | 
				
			||||||
 | 
					    private String password; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 状态;0(默认):正常;4:封号;9:异常; | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("status") | 
				
			||||||
 | 
					    private Integer status; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 权限等级,默认200 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("authority_level") | 
				
			||||||
 | 
					    private Integer authorityLevel; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 密码修改次数 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("psw_change") | 
				
			||||||
 | 
					    private Integer pswChange; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 更新时间 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE) | 
				
			||||||
 | 
					    private LocalDateTime updatedTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 创建时间 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField(value = "created_time", fill = FieldFill.INSERT) | 
				
			||||||
 | 
					    private LocalDateTime createdTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 删除标记 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("removed") | 
				
			||||||
 | 
					    @TableLogic | 
				
			||||||
 | 
					    private Integer removed; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 盐,用于密码加密,未启用 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("salt") | 
				
			||||||
 | 
					    private String salt; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Serializable pkVal() { | 
				
			||||||
 | 
					        return this.id; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,87 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.entity; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.annotation.*; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.extension.activerecord.Model; | 
				
			||||||
 | 
					import lombok.Getter; | 
				
			||||||
 | 
					import lombok.Setter; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Serializable; | 
				
			||||||
 | 
					import java.time.LocalDateTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户登入登出表 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-30 13:57:00 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					@Getter | 
				
			||||||
 | 
					@Setter | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					@TableName("tb_user_login_out") | 
				
			||||||
 | 
					public class UserLoginOutDO extends Model<UserLoginOutDO> { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final long serialVersionUID = 1L; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableId(value = "id", type = IdType.ASSIGN_UUID) | 
				
			||||||
 | 
					    private String id; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("user_id") | 
				
			||||||
 | 
					    private String userId; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户名称 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("user_name") | 
				
			||||||
 | 
					    private String userName; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 登录时间,登录成功才写入 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("login_time") | 
				
			||||||
 | 
					    private LocalDateTime loginTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 登录失效时间 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("lapse_time") | 
				
			||||||
 | 
					    private LocalDateTime lapseTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户操作登出时间 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("logout_time") | 
				
			||||||
 | 
					    private LocalDateTime logoutTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 密码错误次数 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("psw_error_count") | 
				
			||||||
 | 
					    private Integer pswErrorCount; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 创建时间 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField(value = "created_time", fill = FieldFill.INSERT) | 
				
			||||||
 | 
					    private LocalDateTime createdTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 1=删除;0=未删除 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    @TableField("removed") | 
				
			||||||
 | 
					    @TableLogic | 
				
			||||||
 | 
					    private Integer removed; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Serializable pkVal() { | 
				
			||||||
 | 
					        return this.id; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,63 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.interceptor; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.annotation.SkinLogin; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.config.UserLoginStatusBean; | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||||
 | 
					import org.springframework.web.method.HandlerMethod; | 
				
			||||||
 | 
					import org.springframework.web.servlet.HandlerInterceptor; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.servlet.http.HttpServletRequest; | 
				
			||||||
 | 
					import javax.servlet.http.HttpServletResponse; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-04-02 15:31 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TokenInterceptor implements HandlerInterceptor { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private UserLoginStatusBean userLoginStatusBean; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | 
				
			||||||
 | 
					        // 允许OPTIONS请求通过
 | 
				
			||||||
 | 
					        if (isCorsRequest(request)) { | 
				
			||||||
 | 
					            return true; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 跳过登录
 | 
				
			||||||
 | 
					        // 如果处理器是一个方法处理器
 | 
				
			||||||
 | 
					        if (handler instanceof HandlerMethod) { | 
				
			||||||
 | 
					            HandlerMethod handlerMethod = (HandlerMethod) handler; | 
				
			||||||
 | 
					            // 检查方法上是否存在SkinLogin注解
 | 
				
			||||||
 | 
					            if (handlerMethod.getMethod().isAnnotationPresent(SkinLogin.class)) { | 
				
			||||||
 | 
					                // 如果存在,绕过拦截器
 | 
				
			||||||
 | 
					                return true; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        // 验证token
 | 
				
			||||||
 | 
					        // 从请求头中获取 token
 | 
				
			||||||
 | 
					        String token = request.getHeader("jyjc-Token"); | 
				
			||||||
 | 
					        // 检查 token 是否存在并且有效,这里可以根据实际情况自行实现验证逻辑
 | 
				
			||||||
 | 
					        if (token != null && isValidToken(token)) { | 
				
			||||||
 | 
					            // Token 有效,允许请求通过
 | 
				
			||||||
 | 
					            return true; | 
				
			||||||
 | 
					        } else { | 
				
			||||||
 | 
					            // Token 无效,拒绝请求,可以返回特定的响应状态码,例如 401 Unauthorized
 | 
				
			||||||
 | 
					            response.setStatus(40401); | 
				
			||||||
 | 
					            return false; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean isValidToken(String token) { | 
				
			||||||
 | 
					        // 实现 token 验证逻辑,例如验证 token 的签名或者在数据库中验证 token 的有效性
 | 
				
			||||||
 | 
					        return userLoginStatusBean.containsToken(token); | 
				
			||||||
 | 
					        // 返回 true 表示 token 有效,返回 false 表示 token 无效
 | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean isCorsRequest(HttpServletRequest request) { | 
				
			||||||
 | 
					        // 检查请求头中是否包含 Origin 字段,如果存在,则认为是跨域请求
 | 
				
			||||||
 | 
					        return request.getHeader("Origin") != null; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,16 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.mapper; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserLoginOutDO; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.mapper.BaseMapper; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户登入登出表 Mapper 接口 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-29 20:46:42 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					public interface UserLoginOutMapper extends BaseMapper<UserLoginOutDO> { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,16 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.mapper; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserDO; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.mapper.BaseMapper; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户表 Mapper 接口 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-29 20:46:42 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					public interface UserMapper extends BaseMapper<UserDO> { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,62 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.repository; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginOutPageDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLogoutDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserLoginOutDO; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.metadata.IPage; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.extension.service.IService; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户登入登出表 服务类 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-29 20:46:42 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					public interface IUserLoginOutRepository extends IService<UserLoginOutDO> { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 分页查询 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 查询条件 | 
				
			||||||
 | 
					     * @return {@link IPage}<{@link UserLoginOutDO}> | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    IPage<UserLoginOutDO> page(UserLoginOutPageDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户登录 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto  用户信息 | 
				
			||||||
 | 
					     * @param user 用户 | 
				
			||||||
 | 
					     * @return {@link String} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    String login(UserLoginDTO dto, UserDO user); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户登出 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 用户信息 | 
				
			||||||
 | 
					     * @return {@link String} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    String logout(UserLogoutDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户登出 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param userId 用户id | 
				
			||||||
 | 
					     * @return {@link String} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean logoutByUserId(String userId); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 删除目标用户的所有登录记录 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param userId 用户id | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean removeByUserId(String userId); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,54 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.repository; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserPageDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserSaveDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.base.UpdateStatusDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.vo.base.VPage; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.metadata.IPage; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.extension.service.IService; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户表 服务类 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-29 20:46:42 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					public interface IUserRepository extends IService<UserDO> { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 分页查询 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 查询条件 | 
				
			||||||
 | 
					     * @return {@link VPage}<{@link UserDO}> | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    IPage<UserDO> page(UserPageDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 保存或更新 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 有/无id区分更新/新增 | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean saveOrUpdate(UserSaveDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 更新状态 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 新状态 | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean updateStatus(UpdateStatusDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 读取指定名字的用户 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param username 用户名 | 
				
			||||||
 | 
					     * @return {@link UserDO} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    UserDO getOneByUsername(String username); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,99 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.repository.impl; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.config.UserLoginStatusBean; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginOutPageDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLogoutDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserLoginOutDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.mapper.UserLoginOutMapper; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.repository.IUserLoginOutRepository; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.utils.base.PageUtils; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.metadata.IPage; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.toolkit.StringUtils; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.toolkit.Wrappers; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||||
 | 
					import org.springframework.stereotype.Service; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalDateTime; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户登入登出表 服务实现类 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-29 20:46:42 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					@Service | 
				
			||||||
 | 
					public class UserLoginOutRepositoryImpl extends ServiceImpl<UserLoginOutMapper, UserLoginOutDO> implements IUserLoginOutRepository { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private UserLoginStatusBean userLoginStatusBean; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public IPage<UserLoginOutDO> page(UserLoginOutPageDTO dto) { | 
				
			||||||
 | 
					        LambdaQueryWrapper<UserLoginOutDO> query = Wrappers.lambdaQuery(); | 
				
			||||||
 | 
					        query.eq(StringUtils.isNotBlank(dto.getUserId()), UserLoginOutDO::getUserId, dto.getUserId()) | 
				
			||||||
 | 
					                .orderByDesc(UserLoginOutDO::getCreatedTime); | 
				
			||||||
 | 
					        return super.page(PageUtils.build(dto), query); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public String login(UserLoginDTO dto, UserDO user) { | 
				
			||||||
 | 
					        UserLoginOutDO loginOutDO; | 
				
			||||||
 | 
					        boolean saved; | 
				
			||||||
 | 
					        LocalDateTime now = LocalDateTime.now(); | 
				
			||||||
 | 
					        // 判断是否登陆过,在缓存无法读取到目标用户名时即未登录,若登录过则令之前的登录记录失效
 | 
				
			||||||
 | 
					        String token = userLoginStatusBean.getTokenByUsername(dto.getUsername()); | 
				
			||||||
 | 
					        if (token != null) { | 
				
			||||||
 | 
					            userLoginStatusBean.logout(token); | 
				
			||||||
 | 
					            UserLoginOutDO oldLoginOut = super.getById(token); | 
				
			||||||
 | 
					            oldLoginOut.setLapseTime(now).setLogoutTime(now); | 
				
			||||||
 | 
					            super.updateById(oldLoginOut); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        loginOutDO = new UserLoginOutDO(); | 
				
			||||||
 | 
					        loginOutDO.setUserId(user.getId()) | 
				
			||||||
 | 
					                .setUserName(user.getUsername()) | 
				
			||||||
 | 
					                .setLoginTime(now) | 
				
			||||||
 | 
					                .setLapseTime(now.plusHours(2)) | 
				
			||||||
 | 
					        ; | 
				
			||||||
 | 
					        saved = super.save(loginOutDO); | 
				
			||||||
 | 
					        if (saved) { | 
				
			||||||
 | 
					            userLoginStatusBean.login(loginOutDO.getId(), loginOutDO); | 
				
			||||||
 | 
					            return loginOutDO.getId(); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return null; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public String logout(UserLogoutDTO dto) { | 
				
			||||||
 | 
					        // 清除缓存内的登录信息
 | 
				
			||||||
 | 
					        Boolean logout = userLoginStatusBean.logout(dto.getToken()); | 
				
			||||||
 | 
					        // 保存退出登录的时间
 | 
				
			||||||
 | 
					        LocalDateTime now = LocalDateTime.now(); | 
				
			||||||
 | 
					        UserLoginOutDO oldLoginOut = super.getById(dto.getToken()); | 
				
			||||||
 | 
					        oldLoginOut.setLogoutTime(now); | 
				
			||||||
 | 
					        super.updateById(oldLoginOut); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return logout ? dto.getUsername() : null; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Boolean logoutByUserId(String userId) { | 
				
			||||||
 | 
					        return userLoginStatusBean.logoutByUserId(userId); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Boolean removeByUserId(String userId) { | 
				
			||||||
 | 
					        if (org.apache.commons.lang3.StringUtils.isBlank(userId)) { | 
				
			||||||
 | 
					            return Boolean.TRUE; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        LambdaUpdateWrapper<UserLoginOutDO> update = Wrappers.lambdaUpdate(); | 
				
			||||||
 | 
					        update.eq(UserLoginOutDO::getUserId, userId); | 
				
			||||||
 | 
					        return super.remove(update); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,60 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.repository.impl; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserPageDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserSaveDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.base.UpdateStatusDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.mapper.UserMapper; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.repository.IUserRepository; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.utils.base.PageUtils; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.metadata.IPage; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.toolkit.StringUtils; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.core.toolkit.Wrappers; | 
				
			||||||
 | 
					import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | 
				
			||||||
 | 
					import org.springframework.beans.BeanUtils; | 
				
			||||||
 | 
					import org.springframework.stereotype.Service; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * <p> | 
				
			||||||
 | 
					 * 用户表 服务实现类 | 
				
			||||||
 | 
					 * </p> | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @since 2024-03-29 20:46:42 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					@Service | 
				
			||||||
 | 
					public class UserRepositoryImpl extends ServiceImpl<UserMapper, UserDO> implements IUserRepository { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public IPage<UserDO> page(UserPageDTO dto) { | 
				
			||||||
 | 
					        LambdaQueryWrapper<UserDO> query = Wrappers.lambdaQuery(); | 
				
			||||||
 | 
					        query.eq(dto.getStatus() != null, UserDO::getStatus, dto.getStatus()) | 
				
			||||||
 | 
					                .like(StringUtils.isNotBlank(dto.getUsername()), UserDO::getUsername, dto.getUsername()) | 
				
			||||||
 | 
					                .orderByDesc(UserDO::getUpdatedTime); | 
				
			||||||
 | 
					        return super.page(PageUtils.build(dto), query); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Boolean saveOrUpdate(UserSaveDTO dto) { | 
				
			||||||
 | 
					        UserDO user = new UserDO(); | 
				
			||||||
 | 
					        BeanUtils.copyProperties(dto, user); | 
				
			||||||
 | 
					        return super.saveOrUpdate(user); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Boolean updateStatus(UpdateStatusDTO dto) { | 
				
			||||||
 | 
					        LambdaUpdateWrapper<UserDO> update = Wrappers.lambdaUpdate(); | 
				
			||||||
 | 
					        update.set(UserDO::getStatus, dto.getStatus()) | 
				
			||||||
 | 
					                .eq(UserDO::getId, dto.getId()); | 
				
			||||||
 | 
					        return super.update(update); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public UserDO getOneByUsername(String username) { | 
				
			||||||
 | 
					        LambdaQueryWrapper<UserDO> query = Wrappers.lambdaQuery(); | 
				
			||||||
 | 
					        query.eq(UserDO::getUsername, username); | 
				
			||||||
 | 
					        return super.getOne(query, false); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,20 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.service; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.AnswerSubmitDTO; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-27 14:43 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface IAnswerService { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 提交答卷 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 答卷内容 | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean handleSubmit(AnswerSubmitDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,46 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.service; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLogoutDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.vo.UserVO; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 20:47 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public interface IUserService { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 注册一个用户 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 用户名和密码 | 
				
			||||||
 | 
					     * @return {@link UserVO} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    UserVO register(UserLoginDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户登录 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 用户名和密码 | 
				
			||||||
 | 
					     * @return {@link UserVO} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    UserVO login(UserLoginDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 用户退出登录 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param dto 登录key | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean logout(UserLogoutDTO dto); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 删除用户并退出登录,同时将登录记录一并删除 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param userId 用户id | 
				
			||||||
 | 
					     * @return {@link Boolean} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    Boolean remove(String userId); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,58 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.service.impl; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.AnswerSubmitDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.AnswerDetailsDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.AnswerSheetDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.repository.IAnswerDetailsRepository; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.repository.IAnswerSheetRepository; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.service.IAnswerService; | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||||
 | 
					import org.springframework.stereotype.Service; | 
				
			||||||
 | 
					import org.springframework.transaction.annotation.Transactional; | 
				
			||||||
 | 
					import org.springframework.transaction.interceptor.TransactionAspectSupport; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List; | 
				
			||||||
 | 
					import java.util.stream.Collectors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-27 14:43 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Service | 
				
			||||||
 | 
					public class AnswerServiceImpl implements IAnswerService { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private IAnswerSheetRepository sheetRepository; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private IAnswerDetailsRepository detailsRepository; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    @Transactional | 
				
			||||||
 | 
					    public Boolean handleSubmit(AnswerSubmitDTO dto) { | 
				
			||||||
 | 
					        AnswerSheetDO sheet = new AnswerSheetDO(); | 
				
			||||||
 | 
					        sheet.setRespondent(dto.getOpenid()) | 
				
			||||||
 | 
					                .setQnId(dto.getQnId()) | 
				
			||||||
 | 
					                .setQrId(dto.getQrId()); | 
				
			||||||
 | 
					        boolean sheetSaved = sheetRepository.save(sheet); | 
				
			||||||
 | 
					        if (sheetSaved) { | 
				
			||||||
 | 
					            List<AnswerDetailsDO> details = dto.getDetails().stream().map(d -> { | 
				
			||||||
 | 
					                AnswerDetailsDO detail = new AnswerDetailsDO(); | 
				
			||||||
 | 
					                detail.setAnswerContent(d.getContent()) | 
				
			||||||
 | 
					                        .setAnswerSheetId(sheet.getId()) | 
				
			||||||
 | 
					                        .setSubjectType(d.getSubjectType()) | 
				
			||||||
 | 
					                        .setSubjectId(d.getSubjectId()); | 
				
			||||||
 | 
					                return detail; | 
				
			||||||
 | 
					            }).collect(Collectors.toList()); | 
				
			||||||
 | 
					            boolean detailsSaved = detailsRepository.saveBatch(details); | 
				
			||||||
 | 
					            if (!detailsSaved) { | 
				
			||||||
 | 
					                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); | 
				
			||||||
 | 
					                return Boolean.FALSE; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } else { | 
				
			||||||
 | 
					            return Boolean.FALSE; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return Boolean.TRUE; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,87 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.service.impl; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLoginDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.dto.UserLogoutDTO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.entity.UserDO; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.repository.IUserLoginOutRepository; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.repository.IUserRepository; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.service.IUserService; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.utils.Md5Utils; | 
				
			||||||
 | 
					import cn.soul2.jyjc.admin.vo.UserVO; | 
				
			||||||
 | 
					import org.springframework.beans.BeanUtils; | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||||
 | 
					import org.springframework.stereotype.Service; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-29 20:47 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Service | 
				
			||||||
 | 
					public class UserServiceImpl implements IUserService { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private IUserRepository userRepository; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired | 
				
			||||||
 | 
					    private IUserLoginOutRepository loginOutRepository; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public UserVO register(UserLoginDTO dto) { | 
				
			||||||
 | 
					        UserVO vo = new UserVO(); | 
				
			||||||
 | 
					        if (userRepository.getOneByUsername(dto.getUsername()) == null) { | 
				
			||||||
 | 
					            UserDO user = new UserDO(); | 
				
			||||||
 | 
					            user.setUsername(dto.getUsername()) | 
				
			||||||
 | 
					                    .setPassword(Md5Utils.md5(dto.getPassword())); | 
				
			||||||
 | 
					            boolean saved = userRepository.save(user); | 
				
			||||||
 | 
					            if (!saved) { | 
				
			||||||
 | 
					                vo.setLoginFail("注册失败!"); | 
				
			||||||
 | 
					            } else { | 
				
			||||||
 | 
					                String loginKey = loginOutRepository.login(dto, user); | 
				
			||||||
 | 
					                if (loginKey != null) { | 
				
			||||||
 | 
					                    BeanUtils.copyProperties(user, vo); | 
				
			||||||
 | 
					                    vo.setToken(loginKey); | 
				
			||||||
 | 
					                } else { | 
				
			||||||
 | 
					                    vo.setLoginFail("注册成功但登录失败!"); | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } else { | 
				
			||||||
 | 
					            vo.setLoginFail("用户名已存在!"); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return vo; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public UserVO login(UserLoginDTO dto) { | 
				
			||||||
 | 
					        UserVO vo = new UserVO(); | 
				
			||||||
 | 
					        UserDO user = userRepository.getOneByUsername(dto.getUsername()); | 
				
			||||||
 | 
					        if (user != null) { | 
				
			||||||
 | 
					            if (Md5Utils.verify(user.getPassword(), dto.getPassword())) { | 
				
			||||||
 | 
					                String loginKey = loginOutRepository.login(dto, user); | 
				
			||||||
 | 
					                if (loginKey != null) { | 
				
			||||||
 | 
					                    BeanUtils.copyProperties(user, vo); | 
				
			||||||
 | 
					                    vo.setToken(loginKey); | 
				
			||||||
 | 
					                } else { | 
				
			||||||
 | 
					                    vo.setLoginFail("登录失败!"); | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            } else { | 
				
			||||||
 | 
					                vo.setLoginFail("密码错误!"); | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } else { | 
				
			||||||
 | 
					            vo.setLoginFail("该用户尚未注册!"); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return vo; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Boolean logout(UserLogoutDTO dto) { | 
				
			||||||
 | 
					        return loginOutRepository.logout(dto) != null; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override | 
				
			||||||
 | 
					    public Boolean remove(String userId) { | 
				
			||||||
 | 
					        loginOutRepository.logoutByUserId(userId); | 
				
			||||||
 | 
					        loginOutRepository.removeByUserId(userId); | 
				
			||||||
 | 
					        return userRepository.removeById(userId); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,52 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.utils; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Value; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.crypto.Cipher; | 
				
			||||||
 | 
					import javax.crypto.spec.SecretKeySpec; | 
				
			||||||
 | 
					import java.util.Base64; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-30 14:02 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class AesUtils { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Value("${encrypt.keys.aes}") | 
				
			||||||
 | 
					    private String aesKey; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final String AES_ALGORITHM = "AES"; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private SecretKeySpec generateKey(String key) { | 
				
			||||||
 | 
					        return new SecretKeySpec(key.getBytes(), AES_ALGORITHM); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String encrypt(String source) throws Exception { | 
				
			||||||
 | 
					        return encrypt(source, aesKey); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public String decrypt(String encrypted) throws Exception { | 
				
			||||||
 | 
					        return decrypt(encrypted, aesKey); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String encrypt(String source, String key) throws Exception { | 
				
			||||||
 | 
					        Cipher cipher = Cipher.getInstance(AES_ALGORITHM); | 
				
			||||||
 | 
					        cipher.init(Cipher.ENCRYPT_MODE, generateKey(key)); | 
				
			||||||
 | 
					        byte[] encryptedBytes = cipher.doFinal(source.getBytes()); | 
				
			||||||
 | 
					        return Base64.getEncoder().encodeToString(encryptedBytes); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String decrypt(String encrypted, String key) throws Exception { | 
				
			||||||
 | 
					        Cipher cipher = Cipher.getInstance(AES_ALGORITHM); | 
				
			||||||
 | 
					        cipher.init(Cipher.DECRYPT_MODE, generateKey(key)); | 
				
			||||||
 | 
					        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encrypted)); | 
				
			||||||
 | 
					        return new String(decryptedBytes); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void main(String[] args) { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,33 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.utils; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.util.DigestUtils; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.nio.charset.StandardCharsets; | 
				
			||||||
 | 
					import java.util.Objects; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author fuzongyao | 
				
			||||||
 | 
					 * @date 2021/10/14 11:19 | 
				
			||||||
 | 
					 * @since 1.0 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					public class Md5Utils { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 加盐 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private static final String SALT = "4v6dKAOn+tEiVH58/XKeUw=="; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String md5(String body) { | 
				
			||||||
 | 
					        body += SALT; | 
				
			||||||
 | 
					        return DigestUtils.md5DigestAsHex(body.getBytes(StandardCharsets.UTF_8)).toUpperCase(); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static boolean verify(String md5, String body) { | 
				
			||||||
 | 
					        return Objects.equals(md5, md5(body)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void main(String[] args) { | 
				
			||||||
 | 
					        System.out.println(md5("123456")); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,35 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.utils; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.security.SecureRandom; | 
				
			||||||
 | 
					import java.util.Base64; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * 盐值生成 | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-30 14:30 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class SaltUtils { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 生成指定长度的盐值 | 
				
			||||||
 | 
					     * | 
				
			||||||
 | 
					     * @param length 盐值长度 | 
				
			||||||
 | 
					     * @return {@link String} | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    public static String generateSalt(int length) { | 
				
			||||||
 | 
					        SecureRandom random = new SecureRandom(); | 
				
			||||||
 | 
					        byte[] salt = new byte[length]; | 
				
			||||||
 | 
					        random.nextBytes(salt); | 
				
			||||||
 | 
					        return Base64.getEncoder().encodeToString(salt); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void main(String[] args) { | 
				
			||||||
 | 
					        // 设置盐值长度
 | 
				
			||||||
 | 
					        int saltLength = 16; | 
				
			||||||
 | 
					        String salt = generateSalt(saltLength); | 
				
			||||||
 | 
					        System.out.println("Generated Salt: " + salt); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,38 @@ | 
				
			|||||||
 | 
					package cn.soul2.jyjc.admin.vo; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lombok.Data; | 
				
			||||||
 | 
					import lombok.experimental.Accessors; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
 | 
					 * @author Soul2 | 
				
			||||||
 | 
					 * @date 2024-03-30 14:40 | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Data | 
				
			||||||
 | 
					@Accessors(chain = true) | 
				
			||||||
 | 
					public class UserVO { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * username | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String username; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * token | 
				
			||||||
 | 
					     * 其实就是'UserLoginOut'表的id | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String token; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 权限等级 | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private String authorityLevel; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** | 
				
			||||||
 | 
					     * 状态;0(默认):正常;4:封号;9:异常; | 
				
			||||||
 | 
					     */ | 
				
			||||||
 | 
					    private Integer status; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String loginFail; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue