zhangyeguang
4 months ago
95 changed files with 4347 additions and 1 deletions
@ -0,0 +1,101 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<parent> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>ams-social</artifactId> |
|||
<version>${revision}</version> |
|||
</parent> |
|||
|
|||
<artifactId>common</artifactId> |
|||
|
|||
<properties> |
|||
<maven.compiler.source>17</maven.compiler.source> |
|||
<maven.compiler.target>17</maven.compiler.target> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
</properties> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.projectlombok</groupId> |
|||
<artifactId>lombok</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-core</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-http</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-extra</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.alibaba.fastjson2</groupId> |
|||
<artifactId>fastjson2</artifactId> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/ma.glasnost.orika/orika-core --> |
|||
<dependency> |
|||
<groupId>ma.glasnost.orika</groupId> |
|||
<artifactId>orika-core</artifactId> |
|||
<version>1.5.4</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.mapstruct</groupId> |
|||
<artifactId>mapstruct</artifactId> |
|||
<version>1.5.5.Final</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.mapstruct</groupId> |
|||
<artifactId>mapstruct-processor</artifactId> |
|||
<version>1.5.5.Final</version> |
|||
<scope>compile</scope> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-pool2</artifactId> |
|||
<version>2.12.0</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-jdbc</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.baomidou</groupId> |
|||
<artifactId>mybatis-plus-boot-starter</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-json</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi-ooxml</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>easyexcel</artifactId> |
|||
<exclusions> |
|||
<exclusion> |
|||
<artifactId>poi-ooxml-schemas</artifactId> |
|||
<groupId>org.apache.poi</groupId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>jakarta.servlet</groupId> |
|||
<artifactId>jakarta.servlet-api</artifactId> |
|||
</dependency> |
|||
|
|||
</dependencies> |
|||
</project> |
@ -0,0 +1,43 @@ |
|||
package com.jiagutech.ams.annotation; |
|||
|
|||
|
|||
|
|||
import com.jiagutech.ams.enums.LimitType; |
|||
|
|||
import java.lang.annotation.*; |
|||
|
|||
/** |
|||
* 限流注解 |
|||
* |
|||
* @author Lion Li |
|||
*/ |
|||
@Target(ElementType.METHOD) |
|||
@Retention(RetentionPolicy.RUNTIME) |
|||
@Documented |
|||
public @interface RateLimiter { |
|||
/** |
|||
* 限流key,支持使用Spring el表达式来动态获取方法上的参数值 |
|||
* 格式类似于 #code.id #{#code} |
|||
*/ |
|||
String key() default ""; |
|||
|
|||
/** |
|||
* 限流时间,单位秒 |
|||
*/ |
|||
int time() default 60; |
|||
|
|||
/** |
|||
* 限流次数 |
|||
*/ |
|||
int count() default 100; |
|||
|
|||
/** |
|||
* 限流类型 |
|||
*/ |
|||
LimitType limitType() default LimitType.DEFAULT; |
|||
|
|||
/** |
|||
* 提示消息 支持国际化 格式为 {code} |
|||
*/ |
|||
String message() default "{rate.limiter.message}"; |
|||
} |
@ -0,0 +1,81 @@ |
|||
package com.jiagutech.ams.constant; |
|||
|
|||
/** |
|||
* 通用常量信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public interface Constants { |
|||
|
|||
/** |
|||
* UTF-8 字符集 |
|||
*/ |
|||
String UTF8 = "UTF-8"; |
|||
|
|||
/** |
|||
* GBK 字符集 |
|||
*/ |
|||
String GBK = "GBK"; |
|||
|
|||
/** |
|||
* www主域 |
|||
*/ |
|||
String WWW = "www."; |
|||
|
|||
/** |
|||
* http请求 |
|||
*/ |
|||
String HTTP = "http://"; |
|||
|
|||
/** |
|||
* https请求 |
|||
*/ |
|||
String HTTPS = "https://"; |
|||
|
|||
/** |
|||
* 通用成功标识 |
|||
*/ |
|||
String SUCCESS = "0"; |
|||
|
|||
/** |
|||
* 通用失败标识 |
|||
*/ |
|||
String FAIL = "1"; |
|||
|
|||
/** |
|||
* 登录成功 |
|||
*/ |
|||
String LOGIN_SUCCESS = "Success"; |
|||
|
|||
/** |
|||
* 注销 |
|||
*/ |
|||
String LOGOUT = "Logout"; |
|||
|
|||
/** |
|||
* 注册 |
|||
*/ |
|||
String REGISTER = "Register"; |
|||
|
|||
/** |
|||
* 登录失败 |
|||
*/ |
|||
String LOGIN_FAIL = "Error"; |
|||
|
|||
/** |
|||
* 验证码有效期(分钟) |
|||
*/ |
|||
Integer CAPTCHA_EXPIRATION = 2; |
|||
|
|||
/** |
|||
* 令牌 |
|||
*/ |
|||
String TOKEN = "token"; |
|||
|
|||
/** |
|||
* 顶级部门id |
|||
*/ |
|||
Long TOP_PARENT_ID = 0L; |
|||
|
|||
} |
|||
|
@ -0,0 +1,39 @@ |
|||
package com.jiagutech.ams.constant; |
|||
|
|||
/** |
|||
* 全局的key常量 (业务无关的key) |
|||
* |
|||
* @author Lion Li |
|||
*/ |
|||
public interface GlobalConstants { |
|||
|
|||
/** |
|||
* 全局 redis key (业务无关的key) |
|||
*/ |
|||
String GLOBAL_REDIS_KEY = "global:"; |
|||
|
|||
/** |
|||
* 验证码 redis key |
|||
*/ |
|||
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:"; |
|||
|
|||
/** |
|||
* 防重提交 redis key |
|||
*/ |
|||
String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:"; |
|||
|
|||
/** |
|||
* 限流 redis key |
|||
*/ |
|||
String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:"; |
|||
|
|||
/** |
|||
* 登录账户密码错误次数 redis key |
|||
*/ |
|||
String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:"; |
|||
|
|||
/** |
|||
* 三方认证 redis key |
|||
*/ |
|||
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; |
|||
} |
@ -0,0 +1,93 @@ |
|||
package com.jiagutech.ams.constant; |
|||
|
|||
/** |
|||
* 返回状态码 |
|||
* |
|||
* @author Lion Li |
|||
*/ |
|||
public interface HttpStatus { |
|||
/** |
|||
* 操作成功 |
|||
*/ |
|||
int SUCCESS = 200; |
|||
|
|||
/** |
|||
* 对象创建成功 |
|||
*/ |
|||
int CREATED = 201; |
|||
|
|||
/** |
|||
* 请求已经被接受 |
|||
*/ |
|||
int ACCEPTED = 202; |
|||
|
|||
/** |
|||
* 操作已经执行成功,但是没有返回数据 |
|||
*/ |
|||
int NO_CONTENT = 204; |
|||
|
|||
/** |
|||
* 资源已被移除 |
|||
*/ |
|||
int MOVED_PERM = 301; |
|||
|
|||
/** |
|||
* 重定向 |
|||
*/ |
|||
int SEE_OTHER = 303; |
|||
|
|||
/** |
|||
* 资源没有被修改 |
|||
*/ |
|||
int NOT_MODIFIED = 304; |
|||
|
|||
/** |
|||
* 参数列表错误(缺少,格式不匹配) |
|||
*/ |
|||
int BAD_REQUEST = 400; |
|||
|
|||
/** |
|||
* 未授权 |
|||
*/ |
|||
int UNAUTHORIZED = 401; |
|||
|
|||
/** |
|||
* 访问受限,授权过期 |
|||
*/ |
|||
int FORBIDDEN = 403; |
|||
|
|||
/** |
|||
* 资源,服务未找到 |
|||
*/ |
|||
int NOT_FOUND = 404; |
|||
|
|||
/** |
|||
* 不允许的http方法 |
|||
*/ |
|||
int BAD_METHOD = 405; |
|||
|
|||
/** |
|||
* 资源冲突,或者资源被锁 |
|||
*/ |
|||
int CONFLICT = 409; |
|||
|
|||
/** |
|||
* 不支持的数据,媒体类型 |
|||
*/ |
|||
int UNSUPPORTED_TYPE = 415; |
|||
|
|||
/** |
|||
* 系统内部错误 |
|||
*/ |
|||
int ERROR = 500; |
|||
|
|||
/** |
|||
* 接口未实现 |
|||
*/ |
|||
int NOT_IMPLEMENTED = 501; |
|||
|
|||
/** |
|||
* 系统警告消息 |
|||
*/ |
|||
int WARN = 601; |
|||
} |
@ -0,0 +1,143 @@ |
|||
package com.jiagutech.ams.constant; |
|||
|
|||
/** |
|||
* 用户常量信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public interface UserConstants { |
|||
|
|||
/** |
|||
* 平台内系统用户的唯一标志 |
|||
*/ |
|||
String SYS_SESSION = "CURRENT_USER"; |
|||
|
|||
|
|||
/** |
|||
* 正常状态 |
|||
*/ |
|||
String NORMAL = "0"; |
|||
|
|||
/** |
|||
* 异常状态 |
|||
*/ |
|||
String EXCEPTION = "1"; |
|||
|
|||
/** |
|||
* 用户正常状态 |
|||
*/ |
|||
String USER_NORMAL = "0"; |
|||
|
|||
/** |
|||
* 用户封禁状态 |
|||
*/ |
|||
String USER_DISABLE = "1"; |
|||
|
|||
/** |
|||
* 角色正常状态 |
|||
*/ |
|||
String ROLE_NORMAL = "0"; |
|||
|
|||
/** |
|||
* 角色封禁状态 |
|||
*/ |
|||
String ROLE_DISABLE = "1"; |
|||
|
|||
/** |
|||
* 部门正常状态 |
|||
*/ |
|||
String DEPT_NORMAL = "0"; |
|||
|
|||
/** |
|||
* 部门停用状态 |
|||
*/ |
|||
String DEPT_DISABLE = "1"; |
|||
|
|||
/** |
|||
* 岗位正常状态 |
|||
*/ |
|||
String POST_NORMAL = "0"; |
|||
|
|||
/** |
|||
* 岗位停用状态 |
|||
*/ |
|||
String POST_DISABLE = "1"; |
|||
|
|||
/** |
|||
* 字典正常状态 |
|||
*/ |
|||
String DICT_NORMAL = "0"; |
|||
|
|||
/** |
|||
* 是否为系统默认(是) |
|||
*/ |
|||
String YES = "Y"; |
|||
|
|||
/** |
|||
* 是否菜单外链(是) |
|||
*/ |
|||
String YES_FRAME = "0"; |
|||
|
|||
/** |
|||
* 是否菜单外链(否) |
|||
*/ |
|||
String NO_FRAME = "1"; |
|||
|
|||
/** |
|||
* 菜单正常状态 |
|||
*/ |
|||
String MENU_NORMAL = "0"; |
|||
|
|||
/** |
|||
* 菜单停用状态 |
|||
*/ |
|||
String MENU_DISABLE = "1"; |
|||
|
|||
/** |
|||
* 菜单类型(目录) |
|||
*/ |
|||
String TYPE_DIR = "M"; |
|||
|
|||
/** |
|||
* 菜单类型(菜单) |
|||
*/ |
|||
String TYPE_MENU = "C"; |
|||
|
|||
/** |
|||
* 菜单类型(按钮) |
|||
*/ |
|||
String TYPE_BUTTON = "F"; |
|||
|
|||
/** |
|||
* Layout组件标识 |
|||
*/ |
|||
String LAYOUT = "Layout"; |
|||
|
|||
/** |
|||
* ParentView组件标识 |
|||
*/ |
|||
String PARENT_VIEW = "ParentView"; |
|||
|
|||
/** |
|||
* InnerLink组件标识 |
|||
*/ |
|||
String INNER_LINK = "InnerLink"; |
|||
|
|||
/** |
|||
* 用户名长度限制 |
|||
*/ |
|||
int USERNAME_MIN_LENGTH = 2; |
|||
int USERNAME_MAX_LENGTH = 20; |
|||
|
|||
/** |
|||
* 密码长度限制 |
|||
*/ |
|||
int PASSWORD_MIN_LENGTH = 5; |
|||
int PASSWORD_MAX_LENGTH = 20; |
|||
|
|||
/** |
|||
* 超级管理员ID |
|||
*/ |
|||
Long SUPER_ADMIN_ID = 1L; |
|||
|
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.jiagutech.ams.enums; |
|||
|
|||
/** |
|||
* 限流类型 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
|
|||
public enum LimitType { |
|||
/** |
|||
* 默认策略全局限流 |
|||
*/ |
|||
DEFAULT, |
|||
|
|||
/** |
|||
* 根据请求者IP进行限流 |
|||
*/ |
|||
IP, |
|||
|
|||
/** |
|||
* 实例限流(集群多后端实例) |
|||
*/ |
|||
CLUSTER |
|||
} |
@ -0,0 +1,62 @@ |
|||
package com.jiagutech.ams.exception; |
|||
|
|||
import lombok.Getter; |
|||
|
|||
@Getter |
|||
public enum BizCode implements CodeInterface { |
|||
General_Success(200, "接口调用成功"), |
|||
ServerError(10001, "服务器异常"), |
|||
General_Failure(10004, "接口调用失败"), |
|||
General_DBError(10005, "DB错误"), |
|||
General_ParameterInvalid(12001, "参数校验失败"), |
|||
/** |
|||
* 通用类 |
|||
*/ |
|||
USER_UNREGISTERED(12001, "用户未注册"), |
|||
NOT_FOUND(12002, "数据不存在"), |
|||
LOGIN_TYPE_ERROR(12005, "登录类型错误"), |
|||
|
|||
/** |
|||
* 文件服务 |
|||
*/ |
|||
FILE_DOWNLOAD_ERROR(90001, "文件下载错误"), |
|||
|
|||
FILE_UPLOAD_ERROR(90002, "文件上传失败"), |
|||
|
|||
|
|||
|
|||
USER_NOT_FOUND(40004, "用户不存在"), |
|||
|
|||
CAPTCHA_ERROR(40003, "验证码错误"), |
|||
|
|||
PASSWORD_ERROR(40002, "密码错误"), |
|||
|
|||
TOKEN_TIMEOUT_ERROR(40006, "token已过期"), |
|||
|
|||
USER_STOP_FOUND(40008, "用户被禁用"), |
|||
|
|||
USER_NOT_LOGIN(40011, "用户未登录,请登录后再操作"), |
|||
|
|||
ACCESS_TOKEN_INVALID(40040, "用户token无效,请重新登录"), |
|||
|
|||
ACCESS_NOT_ALLOWABLE(50001, "服务不允许直接访问"), |
|||
|
|||
PERMISSION_NOT_FOUND(40001,"该用户无操作权限"), |
|||
|
|||
USER_PHONE_EXIST(40012, "用户手机号已存在"), |
|||
|
|||
NOT_ALLOWABLE(13001, "当前正在作业中无法创建新的作业,请先完成作业任务后再创建") |
|||
|
|||
; |
|||
|
|||
|
|||
private final Integer code; |
|||
|
|||
private final String msg; |
|||
|
|||
BizCode(Integer code, String msg) { |
|||
this.code = code; |
|||
this.msg = msg; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,53 @@ |
|||
package com.jiagutech.ams.exception; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class BusinessException extends RuntimeException { |
|||
|
|||
private int code; |
|||
|
|||
private String message; |
|||
|
|||
public BusinessException( int code,String message) { |
|||
super(message); |
|||
this.code = code; |
|||
this.message = message; |
|||
} |
|||
|
|||
public BusinessException(String message, Throwable cause, int code, String message1) { |
|||
super(message, cause); |
|||
this.code = code; |
|||
this.message = message1; |
|||
} |
|||
|
|||
public BusinessException(Throwable cause, int code, String message) { |
|||
super(cause); |
|||
this.code = code; |
|||
this.message = message; |
|||
} |
|||
|
|||
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, int code, String message1) { |
|||
super(message, cause, enableSuppression, writableStackTrace); |
|||
this.code = code; |
|||
this.message = message1; |
|||
} |
|||
|
|||
public BusinessException(CodeInterface biz) { |
|||
super(); |
|||
this.code = biz.getCode(); |
|||
this.message = biz.getMsg(); |
|||
} |
|||
|
|||
public BusinessException(String message) { |
|||
super(message); |
|||
this.code= BizCode.General_ParameterInvalid.getCode(); |
|||
this.message =message; |
|||
} |
|||
|
|||
public BusinessException(BizCode biz, String msg) { |
|||
super(); |
|||
this.code = biz.getCode(); |
|||
this.message = msg; |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.exception; |
|||
|
|||
/** |
|||
* 业务异常接口 |
|||
*/ |
|||
public interface CodeInterface { |
|||
|
|||
/** |
|||
* 消息 |
|||
* |
|||
* @return String |
|||
*/ |
|||
String getMsg(); |
|||
|
|||
/** |
|||
* 业务代码 |
|||
* |
|||
* @return int |
|||
*/ |
|||
Integer getCode(); |
|||
|
|||
} |
@ -0,0 +1,26 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.RegionVO; |
|||
import com.jiagutech.ams.model.UserDetail; |
|||
import com.jiagutech.ams.model.dto.RegionDTO; |
|||
import com.jiagutech.ams.model.dto.UserDTO; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName UserMapper |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 15:50 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
public interface RegionMapper extends BaseMapper<UserDTO> { |
|||
|
|||
List<RegionDTO> getRegionsByParentCode(@Param("regionCode") long regionCode, @Param("level") int level); |
|||
|
|||
|
|||
RegionVO getCompleteRegionInfo(@Param("regionCode") long regionCode); |
|||
} |
@ -0,0 +1,34 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.dto.UserDTO; |
|||
import com.jiagutech.ams.model.UserDetail; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName UserMapper |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 15:50 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
public interface UserMapper extends BaseMapper<UserDTO> { |
|||
|
|||
|
|||
LoginUser selectLoginUserByPhone(@Param("phone") String phone); |
|||
|
|||
UserDetail selectUserDetail(@Param("userId") Long userId, @Param("phone") String phone); |
|||
|
|||
List<Long> getUserIdsByRegionCodes(@Param("regionCodes") List<Long> regionCodes); |
|||
|
|||
List<UserDTO> getUsersByLikeRegionPath( @Param("regionPath") String regionPath); |
|||
|
|||
|
|||
|
|||
Page<UserDetail> userPage(Page<UserDetail> page,@Param("ew") QueryWrapper<UserDetail> queryWrapper); |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName DeptItem |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 16:52 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class DeptItem { |
|||
@JsonSerialize(using = ToStringSerializer.class) |
|||
private String deptId; |
|||
private String deptName; |
|||
private Long managerId; |
|||
private String managerName; |
|||
private String managerPhone; |
|||
} |
@ -0,0 +1,97 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.jiagutech.ams.model.dto.DeptDTO; |
|||
import com.jiagutech.ams.model.dto.RoleDTO; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
|
|||
import java.io.Serial; |
|||
import java.io.Serializable; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName LoginUser |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 09:28 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@NoArgsConstructor |
|||
public class LoginUser implements Serializable { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
|
|||
/** |
|||
* 用户ID |
|||
*/ |
|||
private Long userId; |
|||
|
|||
/** |
|||
* 部门 |
|||
*/ |
|||
private DeptDTO dept; |
|||
|
|||
/** |
|||
* 用户唯一标识 |
|||
*/ |
|||
private String token; |
|||
|
|||
|
|||
/** |
|||
* 登录时间 |
|||
*/ |
|||
private Long loginTime; |
|||
|
|||
/** |
|||
* 过期时间 |
|||
*/ |
|||
private Long expireTime; |
|||
|
|||
/** |
|||
* 登录IP地址 |
|||
*/ |
|||
private String ipaddr; |
|||
|
|||
|
|||
/** |
|||
* 用户名 |
|||
*/ |
|||
private String username; |
|||
|
|||
/** |
|||
* 用户昵称 |
|||
*/ |
|||
private String nickName; |
|||
/** |
|||
* 手机号 |
|||
*/ |
|||
private String phone; |
|||
@JsonIgnore |
|||
private String password; |
|||
|
|||
private String email; |
|||
/** |
|||
* 头像 |
|||
*/ |
|||
private String avatar; |
|||
|
|||
private Long createTime; |
|||
|
|||
/** |
|||
* 角色对象 |
|||
*/ |
|||
private List<RoleDTO> roles; |
|||
|
|||
/** |
|||
* 区域编码 |
|||
*/ |
|||
private Long regionCode; |
|||
|
|||
private String regionPath; |
|||
|
|||
|
|||
} |
@ -0,0 +1,12 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class RegionVO { |
|||
private String regionCode; |
|||
private String regionName; |
|||
|
|||
} |
@ -0,0 +1,30 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
/** |
|||
* @ClassName UserDetailVO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 10:03 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
|
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
|||
import com.jiagutech.ams.model.dto.DeptDTO; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class UserDetail { |
|||
@JsonSerialize(using = ToStringSerializer.class) |
|||
private Long userId; |
|||
private String userName; |
|||
private String email; |
|||
private String phone; |
|||
private String nickName; |
|||
private DeptDTO dept; |
|||
private Long regionCode; |
|||
private String regionName; |
|||
private String userIdStr; |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.model.common; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName PageInfo |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 15:21 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class PageRequest<T> { |
|||
|
|||
private int pageNum; |
|||
private int pageSize; |
|||
private String oderByColumn; |
|||
|
|||
private T request; |
|||
|
|||
|
|||
} |
@ -0,0 +1,33 @@ |
|||
package com.jiagutech.ams.model.common; |
|||
|
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName PageResult |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 15:22 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class PageResult<T> { |
|||
private int total; |
|||
private int pageSize; |
|||
private int pageNum; |
|||
private int pages; |
|||
private List<T> records; |
|||
|
|||
public static <T> PageResult<T> of(int total, int pageSize, int pageNum, List<T> records) { |
|||
PageResult<T> pageResult = new PageResult<>(); |
|||
pageResult.setTotal(total); |
|||
pageResult.setPageSize(pageSize); |
|||
pageResult.setPageNum(pageNum); |
|||
pageResult.setPages(total % pageSize == 0 ? total / pageSize : total / pageSize + 1); |
|||
pageResult.setRecords(records); |
|||
return pageResult; |
|||
} |
|||
} |
@ -0,0 +1,111 @@ |
|||
package com.jiagutech.ams.model.common; |
|||
|
|||
|
|||
import com.jiagutech.ams.constant.HttpStatus; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
|
|||
import java.io.Serial; |
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* 响应信息主体 |
|||
* |
|||
* @author Lion Li |
|||
*/ |
|||
@Data |
|||
@NoArgsConstructor |
|||
public class R<T> implements Serializable { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 成功 |
|||
*/ |
|||
public static final int SUCCESS = 200; |
|||
|
|||
/** |
|||
* 失败 |
|||
*/ |
|||
public static final int FAIL = 500; |
|||
|
|||
private int code; |
|||
|
|||
private String msg; |
|||
|
|||
private T data; |
|||
|
|||
public static <T> R<T> ok() { |
|||
return restResult(null, SUCCESS, "操作成功"); |
|||
} |
|||
|
|||
public static <T> R<T> ok(T data) { |
|||
return restResult(data, SUCCESS, "操作成功"); |
|||
} |
|||
|
|||
public static <T> R<T> ok(String msg) { |
|||
return restResult(null, SUCCESS, msg); |
|||
} |
|||
|
|||
public static <T> R<T> ok(String msg, T data) { |
|||
return restResult(data, SUCCESS, msg); |
|||
} |
|||
|
|||
public static <T> R<T> fail() { |
|||
return restResult(null, FAIL, "操作失败"); |
|||
} |
|||
|
|||
public static <T> R<T> fail(String msg) { |
|||
return restResult(null, FAIL, msg); |
|||
} |
|||
|
|||
public static <T> R<T> fail(T data) { |
|||
return restResult(data, FAIL, "操作失败"); |
|||
} |
|||
|
|||
public static <T> R<T> fail(String msg, T data) { |
|||
return restResult(data, FAIL, msg); |
|||
} |
|||
|
|||
public static <T> R<T> fail(int code, String msg) { |
|||
return restResult(null, code, msg); |
|||
} |
|||
|
|||
/** |
|||
* 返回警告消息 |
|||
* |
|||
* @param msg 返回内容 |
|||
* @return 警告消息 |
|||
*/ |
|||
public static <T> R<T> warn(String msg) { |
|||
return restResult(null, HttpStatus.WARN, msg); |
|||
} |
|||
|
|||
/** |
|||
* 返回警告消息 |
|||
* |
|||
* @param msg 返回内容 |
|||
* @param data 数据对象 |
|||
* @return 警告消息 |
|||
*/ |
|||
public static <T> R<T> warn(String msg, T data) { |
|||
return restResult(data, HttpStatus.WARN, msg); |
|||
} |
|||
|
|||
private static <T> R<T> restResult(T data, int code, String msg) { |
|||
R<T> r = new R<>(); |
|||
r.setCode(code); |
|||
r.setData(data); |
|||
r.setMsg(msg); |
|||
return r; |
|||
} |
|||
|
|||
public static <T> Boolean isError(R<T> ret) { |
|||
return !isSuccess(ret); |
|||
} |
|||
|
|||
public static <T> Boolean isSuccess(R<T> ret) { |
|||
return R.SUCCESS == ret.getCode(); |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* @ClassName DeptDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 10:22 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@TableName("ams_dept") |
|||
public class DeptDTO implements Serializable { |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private Long id; |
|||
private String name; |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName RegionDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 17:59 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@TableName("region_info") |
|||
public class RegionDTO { |
|||
|
|||
private Long regionCode; |
|||
|
|||
private String regionName; |
|||
|
|||
private Integer level; |
|||
} |
@ -0,0 +1,26 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* @ClassName RoleDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 09:29 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@TableName("ams_role") |
|||
public class RoleDTO implements Serializable { |
|||
private static final long serialVersionUID = 1L; |
|||
@TableId |
|||
private Long id; |
|||
|
|||
private String name; |
|||
|
|||
private String key; |
|||
} |
@ -0,0 +1,28 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName UserDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 15:47 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@TableName("ams_user") |
|||
public class UserDTO { |
|||
@TableId |
|||
private Long id; |
|||
private String username; |
|||
private String password; |
|||
private String nickName; |
|||
private String email; |
|||
private String phone; |
|||
private Integer delFlag = 0; |
|||
private Long regionCode; |
|||
private String regionPath; |
|||
|
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.IdType; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
/** |
|||
* @ClassName UserDeptDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 09:58 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
@TableName("ams_user_dept") |
|||
public class UserDeptDTO { |
|||
|
|||
private Long userId; |
|||
|
|||
private Long deptId; |
|||
} |
@ -0,0 +1,25 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.IdType; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
/** |
|||
* @ClassName UserRoleDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 09:58 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
@TableName("ams_user_role") |
|||
public class UserRoleDTO { |
|||
|
|||
private Long userId; |
|||
|
|||
private Long roleId; |
|||
|
|||
} |
@ -0,0 +1,52 @@ |
|||
package com.jiagutech.ams.utils; |
|||
|
|||
import cn.hutool.core.convert.Convert; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import com.alibaba.excel.converters.Converter; |
|||
import com.alibaba.excel.enums.CellDataTypeEnum; |
|||
import com.alibaba.excel.metadata.GlobalConfiguration; |
|||
import com.alibaba.excel.metadata.data.ReadCellData; |
|||
import com.alibaba.excel.metadata.data.WriteCellData; |
|||
import com.alibaba.excel.metadata.property.ExcelContentProperty; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import java.math.BigDecimal; |
|||
|
|||
/** |
|||
* 大数值转换 |
|||
* Excel 数值长度位15位 大于15位的数值转换位字符串 |
|||
* |
|||
* @author Lion Li |
|||
*/ |
|||
@Slf4j |
|||
public class ExcelBigNumberConvert implements Converter<Long> { |
|||
|
|||
@Override |
|||
public Class<Long> supportJavaTypeKey() { |
|||
return Long.class; |
|||
} |
|||
|
|||
@Override |
|||
public CellDataTypeEnum supportExcelTypeKey() { |
|||
return CellDataTypeEnum.STRING; |
|||
} |
|||
|
|||
@Override |
|||
public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
|||
return Convert.toLong(cellData.getData()); |
|||
} |
|||
|
|||
@Override |
|||
public WriteCellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
|||
if (ObjectUtil.isNotNull(object)) { |
|||
String str = Convert.toStr(object); |
|||
if (str.length() > 15) { |
|||
return new WriteCellData<>(str); |
|||
} |
|||
} |
|||
WriteCellData<Object> cellData = new WriteCellData<>(new BigDecimal(object)); |
|||
cellData.setType(CellDataTypeEnum.NUMBER); |
|||
return cellData; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,49 @@ |
|||
package com.jiagutech.ams.utils; |
|||
|
|||
import cn.hutool.core.util.IdUtil; |
|||
import com.alibaba.excel.EasyExcel; |
|||
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; |
|||
import com.alibaba.excel.write.handler.impl.DefaultRowWriteHandler; |
|||
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; |
|||
import jakarta.servlet.ServletOutputStream; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
|
|||
import java.io.IOException; |
|||
import java.net.URLEncoder; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName ExcelUtil |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-04 10:28 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
public class ExcelUtil { |
|||
|
|||
|
|||
public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) { |
|||
try { |
|||
String filename = IdUtil.fastSimpleUUID() + "_" + sheetName + ".xlsx"; |
|||
String percentEncodedFileName = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20"); |
|||
String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName); |
|||
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); |
|||
response.setHeader("Content-disposition", contentDispositionValue); |
|||
response.setHeader("download-filename", percentEncodedFileName); |
|||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); |
|||
ServletOutputStream os = response.getOutputStream(); |
|||
ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) |
|||
.autoCloseStream(false) |
|||
// 自动适配
|
|||
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) |
|||
// 大数值自动转换 防止失真
|
|||
.registerConverter(new ExcelBigNumberConvert()) |
|||
.sheet(sheetName); |
|||
builder.registerWriteHandler(new DefaultRowWriteHandler()); |
|||
builder.doWrite(list); |
|||
} catch (IOException e) { |
|||
throw new RuntimeException("导出Excel异常"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
package com.jiagutech.ams.utils; |
|||
|
|||
import com.fasterxml.jackson.core.JsonParser; |
|||
import com.fasterxml.jackson.databind.DeserializationContext; |
|||
import com.fasterxml.jackson.databind.JsonDeserializer; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
public class StringToLongDeserializer extends JsonDeserializer<Long> { |
|||
|
|||
@Override |
|||
public Long deserialize(JsonParser jsonParser, DeserializationContext context) |
|||
throws IOException { |
|||
String value = jsonParser.getText(); |
|||
try { |
|||
return Long.parseLong(value); |
|||
} catch (NumberFormatException e) { |
|||
throw new IOException("Unable to parse value as Long: " + value, e); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,185 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>ams-social</artifactId> |
|||
<version>${revision}</version> |
|||
<packaging>pom</packaging> |
|||
<modules> |
|||
<module>system</module> |
|||
<module>social</module> |
|||
<module>web</module> |
|||
<module>common</module> |
|||
</modules> |
|||
<parent> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-parent</artifactId> |
|||
<version>3.1.7</version> |
|||
<relativePath/> |
|||
</parent> |
|||
<properties> |
|||
<java.version>17</java.version> |
|||
<lombok.version>1.18.30</lombok.version> |
|||
<revision>1.0.0-SNAPSHOT</revision> |
|||
<spring-boot.version>3.1.7</spring-boot.version> |
|||
<satoken.version>1.37.0</satoken.version> |
|||
<poi.version>5.2.5</poi.version> |
|||
|
|||
<easyexcel.version>3.3.2</easyexcel.version> |
|||
<springdoc.version>2.2.0</springdoc.version> |
|||
<hutool.version>5.8.22</hutool.version> |
|||
<mybatis-plus.version>3.5.5</mybatis-plus.version> |
|||
<spring-boot.mybatis>3.0.3</spring-boot.mybatis> |
|||
<fastjson.version>1.2.83</fastjson.version> |
|||
<mapstruct-plus.version>1.3.5</mapstruct-plus.version> |
|||
<!-- 插件版本 --> |
|||
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version> |
|||
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison> |
|||
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version> |
|||
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version> |
|||
</properties> |
|||
|
|||
<profiles> |
|||
<profile> |
|||
<id>dev</id> |
|||
<properties> |
|||
<!-- 环境标识,需要与配置文件的名称相对应 --> |
|||
<profiles.active>dev</profiles.active> |
|||
<logging.level>info</logging.level> |
|||
</properties> |
|||
<activation> |
|||
<!-- 默认环境 --> |
|||
<activeByDefault>true</activeByDefault> |
|||
</activation> |
|||
</profile> |
|||
<profile> |
|||
<id>prod</id> |
|||
<properties> |
|||
<profiles.active>prod</profiles.active> |
|||
<logging.level>info</logging.level> |
|||
</properties> |
|||
</profile> |
|||
</profiles> |
|||
<dependencyManagement> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-dependencies</artifactId> |
|||
<version>${spring-boot.version}</version> |
|||
<type>pom</type> |
|||
<scope>import</scope> |
|||
</dependency> |
|||
<!-- hutool 的依赖配置--> |
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-bom</artifactId> |
|||
<version>${hutool.version}</version> |
|||
<type>pom</type> |
|||
<scope>import</scope> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.alibaba.fastjson2</groupId> |
|||
<artifactId>fastjson2</artifactId> |
|||
<version>2.0.43</version> |
|||
</dependency> |
|||
<!-- 提供Redis连接池 --> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-pool2</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-spring-boot3-starter</artifactId> |
|||
<version>${satoken.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) --> |
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-redis-jackson</artifactId> |
|||
<version>${satoken.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-redis</artifactId> |
|||
<version>${satoken.version}</version> |
|||
</dependency> |
|||
<!-- Sa-Token 整合 jwt --> |
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-jwt</artifactId> |
|||
<version>${satoken.version}</version> |
|||
<exclusions> |
|||
<exclusion> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-all</artifactId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> |
|||
<version>${springdoc.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
|||
<version>${springdoc.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.projectlombok</groupId> |
|||
<artifactId>lombok</artifactId> |
|||
<version>${lombok.version}</version> |
|||
</dependency> |
|||
<!-- MyBatis Plus Starter --> |
|||
<dependency> |
|||
<groupId>com.baomidou</groupId> |
|||
<artifactId>mybatis-plus-boot-starter</artifactId> |
|||
<version>${mybatis-plus.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.baomidou</groupId> |
|||
<artifactId>mybatis-plus-extension</artifactId> |
|||
<version>${mybatis-plus.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>mysql</groupId> |
|||
<artifactId>mysql-connector-java</artifactId> |
|||
<version>8.0.33</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>druid-spring-boot-starter</artifactId> |
|||
<version>1.1.21</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi</artifactId> |
|||
<version>${poi.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi-ooxml</artifactId> |
|||
<version>${poi.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>easyexcel</artifactId> |
|||
<version>${easyexcel.version}</version> |
|||
<exclusions> |
|||
<exclusion> |
|||
<artifactId>poi-ooxml-schemas</artifactId> |
|||
<groupId>org.apache.poi</groupId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
</dependencies> |
|||
</dependencyManagement> |
|||
|
|||
</project> |
@ -0,0 +1,97 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<parent> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>ams-social</artifactId> |
|||
<version>${revision}</version> |
|||
</parent> |
|||
|
|||
<artifactId>social</artifactId> |
|||
|
|||
<properties> |
|||
<maven.compiler.source>17</maven.compiler.source> |
|||
<maven.compiler.target>17</maven.compiler.target> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
</properties> |
|||
|
|||
<profiles> |
|||
<profile> |
|||
<id>dev</id> |
|||
<properties> |
|||
<!-- 环境标识,需要与配置文件的名称相对应 --> |
|||
<profiles.active>dev</profiles.active> |
|||
<logging.level>info</logging.level> |
|||
</properties> |
|||
<activation> |
|||
<!-- 默认环境 --> |
|||
<activeByDefault>true</activeByDefault> |
|||
</activation> |
|||
</profile> |
|||
<profile> |
|||
<id>prod</id> |
|||
<properties> |
|||
<profiles.active>prod</profiles.active> |
|||
<logging.level>info</logging.level> |
|||
</properties> |
|||
</profile> |
|||
</profiles> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>common</artifactId> |
|||
<version>1.0.0-SNAPSHOT</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-jdbc</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>mysql</groupId> |
|||
<artifactId>mysql-connector-java</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-redis</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-validation</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.baomidou</groupId> |
|||
<artifactId>mybatis-plus-boot-starter</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-spring-boot3-starter</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi-ooxml</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>easyexcel</artifactId> |
|||
<exclusions> |
|||
<exclusion> |
|||
<artifactId>poi-ooxml-schemas</artifactId> |
|||
<groupId>org.apache.poi</groupId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
</dependencies> |
|||
</project> |
@ -0,0 +1,42 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import cn.dev33.satoken.annotation.SaCheckRole; |
|||
import com.jiagutech.ams.model.common.R; |
|||
import com.jiagutech.ams.model.response.DeviceInfo; |
|||
import com.jiagutech.ams.service.DeviceService; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName DeviceController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 20:26 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RequiredArgsConstructor |
|||
@RestController |
|||
@RequestMapping("/device") |
|||
@Tag(name = "设备", description = "农机管理") |
|||
public class DeviceController { |
|||
|
|||
private final DeviceService deviceService; |
|||
|
|||
@Operation(summary = "获取在线设备列表") |
|||
@GetMapping("/onlineAndRound") |
|||
@SaCheckRole("machinist") |
|||
public R<List<DeviceInfo>> onlineAndRound(@RequestParam(required = false, defaultValue = "0") double maxLng, |
|||
@RequestParam(required = false, defaultValue = "0") double maxLat, |
|||
@RequestParam(required = false, defaultValue = "0") double minLng, |
|||
@RequestParam(required = false, defaultValue = "0") double minLat) { |
|||
return R.ok(deviceService.onlineAndRound(maxLng, maxLat, minLng, minLat)); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,83 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import cn.dev33.satoken.annotation.SaCheckRole; |
|||
import cn.dev33.satoken.annotation.SaMode; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.common.R; |
|||
import com.jiagutech.ams.model.dto.JobTypeDTO; |
|||
import com.jiagutech.ams.model.request.JobCreateRequest; |
|||
import com.jiagutech.ams.model.request.JobPageRequest; |
|||
import com.jiagutech.ams.model.response.JobCreateResponse; |
|||
import com.jiagutech.ams.model.response.JobItem; |
|||
import com.jiagutech.ams.model.response.JobTypeItem; |
|||
import com.jiagutech.ams.service.JobService; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName JobController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 19:29 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RequiredArgsConstructor |
|||
@RestController |
|||
@RequestMapping("/job") |
|||
@Tag(name = "作业", description = "作业管理") |
|||
public class JobController { |
|||
private final JobService jobService; |
|||
|
|||
@GetMapping("/types") |
|||
@Operation(summary = "作业类型列表") |
|||
public R<List<JobTypeDTO>> getJobTypes() { |
|||
return R.ok(jobService.getJobTypes()); |
|||
} |
|||
@Operation(summary = "创建作业记录") |
|||
@PostMapping("/start") |
|||
@SaCheckRole("machinist") |
|||
public R<JobCreateResponse> createJob(@RequestBody JobCreateRequest jobCreateRequest) { |
|||
return R.ok(jobService.createJob(jobCreateRequest)); |
|||
} |
|||
|
|||
@Operation(summary = "更新作业状态") |
|||
@SaCheckRole(value = {"machinist", "admin"}, mode = SaMode.OR) |
|||
@PutMapping("/status") |
|||
public R<Void> updateJobStatus(@RequestParam("jobId") Long jobId, @RequestParam("status") Integer status) { |
|||
jobService.updateJobStatus(jobId, status); |
|||
return R.ok(); |
|||
} |
|||
|
|||
@Operation(summary = "分页获取作业列表") |
|||
@SaCheckRole(value = {"machinist","gov","manager"}, mode = SaMode.OR) |
|||
@PostMapping("/page") |
|||
public R<PageResult<JobItem>> getPages(@RequestBody PageRequest<JobPageRequest> pageRequest) { |
|||
return R.ok(jobService.getPages(pageRequest)); |
|||
} |
|||
|
|||
@Operation(summary = "获取当前作业任务") |
|||
@SaCheckRole("machinist") |
|||
@GetMapping("/inWorking") |
|||
public R<JobItem> inJob() { |
|||
return R.ok(CollectionUtil.isNotEmpty(jobService.inJob()) ? jobService.inJob().get(0) : null); |
|||
} |
|||
|
|||
|
|||
@PostMapping("/export") |
|||
@Operation(summary = "导出作业记录") |
|||
public void exportJobs(@RequestBody(required = false) JobPageRequest jobPageRequest, HttpServletResponse response){ |
|||
jobService.exportJobs(jobPageRequest, response); |
|||
} |
|||
@PostMapping("/exportByFarmer") |
|||
@Operation(summary = "导出作业记录") |
|||
public void exportByFarmer(@RequestBody(required = false) JobPageRequest jobPageRequest, HttpServletResponse response){ |
|||
jobService.exportByFarmer(jobPageRequest, response); |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
/** |
|||
* @ClassName RegionController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 14:32 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RestController |
|||
@RequestMapping("/region") |
|||
@RequiredArgsConstructor |
|||
@Tag(name = "区域", description = "区域管理接口") |
|||
public class RegionController { |
|||
|
|||
|
|||
} |
@ -0,0 +1,21 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
/** |
|||
* @ClassName TrackController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-03 16:07 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RestController |
|||
@RequestMapping("/track") |
|||
@Tag(name = "轨迹") |
|||
public class TrackController { |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,11 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.jiagutech.ams.model.response.DeviceInfo; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface DeviceMapper { |
|||
|
|||
List<DeviceInfo> queryDeviceList(Long detpId); |
|||
|
|||
} |
@ -0,0 +1,21 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.jiagutech.ams.model.dto.JobDTO; |
|||
import com.jiagutech.ams.model.response.JobItem; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface JobMapper extends BaseMapper<JobDTO> { |
|||
|
|||
|
|||
Page<JobItem> jobPage(Page<JobItem> page, @Param("ew") QueryWrapper wrapper); |
|||
|
|||
List<JobItem> jobList(@Param("ew") QueryWrapper wrapper); |
|||
|
|||
List<JobItem> jobListCountByFarmer(@Param("ew") QueryWrapper wrapper); |
|||
} |
@ -0,0 +1,9 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.jiagutech.ams.model.dto.JobTypeDTO; |
|||
|
|||
public interface JobTypeMapper extends BaseMapper<JobTypeDTO> { |
|||
|
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
import com.jiagutech.ams.model.dto.JobDTO; |
|||
import com.jiagutech.ams.model.request.JobCreateRequest; |
|||
import com.jiagutech.ams.model.response.JobCreateResponse; |
|||
import org.mapstruct.Mapper; |
|||
import org.mapstruct.factory.Mappers; |
|||
|
|||
@Mapper |
|||
public interface JobMapping { |
|||
JobMapping INSTANCE = Mappers.getMapper(JobMapping.class); |
|||
|
|||
JobDTO jobCreateToJobDTO(JobCreateRequest job); |
|||
|
|||
JobCreateResponse jobDTOToJobCreateResponse(JobDTO job); |
|||
} |
@ -0,0 +1,120 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Data |
|||
public class TrackDataJG implements Serializable { |
|||
|
|||
|
|||
private String droneId; |
|||
|
|||
/** |
|||
* 架次ID |
|||
*/ |
|||
//替换Int-long
|
|||
//private Integer sortieId;
|
|||
private Long sortieId; |
|||
|
|||
/** |
|||
* 该记录点数据产生的时间 |
|||
*/ |
|||
private Long timeStamp; |
|||
|
|||
/** |
|||
* 纬度 |
|||
*/ |
|||
private Double lat; |
|||
|
|||
/** |
|||
* 经度 |
|||
*/ |
|||
private Double lng; |
|||
|
|||
/** |
|||
* 海拔高度,单位:米 |
|||
*/ |
|||
private Float alt; |
|||
|
|||
/** |
|||
* 当前相对于作物冠层的高度,单位:米 |
|||
*/ |
|||
private Float height; |
|||
|
|||
/** |
|||
* 飞行方向水平速度,单位:米/秒 |
|||
*/ |
|||
private Float hvel; |
|||
|
|||
/** |
|||
* 飞行方向垂直速度,单位:米/秒 |
|||
*/ |
|||
private Float vvel; |
|||
|
|||
/** |
|||
* 航向角.无人机飞行方向与地球北极之间的夹角,(-180 度,180 度],单位为 0.01 度 |
|||
*/ |
|||
private Float yaw; |
|||
|
|||
/** |
|||
* 俯仰角。无人机机体坐标系 x 轴与水平面的夹角。当 x 轴的正半轴位于过坐标原点的 |
|||
* 水平面之上时,俯仰角为正;否则为负。单位为 0.01 度 |
|||
*/ |
|||
private Float pitch; |
|||
|
|||
/** |
|||
* 横滚角。无人机机体坐标系 y 轴与水平面的夹角。当 y 轴的正半轴位于过坐标原点的 |
|||
* 水平面之上时,俯仰角为正;否则为负。单位为 0.01 度 |
|||
*/ |
|||
private Float roll; |
|||
|
|||
/** |
|||
* 本架次起飞后,已飞行的时间。单位:秒 |
|||
*/ |
|||
private Integer ftime; |
|||
|
|||
/** |
|||
* 本架次起飞后,已喷洒的面积。单位:亩 |
|||
*/ |
|||
private Float farea; |
|||
|
|||
/** |
|||
* 喷洒流速,单位:升/分钟 |
|||
*/ |
|||
private Float curFlow; |
|||
|
|||
/** |
|||
* 目前接收到的导航卫星的数量 |
|||
*/ |
|||
private Integer gpsNum; |
|||
|
|||
/** |
|||
* 定位精度类型,1:GPS/BD 单点,2:差分,4:RTK 固定解,5:RTK 浮点解 |
|||
*/ |
|||
private Integer posAccur; |
|||
|
|||
private Integer areaCode; |
|||
|
|||
private Integer flying;//1=正在飞 0在地上
|
|||
|
|||
//替换 int - long
|
|||
//private Integer operUserId;
|
|||
private Long operUserId; |
|||
|
|||
private Float totalArea;//飞控总亩数
|
|||
|
|||
private Integer errorCode; |
|||
|
|||
private Integer deviceType; |
|||
|
|||
// 耕深(厘米)[浮点数,最多保留一位小数]
|
|||
private Double deep; |
|||
// 流量(脉冲值)[浮点数,最多保留一位小数]
|
|||
private Double flow; |
|||
// 播种速度 粒/s生成对应的实体类
|
|||
private Double seeding; |
|||
|
|||
|
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName DeviceDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 19:40 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@TableName("ams_device_info") |
|||
public class DeviceDTO { |
|||
|
|||
private Long id; |
|||
|
|||
private String deviceNum; |
|||
|
|||
private String boxNum; |
|||
|
|||
private Long deptId; |
|||
} |
@ -0,0 +1,44 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
/** |
|||
* @ClassName JobDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 19:35 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
@TableName("ams_job_info") |
|||
public class JobDTO { |
|||
@TableId |
|||
private Long id; |
|||
|
|||
private Long deviceId; |
|||
|
|||
private Long startTime; |
|||
|
|||
private Long endTime; |
|||
|
|||
private Long operatorId; |
|||
|
|||
private Long farmerId; |
|||
|
|||
private Float area; |
|||
|
|||
private Long regionCode; |
|||
|
|||
private Float duration; |
|||
|
|||
private Integer status; |
|||
|
|||
private Integer jobType; |
|||
|
|||
private Long deptId; |
|||
|
|||
} |
@ -0,0 +1,23 @@ |
|||
package com.jiagutech.ams.model.dto; |
|||
|
|||
import com.baomidou.mybatisplus.annotation.IdType; |
|||
import com.baomidou.mybatisplus.annotation.TableField; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName JobTypeDTO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-03 15:03 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@TableName("ams_job_type") |
|||
public class JobTypeDTO { |
|||
@TableId(value = "id", type = IdType.AUTO) |
|||
private Integer typeId; |
|||
@TableField(value = "name") |
|||
private String typeName; |
|||
} |
@ -0,0 +1,46 @@ |
|||
package com.jiagutech.ams.model.request; |
|||
|
|||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; |
|||
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; |
|||
import com.jiagutech.ams.utils.StringToLongDeserializer; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
/** |
|||
* @ClassName JobCreateRequest |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 19:31 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class JobCreateRequest { |
|||
|
|||
private long startTime; |
|||
/** |
|||
* 机手 |
|||
*/ |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long operatorId; |
|||
/** |
|||
* 农户ID |
|||
*/ |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long farmerId; |
|||
/** |
|||
* 区域 |
|||
*/ |
|||
private long regionCode; |
|||
/** |
|||
* 设备ID |
|||
*/ |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long deviceId; |
|||
/** |
|||
* 作业类型 |
|||
*/ |
|||
private int jobType; |
|||
|
|||
|
|||
} |
@ -0,0 +1,35 @@ |
|||
package com.jiagutech.ams.model.request; |
|||
|
|||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; |
|||
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; |
|||
import com.jiagutech.ams.utils.StringToLongDeserializer; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName JobPageRequest |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 15:18 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class JobPageRequest { |
|||
private long startTimeBegin; |
|||
|
|||
private long startTimeEnd; |
|||
|
|||
private long regionCode; |
|||
|
|||
private int JobType; |
|||
|
|||
private int status; |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long operatorId; |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long farmerId; |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long deviceId; |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private long deptId; |
|||
|
|||
} |
@ -0,0 +1,31 @@ |
|||
package com.jiagutech.ams.model.response; |
|||
|
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
/** |
|||
* @ClassName DeviceInfo |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-03 16:26 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class DeviceInfo { |
|||
@JsonSerialize(using = ToStringSerializer.class) |
|||
private long deviceId; |
|||
|
|||
private double lat; |
|||
|
|||
private double lng; |
|||
|
|||
private int status; |
|||
|
|||
private String deviceNum; |
|||
|
|||
private String boxNum; |
|||
|
|||
} |
@ -0,0 +1,30 @@ |
|||
package com.jiagutech.ams.model.response; |
|||
|
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
|||
import lombok.Data; |
|||
import lombok.experimental.Accessors; |
|||
|
|||
/** |
|||
* @ClassName JobVO |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 19:31 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
@Accessors(chain = true) |
|||
public class JobCreateResponse { |
|||
@JsonSerialize(using = ToStringSerializer.class) |
|||
private long jobId; |
|||
|
|||
private long startTime; |
|||
|
|||
private long farmerId; |
|||
|
|||
private long deviceId; |
|||
|
|||
private Integer status; |
|||
|
|||
|
|||
} |
@ -0,0 +1,54 @@ |
|||
package com.jiagutech.ams.model.response; |
|||
|
|||
import com.alibaba.excel.annotation.ExcelIgnore; |
|||
import com.alibaba.excel.annotation.ExcelProperty; |
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName JobItem |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 15:18 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class JobItem { |
|||
@ExcelIgnore |
|||
@JsonSerialize(using = ToStringSerializer.class) |
|||
private Long jobId; |
|||
@ExcelIgnore |
|||
private Long operatorId; |
|||
@ExcelProperty(value = "机手") |
|||
private String operatorName; |
|||
@ExcelIgnore |
|||
private Long farmerId; |
|||
@ExcelProperty(value = "农户") |
|||
private String farmerName; |
|||
@ExcelIgnore |
|||
private Long startTime; |
|||
@ExcelIgnore |
|||
private Long endTime; |
|||
|
|||
@ExcelProperty(value = "开始作业时间") |
|||
private String startTimeStr; |
|||
|
|||
@ExcelProperty(value = "作业面积") |
|||
private Float area; |
|||
@ExcelIgnore |
|||
private Integer status; |
|||
@ExcelIgnore |
|||
private Integer JobType; |
|||
|
|||
@ExcelProperty(value = "作业类型") |
|||
private String typeName; |
|||
@ExcelIgnore |
|||
private Long deviceId; |
|||
@ExcelIgnore |
|||
private long deptId; |
|||
@ExcelProperty(value = "合作社") |
|||
private String deptName; |
|||
|
|||
|
|||
} |
@ -0,0 +1,18 @@ |
|||
package com.jiagutech.ams.model.response; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName JobTypeItem |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-03 15:02 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class JobTypeItem { |
|||
|
|||
private Integer id; |
|||
|
|||
private String name; |
|||
} |
@ -0,0 +1,23 @@ |
|||
package com.jiagutech.ams.rest; |
|||
|
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.client.RestTemplate; |
|||
|
|||
/** |
|||
* @ClassName CenterClient |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-03 16:32 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Component |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public class CenterRestClient { |
|||
private final RestTemplate restTemplate; |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,9 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import com.jiagutech.ams.model.response.DeviceInfo; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface DeviceService { |
|||
List<DeviceInfo> onlineAndRound(double maxLng, double maxLat, double minLng, double minLat); |
|||
} |
@ -0,0 +1,68 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import cn.dev33.satoken.annotation.SaCheckLogin; |
|||
import cn.dev33.satoken.annotation.SaCheckRole; |
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import com.alibaba.fastjson2.JSON; |
|||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import com.jiagutech.ams.mapper.DeviceMapper; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.TrackDataJG; |
|||
import com.jiagutech.ams.model.response.DeviceInfo; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.data.redis.core.StringRedisTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.*; |
|||
import java.util.function.Consumer; |
|||
import java.util.function.Predicate; |
|||
|
|||
/** |
|||
* @ClassName DeviceServiceImpl |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-03 16:46 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Slf4j |
|||
@Service |
|||
@RequiredArgsConstructor |
|||
public class DeviceServiceImpl implements DeviceService { |
|||
public static final String TRACK_PREFIX_REDIS_KEY = "mtrack:*"; |
|||
private final StringRedisTemplate stringRedisTemplate; |
|||
private final DeviceMapper deviceMapper; |
|||
|
|||
@Override |
|||
public List<DeviceInfo> onlineAndRound(double maxLng, double maxLat, double minLng, double minLat) { |
|||
Set<String> keys = stringRedisTemplate.keys(TRACK_PREFIX_REDIS_KEY); |
|||
List<DeviceInfo> deviceInfos = new ArrayList<>(); |
|||
if (CollectionUtils.isNotEmpty(keys)) { |
|||
List<String> values = stringRedisTemplate.opsForValue().multiGet(keys); |
|||
List<TrackDataJG> trackDataJGS = JSON.parseArray(JSON.toJSONString(values), TrackDataJG.class); |
|||
Predicate<TrackDataJG> predicate = t -> t.getLat() <= maxLat && t.getLat() >= minLat |
|||
&& ((t.getLng() >= -180 && t.getLng() <= maxLng) || (t.getLng() >= minLng && t.getLng() <= 180)); |
|||
Consumer<TrackDataJG> consumer = t -> deviceInfos.add(new DeviceInfo().setBoxNum(t.getDroneId()).setLng(t.getLng()).setLat(t.getLat())); |
|||
trackDataJGS.stream().filter(predicate).forEach(consumer); |
|||
LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); |
|||
if (loginUser != null && loginUser.getDept() != null) { |
|||
long deptId = loginUser.getDept().getId(); |
|||
List<DeviceInfo> deviceInfos1 = deviceMapper.queryDeviceList(deptId); |
|||
|
|||
Iterator<DeviceInfo> iterator = deviceInfos.iterator(); |
|||
while (iterator.hasNext()) { |
|||
DeviceInfo deviceInfo = iterator.next(); |
|||
Predicate<DeviceInfo> p = d -> d.getBoxNum().equals(deviceInfo.getBoxNum()); |
|||
Optional<DeviceInfo> exists = deviceInfos1.stream().filter(p).findFirst(); |
|||
if (!exists.isPresent()) { |
|||
iterator.remove(); |
|||
continue; |
|||
} |
|||
deviceInfo.setDeviceId(exists.get().getDeviceId()).setStatus(exists.get().getStatus()); |
|||
} |
|||
} |
|||
} |
|||
return deviceInfos; |
|||
} |
|||
} |
@ -0,0 +1,28 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.dto.JobTypeDTO; |
|||
import com.jiagutech.ams.model.request.JobCreateRequest; |
|||
import com.jiagutech.ams.model.request.JobPageRequest; |
|||
import com.jiagutech.ams.model.response.JobCreateResponse; |
|||
import com.jiagutech.ams.model.response.JobItem; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface JobService { |
|||
JobCreateResponse createJob(JobCreateRequest jobCreateRequest); |
|||
|
|||
void updateJobStatus(Long jobId, Integer status); |
|||
|
|||
PageResult<JobItem> getPages(PageRequest<JobPageRequest> pageRequest); |
|||
|
|||
List<JobItem> inJob(); |
|||
|
|||
List<JobTypeDTO> getJobTypes(); |
|||
|
|||
void exportJobs(JobPageRequest jobPageRequest, HttpServletResponse response); |
|||
|
|||
void exportByFarmer(JobPageRequest jobPageRequest, HttpServletResponse response); |
|||
} |
@ -0,0 +1,169 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.alibaba.excel.EasyExcel; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
|||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import com.jiagutech.ams.exception.BizCode; |
|||
import com.jiagutech.ams.exception.BusinessException; |
|||
import com.jiagutech.ams.mapper.JobMapper; |
|||
import com.jiagutech.ams.mapper.JobTypeMapper; |
|||
import com.jiagutech.ams.mapper.RegionMapper; |
|||
import com.jiagutech.ams.mapper.UserMapper; |
|||
import com.jiagutech.ams.model.JobMapping; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.dto.JobDTO; |
|||
import com.jiagutech.ams.model.dto.JobTypeDTO; |
|||
import com.jiagutech.ams.model.dto.RegionDTO; |
|||
import com.jiagutech.ams.model.dto.RoleDTO; |
|||
import com.jiagutech.ams.model.request.JobCreateRequest; |
|||
import com.jiagutech.ams.model.request.JobPageRequest; |
|||
import com.jiagutech.ams.model.response.JobCreateResponse; |
|||
import com.jiagutech.ams.model.response.JobItem; |
|||
import com.jiagutech.ams.utils.ExcelUtil; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.poi.util.StringUtil; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.UnsupportedEncodingException; |
|||
import java.net.URLEncoder; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.function.Predicate; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* @ClassName JobServiceImpl |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 19:34 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Slf4j |
|||
@Service |
|||
@RequiredArgsConstructor |
|||
public class JobServiceImpl implements JobService { |
|||
private final JobMapper jobMapper; |
|||
private final UserMapper userMapper; |
|||
private final RegionMapper regionMapper; |
|||
|
|||
private final JobTypeMapper jobTypeMapper; |
|||
|
|||
@Override |
|||
public JobCreateResponse createJob(JobCreateRequest jobCreateRequest) { |
|||
LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); |
|||
log.info("create job, loginUser: {}", loginUser); |
|||
if (CollectionUtil.isNotEmpty(inJob())) { |
|||
throw new BusinessException(BizCode.NOT_ALLOWABLE); |
|||
} |
|||
JobDTO jobDTO = JobMapping.INSTANCE.jobCreateToJobDTO(jobCreateRequest); |
|||
jobDTO.setStartTime(System.currentTimeMillis()); |
|||
jobDTO.setArea(0f); |
|||
jobDTO.setStatus(1); |
|||
jobDTO.setOperatorId(StpUtil.getLoginIdAsLong()); |
|||
jobDTO.setDeptId(loginUser.getDept().getId()); |
|||
jobDTO.setRegionCode(userMapper.selectById(jobCreateRequest.getFarmerId()).getRegionCode()); |
|||
jobMapper.insert(jobDTO); |
|||
return JobMapping.INSTANCE.jobDTOToJobCreateResponse(jobDTO); |
|||
} |
|||
|
|||
@Override |
|||
public void updateJobStatus(Long jobId, Integer status) { |
|||
JobDTO jobDTO = new JobDTO().setId(jobId).setStatus(status).setEndTime(System.currentTimeMillis()); |
|||
jobMapper.updateById(jobDTO); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public PageResult<JobItem> getPages(PageRequest<JobPageRequest> pageRequest) { |
|||
JobPageRequest requestParam = pageRequest.getRequest(); |
|||
QueryWrapper<JobItem> queryWrapper = buildQueryWrapper(requestParam); |
|||
Page<JobItem> page = new Page(pageRequest.getPageNum(), pageRequest.getPageSize()); |
|||
Page<JobItem> result = jobMapper.jobPage(page, queryWrapper); |
|||
return PageResult.of((int) result.getTotal(), (int) result.getSize(), (int) result.getCurrent(), result.getRecords()); |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public List<JobItem> inJob() { |
|||
QueryWrapper<JobItem> queryWrapper = Wrappers.query(); |
|||
queryWrapper.eq("operator_id", StpUtil.getLoginIdAsLong()).eq("status", 1); |
|||
return jobMapper.jobList(queryWrapper); |
|||
} |
|||
|
|||
@Override |
|||
public List<JobTypeDTO> getJobTypes() { |
|||
QueryWrapper<JobTypeDTO> queryWrapper = Wrappers.query(); |
|||
return jobTypeMapper.selectList(queryWrapper); |
|||
} |
|||
|
|||
@Override |
|||
public void exportJobs(JobPageRequest jobPageRequest, HttpServletResponse response) { |
|||
QueryWrapper<JobItem> queryWrapper = buildQueryWrapper(jobPageRequest); |
|||
List<JobItem> jobItems = jobMapper.jobList(queryWrapper); |
|||
ExcelUtil.exportExcel(jobItems, "作业记录", JobItem.class, response); |
|||
} |
|||
|
|||
@Override |
|||
public void exportByFarmer(JobPageRequest jobPageRequest, HttpServletResponse response) { |
|||
QueryWrapper<JobItem> queryWrapper = buildQueryWrapper(jobPageRequest); |
|||
List<JobItem> jobItems = jobMapper.jobListCountByFarmer(queryWrapper); |
|||
ExcelUtil.exportExcel(jobItems, "作业记录", JobItem.class, response); |
|||
} |
|||
|
|||
|
|||
private QueryWrapper<JobItem> buildQueryWrapper(JobPageRequest requestParam) { |
|||
|
|||
QueryWrapper queryWrapper = Wrappers.query(); |
|||
if (requestParam != null) { |
|||
if (requestParam.getStartTimeBegin() != 0l && requestParam.getStartTimeEnd() != 0l) { |
|||
queryWrapper.between("j.start_time", requestParam.getStartTimeBegin(), requestParam.getStartTimeEnd()); |
|||
} |
|||
if (requestParam.getJobType() != 0) { |
|||
queryWrapper.eq("j.job_type", requestParam.getJobType()); |
|||
} |
|||
if (requestParam.getStatus() != 0) { |
|||
queryWrapper.eq("j.status", requestParam.getStatus()); |
|||
} |
|||
if (requestParam.getOperatorId() != 0l) { |
|||
queryWrapper.eq("j.operator_id", requestParam.getOperatorId()); |
|||
} |
|||
if (requestParam.getFarmerId() != 0l) { |
|||
queryWrapper.eq("j.farmer_id", requestParam.getFarmerId()); |
|||
} |
|||
} |
|||
|
|||
|
|||
LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); |
|||
Predicate<RoleDTO> predicate1 = r -> r.getKey().equals("manager"); |
|||
Predicate<RoleDTO> predicate2 = r -> r.getKey().equals("gov"); |
|||
Predicate<RoleDTO> predicate3 = r -> r.getKey().equals("machinist"); |
|||
|
|||
boolean hasManager = loginUser.getRoles().stream().anyMatch(predicate1); |
|||
boolean hasGov = loginUser.getRoles().stream().anyMatch(predicate2); |
|||
boolean hasMachinist = loginUser.getRoles().stream().anyMatch(predicate3); |
|||
if (hasManager) { |
|||
queryWrapper.eq("j.dept_id", loginUser.getDept().getId()); |
|||
} |
|||
if (hasGov && loginUser.getRegionCode() != null && StringUtils.isNotBlank(loginUser.getRegionPath())) { |
|||
List<Long> farmerIds = userMapper.getUsersByLikeRegionPath(loginUser.getRegionPath()).stream().map(u -> u.getId()).collect(Collectors.toList()); |
|||
queryWrapper.in("j.farmer_id", farmerIds); |
|||
if (requestParam != null && requestParam.getDeptId() != 0l) { |
|||
queryWrapper.eq("d.id", requestParam.getDeptId()); |
|||
} |
|||
} |
|||
if (hasMachinist) { |
|||
queryWrapper.eq("j.operator_id", loginUser.getUserId()); |
|||
} |
|||
return queryWrapper; |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
<?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="com.jiagutech.ams.mapper.DeviceMapper"> |
|||
|
|||
|
|||
<select id="queryDeviceList" resultType="com.jiagutech.ams.model.response.DeviceInfo"> |
|||
select d.id as deviceId, d.device_num, d.box_num, d.dept_id, case when j.status = 1 then 1 else 0 end as status |
|||
from ams_device_info d |
|||
left join ams_job_info j on d.id = j.device_id |
|||
where d.dept_id = #{deptId} |
|||
</select> |
|||
</mapper> |
@ -0,0 +1,53 @@ |
|||
<?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="com.jiagutech.ams.mapper.JobMapper"> |
|||
|
|||
<sql id="jobItem"> |
|||
select j.id as job_id, |
|||
j.start_time, |
|||
j.end_time, |
|||
j.area, |
|||
j.status, |
|||
j.device_id, |
|||
j.operator_id, |
|||
FROM_UNIXTIME(j.start_time/1000,'%Y-%m-%d %H:%i:%s') as start_time_str, |
|||
u1.nick_name as operator_name, |
|||
j.farmer_id, |
|||
u2.nick_name as farmer_name, |
|||
j.job_type, |
|||
t.name as type_name, |
|||
d.id as dept_id, |
|||
d.name as dept_name |
|||
from ams_job_info j |
|||
left join ams_job_type t on j.job_type = t.id |
|||
left join ams_dept d on j.dept_id=d.id |
|||
left join ams_user u1 on j.operator_id = u1.id |
|||
left join ams_user u2 on j.farmer_id = u2.id |
|||
|
|||
|
|||
</sql> |
|||
|
|||
<select id="jobPage" resultType="com.jiagutech.ams.model.response.JobItem"> |
|||
<include refid="jobItem"></include> |
|||
${ew.getCustomSqlSegment} |
|||
</select> |
|||
|
|||
<select id="jobList" resultType="com.jiagutech.ams.model.response.JobItem"> |
|||
<include refid="jobItem"></include> |
|||
${ew.getCustomSqlSegment} |
|||
order by j.farmer_id,j.start_time |
|||
</select> |
|||
<select id="jobListCountByFarmer" resultType="com.jiagutech.ams.model.response.JobItem"> |
|||
select ROUND(sum(j.area),2) as area,j.farmer_id, |
|||
u2.nick_name as farmer_name, |
|||
j.job_type,t.name as type_name, |
|||
d.id as dept_id, |
|||
d.name as dept_name |
|||
from ams_job_info j |
|||
left join ams_job_type t on j.job_type = t.id |
|||
left join ams_dept d on j.dept_id=d.id |
|||
left join ams_user u2 on j.farmer_id = u2.id |
|||
${ew.getCustomSqlSegment} |
|||
group by j.farmer_id,j.job_type,t.name,d.id,d.name,u2.nick_name |
|||
</select> |
|||
</mapper> |
@ -0,0 +1,47 @@ |
|||
<?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="com.jiagutech.ams.mapper.RegionMapper"> |
|||
|
|||
|
|||
<select id="getRegionsByParentCode" resultType="com.jiagutech.ams.model.dto.RegionDTO"> |
|||
WITH RECURSIVE cte AS ( |
|||
SELECT r1.region_code,r1.parent_code, r1.region_name, r1.level |
|||
FROM region_info r1 |
|||
WHERE r1.region_code = #{regionCode} |
|||
UNION ALL |
|||
SELECT r2.region_code,r2.parent_code, r2.region_name, r2.level |
|||
FROM region_info r2 |
|||
JOIN cte ON r2.parent_code = cte.region_code |
|||
where r2.level <= ${level} |
|||
) |
|||
|
|||
select region_code,region_name from cte; |
|||
</select> |
|||
|
|||
|
|||
<select id="getCompleteRegionInfo" resultType="com.jiagutech.ams.model.RegionVO"> |
|||
WITH RECURSIVE cte AS ( |
|||
SELECT |
|||
region_code, |
|||
parent_code, |
|||
region_name, |
|||
level |
|||
FROM region_info |
|||
WHERE region_code=#{regionCode} |
|||
UNION ALL |
|||
|
|||
|
|||
SELECT |
|||
u.region_code, |
|||
u.parent_code, |
|||
u.region_name, |
|||
u.level |
|||
FROM region_info u |
|||
INNER JOIN cte p ON u.region_code = p.parent_code |
|||
) |
|||
SELECT |
|||
GROUP_CONCAT(region_code ORDER BY level SEPARATOR '->') AS region_code, |
|||
GROUP_CONCAT(region_name ORDER BY level SEPARATOR '->') AS regionName |
|||
from cte |
|||
</select> |
|||
</mapper> |
@ -0,0 +1,75 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<parent> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>ams-social</artifactId> |
|||
<version>${revision}</version> |
|||
</parent> |
|||
|
|||
<artifactId>system</artifactId> |
|||
|
|||
<properties> |
|||
<maven.compiler.source>17</maven.compiler.source> |
|||
<maven.compiler.target>17</maven.compiler.target> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
</properties> |
|||
|
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-web</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>common</artifactId> |
|||
<version>1.0.0-SNAPSHOT</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-core</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-captcha</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-redis</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-aop</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-validation</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>ma.glasnost.orika</groupId> |
|||
<artifactId>orika-core</artifactId> |
|||
<version>1.5.4</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-spring-boot3-starter</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- Sa-Token 整合 jwt --> |
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-jwt</artifactId> |
|||
</dependency> |
|||
|
|||
</dependencies> |
|||
|
|||
</project> |
@ -0,0 +1,16 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
import org.mybatis.spring.annotation.MapperScan; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
/** |
|||
* @ClassName MybatisConfig |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 15:53 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@MapperScan("com.jiagutech.ams.mapper") |
|||
@Configuration |
|||
public class MybatisConfig { |
|||
} |
@ -0,0 +1,51 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import cn.hutool.captcha.CaptchaUtil; |
|||
import cn.hutool.captcha.ShearCaptcha; |
|||
import cn.hutool.core.util.IdUtil; |
|||
import com.jiagutech.ams.constant.Constants; |
|||
import com.jiagutech.ams.constant.GlobalConstants; |
|||
import com.jiagutech.ams.model.response.CaptchaVO; |
|||
import com.jiagutech.ams.model.common.R; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import java.time.Duration; |
|||
|
|||
/** |
|||
* @ClassName CommonController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 11:54 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RequestMapping("/common") |
|||
@RestController |
|||
@RequiredArgsConstructor |
|||
@Tag(name = "基础", description = "基础功能") |
|||
public class CommonController { |
|||
private final RedisTemplate redisTemplate; |
|||
|
|||
@Operation(summary = "验证码") |
|||
@GetMapping("/code") |
|||
public R<CaptchaVO> getCode() { |
|||
CaptchaVO captchaVo = new CaptchaVO(); |
|||
// 保存验证码信息
|
|||
String uuid = IdUtil.simpleUUID(); |
|||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid; |
|||
|
|||
ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(150, 40, 5, 4); |
|||
|
|||
String code = shearCaptcha.getCode(); |
|||
|
|||
redisTemplate.opsForValue().set(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); |
|||
captchaVo.setUuid(uuid); |
|||
captchaVo.setImg(shearCaptcha.getImageBase64()); |
|||
return R.ok(captchaVo); |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import cn.dev33.satoken.annotation.SaCheckRole; |
|||
import com.jiagutech.ams.model.DeptItem; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.common.R; |
|||
import com.jiagutech.ams.model.request.DeptPageRequest; |
|||
import com.jiagutech.ams.service.DeptService; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
/** |
|||
* @ClassName DeptController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 16:47 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RestController |
|||
@RequestMapping("/dept") |
|||
@RequiredArgsConstructor |
|||
@Tag(name = "部门", description = "部门管理") |
|||
public class DeptController { |
|||
private final DeptService deptService; |
|||
|
|||
@SaCheckRole("gov") |
|||
@PostMapping("/page") |
|||
public R<PageResult<DeptItem>> selectPage(@RequestBody PageRequest<DeptPageRequest> pageRequest) { |
|||
return R.ok(deptService.selectPage(pageRequest)); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,76 @@ |
|||
package com.jiagutech.ams.controller; |
|||
|
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.common.R; |
|||
import com.jiagutech.ams.model.request.LoginRequest; |
|||
import com.jiagutech.ams.model.request.PageUserRequest; |
|||
import com.jiagutech.ams.model.request.UserRequest; |
|||
import com.jiagutech.ams.model.response.LoginResponse; |
|||
import com.jiagutech.ams.model.UserDetail; |
|||
import com.jiagutech.ams.service.UserService; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.validation.annotation.Validated; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName UserController |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 15:11 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@RestController |
|||
@RequestMapping("/user") |
|||
@RequiredArgsConstructor |
|||
@Tag(name = "用户", description = "用户管理") |
|||
public class UserController { |
|||
private final UserService userService; |
|||
|
|||
@Operation(summary = "登录接口") |
|||
@PostMapping("/login") |
|||
public R<LoginResponse> login(@Validated @RequestBody LoginRequest loginBody) { |
|||
|
|||
LoginResponse loginVo = userService.login(loginBody); |
|||
return R.ok(loginVo); |
|||
} |
|||
|
|||
@Operation(summary = "添加用户") |
|||
@PostMapping("/add") |
|||
public R<Void> add(@Validated @RequestBody UserRequest user) { |
|||
userService.addUser(user); |
|||
return R.ok(); |
|||
} |
|||
|
|||
@Operation(summary = "获取用户登陆信息") |
|||
@GetMapping("/getUserInfo") |
|||
public R<LoginUser> getUserInfo() { |
|||
return R.ok(StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser())); |
|||
} |
|||
|
|||
@Operation(summary = "获取用户详情") |
|||
@GetMapping("/getUserDetail") |
|||
public R<UserDetail> getUserDetail(@RequestParam(value = "userId", required = false) Long userId, |
|||
@RequestParam(value = "phone", required = false) String phone) { |
|||
return R.ok(userService.getUserDetail(userId, phone)); |
|||
} |
|||
@Operation(summary = "更新用户信息") |
|||
@PutMapping("/update") |
|||
public R<Void> updateUser(@Validated @RequestBody UserRequest user){ |
|||
userService.updateUser(user); |
|||
return R.ok(); |
|||
} |
|||
|
|||
@Operation(summary = "分页获取用户列表") |
|||
@PostMapping("/page") |
|||
public R<PageResult<UserDetail>> getUserList(@RequestBody PageRequest<PageUserRequest> pageRequest) { |
|||
return R.ok(userService.getUserPage(pageRequest)); |
|||
} |
|||
} |
@ -0,0 +1,18 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.jiagutech.ams.model.DeptItem; |
|||
import com.jiagutech.ams.model.dto.DeptDTO; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
/** |
|||
* @ClassName DeptMapper |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-05 14:58 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
public interface DeptMapper extends BaseMapper<DeptDTO> { |
|||
Page<DeptItem> deptPage(Page<DeptItem> page, @Param("deptName") String deptName, @Param("regionPath") String regionPath); |
|||
} |
@ -0,0 +1,7 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.jiagutech.ams.model.dto.RoleDTO; |
|||
|
|||
public interface RoleMapper extends BaseMapper<RoleDTO> { |
|||
} |
@ -0,0 +1,10 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.jiagutech.ams.model.dto.DeptDTO; |
|||
import com.jiagutech.ams.model.dto.UserDeptDTO; |
|||
|
|||
public interface UserDeptMapper extends BaseMapper<UserDeptDTO> { |
|||
|
|||
DeptDTO selectDeptByUserId(Long userId); |
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.jiagutech.ams.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.jiagutech.ams.model.dto.RoleDTO; |
|||
import com.jiagutech.ams.model.dto.UserRoleDTO; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @ClassName UserRoleMapper |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-01 09:57 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
public interface UserRoleMapper extends BaseMapper<UserRoleDTO> { |
|||
|
|||
List<RoleDTO> selectRolesByUserId(Long userId); |
|||
|
|||
void insertUserRole(@Param("userId") Long userId, @Param("roleKey") String roleKey); |
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.jiagutech.ams.model; |
|||
|
|||
import com.jiagutech.ams.model.dto.UserDTO; |
|||
import com.jiagutech.ams.model.request.UserRequest; |
|||
import org.mapstruct.Mapper; |
|||
import org.mapstruct.factory.Mappers; |
|||
|
|||
/** |
|||
* @ClassName UserMapping |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-31 15:13 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Mapper |
|||
public interface UserMapping { |
|||
|
|||
UserMapping INSTANCE = Mappers.getMapper(UserMapping.class); |
|||
|
|||
UserDTO userToUserDTO(UserRequest user); |
|||
|
|||
LoginUser userDTOToLoginUser(UserDTO userDTO); |
|||
|
|||
} |
@ -0,0 +1,18 @@ |
|||
package com.jiagutech.ams.model.request; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName JobPageRequest |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 15:18 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class DeptPageRequest { |
|||
|
|||
private long deptId; |
|||
|
|||
private String deptName; |
|||
} |
@ -0,0 +1,59 @@ |
|||
package com.jiagutech.ams.model.request; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import jakarta.validation.constraints.NotBlank; |
|||
import lombok.Data; |
|||
import org.hibernate.validator.constraints.Length; |
|||
|
|||
import java.io.Serial; |
|||
import java.io.Serializable; |
|||
|
|||
/** |
|||
* 用户登录对象 |
|||
*/ |
|||
|
|||
@Data |
|||
public class LoginRequest implements Serializable { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
|
|||
/** |
|||
* 登陆方式 |
|||
*/ |
|||
|
|||
private String grantType = "password"; |
|||
|
|||
|
|||
/** |
|||
* 验证码 |
|||
*/ |
|||
private String code; |
|||
|
|||
/** |
|||
* 唯一标识 |
|||
*/ |
|||
private String uuid; |
|||
|
|||
/** |
|||
* 用户名 |
|||
*/ |
|||
//@NotBlank(message = "{user.username.not.blank}")
|
|||
@Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") |
|||
@JsonIgnore |
|||
private String username; |
|||
|
|||
/** |
|||
* 用户密码 |
|||
*/ |
|||
@NotBlank(message = "{user.password.not.blank}") |
|||
@Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") |
|||
private String password; |
|||
|
|||
private String phone; |
|||
|
|||
private Integer clientType = 1; |
|||
|
|||
} |
@ -0,0 +1,19 @@ |
|||
package com.jiagutech.ams.model.request; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @ClassName PageUserRequest |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-05 11:48 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class PageUserRequest { |
|||
|
|||
|
|||
private Long userId; |
|||
private String phone; |
|||
private String roleKey; |
|||
} |
@ -0,0 +1,86 @@ |
|||
package com.jiagutech.ams.model.request; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; |
|||
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; |
|||
import com.jiagutech.ams.utils.StringToLongDeserializer; |
|||
import jakarta.validation.constraints.*; |
|||
import lombok.Data; |
|||
import lombok.NonNull; |
|||
|
|||
/** |
|||
* @ClassName UserRequest |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-31 10:00 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Data |
|||
public class UserRequest { |
|||
/** |
|||
* 用户ID |
|||
*/ |
|||
@JsonIgnore |
|||
private Long userId; |
|||
|
|||
/** |
|||
* 部门ID |
|||
*/ |
|||
@JsonDeserialize(using = StringToLongDeserializer.class) |
|||
private Long deptId; |
|||
|
|||
/** |
|||
* 用户账号 |
|||
*/ |
|||
@JsonIgnore |
|||
//@NotBlank(message = "用户账号不能为空")
|
|||
@Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符") |
|||
private String userName; |
|||
|
|||
/** |
|||
* 用户昵称 |
|||
*/ |
|||
@NotBlank(message = "用户昵称不能为空") |
|||
@Size(min = 2, max = 30, message = "用户昵称长度不能超过{max}个字符") |
|||
private String nickName; |
|||
|
|||
|
|||
@JsonIgnore |
|||
private String userType; |
|||
|
|||
/** |
|||
* 用户邮箱 |
|||
*/ |
|||
@Email(message = "邮箱格式不正确") |
|||
@Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符") |
|||
private String email; |
|||
|
|||
/** |
|||
* 手机号码 |
|||
*/ |
|||
@Pattern(regexp = "^1[34578]\\d{9}$", message = "手机号码格式不正确") |
|||
private String phone; |
|||
|
|||
/** |
|||
* 用户性别(0男 1女 2未知) |
|||
*/ |
|||
@JsonIgnore |
|||
private String sex; |
|||
|
|||
/** |
|||
* 密码 |
|||
*/ |
|||
private String password; |
|||
|
|||
/** |
|||
* 帐号状态(0正常 1停用) |
|||
*/ |
|||
@JsonIgnore |
|||
private String status; |
|||
@JsonIgnore |
|||
private Long roleId; |
|||
// @NotBlank(message = "角色不能为空")
|
|||
private String roleKey; |
|||
|
|||
private Long regionCode; |
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.jiagutech.ams.model.response; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 验证码信息 |
|||
* |
|||
*/ |
|||
@Data |
|||
public class CaptchaVO { |
|||
|
|||
/** |
|||
* 是否开启验证码 |
|||
*/ |
|||
private Boolean captchaEnabled = true; |
|||
|
|||
private String uuid; |
|||
|
|||
/** |
|||
* 验证码图片 |
|||
*/ |
|||
private String img; |
|||
|
|||
} |
@ -0,0 +1,37 @@ |
|||
package com.jiagutech.ams.model.response; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 登录验证信息 |
|||
*/ |
|||
@Data |
|||
public class LoginResponse { |
|||
|
|||
/** |
|||
* 授权令牌 |
|||
*/ |
|||
@JsonProperty("access_token") |
|||
private String accessToken; |
|||
|
|||
/** |
|||
* 刷新令牌 |
|||
*/ |
|||
@JsonProperty("refresh_token") |
|||
private String refreshToken; |
|||
|
|||
/** |
|||
* 授权令牌 access_token 的有效期 |
|||
*/ |
|||
@JsonProperty("expire_in") |
|||
private Long expireIn; |
|||
|
|||
/** |
|||
* 刷新令牌 refresh_token 的有效期 |
|||
*/ |
|||
@JsonProperty("refresh_expire_in") |
|||
private Long refreshExpireIn; |
|||
|
|||
|
|||
} |
@ -0,0 +1,41 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import com.jiagutech.ams.mapper.DeptMapper; |
|||
import com.jiagutech.ams.model.DeptItem; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.request.DeptPageRequest; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
/** |
|||
* @ClassName DeptServcieImpl |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 17:35 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Service |
|||
@RequiredArgsConstructor |
|||
public class DeptServcieImpl implements DeptService { |
|||
private final DeptMapper deptMapper; |
|||
@Override |
|||
public PageResult<DeptItem> selectPage(PageRequest<DeptPageRequest> pageRequest) { |
|||
|
|||
DeptPageRequest requestParam = pageRequest.getRequest(); |
|||
Page<DeptItem> page = new Page(pageRequest.getPageNum(), pageRequest.getPageSize()); |
|||
LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION,new LoginUser()); |
|||
|
|||
Page<DeptItem> result = deptMapper.deptPage(page,requestParam!=null ?requestParam.getDeptName():null, loginUser.getRegionPath()); |
|||
return PageResult.of((int) result.getTotal(), (int) result.getSize(), (int) result.getCurrent(), result.getRecords()); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import com.jiagutech.ams.model.DeptItem; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.request.DeptPageRequest; |
|||
|
|||
/** |
|||
* @ClassName DeptService |
|||
* @author: zhangyeguang |
|||
* @create: 2024-09-02 17:34 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
public interface DeptService { |
|||
PageResult<DeptItem> selectPage(PageRequest<DeptPageRequest> pageRequest); |
|||
} |
@ -0,0 +1,27 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
|
|||
import com.jiagutech.ams.model.UserDetail; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.request.LoginRequest; |
|||
import com.jiagutech.ams.model.request.PageUserRequest; |
|||
import com.jiagutech.ams.model.request.UserRequest; |
|||
import com.jiagutech.ams.model.response.LoginResponse; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface UserService { |
|||
LoginResponse login(LoginRequest loginRequest); |
|||
|
|||
|
|||
void addUser(UserRequest userRequest); |
|||
|
|||
UserDetail getUserDetail(Long userId, String phone); |
|||
|
|||
void updateUser(UserRequest user); |
|||
|
|||
List<UserDetail> getUserList(String roleKey); |
|||
|
|||
PageResult<UserDetail> getUserPage(PageRequest<PageUserRequest> pageRequest); |
|||
} |
@ -0,0 +1,198 @@ |
|||
package com.jiagutech.ams.service; |
|||
|
|||
import cn.dev33.satoken.secure.BCrypt; |
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
|||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|||
import com.jiagutech.ams.constant.GlobalConstants; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import com.jiagutech.ams.exception.BizCode; |
|||
import com.jiagutech.ams.exception.BusinessException; |
|||
import com.jiagutech.ams.mapper.RegionMapper; |
|||
import com.jiagutech.ams.mapper.UserDeptMapper; |
|||
import com.jiagutech.ams.mapper.UserMapper; |
|||
import com.jiagutech.ams.mapper.UserRoleMapper; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
import com.jiagutech.ams.model.RegionVO; |
|||
import com.jiagutech.ams.model.UserDetail; |
|||
import com.jiagutech.ams.model.UserMapping; |
|||
import com.jiagutech.ams.model.common.PageRequest; |
|||
import com.jiagutech.ams.model.common.PageResult; |
|||
import com.jiagutech.ams.model.dto.RoleDTO; |
|||
import com.jiagutech.ams.model.dto.UserDTO; |
|||
import com.jiagutech.ams.model.dto.UserDeptDTO; |
|||
import com.jiagutech.ams.model.dto.UserRoleDTO; |
|||
import com.jiagutech.ams.model.request.LoginRequest; |
|||
import com.jiagutech.ams.model.request.PageUserRequest; |
|||
import com.jiagutech.ams.model.request.UserRequest; |
|||
import com.jiagutech.ams.model.response.LoginResponse; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.util.List; |
|||
import java.util.function.Predicate; |
|||
|
|||
/** |
|||
* @ClassName UserServiceImpl |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 15:21 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@Service |
|||
@RequiredArgsConstructor |
|||
public class UserServiceImpl implements UserService { |
|||
|
|||
private final RedisTemplate redisTemplate; |
|||
|
|||
private final UserMapper userMapper; |
|||
|
|||
private final UserRoleMapper userRoleMapper; |
|||
|
|||
private final UserDeptMapper userDeptMapper; |
|||
|
|||
private final RegionMapper regionMapper; |
|||
|
|||
@Override |
|||
public LoginResponse login(LoginRequest loginRequest) { |
|||
String phone = loginRequest.getPhone(); |
|||
String password = loginRequest.getPassword(); |
|||
String code = loginRequest.getCode(); |
|||
String uuid = loginRequest.getUuid(); |
|||
|
|||
// validateCaptcha(code, uuid);
|
|||
Integer clientType = loginRequest.getClientType(); |
|||
LoginUser user = userMapper.selectLoginUserByPhone(phone); |
|||
Predicate<RoleDTO> predicate = role -> role.getKey().equals("manager") || role.getKey().equals("machinist"); |
|||
if (clientType == 2 && user.getRoles().stream().noneMatch(predicate)) { |
|||
throw new BusinessException(BizCode.LOGIN_TYPE_ERROR); |
|||
} |
|||
boolean checkpw = BCrypt.checkpw(password, user.getPassword()); |
|||
if (!checkpw) { |
|||
throw new BusinessException(BizCode.PASSWORD_ERROR); |
|||
} |
|||
StpUtil.login(user.getUserId()); |
|||
StpUtil.getSession().set(UserConstants.SYS_SESSION, user); |
|||
LoginResponse loginVO = new LoginResponse(); |
|||
loginVO.setAccessToken(StpUtil.getTokenValue()); |
|||
loginVO.setExpireIn(StpUtil.getTokenTimeout()); |
|||
return loginVO; |
|||
} |
|||
|
|||
|
|||
@Override |
|||
@Transactional |
|||
public void addUser(UserRequest userRequest) { |
|||
UserDTO userDTO = UserMapping.INSTANCE.userToUserDTO(userRequest); |
|||
userDTO.setPassword(BCrypt.hashpw(userRequest.getPassword())); |
|||
if (userDTO.getRegionCode() != null && userDTO.getRegionCode() != 0l) { |
|||
RegionVO completeRegionInfo = regionMapper.getCompleteRegionInfo(userDTO.getRegionCode()); |
|||
if (completeRegionInfo != null) { |
|||
userDTO.setRegionPath(completeRegionInfo.getRegionCode()); |
|||
} |
|||
} |
|||
userMapper.insert(userDTO); |
|||
insertUserRoleAndDept(userDTO, userRequest.getRoleKey(), userRequest.getDeptId()); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public UserDetail getUserDetail(Long userId, String phone) { |
|||
return userMapper.selectUserDetail(userId, phone); |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void updateUser(UserRequest user) { |
|||
UserDTO userDTO = UserMapping.INSTANCE.userToUserDTO(user); |
|||
userMapper.updateById(userDTO); |
|||
updateUserRoleAndDept(user); |
|||
} |
|||
|
|||
private void insertUserRoleAndDept(UserDTO user, String roleKey, Long deptId) { |
|||
if (StringUtils.isNotBlank(roleKey)) { |
|||
userRoleMapper.insertUserRole(user.getId(), roleKey); |
|||
} |
|||
if (deptId != null) { |
|||
UserDeptDTO userDeptDTO = new UserDeptDTO().setUserId(user.getId()).setDeptId(deptId); |
|||
userDeptMapper.insert(userDeptDTO); |
|||
} |
|||
} |
|||
|
|||
private void updateUserRoleAndDept(UserRequest user) { |
|||
if (user.getRoleId() != null) { |
|||
UserRoleDTO userRoleDTO = new UserRoleDTO().setUserId(user.getUserId()).setRoleId(user.getRoleId()); |
|||
LambdaQueryWrapper<UserRoleDTO> lambdaQueryWrapper = Wrappers.lambdaQuery(); |
|||
lambdaQueryWrapper.eq(UserRoleDTO::getUserId, user.getUserId()); |
|||
userRoleMapper.update(userRoleDTO, lambdaQueryWrapper); |
|||
} |
|||
if (user.getDeptId() != null) { |
|||
UserDeptDTO userDeptDTO = new UserDeptDTO().setUserId(user.getUserId()).setDeptId(user.getDeptId()); |
|||
LambdaQueryWrapper<UserDeptDTO> queryWrapper = Wrappers.lambdaQuery(); |
|||
queryWrapper.eq(UserDeptDTO::getUserId, user.getUserId()); |
|||
userDeptMapper.update(userDeptDTO, queryWrapper); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public List<UserDetail> getUserList(String roleKey) { |
|||
return List.of(); |
|||
} |
|||
|
|||
@Override |
|||
public PageResult<UserDetail> getUserPage(PageRequest<PageUserRequest> pageRequest) { |
|||
PageUserRequest requestParam = pageRequest.getRequest(); |
|||
QueryWrapper<UserDetail> queryWrapper = buildQueryWrapper(requestParam); |
|||
Page<UserDetail> page = new Page(pageRequest.getPageNum(), pageRequest.getPageSize()); |
|||
Page<UserDetail> result = userMapper.userPage(page, queryWrapper); |
|||
return PageResult.of((int) result.getTotal(), (int) result.getSize(), (int) result.getCurrent(), result.getRecords()); |
|||
} |
|||
|
|||
private QueryWrapper<UserDetail> buildQueryWrapper(PageUserRequest requestParam) { |
|||
QueryWrapper<UserDetail> queryWrapper = new QueryWrapper<>(); |
|||
if (requestParam != null) { |
|||
if (requestParam.getUserId() != null) { |
|||
queryWrapper.eq("u.id", requestParam.getUserId()); |
|||
} |
|||
if (requestParam.getPhone() != null) { |
|||
queryWrapper.like("u.phone", requestParam.getPhone()); |
|||
} |
|||
if (requestParam.getRoleKey() != null) { |
|||
queryWrapper.eq("r.key", requestParam.getRoleKey()); |
|||
} |
|||
} |
|||
|
|||
LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); |
|||
Predicate<RoleDTO> predicate1 = r -> r.getKey().equals("manager"); |
|||
Predicate<RoleDTO> predicate2 = r -> r.getKey().equals("gov"); |
|||
Predicate<RoleDTO> predicate3 = r -> r.getKey().equals("machinist"); |
|||
|
|||
boolean hasManager = loginUser.getRoles().stream().anyMatch(predicate1); |
|||
boolean hasGov = loginUser.getRoles().stream().anyMatch(predicate2); |
|||
boolean hasMachinist = loginUser.getRoles().stream().anyMatch(predicate3); |
|||
if (hasManager) { |
|||
queryWrapper.eq("ud.dept_id", loginUser.getDept().getId()); |
|||
} |
|||
if (hasGov) { |
|||
queryWrapper.likeRight("u.region_path", loginUser.getRegionPath()); |
|||
} |
|||
return queryWrapper; |
|||
} |
|||
|
|||
private void validateCaptcha(String code, String uuid) { |
|||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid; |
|||
String captcha = String.valueOf(redisTemplate.opsForValue().get(verifyKey)); |
|||
redisTemplate.delete(verifyKey); |
|||
if (captcha == null) { |
|||
throw new BusinessException(BizCode.CAPTCHA_ERROR); |
|||
} |
|||
if (!code.equalsIgnoreCase(captcha)) { |
|||
throw new BusinessException(BizCode.CAPTCHA_ERROR); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
<?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="com.jiagutech.ams.mapper.DeptMapper"> |
|||
|
|||
|
|||
<select id="deptPage" resultType="com.jiagutech.ams.model.DeptItem"> |
|||
select |
|||
dd.*,ui.user_id as manager_id,ui.nick_name as manager_name,ui.phone as manager_phone |
|||
from |
|||
( |
|||
select |
|||
d1.dept_id, |
|||
d2.name as dept_name |
|||
from |
|||
( |
|||
select |
|||
distinct dept_id |
|||
from |
|||
ams_job_info j |
|||
where |
|||
j.region_code in ( |
|||
select |
|||
region_code |
|||
from |
|||
ams_user u |
|||
where |
|||
|
|||
region_path like CONCAT(#{regionPath},'%') |
|||
) |
|||
) d1 |
|||
left join ams_dept d2 on d1.dept_id = d2.id |
|||
<if test="deptName!= null and deptName !=''"> |
|||
and d2.name like CONCAT('%',#{deptName},'%') |
|||
</if> |
|||
|
|||
) dd |
|||
left join( |
|||
select u.id as user_id ,u.nick_name,u.phone,ud.dept_id from ams_user u |
|||
join ams_user_role ur on u.id=ur.user_id |
|||
join ams_role r on ur.role_id=r.id |
|||
join ams_user_dept ud on ud.user_id=u.id |
|||
where r.key='manager' |
|||
) ui |
|||
on ui.dept_id=dd.dept_id |
|||
|
|||
</select> |
|||
</mapper> |
@ -0,0 +1,8 @@ |
|||
<?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="com.jiagutech.ams.mapper.RoleMapper"> |
|||
|
|||
|
|||
|
|||
|
|||
</mapper> |
@ -0,0 +1,13 @@ |
|||
<?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="com.jiagutech.ams.mapper.UserDeptMapper"> |
|||
|
|||
|
|||
<select id="selectDeptByUserId" resultType="com.jiagutech.ams.model.dto.DeptDTO" parameterType="java.lang.Long"> |
|||
SELECT d.id, d.name |
|||
FROM ams_user_dept ud |
|||
left join ams_dept d on ud.dept_id = d.id |
|||
WHERE ud.user_id = #{userId} |
|||
</select> |
|||
|
|||
</mapper> |
@ -0,0 +1,89 @@ |
|||
<?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="com.jiagutech.ams.mapper.UserMapper"> |
|||
|
|||
|
|||
<resultMap type="com.jiagutech.ams.model.LoginUser" id="LoginUserResult"> |
|||
<id property="userId" column="user_id"/> |
|||
<association property="dept" javaType="com.jiagutech.ams.model.dto.DeptDTO" column="user_id" |
|||
select="com.jiagutech.ams.mapper.UserDeptMapper.selectDeptByUserId"/> |
|||
<collection property="roles" javaType="java.util.List" column="user_id" select="com.jiagutech.ams.mapper.UserRoleMapper.selectRolesByUserId"/> |
|||
|
|||
</resultMap> |
|||
<resultMap type="com.jiagutech.ams.model.UserDetail" id="UserDetailResult"> |
|||
<id property="userId" column="user_id"/> |
|||
<association property="dept" javaType="com.jiagutech.ams.model.dto.DeptDTO" column="user_id" |
|||
select="com.jiagutech.ams.mapper.UserDeptMapper.selectDeptByUserId"/> |
|||
</resultMap> |
|||
<select id="selectLoginUserByPhone" resultMap="LoginUserResult"> |
|||
select id as user_id, |
|||
username, |
|||
nick_name, |
|||
email, |
|||
phone, |
|||
region_code, |
|||
del_flag, |
|||
create_time, |
|||
password, |
|||
avatar, |
|||
region_path |
|||
from ams_user |
|||
where phone = #{phone} |
|||
and del_flag = 0 |
|||
</select> |
|||
<select id="selectUserDetail" resultMap="UserDetailResult"> |
|||
select id as user_id, |
|||
username, |
|||
nick_name, |
|||
email, |
|||
phone, |
|||
create_time, |
|||
avatar, |
|||
u.region_code, |
|||
r.region_name |
|||
from ams_user u left join region_info r on u.region_code=r.region_code |
|||
where del_flag = 0 |
|||
<if test="userId!= null and userId!= 0"> |
|||
and id = #{userId} |
|||
</if> |
|||
<if test="phone != null"> |
|||
and phone = #{phone} |
|||
</if> |
|||
limit 1 |
|||
</select> |
|||
<select id="getUserIdsByRegionCodes" resultType="java.lang.Long"> |
|||
select id from ams_user |
|||
<where> |
|||
<if test="userIds != null and userIds.size() > 0"> |
|||
region_code IN |
|||
<foreach collection="regionCodes" item="regionCode" open="(" separator="," close=")"> |
|||
#{regionCode} |
|||
</foreach> |
|||
</if> |
|||
</where> |
|||
|
|||
</select> |
|||
|
|||
<select id="getUsersByLikeRegionPath" resultType="UserDTO"> |
|||
select id, nick_name, region_code |
|||
from ams_user |
|||
where region_path like CONCAT(#{regionPath}, '%') |
|||
and del_flag = 0 |
|||
</select> |
|||
<select id="userPage" resultType="com.jiagutech.ams.model.UserDetail"> |
|||
select u.id as user_id, |
|||
u.username, |
|||
u.nick_name, |
|||
u.email, |
|||
u.phone, |
|||
u.create_time, |
|||
u.avatar, |
|||
u.region_code |
|||
from ams_user u |
|||
left join ams_user_role ur on u.id = ur.user_id |
|||
left join ams_role r on ur.role_id = r.id |
|||
left join ams_user_dept ud on u.id=ud.user_id |
|||
${ew.getCustomSqlSegment} |
|||
</select> |
|||
|
|||
</mapper> |
@ -0,0 +1,20 @@ |
|||
<?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="com.jiagutech.ams.mapper.UserRoleMapper"> |
|||
|
|||
|
|||
<select id="selectRolesByUserId" resultType="com.jiagutech.ams.model.dto.RoleDTO" parameterType="java.lang.Long"> |
|||
SELECT r.id, r.name,r.key |
|||
FROM ams_role r |
|||
INNER JOIN ams_user_role ur ON r.id = ur.role_id |
|||
WHERE ur.user_id = #{userId} |
|||
</select> |
|||
|
|||
|
|||
<insert id="insertUserRole"> |
|||
insert into ams_user_role(user_id, role_id) |
|||
select #{userId}, r.id as role_id |
|||
from ams_role r |
|||
where r.key = #{roleKey} |
|||
</insert> |
|||
</mapper> |
@ -0,0 +1,102 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<parent> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>ams-social</artifactId> |
|||
<version>${revision}</version> |
|||
</parent> |
|||
|
|||
<artifactId>web</artifactId> |
|||
|
|||
<properties> |
|||
<maven.compiler.source>17</maven.compiler.source> |
|||
<maven.compiler.target>17</maven.compiler.target> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
</properties> |
|||
|
|||
<profiles> |
|||
<profile> |
|||
<id>dev</id> |
|||
<properties> |
|||
<!-- 环境标识,需要与配置文件的名称相对应 --> |
|||
<profiles.active>dev</profiles.active> |
|||
<logging.level>info</logging.level> |
|||
</properties> |
|||
<activation> |
|||
<!-- 默认环境 --> |
|||
<activeByDefault>true</activeByDefault> |
|||
</activation> |
|||
</profile> |
|||
<profile> |
|||
<id>prod</id> |
|||
<properties> |
|||
<profiles.active>prod</profiles.active> |
|||
<logging.level>info</logging.level> |
|||
</properties> |
|||
</profile> |
|||
</profiles> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>system</artifactId> |
|||
<version>1.0.0-SNAPSHOT</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.jiagutech</groupId> |
|||
<artifactId>social</artifactId> |
|||
<version>1.0.0-SNAPSHOT</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-jdbc</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>mysql</groupId> |
|||
<artifactId>mysql-connector-java</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> |
|||
|
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-pool2</artifactId> |
|||
<version>2.12.0</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-spring-boot3-starter</artifactId> |
|||
</dependency> |
|||
|
|||
|
|||
<dependency> |
|||
<groupId>cn.dev33</groupId> |
|||
<artifactId>sa-token-redis</artifactId> |
|||
</dependency> |
|||
</dependencies> |
|||
<build> |
|||
|
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-maven-plugin</artifactId> |
|||
<version>${spring-boot.version}</version> |
|||
<executions> |
|||
<execution> |
|||
<goals> |
|||
<goal>repackage</goal> |
|||
</goals> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
</project> |
@ -0,0 +1,18 @@ |
|||
package com.jiagutech.ams; |
|||
|
|||
import org.springframework.boot.SpringApplication; |
|||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|||
|
|||
/** |
|||
* @ClassName SocialApplication |
|||
* @author: zhangyeguang |
|||
* @create: 2024-08-30 14:26 |
|||
* @Version 1.0 |
|||
* @description: |
|||
**/ |
|||
@SpringBootApplication |
|||
public class SocialApplication { |
|||
public static void main(String[] args) { |
|||
SpringApplication.run(SocialApplication.class, args); |
|||
} |
|||
} |
@ -0,0 +1,74 @@ |
|||
package com.jiagutech.ams.common; |
|||
|
|||
|
|||
import cn.dev33.satoken.exception.NotLoginException; |
|||
import cn.dev33.satoken.exception.NotRoleException; |
|||
import com.alibaba.fastjson2.JSON; |
|||
import com.jiagutech.ams.exception.BizCode; |
|||
import com.jiagutech.ams.exception.BusinessException; |
|||
import com.jiagutech.ams.model.common.R; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.validation.BindException; |
|||
import org.springframework.validation.FieldError; |
|||
import org.springframework.web.bind.MethodArgumentNotValidException; |
|||
import org.springframework.web.bind.annotation.ExceptionHandler; |
|||
import org.springframework.web.bind.annotation.RestControllerAdvice; |
|||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; |
|||
|
|||
import java.sql.SQLIntegrityConstraintViolationException; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Slf4j |
|||
@RestControllerAdvice |
|||
public class GlobalExceptionHandler { |
|||
|
|||
@ExceptionHandler(BindException.class) |
|||
public R handleBindExceptions(BindException ex) { |
|||
log.error("参数绑定失败", ex); |
|||
Map<String, String> errorMap = new HashMap<>(); |
|||
for (FieldError fieldError : ex.getFieldErrors()) { |
|||
errorMap.put(fieldError.getField(), fieldError.getDefaultMessage()); |
|||
} |
|||
return R.fail(BizCode.General_ParameterInvalid.getCode(), JSON.toJSONString(errorMap)); |
|||
} |
|||
|
|||
@ExceptionHandler(MethodArgumentNotValidException.class) |
|||
public R handleValidationExceptions(MethodArgumentNotValidException ex) { |
|||
log.error("参数校验失败", ex); |
|||
Map<String, String> errorMap = new HashMap<>(); |
|||
for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) { |
|||
errorMap.put(fieldError.getField(), fieldError.getDefaultMessage()); |
|||
} |
|||
return R.fail(BizCode.General_ParameterInvalid.getCode(), JSON.toJSONString(errorMap)); |
|||
} |
|||
|
|||
@ExceptionHandler(BusinessException.class) |
|||
public R handleBusinessException(BusinessException ex) { |
|||
return R.fail(ex.getCode(), ex.getMessage()); |
|||
} |
|||
|
|||
@ExceptionHandler(MethodArgumentTypeMismatchException.class) |
|||
public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) { |
|||
log.error("参数类型错误", ex); |
|||
return R.fail(new BusinessException("参数类型错误")); |
|||
} |
|||
|
|||
@ExceptionHandler(NotLoginException.class) |
|||
public R handleLoginException(Exception ex) { |
|||
log.error("系统异常", ex); |
|||
return R.fail(BizCode.USER_NOT_LOGIN.getCode(), BizCode.USER_NOT_LOGIN.getMsg()); |
|||
} |
|||
|
|||
@ExceptionHandler(NotRoleException.class) |
|||
public R handlePermissionException(Exception ex) { |
|||
log.error("鉴权失败", ex); |
|||
return R.fail(BizCode.PERMISSION_NOT_FOUND.getCode(), BizCode.PERMISSION_NOT_FOUND.getMsg()); |
|||
} |
|||
|
|||
@ExceptionHandler(SQLIntegrityConstraintViolationException.class) |
|||
public R handleDuplicateException(Exception ex){ |
|||
log.error("数据重复", ex); |
|||
return R.fail(BizCode.USER_PHONE_EXIST.getCode(), BizCode.USER_PHONE_EXIST.getMsg()); |
|||
} |
|||
} |
@ -0,0 +1,41 @@ |
|||
package com.jiagutech.ams.common; |
|||
|
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.http.client.SimpleClientHttpRequestFactory; |
|||
import org.springframework.http.converter.StringHttpMessageConverter; |
|||
import org.springframework.web.client.RestTemplate; |
|||
|
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.Collections; |
|||
|
|||
|
|||
/** |
|||
* RestTemplate工具类,主要用来提供RestTemplate对象 |
|||
*/ |
|||
@Configuration |
|||
public class RestTemplateConfig { |
|||
|
|||
|
|||
|
|||
@Value("${http.template.connect-timeout}") |
|||
private int connectionTimeout; |
|||
@Value("${http.template.read-timeout}") |
|||
private int readTimeout; |
|||
|
|||
/** |
|||
* 创建RestTemplate对象 |
|||
*/ |
|||
@Bean |
|||
public RestTemplate restTemplate() { |
|||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); |
|||
factory.setConnectTimeout(connectionTimeout); // 设置连接超时时间(毫秒)
|
|||
factory.setReadTimeout(readTimeout); // 设置读取超时时间(毫秒)
|
|||
RestTemplate restTemplate = new RestTemplate(factory); |
|||
restTemplate.setInterceptors(Collections.singletonList(new RestTemplateInterceptor())); |
|||
restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8)); // 支持中文编码
|
|||
return restTemplate; |
|||
} |
|||
} |
|||
|
@ -0,0 +1,36 @@ |
|||
package com.jiagutech.ams.common; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.http.HttpRequest; |
|||
import org.springframework.http.client.ClientHttpRequestExecution; |
|||
import org.springframework.http.client.ClientHttpRequestInterceptor; |
|||
import org.springframework.http.client.ClientHttpResponse; |
|||
|
|||
import java.io.IOException; |
|||
import java.nio.charset.StandardCharsets; |
|||
|
|||
@Slf4j |
|||
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor { |
|||
|
|||
|
|||
@Override |
|||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { |
|||
|
|||
// 打印出请求的详细信息
|
|||
log.info("URI: {}", request.getURI()); |
|||
if (body != null && body.length > 0) { |
|||
log.debug("Request Body: {}", new String(body, StandardCharsets.UTF_8)); |
|||
} |
|||
|
|||
// 执行请求并获取响应
|
|||
ClientHttpResponse response = execution.execute(request, body); |
|||
|
|||
// 打印出响应的详细信息
|
|||
log.info("Response Status: {}", response.getStatusCode()); |
|||
log.info("Response Headers: {}", response.getHeaders()); |
|||
response.getBody(); // 读取响应体,确保内容被完全读取,这样连接才能被关闭
|
|||
|
|||
return response; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
|
|||
import com.baomidou.mybatisplus.annotation.DbType; |
|||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
|||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
@Configuration |
|||
public class MybatisPlusConfig { |
|||
|
|||
/** |
|||
* 添加分页插件 |
|||
*/ |
|||
@Bean |
|||
public MybatisPlusInterceptor mybatisPlusInterceptor() { |
|||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
|||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加
|
|||
return interceptor; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,39 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
import cn.dev33.satoken.stp.StpInterface; |
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import com.jiagutech.ams.constant.UserConstants; |
|||
import com.jiagutech.ams.model.LoginUser; |
|||
|
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* sa-token 权限管理实现类 |
|||
* |
|||
* @author Lion Li |
|||
*/ |
|||
public class SaPermissionImpl implements StpInterface { |
|||
|
|||
/** |
|||
* 获取菜单权限列表 |
|||
*/ |
|||
@Override |
|||
public List<String> getPermissionList(Object loginId, String loginType) { |
|||
|
|||
return new ArrayList<>(); |
|||
} |
|||
|
|||
/** |
|||
* 获取角色权限列表 |
|||
*/ |
|||
@Override |
|||
public List<String> getRoleList(Object loginId, String loginType) { |
|||
LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); |
|||
if (loginUser == null || loginUser.getRoles() == null) { |
|||
return new ArrayList<>(); |
|||
} |
|||
return loginUser.getRoles().stream().map(role -> role.getKey()).toList(); |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
import cn.dev33.satoken.jwt.StpLogicJwtForSimple; |
|||
import cn.dev33.satoken.stp.StpInterface; |
|||
import cn.dev33.satoken.stp.StpLogic; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
/** |
|||
* sa-token 配置 |
|||
*/ |
|||
@Configuration |
|||
public class SaTokenConfig { |
|||
|
|||
@Bean |
|||
public StpLogic getStpLogicJwt() { |
|||
// Sa-Token 整合 jwt (简单模式)
|
|||
return new StpLogicJwtForSimple(); |
|||
} |
|||
|
|||
/** |
|||
* 权限接口实现(使用bean注入方便用户替换) |
|||
*/ |
|||
@Bean |
|||
public StpInterface stpInterface() { |
|||
return new SaPermissionImpl(); |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
import cn.dev33.satoken.interceptor.SaInterceptor; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
|||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
|||
|
|||
@Configuration |
|||
public class SaTokenConfigure implements WebMvcConfigurer { |
|||
// 注册 Sa-Token 拦截器,打开注解式鉴权功能
|
|||
@Override |
|||
public void addInterceptors(InterceptorRegistry registry) { |
|||
// 注册 Sa-Token 拦截器,打开注解式鉴权功能
|
|||
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); |
|||
} |
|||
} |
@ -0,0 +1,46 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
import io.swagger.v3.oas.models.OpenAPI; |
|||
import io.swagger.v3.oas.models.info.Contact; |
|||
import io.swagger.v3.oas.models.info.Info; |
|||
import io.swagger.v3.oas.models.info.License; |
|||
import io.swagger.v3.oas.models.security.SecurityRequirement; |
|||
import io.swagger.v3.oas.models.security.SecurityScheme; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
@Configuration |
|||
public class SpringDocConfig { |
|||
|
|||
@Bean |
|||
public OpenAPI openAPI() { |
|||
return new OpenAPI() |
|||
// 配置接口文档基本信息
|
|||
.info(this.getApiInfo()) |
|||
.addSecurityItem(new SecurityRequirement().addList("Bearer Authentication")) |
|||
.components(new io.swagger.v3.oas.models.Components() |
|||
.addSecuritySchemes("Bearer Authentication", new SecurityScheme() |
|||
.type(SecurityScheme.Type.HTTP) |
|||
.scheme("bearer") |
|||
.bearerFormat("JWT"))); |
|||
|
|||
} |
|||
|
|||
private Info getApiInfo() { |
|||
return new Info() |
|||
// 配置文档标题
|
|||
.title("SpringBoot3集成Swagger3") |
|||
// 配置文档描述
|
|||
.description("SpringBoot3集成Swagger3示例文档") |
|||
// 配置作者信息
|
|||
.contact(new Contact().name("农机管理-社会化").url("https://www.baidu.com")) |
|||
// 配置License许可证信息
|
|||
.license(new License().name("Apache 2.0").url("https://www.xiezhrspace.cn")) |
|||
// 概述信息
|
|||
.summary("SpringBoot3集成Swagger3示例文档aaa") |
|||
.termsOfService("https://www.xiezhrspace.cn") |
|||
// 配置版本号
|
|||
.version("2.0"); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,32 @@ |
|||
package com.jiagutech.ams.config; |
|||
|
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.web.cors.CorsConfiguration; |
|||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; |
|||
import org.springframework.web.filter.CorsFilter; |
|||
|
|||
@Configuration |
|||
public class WebConfig { |
|||
|
|||
|
|||
@Bean |
|||
public CorsFilter corsFilter() { |
|||
CorsConfiguration config = new CorsConfiguration(); |
|||
config.addAllowedOrigin("*"); |
|||
config.addAllowedMethod("GET"); |
|||
config.addAllowedMethod("POST"); |
|||
config.addAllowedMethod("PUT"); |
|||
config.addAllowedMethod("DELETE"); |
|||
config.addAllowedMethod("OPTIONS"); |
|||
config.addAllowedHeader("*"); |
|||
config.setAllowCredentials(false); |
|||
config.setMaxAge(3600L); |
|||
|
|||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); |
|||
source.registerCorsConfiguration("/**", config); |
|||
|
|||
return new CorsFilter(source); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,91 @@ |
|||
server: |
|||
port: 8180 |
|||
|
|||
|
|||
spring: |
|||
application: |
|||
name: ams-social |
|||
datasource: |
|||
type: com.zaxxer.hikari.HikariDataSource |
|||
driver-class-name: com.mysql.cj.jdbc.Driver |
|||
# url: jdbc:mysql://192.168.10.111:23306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true |
|||
# username: root |
|||
# password: 123456 |
|||
url: jdbc:mysql://101.34.243.138:7306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true |
|||
username: ams |
|||
password: ams@1234 |
|||
hikari: |
|||
# 最大连接池数量 |
|||
maxPoolSize: 20 |
|||
# 最小空闲线程数量 |
|||
minIdle: 10 |
|||
# 配置获取连接等待超时的时间 |
|||
connectionTimeout: 30000 |
|||
# 校验超时时间 |
|||
validationTimeout: 5000 |
|||
# 空闲连接存活最大时间,默认10分钟 |
|||
idleTimeout: 600000 |
|||
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟 |
|||
maxLifetime: 1800000 |
|||
# 多久检查一次连接的活性 |
|||
keepaliveTime: 30000 |
|||
data: |
|||
redis: |
|||
host: 192.168.10.111 |
|||
port: 6379 |
|||
database: 10 |
|||
# host: 101.34.243.138 |
|||
# port: 7379 |
|||
# database: 10 |
|||
# # password: 123456 |
|||
timeout: 10s |
|||
# password: tent_zyg@1234 |
|||
lettuce: |
|||
pool: |
|||
# 连接池最大连接数 |
|||
max-active: 200 |
|||
# 连接池最大阻塞等待时间(使用负值表示没有限制) |
|||
max-wait: 3000ms |
|||
# 连接池中的最大空闲连接 |
|||
max-idle: 100 |
|||
# 连接池中的最小空闲连接 |
|||
min-idle: 10 |
|||
|
|||
|
|||
mybatis-plus: |
|||
mapper-locations: classpath*:mapper/*.xml |
|||
type-aliases-package: com.jiagutech.ams.model.dto |
|||
configuration: |
|||
map-underscore-to-camel-case: true |
|||
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl |
|||
global-config: |
|||
db-config: |
|||
id-type: assign_id |
|||
|
|||
|
|||
sa-token: |
|||
# token名称 (同时也是cookie名称) |
|||
token-name: Authorization |
|||
token-prefix: Bearer |
|||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) |
|||
is-concurrent: true |
|||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) |
|||
is-share: false |
|||
# jwt秘钥 |
|||
jwt-secret-key: abcdefghijklmnopqrstuvwxyz |
|||
is-print: true |
|||
is-log: false |
|||
|
|||
http: |
|||
template: |
|||
# 连接超时时间 |
|||
connect-timeout: 1000 |
|||
# 读取超时时间 |
|||
read-timeout: 5000 |
|||
|
|||
|
|||
logging: |
|||
level: |
|||
root: INFO |
|||
com.jiagutech.ams.mapper: DEBUG |
|||
|
@ -0,0 +1,103 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<configuration> |
|||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/> |
|||
|
|||
<springProperty scope="context" name="springAppName" source="spring.application.name"/> |
|||
<!--<springProperty scope="context" name="serverIp" source="spring.cloud.client.hostname" />--> |
|||
<!-- Example for logging into the build folder of your project --> |
|||
<property name="LOG_FILE" value="log"/> |
|||
<property name="LOG_PATTERN" |
|||
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%.-5level) -- %X{traceId:-} -- [%10.10t] %cyan(%-36.36logger{32}) : %m%n"/> |
|||
|
|||
<!-- Appender to log to console --> |
|||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
|||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> |
|||
<!-- Minimum logging level to be presented in the console logs--> |
|||
<level>DEBUG</level> |
|||
</filter> |
|||
<encoder> |
|||
<pattern>${LOG_PATTERN}</pattern> |
|||
<charset>utf8</charset> |
|||
</encoder> |
|||
</appender> |
|||
|
|||
<!-- INFO日志 appender: 按照每天生成日志文件 --> |
|||
<appender name="INFO-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<!-- 写入的日志文件名,可以使相对目录也可以是绝对目录,如果上级目录不存在则自动创建 --> |
|||
<file>${LOG_FILE}/${springAppName}-info.log</file> |
|||
<!-- 如果为true表示日志被追加到文件结尾,如果是false表示清空文件 --> |
|||
<append>true</append> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
|||
<!-- 日志文件输出的文件名: %d可以包含一个Java.text.SimpleDateFormat指定的时间格式 --> |
|||
<fileNamePattern>${LOG_FILE}/${springAppName}-info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> |
|||
<!-- 日志文件保存历史数量:控制保留的归档文件的最大数量,如果超出数量就删除旧文件 --> |
|||
<maxHistory>20</maxHistory> |
|||
<!-- 文件大小超过100MB归档 --> |
|||
<maxFileSize>100MB</maxFileSize> |
|||
</rollingPolicy> |
|||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> |
|||
<pattern>${LOG_PATTERN}</pattern> |
|||
<charset>utf8</charset> |
|||
</encoder> |
|||
</appender> |
|||
<appender name="ASYNC-INFO-APPENDER" class="ch.qos.logback.classic.AsyncAppender"> |
|||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> |
|||
<discardingThreshold>0</discardingThreshold> |
|||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> |
|||
<queueSize>256</queueSize> |
|||
<!-- 添加附加的appender,最多只能添加一个 --> |
|||
<appender-ref ref="INFO-APPENDER"/> |
|||
</appender> |
|||
<!-- 错误日志 appender: 按照每天生成日志文件 --> |
|||
<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<!-- 过滤器,只记录error级别的日志 --> |
|||
<filter class="ch.qos.logback.classic.filter.LevelFilter"> |
|||
<level>ERROR</level> |
|||
<onMatch>ACCEPT</onMatch> |
|||
<onMismatch>DENY</onMismatch> |
|||
</filter> |
|||
<!-- 日志名称 --> |
|||
<file>${LOG_FILE}/${springAppName}-error.log</file> |
|||
<append>true</append> |
|||
<!-- 每天生成一个日志文件,保存30天的日志文件 --> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
|||
<!-- 日志文件输出的文件名:按天回滚 daily --> |
|||
<fileNamePattern>${LOG_FILE}/${springAppName}-error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> |
|||
<!-- 日志文件保留天数 --> |
|||
<maxHistory>20</maxHistory> |
|||
<!-- 文件大小超过100MB归档 --> |
|||
<maxFileSize>100MB</maxFileSize> |
|||
</rollingPolicy> |
|||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> |
|||
<pattern>${LOG_PATTERN}</pattern> |
|||
<charset>utf8</charset> |
|||
</encoder> |
|||
</appender> |
|||
<appender name="ASYNC-ERROR-APPENDER" class="ch.qos.logback.classic.AsyncAppender"> |
|||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> |
|||
<discardingThreshold>0</discardingThreshold> |
|||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> |
|||
<queueSize>256</queueSize> |
|||
<!-- 添加附加的appender,最多只能添加一个 --> |
|||
<appender-ref ref="ERROR-APPENDER"/> |
|||
</appender> |
|||
|
|||
<logger name="com.jiagu.oper.dao" level="DEBUG"> |
|||
<appender-ref ref="console"/> |
|||
<appender-ref ref="ASYNC-INFO-APPENDER"/> |
|||
</logger> |
|||
|
|||
<root level="INFO"> |
|||
<appender-ref ref="console"/> |
|||
<appender-ref ref="ASYNC-INFO-APPENDER"/> |
|||
<appender-ref ref="ASYNC-ERROR-APPENDER"/> |
|||
</root> |
|||
|
|||
|
|||
<springProfile name="local"> |
|||
<root level="INFO"> |
|||
<appender-ref ref="console"/> |
|||
</root> |
|||
</springProfile> |
|||
|
|||
</configuration> |
Loading…
Reference in new issue