Initial commit

This commit is contained in:
jackyu66git
2026-03-23 11:52:51 +08:00
commit ea8d889fbe
1114 changed files with 92438 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
<?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.oneone.cloud</groupId>
<artifactId>oneone-upms</artifactId>
<version>${revision}</version>
</parent>
<artifactId>oneone-upms-api</artifactId>
<dependencies>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-core</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<scope>provided</scope> <!-- 设置为 provided,主要是 PageParam 使用到 -->
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,13 @@
package com.oneone.upms.api;
import com.oneone.common.constant.GlobalConstants;
public class ApiConstants {
public static final String NAME = "upms-server";
public static final String PREFIX = GlobalConstants.INNER_RPC + "/system";
public static final String VERSION = "1.0.0";
}
@@ -0,0 +1,56 @@
package com.oneone.upms.api.dept;
import com.oneone.common.result.Result;
import com.oneone.common.util.collection.CollectionUtils;
import com.oneone.upms.api.dept.dto.DeptRespDTO;
import com.oneone.upms.api.ApiConstants;
import com.oneone.common.result.Result;
import com.oneone.common.util.collection.CollectionUtils;
import com.oneone.upms.api.ApiConstants;
import com.oneone.upms.api.dept.dto.DeptRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 部门")
public interface DeptApi {
String PREFIX = ApiConstants.PREFIX + "/dept";
@GetMapping(PREFIX + "/get")
@Operation(summary = "获得部门信息")
@Parameter(name = "id", description = "部门编号", example = "1024", required = true)
Result<DeptRespDTO> getDept(@RequestParam("id") Long id);
@GetMapping(PREFIX + "/list")
@Operation(summary = "获得部门信息数组")
@Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
Result<List<DeptRespDTO>> getDeptList(@RequestParam("ids") Collection<Long> ids);
@GetMapping(PREFIX + "/valid")
@Operation(summary = "校验部门是否合法")
@Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
Result<Boolean> validateDeptList(@RequestParam("ids") Collection<Long> ids);
/**
* 获得指定编号的部门 Map
*
* @param ids 部门编号数组
* @return 部门 Map
*/
default Map<Long, DeptRespDTO> getDeptMap(Set<Long> ids) {
List<DeptRespDTO> list = getDeptList(ids).getCheckedData();
return CollectionUtils.convertMap(list, DeptRespDTO::getId);
}
}
@@ -0,0 +1,27 @@
package com.oneone.upms.api.dept;
import com.oneone.common.result.Result;
import com.oneone.upms.api.ApiConstants;
import com.oneone.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 岗位")
public interface PostApi {
String PREFIX = ApiConstants.PREFIX + "/post";
@GetMapping(PREFIX + "/valid")
@Operation(summary = "校验岗位是否合法")
@Parameter(name = "ids", description = "岗位编号数组", example = "1,2", required = true)
Result<Boolean> validPostList(@RequestParam("ids") Collection<Long> ids);
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.dept.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "RPC 服务 - 部门 Response DTO")
@Data
public class DeptRespDTO {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部")
private String name;
@Schema(description = "父部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long parentId;
@Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long leaderUserId;
@Schema(description = "部门状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status; // 参见 CommonStatusEnum 枚举
}
@@ -0,0 +1,60 @@
package com.oneone.upms.api.dict;
import com.oneone.common.result.Result;
import com.oneone.upms.api.dict.dto.DictDataRespDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.List;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 字典数据")
public interface DictDataApi {
String PREFIX = ApiConstants.PREFIX + "/dict-data";
@GetMapping(PREFIX + "/valid")
@Operation(summary = "校验字典数据们是否有效")
@Parameters({
@Parameter(name = "dictType", description = "字典类型", example = "SEX", required = true),
@Parameter(name = "descriptions", description = "字典数据值的数组", example = "1,2", required = true)
})
Result<Boolean> validateDictDataList(@RequestParam("dictType") String dictType,
@RequestParam("values") Collection<String> values);
@GetMapping(PREFIX + "/get")
@Operation(summary = "获得指定的字典数据")
@Parameters({
@Parameter(name = "dictType", description = "字典类型", example = "SEX", required = true),
@Parameter(name = "description", description = "字典数据值", example = "1", required = true)
})
Result<DictDataRespDTO> getDictData(@RequestParam("dictType") String dictType,
@RequestParam("value") String value);
@GetMapping(PREFIX + "/get-by-dict-type")
@Operation(summary = "获得指定的字典数据")
@Parameters({
@Parameter(name = "dictType", description = "字典类型", example = "SEX", required = true),
@Parameter(name = "description", description = "字典数据值", example = "1", required = true)
})
Result<List<DictDataRespDTO>> getDictDataByType(@RequestParam("dictType") String dictType);
@GetMapping(PREFIX + "/parse")
@Operation(summary = "解析获得指定的字典数据")
@Parameters({
@Parameter(name = "dictType", description = "字典类型", example = "SEX", required = true),
@Parameter(name = "label", description = "字典标签", example = "", required = true)
})
Result<DictDataRespDTO> parseDictData(@RequestParam("dictType") String dictType,
@RequestParam("label") String label);
}
@@ -0,0 +1,22 @@
package com.oneone.upms.api.dict.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "RPC 服务 - 字典数据 Response DTO")
@Data
public class DictDataRespDTO {
@Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String label;
@Schema(description = "字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "iocoder")
private String value;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
private String dictType;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status; // 参见 CommonStatusEnum 枚举
}
@@ -0,0 +1,23 @@
package com.oneone.upms.api.enums;
/**
* API 相关的枚举
*
*
*/
public class ApiConstants {
/**
* 服务名
*
* 注意,需要保证和 spring.application.name 保持一致
*/
public static final String NAME = "system-server";
// public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/system";
public static final String PREFIX = "/system";
public static final String VERSION = "1.0.0";
}
@@ -0,0 +1,29 @@
package com.oneone.upms.api.enums;
/**
* System 字典类型的枚举类
*
*
*/
public interface DictTypeConstants {
String USER_TYPE = "user_type"; // 用户类型
String COMMON_STATUS = "common_status"; // 系统状态
// ========== SYSTEM 模块 ==========
String USER_SEX = "system_user_sex"; // 用户性别
String OPERATE_TYPE = "system_operate_type"; // 操作类型
String LOGIN_TYPE = "system_login_type"; // 登录日志的类型
String LOGIN_RESULT = "system_login_result"; // 登录结果
String ERROR_CODE_TYPE = "system_error_code_type"; // 错误码的类型枚举
String SMS_CHANNEL_CODE = "system_sms_channel_code"; // 短信渠道编码
String SMS_TEMPLATE_TYPE = "system_sms_template_type"; // 短信模板类型
String SMS_SEND_STATUS = "system_sms_send_status"; // 短信发送状态
String SMS_RECEIVE_STATUS = "system_sms_receive_status"; // 短信接收状态
}
@@ -0,0 +1,193 @@
package com.oneone.upms.api.enums;
import com.oneone.common.exception.ErrorCode;
/**
* System 错误码枚举类
*
* system 系统,使用 1-002-000-000 段
*/
public interface ErrorCodeConstants {
// ========== AUTH 模块 1-002-000-000 ==========
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_002_000_000, "登录失败,账号密码不正确");
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用");
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1_002_000_006, "Token 已经过期");
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
// ========== 菜单模块 1-002-001-000 ==========
ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单");
ErrorCode MENU_PARENT_NOT_EXISTS = new ErrorCode(1_002_001_001, "父菜单不存在");
ErrorCode MENU_PARENT_ERROR = new ErrorCode(1_002_001_002, "不能设置自己为父菜单");
ErrorCode MENU_NOT_EXISTS = new ErrorCode(1_002_001_003, "菜单不存在");
ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1_002_001_004, "存在子菜单,无法删除");
ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1_002_001_005, "父菜单的类型必须是目录或者菜单");
// ========== 角色模块 1-002-002-000 ==========
ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1_002_002_000, "角色不存在");
ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1_002_002_001, "已经存在名为【{}】的角色");
ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1_002_002_002, "已经存在编码为【{}】的角色");
ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1_002_002_003, "不能操作类型为系统内置的角色");
ErrorCode ROLE_IS_DISABLE = new ErrorCode(1_002_002_004, "名字为【{}】的角色已被禁用");
ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "编码【{}】不能使用");
// ========== 用户模块 1-002-003-000 ==========
ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_002_003_000, "用户账号已经存在");
ErrorCode USER_MOBILE_EXISTS = new ErrorCode(1_002_003_001, "手机号已经存在");
ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1_002_003_002, "邮箱已经存在");
ErrorCode USER_NOT_EXISTS = new ErrorCode(1_002_003_003, "用户不存在");
ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_002_003_004, "导入用户数据不能为空!");
ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败");
ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
// ========== 部门模块 1-002-004-000 ==========
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1_002_004_001,"父级部门不存在");
ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在");
ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");
ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门");
ErrorCode DEPT_EXISTS_USER = new ErrorCode(1_002_004_005, "部门中存在员工,无法删除");
ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择");
ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门");
// ========== 岗位模块 1-002-005-000 ==========
ErrorCode POST_NOT_FOUND = new ErrorCode(1_002_005_000, "当前岗位不存在");
ErrorCode POST_NOT_ENABLE = new ErrorCode(1_002_005_001, "岗位({}) 不处于开启状态,不允许选择");
ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1_002_005_002, "已经存在该名字的岗位");
ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1_002_005_003, "已经存在该标识的岗位");
// ========== 字典类型 1-002-006-000 ==========
ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1_002_006_001, "当前字典类型不存在");
ErrorCode DICT_TYPE_NOT_ENABLE = new ErrorCode(1_002_006_002, "字典类型不处于开启状态,不允许选择");
ErrorCode DICT_TYPE_NAME_DUPLICATE = new ErrorCode(1_002_006_003, "已经存在该名字的字典类型");
ErrorCode DICT_TYPE_TYPE_DUPLICATE = new ErrorCode(1_002_006_004, "已经存在该类型的字典类型");
ErrorCode DICT_TYPE_HAS_CHILDREN = new ErrorCode(1_002_006_005, "无法删除,该字典类型还有字典数据");
// ========== 字典数据 1-002-007-000 ==========
ErrorCode DICT_DATA_NOT_EXISTS = new ErrorCode(1_002_007_001, "当前字典数据不存在");
ErrorCode DICT_DATA_NOT_ENABLE = new ErrorCode(1_002_007_002, "字典数据({})不处于开启状态,不允许选择");
ErrorCode DICT_DATA_VALUE_DUPLICATE = new ErrorCode(1_002_007_003, "已经存在该值的字典数据");
// ========== 通知公告 1-002-008-000 ==========
ErrorCode NOTICE_NOT_FOUND = new ErrorCode(1_002_008_001, "当前通知公告不存在");
// ========== 短信渠道 1-002-011-000 ==========
ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1_002_011_000, "短信渠道不存在");
ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1_002_011_001, "短信渠道不处于开启状态,不允许选择");
ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1_002_011_002, "无法删除,该短信渠道还有短信模板");
// ========== 短信模板 1-002-012-000 ==========
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在");
ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_012_001, "已经存在编码为【{}】的短信模板");
// ========== 短信发送 1-002-013-000 ==========
ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在");
ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_013_001, "模板参数({})缺失");
ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_013_002, "短信模板不存在");
// ========== 短信验证码 1-002-014-000 ==========
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确");
ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率");
ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用");
ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用");
// ========== 租户信息 1-002-015-000 ==========
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
ErrorCode TENANT_DISABLE = new ErrorCode(1_002_015_001, "名字为【{}】的租户已被禁用");
ErrorCode TENANT_EXPIRE = new ErrorCode(1_002_015_002, "名字为【{}】的租户已过期");
ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1_002_015_003, "系统租户不能进行修改、删除等操作!");
ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1_002_015_004, "名字为【{}】的租户已存在");
ErrorCode TENANT_WEBSITE_DUPLICATE = new ErrorCode(1_002_015_005, "域名为【{}】的租户已存在");
// ========== 租户套餐 1-002-016-000 ==========
ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在");
ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1_002_016_001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除");
ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1_002_016_002, "名字为【{}】的租户套餐已被禁用");
// ========== 错误码模块 1-002-017-000 ==========
ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1_002_017_000, "错误码不存在");
ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1_002_017_001, "已经存在编码为【{}】的错误码");
// ========== 社交用户 1-002-018-000 ==========
ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1_002_018_000, "社交授权失败,原因是:{}");
ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1_002_018_001, "社交授权失败,找不到对应的用户");
ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1_002_018_200, "获得手机号失败");
ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_201, "社交客户端不存在");
ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_201, "社交客户端已存在配置");
// ========== 系统敏感词 1-002-019-000 =========
ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1_002_019_000, "系统敏感词在所有标签中都不存在");
ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1_002_019_001, "系统敏感词已在标签中存在");
// ========== OAuth2 客户端 1-002-020-000 =========
ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在");
ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 客户端编号已存在");
ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1_002_020_002, "OAuth2 客户端已禁用");
ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1_002_020_003, "不支持该授权类型");
ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1_002_020_004, "授权范围过大");
ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1_002_020_005, "无效 redirect_uri: {}");
ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1_002_020_006, "无效 client_secret: {}");
// ========== OAuth2 授权 1-002-021-000 =========
ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1_002_021_000, "client_id 不匹配");
ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1_002_021_001, "redirect_uri 不匹配");
ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1_002_021_002, "state 不匹配");
ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1_002_021_003, "code 不存在");
// ========== OAuth2 授权 1-002-022-000 =========
ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1_002_022_000, "code 不存在");
ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1_002_022_001, "code 已过期");
// ========== 邮箱账号 1-002-023-000 ==========
ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1_002_023_000, "邮箱账号不存在");
ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1_002_023_001, "无法删除,该邮箱账号还有邮件模板");
// ========== 邮件模版 1-002-024-000 ==========
ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_024_000, "邮件模版不存在");
ErrorCode MAIL_TEMPLATE_CODE_EXISTS = new ErrorCode(1_002_024_001, "邮件模版 code({}) 已存在");
// ========== 邮件发送 1-002-025-000 ==========
ErrorCode MAIL_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_025_000, "模板参数({})缺失");
ErrorCode MAIL_SEND_MAIL_NOT_EXISTS = new ErrorCode(1_002_025_001, "邮箱不存在");
// ========== 站内信模版 1-002-026-000 ==========
ErrorCode NOTIFY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_026_000, "站内信模版不存在");
ErrorCode NOTIFY_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_026_001, "已经存在编码为【{}】的站内信模板");
// ========== 站内信模版 1-002-027-000 ==========
// ========== 站内信发送 1-002-028-000 ==========
ErrorCode NOTIFY_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_028_000, "模板参数({})缺失");
// ========= 文件相关 1-001-003-000 =================
ErrorCode FILE_PATH_EXISTS = new ErrorCode(1_001_003_000, "文件路径已存在");
ErrorCode FILE_NOT_EXISTS = new ErrorCode(1_001_003_001, "文件不存在");
ErrorCode FILE_IS_EMPTY = new ErrorCode(1_001_003_002, "文件为空");
// ========== 代码生成器 1-001-004-000 ==========
ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1_003_001_000, "表定义已经存在");
ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1_003_001_001, "导入的表不存在");
ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1_003_001_002, "导入的字段不存在");
ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_004, "表定义不存在");
ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_005, "字段义不存在");
ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1_003_001_006, "同步的字段不存在");
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变");
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写");
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写");
ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_010, "主表(id={})定义不存在,请检查");
ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_011, "子表的字段(id={})不存在,请检查");
ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE = new ErrorCode(1_003_001_012, "主表生成代码失败,原因:它没有子表");
ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_COLUMN = new ErrorCode(1_003_001_013, "主表生成代码失败,原因:它的子表({})没有字段");
// ========== 数据源配置 1-001-007-000 ==========
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在");
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接");
}
@@ -0,0 +1,35 @@
package com.oneone.upms.api.enums;
import cn.hutool.core.util.ArrayUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 全局用户类型枚举
*/
@AllArgsConstructor
@Getter
public enum UserTypeEnum {
MEMBER(1, "会员"), // 面向 c 端,普通用户
ADMIN(2, "管理员"); // 面向 b 端,管理后台
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();
/**
* 类型
*/
private final Integer value;
/**
* 类型名
*/
private final String name;
public static UserTypeEnum valueOf(Integer value) {
return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values());
}
}
@@ -0,0 +1,27 @@
package com.oneone.upms.api.enums.common;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 性别的枚举值
*
*
*/
@Getter
@AllArgsConstructor
public enum SexEnum {
/** 男 */
MALE(1),
/** 女 */
FEMALE(2),
/* 未知 */
UNKNOWN(3);
/**
* 性别
*/
private final Integer sex;
}
@@ -0,0 +1,20 @@
package com.oneone.upms.api.enums.dept;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 部门编号枚举
*/
@Getter
@AllArgsConstructor
public enum DeptIdEnum {
/**
* 根节点
*/
ROOT(0L);
private final Long id;
}
@@ -0,0 +1,39 @@
package com.oneone.upms.api.enums.errorcode;
import com.oneone.common.enums.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 错误码的类型枚举
*
* @author dylan
*/
@AllArgsConstructor
@Getter
public enum ErrorCodeTypeEnum implements IntArrayValuable {
/**
* 自动生成
*/
AUTO_GENERATION(1),
/**
* 手动编辑
*/
MANUAL_OPERATION(2);
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErrorCodeTypeEnum::getType).toArray();
/**
* 类型
*/
private final Integer type;
@Override
public int[] array() {
return ARRAYS;
}
}
@@ -0,0 +1,27 @@
package com.oneone.upms.api.enums.logger;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 登录日志的类型枚举
*/
@Getter
@AllArgsConstructor
public enum LoginLogTypeEnum {
LOGIN_USERNAME(100), // 使用账号登录
LOGIN_SOCIAL(101), // 使用社交登录
LOGIN_MOBILE(103), // 使用手机登陆
LOGIN_SMS(104), // 使用短信登陆
LOGOUT_SELF(200), // 自己主动登出
LOGOUT_DELETE(202), // 强制退出
;
/**
* 日志类型
*/
private final Integer type;
}
@@ -0,0 +1,26 @@
package com.oneone.upms.api.enums.logger;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 登录结果的枚举类
*/
@Getter
@AllArgsConstructor
public enum LoginResultEnum {
SUCCESS(0), // 成功
BAD_CREDENTIALS(10), // 账号或密码不正确
USER_DISABLED(20), // 用户被禁用
CAPTCHA_NOT_FOUND(30), // 图片验证码不存在
CAPTCHA_CODE_ERROR(31), // 图片验证码不正确
;
/**
* 结果
*/
private final Integer result;
}
@@ -0,0 +1,24 @@
package com.oneone.upms.api.enums.mail;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 邮件的发送状态枚举
*
* @author wangjingyi
* @since 2022/4/10 13:39
*/
@Getter
@AllArgsConstructor
public enum MailSendStatusEnum {
INIT(0), // 初始化
SUCCESS(10), // 发送成功
FAILURE(20), // 发送失败
IGNORE(30), // 忽略,即不发送
;
private final int status;
}
@@ -0,0 +1,23 @@
package com.oneone.upms.api.enums.notice;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 通知类型
*
*
*/
@Getter
@AllArgsConstructor
public enum NoticeTypeEnum {
NOTICE(1),
ANNOUNCEMENT(2);
/**
* 类型
*/
private final Integer type;
}
@@ -0,0 +1,26 @@
package com.oneone.upms.api.enums.notify;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 通知模板类型枚举
*
* @author HUIHUI
*/
@Getter
@AllArgsConstructor
public enum NotifyTemplateTypeEnum {
/**
* 系统消息
*/
SYSTEM_MESSAGE(2),
/**
* 通知消息
*/
NOTIFICATION_MESSAGE(1);
private final Integer type;
}
@@ -0,0 +1,12 @@
package com.oneone.upms.api.enums.oauth2;
/**
* OAuth2.0 客户端的通用枚举
*
*
*/
public interface OAuth2ClientConstants {
String CLIENT_ID_DEFAULT = "default";
}
@@ -0,0 +1,29 @@
package com.oneone.upms.api.enums.oauth2;
import cn.hutool.core.util.ArrayUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* OAuth2 授权类型(模式)的枚举
*
*
*/
@AllArgsConstructor
@Getter
public enum OAuth2GrantTypeEnum {
PASSWORD("password"), // 密码模式
AUTHORIZATION_CODE("authorization_code"), // 授权码模式
IMPLICIT("implicit"), // 简化模式
CLIENT_CREDENTIALS("client_credentials"), // 客户端模式
REFRESH_TOKEN("refresh_token"), // 刷新模式
;
private final String grantType;
public static OAuth2GrantTypeEnum getByGranType(String grantType) {
return ArrayUtil.firstMatch(o -> o.getGrantType().equals(grantType), values());
}
}
@@ -0,0 +1,30 @@
package com.oneone.upms.api.enums.permission;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 数据范围枚举类
*
* 用于实现数据级别的权限
*
*
*/
@Getter
@AllArgsConstructor
public enum DataScopeEnum {
ALL(1), // 全部数据权限
DEPT_CUSTOM(2), // 指定部门数据权限
DEPT_ONLY(3), // 部门数据权限
DEPT_AND_CHILD(4), // 部门及以下数据权限
SELF(5); // 仅本人数据权限
/**
* 范围
*/
private final Integer scope;
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.enums.permission;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 菜单类型枚举类
*
*
*/
@Getter
@AllArgsConstructor
public enum MenuTypeEnum {
DIR(1), // 目录
MENU(2), // 菜单
BUTTON(3) // 按钮
;
/**
* 类型
*/
private final Integer type;
}
@@ -0,0 +1,31 @@
package com.oneone.upms.api.enums.permission;
import com.oneone.common.util.ObjectUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 角色标识枚举
*/
@Getter
@AllArgsConstructor
public enum RoleCodeEnum {
SUPER_ADMIN("super_admin", "超级管理员"),
TENANT_ADMIN("tenant_admin", "租户管理员"),
;
/**
* 角色编码
*/
private final String code;
/**
* 名字
*/
private final String name;
public static boolean isSuperAdmin(String code) {
return ObjectUtils.equalsAny(code, SUPER_ADMIN.getCode());
}
}
@@ -0,0 +1,21 @@
package com.oneone.upms.api.enums.permission;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum RoleTypeEnum {
/**
* 内置角色
*/
SYSTEM(1),
/**
* 自定义角色
*/
CUSTOM(2);
private final Integer type;
}
@@ -0,0 +1,36 @@
package com.oneone.upms.api.enums.sms;
import cn.hutool.core.util.ArrayUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 短信渠道枚举
*
* @author zzf
* @since 2021/1/25 10:56
*/
@Getter
@AllArgsConstructor
public enum SmsChannelEnum {
DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"),
ALIYUN("ALIYUN", "阿里云"),
TENCENT("TENCENT", "腾讯云"),
// HUA_WEI("HUA_WEI", "华为云"),
;
/**
* 编码
*/
private final String code;
/**
* 名字
*/
private final String name;
public static SmsChannelEnum getByCode(String code) {
return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
}
}
@@ -0,0 +1,23 @@
package com.oneone.upms.api.enums.sms;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 短信的接收状态枚举
*
*
* @date 2021/2/1 13:39
*/
@Getter
@AllArgsConstructor
public enum SmsReceiveStatusEnum {
INIT(0), // 初始化
SUCCESS(10), // 接收成功
FAILURE(20), // 接收失败
;
private final int status;
}
@@ -0,0 +1,51 @@
package com.oneone.upms.api.enums.sms;
import cn.hutool.core.util.ArrayUtil;
import com.oneone.common.enums.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 用户短信验证码发送场景的枚举
*
*
*/
@Getter
@AllArgsConstructor
public enum SmsSceneEnum implements IntArrayValuable {
MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"),
MEMBER_UPDATE_MOBILE(2, "user-update-mobile", "会员用户 - 修改手机"),
MEMBER_UPDATE_PASSWORD(3, "user-update-mobile", "会员用户 - 修改密码"),
MEMBER_RESET_PASSWORD(4, "user-reset-password", "会员用户 - 忘记密码"),
ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray();
/**
* 验证场景的编号
*/
private final Integer scene;
/**
* 模版编码
*/
private final String templateCode;
/**
* 描述
*/
private final String description;
@Override
public int[] array() {
return ARRAYS;
}
public static SmsSceneEnum getCodeByScene(Integer scene) {
return ArrayUtil.firstMatch(sceneEnum -> sceneEnum.getScene().equals(scene),
values());
}
}
@@ -0,0 +1,24 @@
package com.oneone.upms.api.enums.sms;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 短信的发送状态枚举
*
* @author zzf
* @date 2021/2/1 13:39
*/
@Getter
@AllArgsConstructor
public enum SmsSendStatusEnum {
INIT(0), // 初始化
SUCCESS(10), // 发送成功
FAILURE(20), // 发送失败
IGNORE(30), // 忽略,即不发送
;
private final int status;
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.enums.sms;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 短信的模板类型枚举
*
*
*/
@Getter
@AllArgsConstructor
public enum SmsTemplateTypeEnum {
VERIFICATION_CODE(1), // 验证码
NOTICE(2), // 通知
PROMOTION(3), // 营销
;
/**
* 类型
*/
private final int type;
}
@@ -0,0 +1,78 @@
package com.oneone.upms.api.enums.social;
import cn.hutool.core.util.ArrayUtil;
import com.oneone.common.enums.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 社交平台的类型枚举
*
*
*/
@Getter
@AllArgsConstructor
public enum SocialTypeEnum implements IntArrayValuable {
/**
* Gitee
*
* @see <a href="https://gitee.com/api/v5/oauth_doc#/">接入文档</a>
*/
GITEE(10, "GITEE"),
/**
* 钉钉
*
* @see <a href="https://developers.dingtalk.com/document/app/obtain-identity-credentials">接入文档</a>
*/
DINGTALK(20, "DINGTALK"),
/**
* 企业微信
*
* @see <a href="https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html">接入文档</a>
*/
WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"),
/**
* 微信公众平台 - 移动端 H5
*
* @see <a href="https://www.cnblogs.com/juewuzhe/p/11905461.html">接入文档</a>
*/
WECHAT_MP(31, "WECHAT_MP"),
/**
* 微信开放平台 - 网站应用 PC 端扫码授权登录
*
* @see <a href="https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证">接入文档</a>
*/
WECHAT_OPEN(32, "WECHAT_OPEN"),
/**
* 微信小程序
*
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html">接入文档</a>
*/
WECHAT_MINI_APP(34, "WECHAT_MINI_APP"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SocialTypeEnum::getType).toArray();
/**
* 类型
*/
private final Integer type;
/**
* 类型的标识
*/
private final String source;
@Override
public int[] array() {
return ARRAYS;
}
public static SocialTypeEnum valueOfType(Integer type) {
return ArrayUtil.firstMatch(o -> o.getType().equals(type), values());
}
}
@@ -0,0 +1,47 @@
package com.oneone.upms.api.errorcode;
import com.oneone.common.result.Result;
import com.oneone.upms.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import com.oneone.upms.api.errorcode.dto.ErrorCodeRespDTO;
import com.oneone.upms.api.ApiConstants;
import com.oneone.upms.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 错误码")
public interface ErrorCodeApi {
String PREFIX = ApiConstants.PREFIX + "/error-code";
@PostMapping(PREFIX + "/auto-generate")
@Operation(summary = "自动创建错误码")
Result<Boolean> autoGenerateErrorCodeList(@Valid @RequestBody List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs);
@GetMapping(PREFIX + "/list")
@Operation(summary = "增量获得错误码数组", description = "如果 minUpdateTime 为空时,则获取所有错误码")
@Parameters({
@Parameter(name = "applicationName", description = "应用名", example = "system-server", required = true),
@Parameter(name = "minUpdateTime", description = "最小更新时间")
})
Result<List<ErrorCodeRespDTO>> getErrorCodeList(
@RequestParam(value = "applicationName") String applicationName,
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@RequestParam(value = "minUpdateTime", required = false) LocalDateTime minUpdateTime);
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.errorcode.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "RPC 服务 - 错误码自动生成 Request DTO")
@Data
public class ErrorCodeAutoGenerateReqDTO {
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotNull(message = "应用名不能为空")
private String applicationName;
@Schema(description = "错误码编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "错误码编码不能为空")
private Integer code;
@Schema(description = "错误码错误提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "业务不能为空")
@NotEmpty(message = "错误码错误提示不能为空")
private String message;
}
@@ -0,0 +1,28 @@
package com.oneone.upms.api.errorcode.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "RPC 服务 - 错误码 Response DTO")
@Data
public class ErrorCodeRespDTO {
/**
* 错误码编码
*/
@Schema(description = "错误码编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer code;
/**
* 错误码错误提示
*/
@Schema(description = "错误码错误提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "业务不能为空")
private String message;
/**
* 更新时间
*/
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
}
@@ -0,0 +1,30 @@
package com.oneone.upms.api.file;
import com.oneone.common.result.Result;
import com.oneone.common.util.collection.CollectionUtils;
import com.oneone.upms.api.ApiConstants;
import com.oneone.upms.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 服务 - 文件上传")
public interface FileUploadApi {
String PREFIX = ApiConstants.PREFIX + "/file";
@PostMapping(PREFIX + "/upload")
@Operation(summary = "文件上传")
Result<String> uploadFile(@RequestParam("file") MultipartFile files);
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.logger;
import com.oneone.common.result.Result;
import com.oneone.upms.api.logger.dto.LoginLogCreateReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 登录日志")
public interface LoginLogApi {
String PREFIX = ApiConstants.PREFIX + "/login-log";
@PostMapping(PREFIX + "/create")
@Operation(summary = "创建登录日志")
Result<Boolean> createLoginLog(@Valid @RequestBody LoginLogCreateReqDTO reqDTO);
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.logger;
import com.oneone.common.result.Result;
import com.oneone.upms.api.logger.dto.OperateLogCreateReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 操作日志")
public interface OperateLogApi {
String PREFIX = ApiConstants.PREFIX + "/operate-log";
@PostMapping(PREFIX + "/create")
@Operation(summary = "创建操作日志")
Result<Boolean> createOperateLog(@Valid @RequestBody OperateLogCreateReqDTO createReqDTO);
}
@@ -0,0 +1,43 @@
package com.oneone.upms.api.logger.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Schema(description = "RPC 服务 - 登录日志创建 Request DTO")
@Data
public class LoginLogCreateReqDTO {
@Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1" )
@NotNull(message = "日志类型不能为空")
private Integer logType;
@Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
private String traceId;
@Schema(description = "用户编号", example = "666")
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2" )
@NotNull(message = "用户类型不能为空")
private Integer userType;
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotBlank(message = "用户账号不能为空")
@Size(max = 30, message = "用户账号长度不能超过30个字符")
private String username;
@Schema(description = "登录结果,参见 LoginResultEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "登录结果不能为空")
private Integer result;
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
@NotEmpty(message = "用户 IP 不能为空")
private String userIp;
@Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
private String userAgent;
}
@@ -0,0 +1,84 @@
package com.oneone.upms.api.logger.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.Map;
@Schema(description = "RPC 服务 - 操作日志创建 Request DTO")
@Data
public class OperateLogCreateReqDTO {
@Schema(description = "链路追踪编号", example = "89aca178-a370-411c-ae02-3f0d672be4ab")
private String traceId;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "用户类型不能为空")
private Integer userType;
@Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
@NotEmpty(message = "操作模块不能为空")
private String module;
@Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单")
@NotEmpty(message = "操作名")
private String name;
@Schema(description = "操作分类,参见 SysOperateLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "操作分类不能为空")
private Integer type;
@Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
private String content;
@Schema(description = "拓展字段", example = "{'orderId': 1}")
private Map<String, Object> exts;
@Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET")
@NotEmpty(message = "请求方法名不能为空")
private String requestMethod;
@Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy")
@NotEmpty(message = "请求地址不能为空")
private String requestUrl;
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
@NotEmpty(message = "用户 IP 不能为空")
private String userIp;
@Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
@NotEmpty(message = "浏览器 UserAgent 不能为空")
private String userAgent;
@Schema(description = "Java 方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "cn.iocoder.yudao.UserController.save(...)")
@NotEmpty(message = "Java 方法名不能为空")
private String javaMethod;
@Schema(description = "Java 方法的参数")
private String javaMethodArgs;
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "开始时间不能为空")
private LocalDateTime startTime;
@Schema(description = "执行时长,单位:毫秒", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "执行时长不能为空")
private Integer duration;
@Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结果码不能为空")
private String resultCode;
@Schema(description = "结果提示")
private String resultMsg;
@Schema(description = "结果数据")
private String resultData;
}
@@ -0,0 +1,28 @@
package com.oneone.upms.api.mail;
import com.oneone.common.result.Result;
import com.oneone.upms.api.mail.dto.MailSendSingleToUserReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 邮件发送")
public interface MailSendApi {
String PREFIX = ApiConstants.PREFIX + "/mail/send";
@PostMapping(PREFIX + "/send-single-admin")
@Operation(summary = "发送单条邮件给 Admin 用户", description = "在 mail 为空时,使用 userId 加载对应 Admin 的邮箱")
Result<Long> sendSingleMailToAdmin(@Valid MailSendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/send-single-member")
@Operation(summary = "发送单条邮件给 Member 用户", description = "在 mail 为空时,使用 userId 加载对应 Member 的邮箱")
Result<Long> sendSingleMailToMember(@Valid MailSendSingleToUserReqDTO reqDTO);
}
@@ -0,0 +1,27 @@
package com.oneone.upms.api.mail.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import java.util.Map;
@Schema(description = "RPC 服务 - 邮件发送给 Admin 或者 Member 用户 Request DTO")
@Data
public class MailSendSingleToUserReqDTO {
@Schema(description = "用户编号", example = "1024")
private Long userId;
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
@Email
private String mail;
@Schema(description = "邮件模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "USER_SEND")
@NotNull(message = "邮件模板编号不能为空")
private String templateCode;
@Schema(description = "邮件模板参数")
private Map<String, Object> templateParams;
}
@@ -0,0 +1,28 @@
package com.oneone.upms.api.notify;
import com.oneone.common.result.Result;
import com.oneone.upms.api.notify.dto.NotifySendSingleToUserReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 站内信发送")
public interface NotifyMessageSendApi {
String PREFIX = ApiConstants.PREFIX + "/notify/send";
@PostMapping(PREFIX + "/send-single-admin")
@Operation(summary = "发送单条站内信给 Admin 用户")
Result<Long> sendSingleMessageToAdmin(@Valid NotifySendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/send-single-member")
@Operation(summary = "发送单条站内信给 Member 用户")
Result<Long> sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO);
}
@@ -0,0 +1,23 @@
package com.oneone.upms.api.notify.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Map;
@Schema(description = "RPC 服务 - 站内信发送给 Admin 或者 Member 用户 Request DTO")
@Data
public class NotifySendSingleToUserReqDTO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "站内信模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "USER_SEND")
@NotEmpty(message = "站内信模板编号不能为空")
private String templateCode;
@Schema(description = "邮件模板参数")
private Map<String, Object> templateParams;
}
@@ -0,0 +1,52 @@
package com.oneone.upms.api.permission;
import com.oneone.common.result.Result;
import com.oneone.upms.api.permission.dto.DeptDataPermissionRespDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.Set;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 权限")
public interface PermissionApi {
String PREFIX = ApiConstants.PREFIX + "/permission";
@GetMapping(PREFIX + "/user-role-id-list-by-role-id")
@Operation(summary = "获得拥有多个角色的用户编号集合")
@Parameter(name = "roleIds", description = "角色编号集合", example = "1,2", required = true)
Result<Set<Long>> getUserRoleIdListByRoleIds(@RequestParam("roleIds") Collection<Long> roleIds);
@GetMapping(PREFIX + "/has-any-permissions")
@Operation(summary = "判断是否有权限,任一一个即可")
@Parameters({
@Parameter(name = "userId", description = "用户编号", example = "1", required = true),
@Parameter(name = "permissions", description = "权限", example = "read,write", required = true)
})
Result<Boolean> hasAnyPermissions(@RequestParam("userId") Long userId,
@RequestParam("permissions") String... permissions);
@GetMapping(PREFIX + "/has-any-roles")
@Operation(summary = "判断是否有角色,任一一个即可")
@Parameters({
@Parameter(name = "userId", description = "用户编号", example = "1", required = true),
@Parameter(name = "roles", description = "角色数组", example = "2", required = true)
})
Result<Boolean> hasAnyRoles(@RequestParam("userId") Long userId,
@RequestParam("roles") String... roles);
@GetMapping(PREFIX + "/get-dept-data-permission")
@Operation(summary = "获得登陆用户的部门数据权限")
@Parameter(name = "userId", description = "用户编号", example = "2", required = true)
Result<DeptDataPermissionRespDTO> getDeptDataPermission(@RequestParam("userId") Long userId);
}
@@ -0,0 +1,26 @@
package com.oneone.upms.api.permission;
import com.oneone.common.result.Result;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 角色")
public interface RoleApi {
String PREFIX = ApiConstants.PREFIX + "/role";
@GetMapping(PREFIX + "/valid")
@Operation(summary = "校验角色是否合法")
@Parameter(name = "ids", description = "角色编号数组", example = "1,2", required = true)
Result<Boolean> validRoleList(@RequestParam("ids") Collection<Long> ids);
}
@@ -0,0 +1,28 @@
package com.oneone.upms.api.permission.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.HashSet;
import java.util.Set;
@Schema(description = "RPC 服务 - 部门的数据权限 Response DTO")
@Data
public class DeptDataPermissionRespDTO {
@Schema(description = "是否可查看全部数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean all;
@Schema(description = "是否可查看自己的数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean self;
@Schema(description = "可查看的部门编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 3]")
private Set<Long> deptIds;
public DeptDataPermissionRespDTO() {
this.all = false;
this.self = false;
this.deptIds = new HashSet<>();
}
}
@@ -0,0 +1,40 @@
package com.oneone.upms.api.sensitiveword;
import com.oneone.common.result.Result;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFacx`tory =
@Tag(name = "RPC 服务 - 敏感词")
public interface SensitiveWordApi {
String PREFIX = ApiConstants.PREFIX + "/sensitive-word";
@GetMapping(PREFIX + "/validate-text")
@Operation(summary = "获得文本所包含的不合法的敏感词数组")
@Parameters({
@Parameter(name = "text", description = "文本", example = "傻瓜", required = true),
@Parameter(name = "tags", description = "标签数组", example = "product,life", required = true)
})
Result<List<String>> validateText(@RequestParam("text") String text,
@RequestParam("tags") List<String> tags);
@GetMapping(PREFIX + "/is-text-valid")
@Operation(summary = "判断文本是否包含敏感词")
@Parameters({
@Parameter(name = "text", description = "文本", example = "傻瓜", required = true),
@Parameter(name = "tags", description = "标签数组", example = "product,life", required = true)
})
Result<Boolean> isTextValid(@RequestParam("text") String text,
@RequestParam("tags") List<String> tags);
}
@@ -0,0 +1,37 @@
package com.oneone.upms.api.sms;
import com.oneone.common.result.Result;
import com.oneone.upms.api.sms.dto.code.SmsCodeSendReqDTO;
import com.oneone.upms.api.sms.dto.code.SmsCodeUseReqDTO;
import com.oneone.upms.api.sms.dto.code.SmsCodeValidateReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
//@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 短信验证码")
public interface SmsCodeApi {
String PREFIX = ApiConstants.PREFIX + "/oauth2/sms/code";
@PostMapping(PREFIX + "/send")
@Operation(summary = "创建短信验证码,并进行发送")
Result<Boolean> sendSmsCode(@Valid @RequestBody SmsCodeSendReqDTO reqDTO);
@PutMapping(PREFIX + "/use")
@Operation(summary = "验证短信验证码,并进行使用")
Result<Boolean> useSmsCode(@Valid @RequestBody SmsCodeUseReqDTO reqDTO);
@GetMapping(PREFIX + "/validate")
@Operation(summary = "检查验证码是否有效")
Result<Boolean> validateSmsCode(@Valid @RequestBody SmsCodeValidateReqDTO reqDTO);
}
@@ -0,0 +1,29 @@
package com.oneone.upms.api.sms;
import com.oneone.common.result.Result;
import com.oneone.upms.api.sms.dto.send.SmsSendSingleToUserReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 短信发送")
public interface SmsSendApi {
String PREFIX = ApiConstants.PREFIX + "/sms/send";
@PostMapping(PREFIX + "/send-single-admin")
@Operation(summary = "发送单条短信给 Admin 用户", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
Result<Long> sendSingleSmsToAdmin(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/send-single-member")
@Operation(summary = "发送单条短信给 Member 用户", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
Result<Long> sendSingleSmsToMember(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
}
@@ -0,0 +1,30 @@
package com.oneone.upms.api.sms.dto.code;
import com.oneone.common.validation.Mobile;
import com.oneone.upms.api.enums.sms.SmsSceneEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "RPC 服务 - 短信验证码的发送 Request DTO")
@Data
public class SmsCodeSendReqDTO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
@Mobile
@NotEmpty(message = "手机号不能为空")
private String mobile;
@Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "发送场景不能为空")
// @InEnum(SmsSceneEnum.class)
private Integer scene;
@Schema(description = "发送 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.20.30.40")
@NotEmpty(message = "发送 IP 不能为空")
private String createIp;
}
@@ -0,0 +1,34 @@
package com.oneone.upms.api.sms.dto.code;
import com.oneone.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "RPC 服务 - 短信验证码的使用 Request DTO")
@Data
public class SmsCodeUseReqDTO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
@Mobile
@NotEmpty(message = "手机号不能为空")
private String mobile;
@Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "发送场景不能为空")
// @InEnum(SmsSceneEnum.class)
private Integer scene;
@Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotEmpty(message = "验证码")
private String code;
@Schema(description = "发送 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.20.30.40")
@NotEmpty(message = "使用 IP 不能为空")
private String usedIp;
}
@@ -0,0 +1,30 @@
package com.oneone.upms.api.sms.dto.code;
import com.oneone.common.validation.Mobile;
import com.oneone.upms.api.enums.sms.SmsSceneEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "RPC 服务 - 短信验证码的校验 Request DTO")
@Data
public class SmsCodeValidateReqDTO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
@Mobile
@NotEmpty(message = "手机号不能为空")
private String mobile;
@Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "发送场景不能为空")
// @InEnum(SmsSceneEnum.class)
private Integer scene;
@Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotEmpty(message = "验证码")
private String code;
}
@@ -0,0 +1,26 @@
package com.oneone.upms.api.sms.dto.send;
import com.oneone.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.Map;
@Schema(description = "RPC 服务 - 短信发送给 Admin 或者 Member 用户 Request DTO")
@Data
public class SmsSendSingleToUserReqDTO {
@Schema(description = "用户编号", example = "1024")
private Long userId;
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
@Mobile
private String mobile;
@Schema(description = "短信模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "USER_SEND")
@NotEmpty(message = "短信模板编号不能为空")
private String templateCode;
@Schema(description = "短信模板参数")
private Map<String, Object> templateParams;
}
@@ -0,0 +1,51 @@
package com.oneone.upms.api.social;
import com.oneone.common.result.Result;
import com.oneone.upms.api.social.dto.SocialWxJsapiSignatureRespDTO;
import com.oneone.upms.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 社交应用")
public interface SocialClientApi {
String PREFIX = ApiConstants.PREFIX + "/social-client";
@GetMapping(PREFIX + "/get-authorize-url")
@Operation(summary = "获得社交平台的授权 URL")
@Parameters({
@Parameter(name = "socialType", description = "社交平台的类型", example = "1", required = true),
@Parameter(name = "userType", description = "用户类型", example = "1", required = true),
@Parameter(name = "redirectUri", description = "重定向 URL", example = "https://www.iocoder.cn", required = true)
})
Result<String> getAuthorizeUrl(@RequestParam("socialType") Integer socialType,
@RequestParam("userType") Integer userType,
@RequestParam("redirectUri") String redirectUri);
@GetMapping(PREFIX + "/create-wx-mp-jsapi-signature")
@Operation(summary = "创建微信公众号 JS SDK 初始化所需的签名")
@Parameters({
@Parameter(name = "userType", description = "用户类型", example = "1", required = true),
@Parameter(name = "url", description = "访问 URL", example = "https://www.iocoder.cn", required = true)
})
Result<SocialWxJsapiSignatureRespDTO> createWxMpJsapiSignature(@RequestParam("userType") Integer userType,
@RequestParam("url") String url);
@GetMapping(PREFIX + "/create-wx-ma-phone-number-info")
@Operation(summary = "获得微信小程序的手机信息")
@Parameters({
@Parameter(name = "userType", description = "用户类型", example = "1", required = true),
@Parameter(name = "phoneCode", description = "手机授权码", example = "yudao11", required = true)
})
Result<SocialWxPhoneNumberInfoRespDTO> getWxMaPhoneNumberInfo(@RequestParam("userType") Integer userType,
@RequestParam("phoneCode") String phoneCode);
}
@@ -0,0 +1,44 @@
package com.oneone.upms.api.social;
import com.oneone.common.result.Result;
import com.oneone.upms.api.social.dto.SocialUserBindReqDTO;
import com.oneone.upms.api.social.dto.SocialUserRespDTO;
import com.oneone.upms.api.social.dto.SocialUserUnbindReqDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import javax.validation.Valid;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 社交用户")
public interface SocialUserApi {
String PREFIX = ApiConstants.PREFIX + "/social-user";
@PostMapping(PREFIX + "/bind")
@Operation(summary = "绑定社交用户")
Result<String> bindSocialUser(@Valid @RequestBody SocialUserBindReqDTO reqDTO);
@DeleteMapping(PREFIX + "/unbind")
@Operation(summary = "取消绑定社交用户")
Result<Boolean> unbindSocialUser(@Valid @RequestBody SocialUserUnbindReqDTO reqDTO);
@GetMapping(PREFIX + "/get")
@Operation(summary = "获得社交用户的绑定用户编号")
@Parameters({
@Parameter(name = "userType", description = "用户类型", example = "2", required = true),
@Parameter(name = "socialType", description = "社交平台的类型", example = "1", required = true),
@Parameter(name = "code", description = "授权码", required = true, example = "tudou"),
@Parameter(name = "state", description = "state", required = true, example = "coke")
})
Result<SocialUserRespDTO> getSocialUser(@RequestParam("userType") Integer userType,
@RequestParam("socialType") Integer socialType,
@RequestParam("code") String code,
@RequestParam("state") String state);
}
@@ -0,0 +1,38 @@
package com.oneone.upms.api.social.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "RPC 服务 - 取消绑定社交用户 Request DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SocialUserBindReqDTO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
// @InEnum(UserTypeEnum.class)
@NotNull(message = "用户类型不能为空")
private Integer userType;
@Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
// @InEnum(SocialTypeEnum.class)
@NotNull(message = "社交平台的类型不能为空")
private Integer socialType;
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "zsw")
@NotEmpty(message = "授权码不能为空")
private String code;
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "qtw")
@NotEmpty(message = "state 不能为空")
private String state;
}
@@ -0,0 +1,20 @@
package com.oneone.upms.api.social.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "RPC 服务 - 社交用户 Response DTO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SocialUserRespDTO {
@Schema(description = "社交用户 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "zsw")
private String openid;
@Schema(description = "关联的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId;
}
@@ -0,0 +1,32 @@
package com.oneone.upms.api.social.dto;
import com.oneone.upms.api.enums.social.SocialTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "RPC 服务 - 取消绑定社交用户 Request DTO")
@Data
public class SocialUserUnbindReqDTO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
// @InEnum(UserTypeEnum.class)
@NotNull(message = "用户类型不能为空")
private Integer userType;
@Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
// @InEnum(SocialTypeEnum.class)
@NotNull(message = "社交平台的类型不能为空")
private Integer socialType;
@Schema(description = "社交平台的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "zsw")
@NotEmpty(message = "社交平台的 openid 不能为空")
private String openid;
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.social.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "RPC 服务 - 微信公众号 JSAPI 签名 Response DTO")
@Data
public class SocialWxJsapiSignatureRespDTO {
@Schema(description = "微信公众号的 appId", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx123456")
private String appId;
@Schema(description = "匿名串", requiredMode = Schema.RequiredMode.REQUIRED, example = "zsw")
private String nonceStr;
@Schema(description = "时间戳", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789")
private Long timestamp;
@Schema(description = "URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
private String url;
@Schema(description = "签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "zsw")
private String signature;
}
@@ -0,0 +1,18 @@
package com.oneone.upms.api.social.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "RPC 服务 - 微信小程序的手机信息 Response DTO")
@Data
public class SocialWxPhoneNumberInfoRespDTO {
@Schema(description = "用户绑定的手机号(国外手机号会有区号)", requiredMode = Schema.RequiredMode.REQUIRED, example = "021-13579246810")
private String phoneNumber;
@Schema(description = "没有区号的手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13579246810")
private String purePhoneNumber;
@Schema(description = "区号", requiredMode = Schema.RequiredMode.REQUIRED, example = "021")
private String countryCode;
}
@@ -0,0 +1,62 @@
package com.oneone.upms.api.user;
import com.oneone.common.result.Result;
import com.oneone.common.util.collection.CollectionUtils;
import com.oneone.upms.api.user.dto.AdminUserRespDTO;
import com.oneone.upms.api.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@FeignClient(name = ApiConstants.NAME) // TODO fallbackFactory =
@Tag(name = "RPC 服务 - 管理员用户")
public interface AdminUserApi {
String PREFIX = ApiConstants.PREFIX + "/user";
@GetMapping(PREFIX + "/get")
@Operation(summary = "通过用户 ID 查询用户")
@Parameter(name = "id", description = "用户编号", example = "1", required = true)
Result<AdminUserRespDTO> getUser(@RequestParam("id") Long id);
@GetMapping(PREFIX + "/list")
@Operation(summary = "通过用户 ID 查询用户们")
@Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
Result<List<AdminUserRespDTO>> getUserList(@RequestParam("ids") Collection<Long> ids);
@GetMapping(PREFIX + "/list-by-dept-id")
@Operation(summary = "获得指定部门的用户数组")
@Parameter(name = "deptIds", description = "部门编号数组", example = "1,2", required = true)
Result<List<AdminUserRespDTO>> getUserListByDeptIds(@RequestParam("deptIds") Collection<Long> deptIds);
@GetMapping(PREFIX + "/list-by-post-id")
@Operation(summary = "获得指定岗位的用户数组")
@Parameter(name = "postIds", description = "岗位编号数组", example = "2,3", required = true)
Result<List<AdminUserRespDTO>> getUserListByPostIds(@RequestParam("postIds") Collection<Long> postIds);
/**
* 获得用户 Map
*
* @param ids 用户编号数组
* @return 用户 Map
*/
default Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) {
List<AdminUserRespDTO> users = getUserList(ids).getCheckedData();
return CollectionUtils.convertMap(users, AdminUserRespDTO::getId);
}
@GetMapping(PREFIX + "/valid")
@Operation(summary = "校验用户们是否有效")
@Parameter(name = "ids", description = "用户编号数组", example = "3,5", required = true)
Result<Boolean> validateUserList(@RequestParam("ids") Set<Long> ids);
}
@@ -0,0 +1,30 @@
package com.oneone.upms.api.user.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Set;
@Schema(description = "RPC 服务 - Admin 用户 Response DTO")
@Data
public class AdminUserRespDTO {
@Schema(description = "用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "帐号状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status; // 参见 CommonStatusEnum 枚举
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long deptId;
@Schema(description = "岗位编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 3]")
private Set<Long> postIds;
@Schema(description = "手机号码", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
private String mobile;
}
+119
View File
@@ -0,0 +1,119 @@
<?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.oneone.cloud</groupId>
<artifactId>oneone-upms</artifactId>
<version>${revision}</version>
</parent>
<artifactId>oneone-upms-boot</artifactId>
<dependencies>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>oneone-upms-api</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-web</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-biz</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-log</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-redis</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-mybatis-plus</artifactId>
</dependency>
<!-- Registry 注册中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Config 配置中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
</dependency>
<!--<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
</dependency>-->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
</dependency>
<dependency>
<groupId>cn.smallbun.screw</groupId>
<artifactId>screw-core</artifactId> <!-- 实现数据库文档 -->
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId> <!-- 实现代码生成 -->
</dependency>
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-captcha-plus</artifactId>
<scope>provided</scope>
</dependency>
<!-- 阿里云 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,15 @@
package com.oneone.upms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class UpmsApplication {
public static void main(String[] args) {
SpringApplication.run(UpmsApplication.class, args);
}
}
@@ -0,0 +1,46 @@
package com.oneone.upms.api.dict;
import com.oneone.common.result.Result;
import com.oneone.common.util.BeanUtils;
import com.oneone.upms.api.dict.dto.DictDataRespDTO;
import com.oneone.upms.dal.dataobject.dict.DictDataDO;
import com.oneone.upms.service.dict.DictDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
@Slf4j
public class DictDataApiImpl implements DictDataApi{
@Resource
@Lazy
private DictDataService dictDataService;
@Override
public Result<Boolean> validateDictDataList(String dictType, Collection<String> values) {
return null;
}
@Override
public Result<DictDataRespDTO> getDictData(String dictType, String value) {
return null;
}
@Override
public Result<DictDataRespDTO> parseDictData(String dictType, String label) {
return null;
}
@Override
public Result<List<DictDataRespDTO>> getDictDataByType(String dictType) {
List<DictDataDO> dictDataDOS = dictDataService.getEnabledDictDataListByType(dictType);
return Result.success(BeanUtils.toBean(dictDataDOS,DictDataRespDTO.class));
}
}
@@ -0,0 +1,37 @@
package com.oneone.upms.api.file;
import com.oneone.common.result.Result;
import com.oneone.upms.api.user.dto.AdminUserRespDTO;
import com.oneone.upms.service.file.ISysFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import static com.oneone.common.result.Result.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
@Slf4j
public class FileApiImpl implements FileUploadApi{
@Autowired
private ISysFileService localSysFileByPathServiceImpl;
@Override
public Result<String> uploadFile(MultipartFile file) {
String url="";
try {
url = localSysFileByPathServiceImpl.uploadFile(file);
} catch (Exception e) {
log.error("上传文件失败!",e);
return Result.failed("上传文件失败!");
}
return success(url);
}
}
@@ -0,0 +1,27 @@
package com.oneone.upms.api.logger;
import com.oneone.common.result.Result;
import com.oneone.upms.api.logger.dto.LoginLogCreateReqDTO;
import com.oneone.upms.service.logger.LoginLogService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import static com.oneone.common.result.Result.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class LoginLogApiImpl implements LoginLogApi {
@Resource
private LoginLogService loginLogService;
@Override
public Result<Boolean> createLoginLog(LoginLogCreateReqDTO reqDTO) {
loginLogService.createLoginLog(reqDTO);
return success(true);
}
}
@@ -0,0 +1,26 @@
package com.oneone.upms.api.logger;
import com.oneone.common.result.Result;
import com.oneone.upms.api.logger.dto.OperateLogCreateReqDTO;
import com.oneone.upms.service.logger.OperateLogService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import static com.oneone.common.result.Result.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class OperateLogApiImpl implements OperateLogApi {
@Resource
private OperateLogService operateLogService;
@Override
public Result<Boolean> createOperateLog(OperateLogCreateReqDTO createReqDTO) {
operateLogService.createOperateLog(createReqDTO);
return success(true);
}
}
@@ -0,0 +1,29 @@
package com.oneone.upms.api.notify;
import com.oneone.common.result.Result;
import com.oneone.upms.api.notify.dto.NotifySendSingleToUserReqDTO;
import com.oneone.upms.service.notify.NotifySendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
@Slf4j
public class NotifyMessageSendApiImpl implements NotifyMessageSendApi{
@Resource
private NotifySendService notifySendService;
@Override
public Result<Long> sendSingleMessageToAdmin(NotifySendSingleToUserReqDTO reqDTO) {
return Result.success(notifySendService.sendSingleNotifyToAdmin(reqDTO.getUserId(), reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
}
@Override
public Result<Long> sendSingleMessageToMember(NotifySendSingleToUserReqDTO reqDTO) {
return Result.success(notifySendService.sendSingleNotifyToMember(reqDTO.getUserId(), reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
}
}
@@ -0,0 +1,43 @@
package com.oneone.upms.api.permission;
import com.oneone.common.result.Result;
import com.oneone.upms.api.permission.dto.DeptDataPermissionRespDTO;
import com.oneone.upms.service.permission.PermissionService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.Set;
import static com.oneone.common.result.Result.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class PermissionApiImpl implements PermissionApi {
@Resource
private PermissionService permissionService;
@Override
public Result<Set<Long>> getUserRoleIdListByRoleIds(Collection<Long> roleIds) {
return success(permissionService.getUserRoleIdListByRoleId(roleIds));
}
@Override
public Result<Boolean> hasAnyPermissions(Long userId, String... permissions) {
return success(permissionService.hasAnyPermissions(userId, permissions));
}
@Override
public Result<Boolean> hasAnyRoles(Long userId, String... roles) {
return success(permissionService.hasAnyRoles(userId, roles));
}
@Override
public Result<DeptDataPermissionRespDTO> getDeptDataPermission(Long userId) {
return success(permissionService.getDeptDataPermission(userId));
}
}
@@ -0,0 +1,25 @@
package com.oneone.upms.api.permission;
import com.oneone.common.result.Result;
import com.oneone.upms.service.permission.RoleService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Collection;
import static com.oneone.common.result.Result.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class RoleApiImpl implements RoleApi {
@Resource
private RoleService roleService;
@Override
public Result<Boolean> validRoleList(Collection<Long> ids) {
roleService.validateRoleList(ids);
return success(true);
}
}
@@ -0,0 +1,29 @@
package com.oneone.upms.common.codegen;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 代码生成器的字段 HTML 展示枚举
*/
@AllArgsConstructor
@Getter
public enum CodegenColumnHtmlTypeEnum {
INPUT("input"), // 文本框
TEXTAREA("textarea"), // 文本域
SELECT("select"), // 下拉框
RADIO("radio"), // 单选框
CHECKBOX("checkbox"), // 复选框
DATETIME("datetime"), // 日期控件
IMAGE_UPLOAD("imageUpload"), // 上传图片
FILE_UPLOAD("fileUpload"), // 上传文件
EDITOR("editor"), // 富文本控件
;
/**
* 条件
*/
private final String type;
}
@@ -0,0 +1,27 @@
package com.oneone.upms.common.codegen;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 代码生成器的字段过滤条件枚举
*/
@AllArgsConstructor
@Getter
public enum CodegenColumnListConditionEnum {
EQ("="),
NE("!="),
GT(">"),
GTE(">="),
LT("<"),
LTE("<="),
LIKE("LIKE"),
BETWEEN("BETWEEN");
/**
* 条件
*/
private final String condition;
}
@@ -0,0 +1,26 @@
package com.oneone.upms.common.codegen;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 代码生成的前端类型枚举
*
*
*/
@AllArgsConstructor
@Getter
public enum CodegenFrontTypeEnum {
VUE2(10), // Vue2 Element UI 标准模版
VUE3(20), // Vue3 Element Plus 标准模版
VUE3_SCHEMA(21), // Vue3 Element Plus Schema 模版
VUE3_VBEN(30), // Vue3 VBEN 模版
;
/**
* 类型
*/
private final Integer type;
}
@@ -0,0 +1,41 @@
package com.oneone.upms.common.codegen;
import lombok.AllArgsConstructor;
import lombok.Getter;
import static cn.hutool.core.util.ArrayUtil.firstMatch;
/**
* 代码生成的场景枚举
*
*
*/
@AllArgsConstructor
@Getter
public enum CodegenSceneEnum {
ADMIN(1, "管理后台", "admin", ""),
APP(2, "用户 APP", "app", "App");
/**
* 场景
*/
private final Integer scene;
/**
* 场景名
*/
private final String name;
/**
* 基础包名
*/
private final String basePackage;
/**
* Controller 和 VO 类的前缀
*/
private final String prefixClass;
public static CodegenSceneEnum valueOf(Integer scene) {
return firstMatch(sceneEnum -> sceneEnum.getScene().equals(scene), values());
}
}
@@ -0,0 +1,53 @@
package com.oneone.upms.common.codegen;
import com.oneone.common.util.ObjectUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
/**
* 代码生成模板类型
*
*
*/
@AllArgsConstructor
@Getter
public enum CodegenTemplateTypeEnum {
ONE(1), // 单表(增删改查)
TREE(2), // 树表(增删改查)
MASTER_NORMAL(10), // 主子表 - 主表 - 普通模式
MASTER_ERP(11), // 主子表 - 主表 - ERP 模式
MASTER_INNER(12), // 主子表 - 主表 - 内嵌模式
SUB(15), // 主子表 - 子表
;
/**
* 类型
*/
private final Integer type;
/**
* 是否为主表
*
* @param type 类型
* @return 是否主表
*/
public static boolean isMaster(Integer type) {
return ObjectUtils.equalsAny(type,
MASTER_NORMAL.type, MASTER_ERP.type, MASTER_INNER.type);
}
/**
* 是否为树表
*
* @param type 类型
* @return 是否树表
*/
public static boolean isTree(Integer type) {
return Objects.equals(type, TREE.type);
}
}
@@ -0,0 +1,9 @@
package com.oneone.upms.config;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(CodegenProperties.class)
public class CodegenConfiguration {
}
@@ -0,0 +1,37 @@
package com.oneone.upms.config;
import com.oneone.upms.common.codegen.CodegenFrontTypeEnum;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Collection;
@ConfigurationProperties(prefix = "oneone.codegen")
@Validated
@Data
public class CodegenProperties {
/**
* 生成的 Java 代码的基础包
*/
@NotNull(message = "Java 代码的基础包不能为空")
private String basePackage;
/**
* 数据库名数组
*/
@NotEmpty(message = "数据库不能为空")
private Collection<String> dbSchemas;
/**
* 代码生成的前端类型(默认)
*
* 枚举 {@link CodegenFrontTypeEnum#getType()}
*/
@NotNull(message = "代码生成的前端类型不能为空")
private Integer frontType;
}
@@ -0,0 +1,26 @@
package com.oneone.upms.config;
import com.oneone.common.biz.datapermission.rule.dept.DeptDataPermissionRuleCustomizer;
import com.oneone.upms.dal.dataobject.dept.DeptDO;
import com.oneone.upms.dal.dataobject.user.AdminUserDO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* system 模块的数据权限 Configuration
*/
@Configuration(proxyBeanMethods = false)
public class DataPermissionConfiguration {
@Bean
public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {
return rule -> {
// dept
rule.addDeptColumn(AdminUserDO.class);
rule.addDeptColumn(DeptDO.class, "id");
// user
rule.addUserColumn(AdminUserDO.class, "id");
};
}
}
@@ -0,0 +1,23 @@
package com.oneone.upms.config;
import com.oneone.common.redis.utils.LocalRedisTokenStore;
import com.oneone.common.redis.utils.RedisUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author mice
* @version 1.0
* @date 2022-04-07 16:44
*/
@Configuration
public class RedisStoreConfig {
@Bean(value = "upmsRedisTokenStore")
public LocalRedisTokenStore upmsRedisTokenStore(RedisUtils redisUtils){
LocalRedisTokenStore upmsRedisTokenStore = new LocalRedisTokenStore(redisUtils);
upmsRedisTokenStore.setPrefix("upms_token:");
return upmsRedisTokenStore;
}
}
@@ -0,0 +1,33 @@
### 请求 /login 接口 => 成功
POST {{baseUrl}}/system/auth/login
Content-Type: application/json
tenant-id: {{adminTenentId}}
tag: Yunai.local
{
"username": "admin",
"password": "admin123",
"uuid": "3acd87a09a4f48fb9118333780e94883",
"code": "1024"
}
### 请求 /login 接口 => 成功(无验证码)
POST {{baseUrl}}/system/auth/login
Content-Type: application/json
tenant-id: {{adminTenentId}}
{
"username": "admin",
"password": "admin123"
}
### 请求 /get-permission-info 接口 => 成功
GET {{baseUrl}}/system/auth/get-permission-info
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 请求 /list-menus 接口 => 成功
GET {{baseUrl}}/system/list-menus
Authorization: Bearer {{token}}
#Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a
tenant-id: {{adminTenentId}}
@@ -0,0 +1,119 @@
package com.oneone.upms.controller.admin.auth;
import cn.hutool.core.collection.CollUtil;
import com.oneone.common.enums.CommonStatusEnum;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.result.Result;
import com.oneone.common.web.util.UserContext;
import com.oneone.upms.api.enums.logger.LoginLogTypeEnum;
import com.oneone.upms.controller.admin.auth.vo.*;
import com.oneone.upms.convert.auth.AuthConvert;
import com.oneone.upms.dal.dataobject.permission.MenuDO;
import com.oneone.upms.dal.dataobject.permission.RoleDO;
import com.oneone.upms.dal.dataobject.user.AdminUserDO;
import com.oneone.upms.service.auth.AdminAuthService;
import com.oneone.upms.service.permission.MenuService;
import com.oneone.upms.service.permission.PermissionService;
import com.oneone.upms.service.permission.RoleService;
import com.oneone.upms.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static com.oneone.common.result.Result.success;
import static com.oneone.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 认证")
@RestController
@RequestMapping("/system/auth")
@Validated
@Slf4j
public class AuthController {
@Resource
private AdminAuthService authService;
@Resource
private AdminUserService userService;
@Resource
private RoleService roleService;
@Resource
private MenuService menuService;
@Resource
private PermissionService permissionService;
@PostMapping("/login")
@Operation(summary = "使用账号密码登录")
@ISysLog("使用账号密码登录")
public Result<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
return success(authService.login(reqVO));
}
@PostMapping("/logout")
@Operation(summary = "登出系统")
@ISysLog("登出系统")
public Result<Boolean> logout() {
authService.logout(LoginLogTypeEnum.LOGOUT_SELF.getType());
return success(true);
}
@PostMapping("/refresh-token")
@Operation(summary = "刷新令牌")
@Parameter(name = "refreshToken", description = "刷新令牌", required = true)
@ISysLog("刷新令牌")
public Result<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
return success(authService.refreshToken(refreshToken));
}
@GetMapping("/get-permission-info")
@Operation(summary = "获取登录用户的权限信息")
public Result<AuthPermissionInfoRespVO> getPermissionInfo() {
// 1.1 获得用户信息
AdminUserDO user = userService.getUser(UserContext.getUserId());
if (user == null) {
return Result.failed();
}
// 1.2 获得角色列表
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(UserContext.getUserId());
if (CollUtil.isEmpty(roleIds)) {
return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList()));
}
List<RoleDO> roles = roleService.getRoleList(roleIds);
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
// 1.3 获得菜单列表
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
List<MenuDO> menuList = menuService.getMenuList(menuIds);
menuList.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单
// 2. 拼接结果返回
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
}
// ========== 短信登录相关 ==========
@PostMapping("/sms-login")
@Operation(summary = "使用短信验证码登录")
@ISysLog("使用短信验证码登录")
public Result<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
/* return success(authService.smsLogin(reqVO));*/
return null;
}
@PostMapping("/send-sms-code")
@Operation(summary = "发送手机验证码")
@ISysLog("发送手机验证码")
public Result<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
//authService.sendSmsCode(reqVO);
return success(true);
}
}
@@ -0,0 +1,70 @@
package com.oneone.upms.controller.admin.auth.vo;
import cn.hutool.core.util.StrUtil;
import com.oneone.common.desensitize.base.annotation.DesensitizeBy;
import com.oneone.common.desensitize.slider.annotation.PasswordDesensitize;
import com.oneone.common.desensitize.slider.handler.PasswordDesensitization;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
@Schema(description = "管理后台 - 账号密码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginReqVO {
@Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18780220566")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
@PasswordDesensitize
private String password;
// ========== 图片验证码相关 ==========
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
private String captchaVerification;
// ========== 绑定社交登录时,需要传递如下参数 ==========
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer socialType;
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String socialCode;
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
private String socialState;
/**
* 开启验证码的 Group
*/
public interface CodeEnableGroup {}
@AssertTrue(message = "授权码不能为空")
public boolean isSocialCodeValid() {
return socialType == null || StrUtil.isNotEmpty(socialCode);
}
@AssertTrue(message = "授权 state 不能为空")
public boolean isSocialState() {
return socialType == null || StrUtil.isNotEmpty(socialState);
}
}
@@ -0,0 +1,30 @@
package com.oneone.upms.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 登录 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId;
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "happy")
private String accessToken;
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
private String refreshToken;
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime expiresTime;
}
@@ -0,0 +1,53 @@
package com.oneone.upms.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthMenuRespVO {
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private Long id;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long parentId;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post")
private String path;
@Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index")
private String component;
@Schema(description = "组件名", example = "SystemUser")
private String componentName;
@Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list")
private String icon;
@Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean visible;
@Schema(description = "是否缓存", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean keepAlive;
@Schema(description = "是否总是显示", example = "false")
private Boolean alwaysShow;
/**
* 子路由
*/
private List<AuthMenuRespVO> children;
}
@@ -0,0 +1,93 @@
package com.oneone.upms.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Set;
@Schema(description = "管理后台 - 登录用户的权限信息 Response VO,额外包括用户信息和角色列表")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthPermissionInfoRespVO {
@Schema(description = "用户信息", requiredMode = Schema.RequiredMode.REQUIRED)
private UserVO user;
@Schema(description = "角色标识数组", requiredMode = Schema.RequiredMode.REQUIRED)
private Set<String> roles;
@Schema(description = "操作权限数组", requiredMode = Schema.RequiredMode.REQUIRED)
private Set<String> permissions;
@Schema(description = "菜单树", requiredMode = Schema.RequiredMode.REQUIRED)
private List<MenuVO> menus;
@Schema(description = "用户信息 VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class UserVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg")
private String avatar;
}
@Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class MenuVO {
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private Long id;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long parentId;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post")
private String path;
@Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index")
private String component;
@Schema(description = "组件名", example = "SystemUser")
private String componentName;
@Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list")
private String icon;
@Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean visible;
@Schema(description = "是否缓存", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean keepAlive;
@Schema(description = "是否总是显示", example = "false")
private Boolean alwaysShow;
/**
* 子路由
*/
private List<MenuVO> children;
}
}
@@ -0,0 +1,28 @@
package com.oneone.upms.controller.admin.auth.vo;
import com.oneone.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
@Schema(description = "管理后台 - 短信验证码的登录 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSmsLoginReqVO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18780220566")
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
@Schema(description = "短信验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotEmpty(message = "验证码不能为空")
private String code;
}
@@ -0,0 +1,29 @@
package com.oneone.upms.controller.admin.auth.vo;
import com.oneone.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 发送手机验证码 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSmsSendReqVO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18780220566")
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
@Schema(description = "短信场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "发送场景不能为空")
private Integer scene;
}
@@ -0,0 +1,44 @@
package com.oneone.upms.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
@Schema(description = "管理后台 - 社交绑定登录 Request VO,使用 code 授权码 + 账号密码")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSocialBindLoginReqVO {
@Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "社交平台的类型不能为空")
private Integer type;
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotEmpty(message = "授权码不能为空")
private String code;
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
@NotEmpty(message = "state 不能为空")
private String state;
@Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18780220566")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
}
@@ -0,0 +1,31 @@
package com.oneone.upms.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 社交绑定登录 Request VO,使用 code 授权码 + 账号密码")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSocialLoginReqVO {
@Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "社交平台的类型不能为空")
private Integer type;
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotEmpty(message = "授权码不能为空")
private String code;
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
@NotEmpty(message = "state 不能为空")
private String state;
}
@@ -0,0 +1,56 @@
package com.oneone.upms.controller.admin.captcha;
import cn.hutool.core.util.StrUtil;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.web.util.IPUtils;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* 验证码
*
*
*/
@Tag(name = "管理后台 - 验证码")
@RestController("adminCaptchaController")
@RequestMapping("/system/captcha")
public class CaptchaController {
@Resource
private CaptchaService captchaService;
@PostMapping({"/get"})
@Operation(summary = "获得验证码")
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
assert request.getRemoteHost() != null;
data.setBrowserInfo(getRemoteId(request));
return captchaService.get(data);
}
@PostMapping("/check")
@Operation(summary = "校验验证码")
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
data.setBrowserInfo(getRemoteId(request));
return captchaService.check(data);
}
public static String getRemoteId(HttpServletRequest request) {
String ip = IPUtils.getIpAddrByServlet();
String ua = request.getHeader("user-agent");
if (StrUtil.isNotBlank(ip)) {
return ip + ua;
}
return request.getRemoteAddr() + ua;
}
}
@@ -0,0 +1,151 @@
package com.oneone.upms.controller.admin.codegen;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import com.oneone.common.result.PageResult;
import com.oneone.common.result.Result;
import com.oneone.common.util.ServletUtils;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.common.web.util.UserContext;
import com.oneone.upms.controller.admin.codegen.vo.CodegenCreateListReqVO;
import com.oneone.upms.controller.admin.codegen.vo.CodegenDetailRespVO;
import com.oneone.upms.controller.admin.codegen.vo.CodegenPreviewRespVO;
import com.oneone.upms.controller.admin.codegen.vo.CodegenUpdateReqVO;
import com.oneone.upms.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
import com.oneone.upms.controller.admin.codegen.vo.table.CodegenTableRespVO;
import com.oneone.upms.controller.admin.codegen.vo.table.DatabaseTableRespVO;
import com.oneone.upms.convert.codegen.CodegenConvert;
import com.oneone.upms.dal.dataobject.codegen.CodegenColumnDO;
import com.oneone.upms.dal.dataobject.codegen.CodegenTableDO;
import com.oneone.upms.service.codegen.CodegenService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 代码生成器")
@RestController
@RequestMapping("/infra/codegen")
@Validated
public class CodegenController {
@Resource
private CodegenService codegenService;
@GetMapping("/db/table/list")
@Operation(summary = "获得数据库自带的表定义列表", description = "会过滤掉已经导入 Codegen 的表")
@Parameters({
@Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1"),
@Parameter(name = "name", description = "表名,模糊匹配", example = "yudao"),
@Parameter(name = "comment", description = "描述,模糊匹配", example = "芋道")
})
@RequiresPermissions("infra:codegen:query")
public Result<List<DatabaseTableRespVO>> getDatabaseTableList(
@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "comment", required = false) String comment) {
return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment));
}
@GetMapping("/table/list")
@Operation(summary = "获得表定义列表")
@Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1")
@RequiresPermissions("infra:codegen:query")
public Result<List<CodegenTableRespVO>> getCodegenTableList(@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId) {
List<CodegenTableDO> list = codegenService.getCodegenTableList(dataSourceConfigId);
return success(CodegenConvert.INSTANCE.convertList05(list));
}
@GetMapping("/table/page")
@Operation(summary = "获得表定义分页")
@RequiresPermissions("infra:codegen:query")
public Result<PageResult<CodegenTableRespVO>> getCodegenTablePage(@Valid CodegenTablePageReqVO pageReqVO) {
PageResult<CodegenTableDO> pageResult = codegenService.getCodegenTablePage(pageReqVO);
return success(CodegenConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/detail")
@Operation(summary = "获得表和字段的明细")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
@RequiresPermissions("infra:codegen:query")
public Result<CodegenDetailRespVO> getCodegenDetail(@RequestParam("tableId") Long tableId) {
CodegenTableDO table = codegenService.getCodegenTablePage(tableId);
List<CodegenColumnDO> columns = codegenService.getCodegenColumnListByTableId(tableId);
// 拼装返回
return success(CodegenConvert.INSTANCE.convert(table, columns));
}
@Operation(summary = "基于数据库的表结构,创建代码生成器的表和字段定义")
@PostMapping("/create-list")
@RequiresPermissions("infra:codegen:create")
public Result<List<Long>> createCodegenList(@Valid @RequestBody CodegenCreateListReqVO reqVO) {
return success(codegenService.createCodegenList(UserContext.getUserId(), reqVO));
}
@Operation(summary = "更新数据库的表和字段定义")
@PutMapping("/update")
@RequiresPermissions("infra:codegen:update")
public Result<Boolean> updateCodegen(@Valid @RequestBody CodegenUpdateReqVO updateReqVO) {
codegenService.updateCodegen(updateReqVO);
return success(true);
}
@Operation(summary = "基于数据库的表结构,同步数据库的表和字段定义")
@PutMapping("/sync-from-db")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
@RequiresPermissions("infra:codegen:update")
public Result<Boolean> syncCodegenFromDB(@RequestParam("tableId") Long tableId) {
codegenService.syncCodegenFromDB(tableId);
return success(true);
}
@Operation(summary = "删除数据库的表和字段定义")
@DeleteMapping("/delete")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
@RequiresPermissions("infra:codegen:delete")
public Result<Boolean> deleteCodegen(@RequestParam("tableId") Long tableId) {
codegenService.deleteCodegen(tableId);
return success(true);
}
@Operation(summary = "预览生成代码")
@GetMapping("/preview")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
@RequiresPermissions("infra:codegen:preview")
public Result<List<CodegenPreviewRespVO>> previewCodegen(@RequestParam("tableId") Long tableId) {
Map<String, String> codes = codegenService.generationCodes(tableId);
return success(CodegenConvert.INSTANCE.convert(codes));
}
@Operation(summary = "下载生成代码")
@GetMapping("/download")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
@RequiresPermissions("infra:codegen:download")
public void downloadCodegen(@RequestParam("tableId") Long tableId,
HttpServletResponse response) throws IOException {
// 生成代码
Map<String, String> codes = codegenService.generationCodes(tableId);
// 构建 zip 包
String[] paths = codes.keySet().toArray(new String[0]);
ByteArrayInputStream[] ins = codes.values().stream().map(IoUtil::toUtf8Stream).toArray(ByteArrayInputStream[]::new);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipUtil.zip(outputStream, paths, ins);
// 输出
ServletUtils.writeAttachment(response, "codegen.zip", outputStream.toByteArray());
}
}
@@ -0,0 +1,21 @@
package com.oneone.upms.controller.admin.codegen.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - 基于数据库的表结构,创建代码生成器的表和字段定义 Request VO")
@Data
public class CodegenCreateListReqVO {
@Schema(description = "数据源配置的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "数据源配置的编号不能为空")
private Long dataSourceConfigId;
@Schema(description = "表名数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2, 3]")
@NotNull(message = "表名数组不能为空")
private List<String> tableNames;
}
@@ -0,0 +1,20 @@
package com.oneone.upms.controller.admin.codegen.vo;
import com.oneone.upms.controller.admin.codegen.vo.column.CodegenColumnRespVO;
import com.oneone.upms.controller.admin.codegen.vo.table.CodegenTableRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 代码生成表和字段的明细 Response VO")
@Data
public class CodegenDetailRespVO {
@Schema(description = "表定义")
private CodegenTableRespVO table;
@Schema(description = "字段定义")
private List<CodegenColumnRespVO> columns;
}
@@ -0,0 +1,16 @@
package com.oneone.upms.controller.admin.codegen.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 代码生成预览 Response VO,注意,每个文件都是一个该对象")
@Data
public class CodegenPreviewRespVO {
@Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "java/cn/iocoder/yudao/adminserver/modules/system/controller/test/SysTestDemoController.java")
private String filePath;
@Schema(description = "代码", requiredMode = Schema.RequiredMode.REQUIRED, example = "Hello World")
private String code;
}
@@ -0,0 +1,76 @@
package com.oneone.upms.controller.admin.codegen.vo;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.oneone.upms.common.codegen.CodegenSceneEnum;
import com.oneone.upms.common.codegen.CodegenTemplateTypeEnum;
import com.oneone.upms.controller.admin.codegen.vo.column.CodegenColumnBaseVO;
import com.oneone.upms.controller.admin.codegen.vo.table.CodegenTableBaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - 代码生成表和字段的修改 Request VO")
@Data
public class CodegenUpdateReqVO {
@Valid // 校验内嵌的字段
@NotNull(message = "表定义不能为空")
private Table table;
@Valid // 校验内嵌的字段
@NotNull(message = "字段定义不能为空")
private List<Column> columns;
@Schema(description = "更新表定义")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Valid
public static class Table extends CodegenTableBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段")
@JsonIgnore
public boolean isParentMenuIdValid() {
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene())
|| getParentMenuId() != null;
}
@AssertTrue(message = "关联的父表信息不全")
@JsonIgnore
public boolean isSubValid() {
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.SUB)
|| (ObjectUtil.isAllNotEmpty(getMasterTableId(), getSubJoinColumnId(), getSubJoinMany()));
}
@AssertTrue(message = "关联的树表信息不全")
@JsonIgnore
public boolean isTreeValid() {
return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.TREE)
|| (ObjectUtil.isAllNotEmpty(getTreeParentColumnId(), getTreeNameColumnId()));
}
}
@Schema(description = "更新表定义")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public static class Column extends CodegenColumnBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
}
}
@@ -0,0 +1,85 @@
package com.oneone.upms.controller.admin.codegen.vo.column;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 代码生成字段定义 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class CodegenColumnBaseVO {
@Schema(description = "表编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "表编号不能为空")
private Long tableId;
@Schema(description = "字段名", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_age")
@NotNull(message = "字段名不能为空")
private String columnName;
@Schema(description = "字段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "int(11)")
@NotNull(message = "字段类型不能为空")
private String dataType;
@Schema(description = "字段描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "年龄")
@NotNull(message = "字段描述不能为空")
private String columnComment;
@Schema(description = "是否允许为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否允许为空不能为空")
private Boolean nullable;
@Schema(description = "是否主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "是否主键不能为空")
private Boolean primaryKey;
@Schema(description = "是否自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否自增不能为空")
private String autoIncrement;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "排序不能为空")
private Integer ordinalPosition;
@Schema(description = "Java 属性类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "userAge")
@NotNull(message = "Java 属性类型不能为空")
private String javaType;
@Schema(description = "Java 属性名", requiredMode = Schema.RequiredMode.REQUIRED, example = "Integer")
@NotNull(message = "Java 属性名不能为空")
private String javaField;
@Schema(description = "字典类型", example = "sys_gender")
private String dictType;
@Schema(description = "数据示例", example = "1024")
private String example;
@Schema(description = "是否为 Create 创建操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否为 Create 创建操作的字段不能为空")
private Boolean createOperation;
@Schema(description = "是否为 Update 更新操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "是否为 Update 更新操作的字段不能为空")
private Boolean updateOperation;
@Schema(description = "是否为 List 查询操作的字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否为 List 查询操作的字段不能为空")
private Boolean listOperation;
@Schema(description = "List 查询操作的条件类型,参见 CodegenColumnListConditionEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "LIKE")
@NotNull(message = "List 查询操作的条件类型不能为空")
private String listOperationCondition;
@Schema(description = "是否为 List 查询操作的返回字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否为 List 查询操作的返回字段不能为空")
private Boolean listOperationResult;
@Schema(description = "显示类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "input")
@NotNull(message = "显示类型不能为空")
private String htmlType;
}
@@ -0,0 +1,22 @@
package com.oneone.upms.controller.admin.codegen.vo.column;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 代码生成字段定义 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CodegenColumnRespVO extends CodegenColumnBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -0,0 +1,73 @@
package com.oneone.upms.controller.admin.codegen.vo.table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 代码生成 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class CodegenTableBaseVO {
@Schema(description = "生成场景,参见 CodegenSceneEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "导入类型不能为空")
private Integer scene;
@Schema(description = "表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotNull(message = "表名称不能为空")
private String tableName;
@Schema(description = "表描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@NotNull(message = "表描述不能为空")
private String tableComment;
@Schema(description = "备注", example = "我是备注")
private String remark;
@Schema(description = "模块名", requiredMode = Schema.RequiredMode.REQUIRED, example = "system")
@NotNull(message = "模块名不能为空")
private String moduleName;
@Schema(description = "业务名", requiredMode = Schema.RequiredMode.REQUIRED, example = "codegen")
@NotNull(message = "业务名不能为空")
private String businessName;
@Schema(description = "类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CodegenTable")
@NotNull(message = "类名称不能为空")
private String className;
@Schema(description = "类描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "代码生成器的表定义")
@NotNull(message = "类描述不能为空")
private String classComment;
@Schema(description = "作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
@NotNull(message = "作者不能为空")
private String author;
@Schema(description = "模板类型,参见 CodegenTemplateTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "模板类型不能为空")
private Integer templateType;
@Schema(description = "前端类型,参见 CodegenFrontTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
@NotNull(message = "前端类型不能为空")
private Integer frontType;
@Schema(description = "父菜单编号", example = "1024")
private Long parentMenuId;
@Schema(description = "主表的编号", example = "2048")
private Long masterTableId;
@Schema(description = "子表关联主表的字段编号", example = "4096")
private Long subJoinColumnId;
@Schema(description = "主表与子表是否一对多", example = "4096")
private Boolean subJoinMany;
@Schema(description = "树表的父字段编号", example = "8192")
private Long treeParentColumnId;
@Schema(description = "树表的名字字段编号", example = "16384")
private Long treeNameColumnId;
}
@@ -0,0 +1,34 @@
package com.oneone.upms.controller.admin.codegen.vo.table;
import com.oneone.common.base.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.oneone.common.util.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 表定义分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CodegenTablePageReqVO extends PageParam {
@Schema(description = "表名称,模糊匹配", example = "yudao")
private String tableName;
@Schema(description = "表描述,模糊匹配", example = "芋道")
private String tableComment;
@Schema(description = "实体,模糊匹配", example = "Yudao")
private String className;
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

Some files were not shown because too many files have changed in this diff Show More