Browse Source

ams social project

master
zhangyeguang 4 months ago
parent
commit
85cc4c1bd4
  1. 3
      .gitignore
  2. 101
      common/pom.xml
  3. 43
      common/src/main/java/com/jiagutech/ams/annotation/RateLimiter.java
  4. 81
      common/src/main/java/com/jiagutech/ams/constant/Constants.java
  5. 39
      common/src/main/java/com/jiagutech/ams/constant/GlobalConstants.java
  6. 93
      common/src/main/java/com/jiagutech/ams/constant/HttpStatus.java
  7. 143
      common/src/main/java/com/jiagutech/ams/constant/UserConstants.java
  8. 24
      common/src/main/java/com/jiagutech/ams/enums/LimitType.java
  9. 62
      common/src/main/java/com/jiagutech/ams/exception/BizCode.java
  10. 53
      common/src/main/java/com/jiagutech/ams/exception/BusinessException.java
  11. 22
      common/src/main/java/com/jiagutech/ams/exception/CodeInterface.java
  12. 26
      common/src/main/java/com/jiagutech/ams/mapper/RegionMapper.java
  13. 34
      common/src/main/java/com/jiagutech/ams/mapper/UserMapper.java
  14. 22
      common/src/main/java/com/jiagutech/ams/model/DeptItem.java
  15. 97
      common/src/main/java/com/jiagutech/ams/model/LoginUser.java
  16. 12
      common/src/main/java/com/jiagutech/ams/model/RegionVO.java
  17. 30
      common/src/main/java/com/jiagutech/ams/model/UserDetail.java
  18. 22
      common/src/main/java/com/jiagutech/ams/model/common/PageRequest.java
  19. 33
      common/src/main/java/com/jiagutech/ams/model/common/PageResult.java
  20. 111
      common/src/main/java/com/jiagutech/ams/model/common/R.java
  21. 22
      common/src/main/java/com/jiagutech/ams/model/dto/DeptDTO.java
  22. 22
      common/src/main/java/com/jiagutech/ams/model/dto/RegionDTO.java
  23. 26
      common/src/main/java/com/jiagutech/ams/model/dto/RoleDTO.java
  24. 28
      common/src/main/java/com/jiagutech/ams/model/dto/UserDTO.java
  25. 24
      common/src/main/java/com/jiagutech/ams/model/dto/UserDeptDTO.java
  26. 25
      common/src/main/java/com/jiagutech/ams/model/dto/UserRoleDTO.java
  27. 52
      common/src/main/java/com/jiagutech/ams/utils/ExcelBigNumberConvert.java
  28. 49
      common/src/main/java/com/jiagutech/ams/utils/ExcelUtil.java
  29. 21
      common/src/main/java/com/jiagutech/ams/utils/StringToLongDeserializer.java
  30. 185
      pom.xml
  31. 97
      social/pom.xml
  32. 42
      social/src/main/java/com/jiagutech/ams/controller/DeviceController.java
  33. 83
      social/src/main/java/com/jiagutech/ams/controller/JobController.java
  34. 22
      social/src/main/java/com/jiagutech/ams/controller/RegionController.java
  35. 21
      social/src/main/java/com/jiagutech/ams/controller/TrackController.java
  36. 11
      social/src/main/java/com/jiagutech/ams/mapper/DeviceMapper.java
  37. 21
      social/src/main/java/com/jiagutech/ams/mapper/JobMapper.java
  38. 9
      social/src/main/java/com/jiagutech/ams/mapper/JobTypeMapper.java
  39. 16
      social/src/main/java/com/jiagutech/ams/model/JobMapping.java
  40. 120
      social/src/main/java/com/jiagutech/ams/model/TrackDataJG.java
  41. 24
      social/src/main/java/com/jiagutech/ams/model/dto/DeviceDTO.java
  42. 44
      social/src/main/java/com/jiagutech/ams/model/dto/JobDTO.java
  43. 23
      social/src/main/java/com/jiagutech/ams/model/dto/JobTypeDTO.java
  44. 46
      social/src/main/java/com/jiagutech/ams/model/request/JobCreateRequest.java
  45. 35
      social/src/main/java/com/jiagutech/ams/model/request/JobPageRequest.java
  46. 31
      social/src/main/java/com/jiagutech/ams/model/response/DeviceInfo.java
  47. 30
      social/src/main/java/com/jiagutech/ams/model/response/JobCreateResponse.java
  48. 54
      social/src/main/java/com/jiagutech/ams/model/response/JobItem.java
  49. 18
      social/src/main/java/com/jiagutech/ams/model/response/JobTypeItem.java
  50. 23
      social/src/main/java/com/jiagutech/ams/rest/CenterRestClient.java
  51. 9
      social/src/main/java/com/jiagutech/ams/service/DeviceService.java
  52. 68
      social/src/main/java/com/jiagutech/ams/service/DeviceServiceImpl.java
  53. 28
      social/src/main/java/com/jiagutech/ams/service/JobService.java
  54. 169
      social/src/main/java/com/jiagutech/ams/service/JobServiceImpl.java
  55. 12
      social/src/main/resources/mapper/DeviceMapper.xml
  56. 53
      social/src/main/resources/mapper/JobMapper.xml
  57. 47
      social/src/main/resources/mapper/RegionMapper.xml
  58. 75
      system/pom.xml
  59. 16
      system/src/main/java/com/jiagutech/ams/config/MybatisConfig.java
  60. 51
      system/src/main/java/com/jiagutech/ams/controller/CommonController.java
  61. 34
      system/src/main/java/com/jiagutech/ams/controller/DeptController.java
  62. 76
      system/src/main/java/com/jiagutech/ams/controller/UserController.java
  63. 18
      system/src/main/java/com/jiagutech/ams/mapper/DeptMapper.java
  64. 7
      system/src/main/java/com/jiagutech/ams/mapper/RoleMapper.java
  65. 10
      system/src/main/java/com/jiagutech/ams/mapper/UserDeptMapper.java
  66. 22
      system/src/main/java/com/jiagutech/ams/mapper/UserRoleMapper.java
  67. 24
      system/src/main/java/com/jiagutech/ams/model/UserMapping.java
  68. 18
      system/src/main/java/com/jiagutech/ams/model/request/DeptPageRequest.java
  69. 59
      system/src/main/java/com/jiagutech/ams/model/request/LoginRequest.java
  70. 19
      system/src/main/java/com/jiagutech/ams/model/request/PageUserRequest.java
  71. 86
      system/src/main/java/com/jiagutech/ams/model/request/UserRequest.java
  72. 24
      system/src/main/java/com/jiagutech/ams/model/response/CaptchaVO.java
  73. 37
      system/src/main/java/com/jiagutech/ams/model/response/LoginResponse.java
  74. 41
      system/src/main/java/com/jiagutech/ams/service/DeptServcieImpl.java
  75. 17
      system/src/main/java/com/jiagutech/ams/service/DeptService.java
  76. 27
      system/src/main/java/com/jiagutech/ams/service/UserService.java
  77. 198
      system/src/main/java/com/jiagutech/ams/service/UserServiceImpl.java
  78. 47
      system/src/main/resources/mapper/DeptMapper.xml
  79. 8
      system/src/main/resources/mapper/RoleMapper.xml
  80. 13
      system/src/main/resources/mapper/UserDeptMapper.xml
  81. 89
      system/src/main/resources/mapper/UserMapper.xml
  82. 20
      system/src/main/resources/mapper/UserRoleMapper.xml
  83. 102
      web/pom.xml
  84. 18
      web/src/main/java/com/jiagutech/ams/SocialApplication.java
  85. 74
      web/src/main/java/com/jiagutech/ams/common/GlobalExceptionHandler.java
  86. 41
      web/src/main/java/com/jiagutech/ams/common/RestTemplateConfig.java
  87. 36
      web/src/main/java/com/jiagutech/ams/common/RestTemplateInterceptor.java
  88. 23
      web/src/main/java/com/jiagutech/ams/config/MybatisPlusConfig.java
  89. 39
      web/src/main/java/com/jiagutech/ams/config/SaPermissionImpl.java
  90. 30
      web/src/main/java/com/jiagutech/ams/config/SaTokenConfig.java
  91. 16
      web/src/main/java/com/jiagutech/ams/config/SaTokenConfigure.java
  92. 46
      web/src/main/java/com/jiagutech/ams/config/SpringDocConfig.java
  93. 32
      web/src/main/java/com/jiagutech/ams/config/WebConfig.java
  94. 91
      web/src/main/resources/application.yml
  95. 103
      web/src/main/resources/logback-spring.xml

3
.gitignore

@ -22,7 +22,8 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.vscode
log
# ---> Maven
target/
pom.xml.tag

101
common/pom.xml

@ -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>

43
common/src/main/java/com/jiagutech/ams/annotation/RateLimiter.java

@ -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}";
}

81
common/src/main/java/com/jiagutech/ams/constant/Constants.java

@ -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;
}

39
common/src/main/java/com/jiagutech/ams/constant/GlobalConstants.java

@ -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:";
}

93
common/src/main/java/com/jiagutech/ams/constant/HttpStatus.java

@ -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;
}

143
common/src/main/java/com/jiagutech/ams/constant/UserConstants.java

@ -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;
}

24
common/src/main/java/com/jiagutech/ams/enums/LimitType.java

@ -0,0 +1,24 @@
package com.jiagutech.ams.enums;
/**
* 限流类型
*
* @author ruoyi
*/
public enum LimitType {
/**
* 默认策略全局限流
*/
DEFAULT,
/**
* 根据请求者IP进行限流
*/
IP,
/**
* 实例限流(集群多后端实例)
*/
CLUSTER
}

62
common/src/main/java/com/jiagutech/ams/exception/BizCode.java

@ -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;
}
}

53
common/src/main/java/com/jiagutech/ams/exception/BusinessException.java

@ -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;
}
}

22
common/src/main/java/com/jiagutech/ams/exception/CodeInterface.java

@ -0,0 +1,22 @@
package com.jiagutech.ams.exception;
/**
* 业务异常接口
*/
public interface CodeInterface {
/**
* 消息
*
* @return String
*/
String getMsg();
/**
* 业务代码
*
* @return int
*/
Integer getCode();
}

26
common/src/main/java/com/jiagutech/ams/mapper/RegionMapper.java

@ -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);
}

34
common/src/main/java/com/jiagutech/ams/mapper/UserMapper.java

@ -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);
}

22
common/src/main/java/com/jiagutech/ams/model/DeptItem.java

@ -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;
}

97
common/src/main/java/com/jiagutech/ams/model/LoginUser.java

@ -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;
}

12
common/src/main/java/com/jiagutech/ams/model/RegionVO.java

@ -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;
}

30
common/src/main/java/com/jiagutech/ams/model/UserDetail.java

@ -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;
}

22
common/src/main/java/com/jiagutech/ams/model/common/PageRequest.java

@ -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;
}

33
common/src/main/java/com/jiagutech/ams/model/common/PageResult.java

@ -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;
}
}

111
common/src/main/java/com/jiagutech/ams/model/common/R.java

@ -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();
}
}

22
common/src/main/java/com/jiagutech/ams/model/dto/DeptDTO.java

@ -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;
}

22
common/src/main/java/com/jiagutech/ams/model/dto/RegionDTO.java

@ -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;
}

26
common/src/main/java/com/jiagutech/ams/model/dto/RoleDTO.java

@ -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;
}

28
common/src/main/java/com/jiagutech/ams/model/dto/UserDTO.java

@ -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;
}

24
common/src/main/java/com/jiagutech/ams/model/dto/UserDeptDTO.java

@ -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;
}

25
common/src/main/java/com/jiagutech/ams/model/dto/UserRoleDTO.java

@ -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;
}

52
common/src/main/java/com/jiagutech/ams/utils/ExcelBigNumberConvert.java

@ -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;
}
}

49
common/src/main/java/com/jiagutech/ams/utils/ExcelUtil.java

@ -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异常");
}
}
}

21
common/src/main/java/com/jiagutech/ams/utils/StringToLongDeserializer.java

@ -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);
}
}
}

185
pom.xml

@ -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>

97
social/pom.xml

@ -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>

42
social/src/main/java/com/jiagutech/ams/controller/DeviceController.java

@ -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));
}
}

83
social/src/main/java/com/jiagutech/ams/controller/JobController.java

@ -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);
}
}

22
social/src/main/java/com/jiagutech/ams/controller/RegionController.java

@ -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 {
}

21
social/src/main/java/com/jiagutech/ams/controller/TrackController.java

@ -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 {
}

11
social/src/main/java/com/jiagutech/ams/mapper/DeviceMapper.java

@ -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);
}

21
social/src/main/java/com/jiagutech/ams/mapper/JobMapper.java

@ -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);
}

9
social/src/main/java/com/jiagutech/ams/mapper/JobTypeMapper.java

@ -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> {
}

16
social/src/main/java/com/jiagutech/ams/model/JobMapping.java

@ -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);
}

120
social/src/main/java/com/jiagutech/ams/model/TrackDataJG.java

@ -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;
}

24
social/src/main/java/com/jiagutech/ams/model/dto/DeviceDTO.java

@ -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;
}

44
social/src/main/java/com/jiagutech/ams/model/dto/JobDTO.java

@ -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;
}

23
social/src/main/java/com/jiagutech/ams/model/dto/JobTypeDTO.java

@ -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;
}

46
social/src/main/java/com/jiagutech/ams/model/request/JobCreateRequest.java

@ -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;
}

35
social/src/main/java/com/jiagutech/ams/model/request/JobPageRequest.java

@ -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;
}

31
social/src/main/java/com/jiagutech/ams/model/response/DeviceInfo.java

@ -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;
}

30
social/src/main/java/com/jiagutech/ams/model/response/JobCreateResponse.java

@ -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;
}

54
social/src/main/java/com/jiagutech/ams/model/response/JobItem.java

@ -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;
}

18
social/src/main/java/com/jiagutech/ams/model/response/JobTypeItem.java

@ -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;
}

23
social/src/main/java/com/jiagutech/ams/rest/CenterRestClient.java

@ -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;
}

9
social/src/main/java/com/jiagutech/ams/service/DeviceService.java

@ -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);
}

68
social/src/main/java/com/jiagutech/ams/service/DeviceServiceImpl.java

@ -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;
}
}

28
social/src/main/java/com/jiagutech/ams/service/JobService.java

@ -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);
}

169
social/src/main/java/com/jiagutech/ams/service/JobServiceImpl.java

@ -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;
}
}

12
social/src/main/resources/mapper/DeviceMapper.xml

@ -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>

53
social/src/main/resources/mapper/JobMapper.xml

@ -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>

47
social/src/main/resources/mapper/RegionMapper.xml

@ -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 &lt;= ${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>

75
system/pom.xml

@ -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>

16
system/src/main/java/com/jiagutech/ams/config/MybatisConfig.java

@ -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 {
}

51
system/src/main/java/com/jiagutech/ams/controller/CommonController.java

@ -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);
}
}

34
system/src/main/java/com/jiagutech/ams/controller/DeptController.java

@ -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));
}
}

76
system/src/main/java/com/jiagutech/ams/controller/UserController.java

@ -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));
}
}

18
system/src/main/java/com/jiagutech/ams/mapper/DeptMapper.java

@ -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);
}

7
system/src/main/java/com/jiagutech/ams/mapper/RoleMapper.java

@ -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> {
}

10
system/src/main/java/com/jiagutech/ams/mapper/UserDeptMapper.java

@ -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);
}

22
system/src/main/java/com/jiagutech/ams/mapper/UserRoleMapper.java

@ -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);
}

24
system/src/main/java/com/jiagutech/ams/model/UserMapping.java

@ -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);
}

18
system/src/main/java/com/jiagutech/ams/model/request/DeptPageRequest.java

@ -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;
}

59
system/src/main/java/com/jiagutech/ams/model/request/LoginRequest.java

@ -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;
}

19
system/src/main/java/com/jiagutech/ams/model/request/PageUserRequest.java

@ -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;
}

86
system/src/main/java/com/jiagutech/ams/model/request/UserRequest.java

@ -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;
}

24
system/src/main/java/com/jiagutech/ams/model/response/CaptchaVO.java

@ -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;
}

37
system/src/main/java/com/jiagutech/ams/model/response/LoginResponse.java

@ -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;
}

41
system/src/main/java/com/jiagutech/ams/service/DeptServcieImpl.java

@ -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());
}
}

17
system/src/main/java/com/jiagutech/ams/service/DeptService.java

@ -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);
}

27
system/src/main/java/com/jiagutech/ams/service/UserService.java

@ -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);
}

198
system/src/main/java/com/jiagutech/ams/service/UserServiceImpl.java

@ -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);
}
}
}

47
system/src/main/resources/mapper/DeptMapper.xml

@ -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>

8
system/src/main/resources/mapper/RoleMapper.xml

@ -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>

13
system/src/main/resources/mapper/UserDeptMapper.xml

@ -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>

89
system/src/main/resources/mapper/UserMapper.xml

@ -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>

20
system/src/main/resources/mapper/UserRoleMapper.xml

@ -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>

102
web/pom.xml

@ -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>

18
web/src/main/java/com/jiagutech/ams/SocialApplication.java

@ -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);
}
}

74
web/src/main/java/com/jiagutech/ams/common/GlobalExceptionHandler.java

@ -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());
}
}

41
web/src/main/java/com/jiagutech/ams/common/RestTemplateConfig.java

@ -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;
}
}

36
web/src/main/java/com/jiagutech/ams/common/RestTemplateInterceptor.java

@ -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;
}
}

23
web/src/main/java/com/jiagutech/ams/config/MybatisPlusConfig.java

@ -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;
}
}

39
web/src/main/java/com/jiagutech/ams/config/SaPermissionImpl.java

@ -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();
}
}

30
web/src/main/java/com/jiagutech/ams/config/SaTokenConfig.java

@ -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();
}
}

16
web/src/main/java/com/jiagutech/ams/config/SaTokenConfigure.java

@ -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("/**");
}
}

46
web/src/main/java/com/jiagutech/ams/config/SpringDocConfig.java

@ -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");
}
}

32
web/src/main/java/com/jiagutech/ams/config/WebConfig.java

@ -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);
}
}

91
web/src/main/resources/application.yml

@ -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

103
web/src/main/resources/logback-spring.xml

@ -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…
Cancel
Save