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
+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;
}
@@ -0,0 +1,28 @@
package com.oneone.upms.controller.admin.codegen.vo.table;
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 CodegenTableRespVO extends CodegenTableBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer dataSourceConfigId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
}
@@ -0,0 +1,16 @@
package com.oneone.upms.controller.admin.codegen.vo.table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 数据库的表定义 Response VO")
@Data
public class DatabaseTableRespVO {
@Schema(description = "表名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "yuanma")
private String name;
@Schema(description = "表描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String comment;
}
@@ -0,0 +1,74 @@
package com.oneone.upms.controller.admin.db;
import com.oneone.common.result.Result;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.db.vo.DataSourceConfigCreateReqVO;
import com.oneone.upms.controller.admin.db.vo.DataSourceConfigRespVO;
import com.oneone.upms.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
import com.oneone.upms.convert.db.DataSourceConfigConvert;
import com.oneone.upms.dal.dataobject.db.DataSourceConfigDO;
import com.oneone.upms.service.db.DataSourceConfigService;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 数据源配置")
@RestController
@RequestMapping("/infra/data-source-config")
@Validated
public class DataSourceConfigController {
@Resource
private DataSourceConfigService dataSourceConfigService;
@PostMapping("/create")
@Operation(summary = "创建数据源配置")
@RequiresPermissions("infra:data-source-config:create")
public Result<Long> createDataSourceConfig(@Valid @RequestBody DataSourceConfigCreateReqVO createReqVO) {
return success(dataSourceConfigService.createDataSourceConfig(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新数据源配置")
@RequiresPermissions("infra:data-source-config:update")
public Result<Boolean> updateDataSourceConfig(@Valid @RequestBody DataSourceConfigUpdateReqVO updateReqVO) {
dataSourceConfigService.updateDataSourceConfig(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除数据源配置")
@Parameter(name = "id", description = "编号", required = true)
@RequiresPermissions("infra:data-source-config:delete")
public Result<Boolean> deleteDataSourceConfig(@RequestParam("id") Long id) {
dataSourceConfigService.deleteDataSourceConfig(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得数据源配置")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@RequiresPermissions("infra:data-source-config:query")
public Result<DataSourceConfigRespVO> getDataSourceConfig(@RequestParam("id") Long id) {
DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id);
return success(DataSourceConfigConvert.INSTANCE.convert(dataSourceConfig));
}
@GetMapping("/list")
@Operation(summary = "获得数据源配置列表")
@RequiresPermissions("infra:data-source-config:query")
public Result<List<DataSourceConfigRespVO>> getDataSourceConfigList() {
List<DataSourceConfigDO> list = dataSourceConfigService.getDataSourceConfigList();
return success(DataSourceConfigConvert.INSTANCE.convertList(list));
}
}
@@ -0,0 +1,154 @@
package com.oneone.upms.controller.admin.db;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.smallbun.screw.core.Configuration;
import cn.smallbun.screw.core.engine.EngineConfig;
import cn.smallbun.screw.core.engine.EngineFileType;
import cn.smallbun.screw.core.engine.EngineTemplateType;
import cn.smallbun.screw.core.execute.DocumentationExecute;
import cn.smallbun.screw.core.process.ProcessConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.oneone.common.util.ServletUtils;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
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.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
@Tag(name = "管理后台 - 数据库文档")
@RestController
@RequestMapping("/infra/db-doc")
public class DatabaseDocController {
@Resource
private DynamicDataSourceProperties dynamicDataSourceProperties;
private static final String FILE_OUTPUT_DIR = System.getProperty("java.io.tmpdir") + File.separator
+ "db-doc";
private static final String DOC_FILE_NAME = "数据库文档";
private static final String DOC_VERSION = "1.0.0";
private static final String DOC_DESCRIPTION = "文档描述";
@GetMapping("/export-html")
@Operation(summary = "导出 html 格式的数据文档")
@Parameter(name = "deleteFile", description = "是否删除在服务器本地生成的数据库文档", example = "true")
public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile,
HttpServletResponse response) throws IOException {
doExportFile(EngineFileType.HTML, deleteFile, response);
}
@GetMapping("/export-word")
@Operation(summary = "导出 word 格式的数据文档")
@Parameter(name = "deleteFile", description = "是否删除在服务器本地生成的数据库文档", example = "true")
public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile,
HttpServletResponse response) throws IOException {
doExportFile(EngineFileType.WORD, deleteFile, response);
}
@GetMapping("/export-markdown")
@Operation(summary = "导出 markdown 格式的数据文档")
@Parameter(name = "deleteFile", description = "是否删除在服务器本地生成的数据库文档", example = "true")
public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile,
HttpServletResponse response) throws IOException {
doExportFile(EngineFileType.MD, deleteFile, response);
}
private void doExportFile(EngineFileType fileOutputType, Boolean deleteFile,
HttpServletResponse response) throws IOException {
String docFileName = DOC_FILE_NAME + "_" + IdUtil.fastSimpleUUID();
String filePath = doExportFile(fileOutputType, docFileName);
String downloadFileName = DOC_FILE_NAME + fileOutputType.getFileSuffix(); //下载后的文件名
try {
// 读取,返回
ServletUtils.writeAttachment(response, downloadFileName, FileUtil.readBytes(filePath));
} finally {
handleDeleteFile(deleteFile, filePath);
}
}
/**
* 输出文件,返回文件路径
*
* @param fileOutputType 文件类型
* @param fileName 文件名, 无需 ".docx" 等文件后缀
* @return 生成的文件所在路径
*/
private String doExportFile(EngineFileType fileOutputType, String fileName) {
try (HikariDataSource dataSource = buildDataSource()) {
// 创建 screw 的配置
Configuration config = Configuration.builder()
.version(DOC_VERSION) // 版本
.description(DOC_DESCRIPTION) // 描述
.dataSource(dataSource) // 数据源
.engineConfig(buildEngineConfig(fileOutputType, fileName)) // 引擎配置
.produceConfig(buildProcessConfig()) // 处理配置
.build();
// 执行 screw,生成数据库文档
new DocumentationExecute(config).execute();
return FILE_OUTPUT_DIR + File.separator + fileName + fileOutputType.getFileSuffix();
}
}
private void handleDeleteFile(Boolean deleteFile, String filePath) {
if (!deleteFile) {
return;
}
FileUtil.del(filePath);
}
/**
* 创建数据源
*/
// TODO screw 暂时不支持 druid,尴尬
private HikariDataSource buildDataSource() {
// 获得 DataSource 数据源,目前只支持首个
String primary = dynamicDataSourceProperties.getPrimary();
DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary);
// 创建 HikariConfig 配置类
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(dataSourceProperty.getUrl());
hikariConfig.setUsername(dataSourceProperty.getUsername());
hikariConfig.setPassword(dataSourceProperty.getPassword());
hikariConfig.addDataSourceProperty("useInformationSchema", "true"); // 设置可以获取 tables remarks 信息
// 创建数据源
return new HikariDataSource(hikariConfig);
}
/**
* 创建 screw 的引擎配置
*/
private static EngineConfig buildEngineConfig(EngineFileType fileOutputType, String docFileName) {
return EngineConfig.builder()
.fileOutputDir(FILE_OUTPUT_DIR) // 生成文件路径
.openOutputDir(false) // 打开目录
.fileType(fileOutputType) // 文件类型
.produceType(EngineTemplateType.velocity) // 文件类型
.fileName(docFileName) // 自定义文件名称
.build();
}
/**
* 创建 screw 的处理配置,一般可忽略
* 指定生成逻辑、当存在指定表、指定表前缀、指定表后缀时,将生成指定表,其余表不生成、并跳过忽略表配置
*/
private static ProcessConfig buildProcessConfig() {
return ProcessConfig.builder()
.ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_", "FLW_")) // 忽略表前缀
.build();
}
}
@@ -0,0 +1,27 @@
package com.oneone.upms.controller.admin.db.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 数据源配置 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DataSourceConfigBaseVO {
@Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
@NotNull(message = "数据源名称不能为空")
private String name;
@Schema(description = "数据源连接", requiredMode = Schema.RequiredMode.REQUIRED, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro")
@NotNull(message = "数据源连接不能为空")
private String url;
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "root")
@NotNull(message = "用户名不能为空")
private String username;
}
@@ -0,0 +1,20 @@
package com.oneone.upms.controller.admin.db.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 数据源配置创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DataSourceConfigCreateReqVO extends DataSourceConfigBaseVO {
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotNull(message = "密码不能为空")
private String password;
}
@@ -0,0 +1,22 @@
package com.oneone.upms.controller.admin.db.vo;
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 DataSourceConfigRespVO extends DataSourceConfigBaseVO {
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -0,0 +1,24 @@
package com.oneone.upms.controller.admin.db.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 数据源配置更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DataSourceConfigUpdateReqVO extends DataSourceConfigBaseVO {
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "主键编号不能为空")
private Long id;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotNull(message = "密码不能为空")
private String password;
}
@@ -0,0 +1,92 @@
package com.oneone.upms.controller.admin.dept;
import com.oneone.common.enums.CommonStatusEnum;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.result.Result;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.dept.vo.dept.*;
import com.oneone.upms.convert.dept.DeptConvert;
import com.oneone.upms.dal.dataobject.dept.DeptDO;
import com.oneone.upms.service.dept.DeptService;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Comparator;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 部门")
@RestController
@RequestMapping("/system/dept")
@Validated
public class DeptController {
@Resource
private DeptService deptService;
@PostMapping("create")
@Operation(summary = "创建部门")
@RequiresPermissions("system:dept:create")
@ISysLog("创建部门")
public Result<Long> createDept(@Valid @RequestBody DeptCreateReqVO reqVO) {
Long deptId = deptService.createDept(reqVO);
return success(deptId);
}
@PutMapping("update")
@Operation(summary = "更新部门")
@RequiresPermissions("system:dept:update")
@ISysLog("更新部门")
public Result<Boolean> updateDept(@Valid @RequestBody DeptUpdateReqVO reqVO) {
deptService.updateDept(reqVO);
return success(true);
}
@DeleteMapping("delete")
@Operation(summary = "删除部门")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@RequiresPermissions("system:dept:delete")
@ISysLog("删除部门")
public Result<Boolean> deleteDept(@RequestParam("id") Long id) {
deptService.deleteDept(id);
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获取部门列表")
@RequiresPermissions("system:dept:query")
public Result<List<DeptRespVO>> getDeptList(DeptListReqVO reqVO) {
List<DeptDO> list = deptService.getDeptList(reqVO);
list.sort(Comparator.comparing(DeptDO::getSort));
return success(DeptConvert.INSTANCE.convertList(list));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项")
public Result<List<DeptSimpleRespVO>> getSimpleDeptList() {
// 获得部门列表,只要开启状态的
DeptListReqVO reqVO = new DeptListReqVO();
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
List<DeptDO> list = deptService.getDeptList(reqVO);
// 排序后,返回给前端
list.sort(Comparator.comparing(DeptDO::getSort));
return success(DeptConvert.INSTANCE.convertList02(list));
}
@GetMapping("/get")
@Operation(summary = "获得部门信息")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@RequiresPermissions("system:dept:query")
public Result<DeptRespVO> getDept(@RequestParam("id") Long id) {
return success(DeptConvert.INSTANCE.convert(deptService.getDept(id)));
}
}
@@ -0,0 +1,110 @@
package com.oneone.upms.controller.admin.dept;
import cn.hutool.core.bean.BeanUtil;
import com.oneone.common.base.PageParam;
import com.oneone.common.enums.CommonStatusEnum;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.result.PageResult;
import com.oneone.common.result.Result;
import com.oneone.common.util.BeanUtils;
import com.oneone.common.util.ExcelUtils;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.dept.vo.post.PostPageReqVO;
import com.oneone.upms.controller.admin.dept.vo.post.PostRespVO;
import com.oneone.upms.controller.admin.dept.vo.post.PostSaveReqVO;
import com.oneone.upms.controller.admin.dept.vo.post.PostSimpleRespVO;
import com.oneone.upms.dal.dataobject.dept.PostDO;
import com.oneone.upms.service.dept.PostService;
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.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.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 岗位")
@RestController
@RequestMapping("/system/post")
@Validated
public class PostController {
@Resource
private PostService postService;
@PostMapping("/create")
@Operation(summary = "创建岗位")
@RequiresPermissions("system:post:create")
@ISysLog("创建岗位")
public Result<Long> createPost(@Valid @RequestBody PostSaveReqVO createReqVO) {
Long postId = postService.createPost(createReqVO);
return success(postId);
}
@PutMapping("/update")
@Operation(summary = "修改岗位")
@RequiresPermissions("system:post:update")
@ISysLog("修改岗位")
public Result<Boolean> updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) {
postService.updatePost(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除岗位")
@ISysLog("删除岗位")
@RequiresPermissions("system:post:delete")
public Result<Boolean> deletePost(@RequestParam("id") Long id) {
postService.deletePost(id);
return success(true);
}
@GetMapping(value = "/get")
@Operation(summary = "获得岗位信息")
@Parameter(name = "id", description = "岗位编号", required = true, example = "1024")
@RequiresPermissions("system:post:query")
public Result<PostRespVO> getPost(@RequestParam("id") Long id) {
PostDO post = postService.getPost(id);
return success(BeanUtil.toBean(post, PostRespVO.class));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项")
public Result<List<PostSimpleRespVO>> getSimplePostList() {
// 获得岗位列表,只要开启状态的
List<PostDO> list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus()));
// 排序后,返回给前端
list.sort(Comparator.comparing(PostDO::getSort));
return success(BeanUtils.toBean(list, PostSimpleRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得岗位分页列表")
@RequiresPermissions("system:post:query")
public Result<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO pageReqVO) {
PageResult<PostDO> pageResult = postService.getPostPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, PostRespVO.class));
}
@GetMapping("/export")
@Operation(summary = "岗位管理")
@RequiresPermissions("system:post:export")
@ISysLog("导出管理岗位")
public void export(HttpServletResponse response, @Validated PostPageReqVO reqVO) throws IOException {
reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<PostDO> list = postService.getPostPage(reqVO).getList();
// 输出
ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostRespVO.class,
BeanUtils.toBean(list, PostRespVO.class));
}
}
@@ -0,0 +1,47 @@
package com.oneone.upms.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 部门 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DeptBaseVO {
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@NotBlank(message = "部门名称不能为空")
@Size(max = 30, message = "部门名称长度不能超过30个字符")
private String name;
@Schema(description = "父菜单 ID", example = "1024")
private Long parentId;
@Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "负责人的用户编号", example = "2048")
private Long leaderUserId;
@Schema(description = "联系电话", example = "15601691000")
@Size(max = 11, message = "联系电话长度不能超过11个字符")
private String phone;
@Schema(description = "邮箱", example = "yudao@iocoder.cn")
@Email(message = "邮箱格式不正确")
@Size(max = 50, message = "邮箱长度不能超过50个字符")
private String email;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
// // @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
}
@@ -0,0 +1,13 @@
package com.oneone.upms.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 部门创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeptCreateReqVO extends DeptBaseVO {
}
@@ -0,0 +1,16 @@
package com.oneone.upms.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 部门列表 Request VO")
@Data
public class DeptListReqVO {
@Schema(description = "部门名称,模糊匹配", example = "芋道")
private String name;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
}
@@ -0,0 +1,23 @@
package com.oneone.upms.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 部门信息 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DeptRespVO extends DeptBaseVO {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
private LocalDateTime createTime;
}
@@ -0,0 +1,23 @@
package com.oneone.upms.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 部门精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptSimpleRespVO {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "父部门 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long parentId;
}
@@ -0,0 +1,18 @@
package com.oneone.upms.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 部门更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DeptUpdateReqVO extends DeptBaseVO {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "部门编号不能为空")
private Long id;
}
@@ -0,0 +1,22 @@
package com.oneone.upms.controller.admin.dept.vo.post;
import com.oneone.common.base.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 岗位分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class PostPageReqVO extends PageParam {
@Schema(description = "岗位编码,模糊匹配", example = "yudao")
private String code;
@Schema(description = "岗位名称,模糊匹配", example = "芋道")
private String name;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
}
@@ -0,0 +1,33 @@
package com.oneone.upms.controller.admin.dept.vo.post;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 岗位信息 Response VO")
@Data
public class PostRespVO {
@Schema(description = "岗位序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
private String name;
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
private String code;
@Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer sort;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -0,0 +1,37 @@
package com.oneone.upms.controller.admin.dept.vo.post;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Schema(description = "管理后台 - 岗位创建/修改 Request VO")
@Data
public class PostSaveReqVO {
@Schema(description = "岗位编号", example = "1024")
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
@NotBlank(message = "岗位名称不能为空")
@Size(max = 50, message = "岗位名称长度不能超过 50 个字符")
private String name;
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotBlank(message = "岗位编码不能为空")
@Size(max = 64, message = "岗位编码长度不能超过64个字符")
private String code;
@Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
private String remark;
}
@@ -0,0 +1,16 @@
package com.oneone.upms.controller.admin.dept.vo.post;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 岗位信息的精简 Response VO")
@Data
public class PostSimpleRespVO {
@Schema(description = "岗位序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
private String name;
}
@@ -0,0 +1,4 @@
### 请求 /menu/list 接口 => 成功
GET {{baseUrl}}/system/dict-data/list-all-simple
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
@@ -0,0 +1,96 @@
package com.oneone.upms.controller.admin.dict;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.result.PageResult;
import com.oneone.common.result.Result;
import com.oneone.common.util.BeanUtils;
import com.oneone.common.util.ExcelUtils;
import com.oneone.common.web.security.annotation.RequiresLogin;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.dict.vo.data.*;
import com.oneone.upms.dal.dataobject.dict.DictDataDO;
import com.oneone.upms.service.dict.DictDataService;
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.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.IOException;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 字典数据")
@RestController
@RequestMapping("/system/dict-data")
@Validated
public class DictDataController {
@Resource
private DictDataService dictDataService;
@PostMapping("/create")
@Operation(summary = "新增字典数据")
@RequiresPermissions("system:dict:create")
public Result<Long> createDictData(@Valid @RequestBody DictDataCreateReqVO reqVO) {
Long dictDataId = dictDataService.createDictData(reqVO);
return success(dictDataId);
}
@PutMapping("/update")
@Operation(summary = "修改字典数据")
@RequiresPermissions("system:dict:update")
public Result<Boolean> updateDictData(@Valid @RequestBody DictDataUpdateReqVO reqVO) {
dictDataService.updateDictData(reqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除字典数据")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@RequiresPermissions("system:dict:delete")
public Result<Boolean> deleteDictData(Long id) {
dictDataService.deleteDictData(id);
return success(true);
}
@GetMapping("/list-all-simple")
@Operation(summary = "获得全部字典数据列表", description = "一般用于管理后台缓存字典数据在本地")
// 无需添加权限认证,因为前端全局都需要
// @RequiresPermissions("system:dict:query")
public Result<List<DictDataSimpleRespVO>> getSimpleDictDataList() {
List<DictDataDO> list = dictDataService.getDictDataList();
return success(BeanUtils.toBean(list,DictDataSimpleRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "/获得字典类型的分页列表")
// @RequiresPermissions("system:dict:query")
public Result<PageResult<DictDataRespVO>> getDictTypePage(@Valid DictDataPageReqVO reqVO) {
return success(BeanUtils.toBean(dictDataService.getDictDataPage(reqVO), DictDataRespVO.class));
}
@GetMapping(value = "/get")
@Operation(summary = "/查询字典数据详细")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
// @RequiresPermissions("system:dict:query")
public Result<DictDataRespVO> getDictData(@RequestParam("id") Long id) {
return success(BeanUtils.toBean(dictDataService.getDictData(id),DictDataRespVO.class));
}
@GetMapping("/export")
@Operation(summary = "导出字典数据")
@RequiresPermissions("system:dict:export")
@ISysLog("导出字典数据")
public void export(HttpServletResponse response, @Valid DictDataExportReqVO reqVO) throws IOException {
List<DictDataDO> list = dictDataService.getDictDataList(reqVO);
List<DictDataExcelVO> data = BeanUtils.toBean(list,DictDataExcelVO.class);
// 输出
ExcelUtils.write(response, "字典数据.xls", "数据列表", DictDataExcelVO.class, data);
}
}
@@ -0,0 +1,95 @@
package com.oneone.upms.controller.admin.dict;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.result.PageResult;
import com.oneone.common.result.Result;
import com.oneone.common.util.BeanUtils;
import com.oneone.common.util.ExcelUtils;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.dict.vo.type.*;
import com.oneone.upms.dal.dataobject.dict.DictTypeDO;
import com.oneone.upms.service.dict.DictTypeService;
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.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.IOException;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 字典类型")
@RestController
@RequestMapping("/system/dict-type")
@Validated
public class DictTypeController {
@Resource
private DictTypeService dictTypeService;
@PostMapping("/create")
@Operation(summary = "创建字典类型")
@RequiresPermissions("system:dict:create")
public Result<Long> createDictType(@Valid @RequestBody DictTypeCreateReqVO reqVO) {
Long dictTypeId = dictTypeService.createDictType(reqVO);
return success(dictTypeId);
}
@PutMapping("/update")
@Operation(summary = "修改字典类型")
@RequiresPermissions("system:dict:update")
public Result<Boolean> updateDictType(@Valid @RequestBody DictTypeUpdateReqVO reqVO) {
dictTypeService.updateDictType(reqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除字典类型")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@RequiresPermissions("system:dict:delete")
public Result<Boolean> deleteDictType(Long id) {
dictTypeService.deleteDictType(id);
return success(true);
}
@Operation(summary = "/获得字典类型的分页列表")
@GetMapping("/page")
@RequiresPermissions("system:dict:query")
public Result<PageResult<DictTypeRespVO>> pageDictTypes(@Valid DictTypePageReqVO reqVO) {
return success(BeanUtils.toBean(dictTypeService.getDictTypePage(reqVO),DictTypeRespVO.class));
}
@Operation(summary = "/查询字典类型详细")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@GetMapping(value = "/get")
@RequiresPermissions("system:dict:query")
public Result<DictTypeRespVO> getDictType(@RequestParam("id") Long id) {
return success(BeanUtils.toBean(dictTypeService.getDictType(id),DictTypeRespVO.class));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获得全部字典类型列表", description = "包括开启 + 禁用的字典类型,主要用于前端的下拉选项")
// 无需添加权限认证,因为前端全局都需要
public Result<List<DictTypeSimpleRespVO>> getSimpleDictTypeList() {
List<DictTypeDO> list = dictTypeService.getDictTypeList();
return success(BeanUtils.toBean(list,DictTypeSimpleRespVO.class));
}
@Operation(summary = "导出数据类型")
@GetMapping("/export")
@RequiresPermissions("system:dict:query")
@ISysLog("导出数据类型")
public void export(HttpServletResponse response, @Valid DictTypeExportReqVO reqVO) throws IOException {
List<DictTypeDO> list = dictTypeService.getDictTypeList(reqVO);
List<DictTypeExcelVO> data = BeanUtils.toBean(list,DictTypeExcelVO.class);
// 输出
ExcelUtils.write(response, "字典类型.xls", "类型列表", DictTypeExcelVO.class, data);
}
}
@@ -0,0 +1,49 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 字典数据 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DictDataBaseVO {
@Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@NotBlank(message = "字典标签不能为空")
@Size(max = 100, message = "字典标签长度不能超过100个字符")
private String label;
@Schema(description = "字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "iocoder")
@NotBlank(message = "字典键值不能为空")
@Size(max = 100, message = "字典键值长度不能超过100个字符")
private String value;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
@NotBlank(message = "字典类型不能为空")
@Size(max = 100, message = "字典类型长度不能超过100个字符")
private String dictType;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
// // @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
private String colorType;
@Schema(description = "css 样式", example = "btn-visible")
private String cssClass;
@Schema(description = "备注", example = "我是一个角色")
private String remark;
}
@@ -0,0 +1,12 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 字典数据创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DictDataCreateReqVO extends DictDataBaseVO {
}
@@ -0,0 +1,29 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 字典数据 Excel 导出响应 VO
*/
@Data
public class DictDataExcelVO {
@ExcelProperty("字典编码")
private Long id;
@ExcelProperty("字典排序")
private Integer sort;
@ExcelProperty("字典标签")
private String label;
@ExcelProperty("字典键值")
private String value;
@ExcelProperty("字典类型")
private String dictType;
private Integer status;
}
@@ -0,0 +1,23 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.Size;
@Schema(description = "管理后台 - 字典类型导出 Request VO")
@Data
public class DictDataExportReqVO {
@Schema(description = "字典标签", example = "芋道")
@Size(max = 100, message = "字典标签长度不能超过100个字符")
private String label;
@Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
@Size(max = 100, message = "字典类型类型长度不能超过100个字符")
private String dictType;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
}
@@ -0,0 +1,26 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import com.oneone.common.base.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.Size;
@Schema(description = "管理后台 - 字典类型分页列表 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DictDataPageReqVO extends PageParam {
@Schema(description = "字典标签", example = "芋道")
@Size(max = 100, message = "字典标签长度不能超过100个字符")
private String label;
@Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
@Size(max = 100, message = "字典类型类型长度不能超过100个字符")
private String dictType;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
}
@@ -0,0 +1,24 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典数据信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class DictDataRespVO extends DictDataBaseVO {
@Schema(description = "字典数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
private LocalDateTime createTime;
}
@@ -0,0 +1,25 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 数据字典精简 Response VO")
@Data
public class DictDataSimpleRespVO {
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "gender")
private String dictType;
@Schema(description = "字典键值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String value;
@Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
private String label;
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
private String colorType;
@Schema(description = "css 样式", example = "btn-visible")
private String cssClass;
}
@@ -0,0 +1,18 @@
package com.oneone.upms.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 字典数据更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DictDataUpdateReqVO extends DictDataBaseVO {
@Schema(description = "字典数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "字典数据编号不能为空")
private Long id;
}
@@ -0,0 +1,29 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class DictTypeBaseVO {
@Schema(description = "字典名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "性别")
@NotBlank(message = "字典名称不能为空")
@Size(max = 100, message = "字典类型名称长度不能超过100个字符")
private String name;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
private String remark;
}
@@ -0,0 +1,20 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Schema(description = "管理后台 - 字典类型创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DictTypeCreateReqVO extends DictTypeBaseVO {
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
@NotNull(message = "字典类型不能为空")
@Size(max = 100, message = "字典类型类型长度不能超过100个字符")
private String type;
}
@@ -0,0 +1,24 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import com.oneone.upms.api.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 字典类型 Excel 导出响应 VO
*/
@Data
public class DictTypeExcelVO {
@ExcelProperty("字典主键")
private Long id;
@ExcelProperty("字典名称")
private String name;
@ExcelProperty("字典类型")
private String type;
private Integer status;
}
@@ -0,0 +1,28 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典类型分页列表 Request VO")
@Data
public class DictTypeExportReqVO {
@Schema(description = "字典类型名称,模糊匹配", example = "芋道")
private String name;
@Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
private String type;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建时间")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,33 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import com.oneone.common.base.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典类型分页列表 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DictTypePageReqVO extends PageParam {
@Schema(description = "字典类型名称,模糊匹配", example = "芋道")
private String name;
@Schema(description = "字典类型,模糊匹配", example = "sys_common_sex")
@Size(max = 100, message = "字典类型类型长度不能超过100个字符")
private String type;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建时间")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,27 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典类型信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class DictTypeRespVO extends DictTypeBaseVO {
@Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
private String type;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
private LocalDateTime createTime;
}
@@ -0,0 +1,23 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 字典类型精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DictTypeSimpleRespVO {
@Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "字典类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
private String type;
}
@@ -0,0 +1,18 @@
package com.oneone.upms.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 字典类型更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class DictTypeUpdateReqVO extends DictTypeBaseVO {
@Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "字典类型编号不能为空")
private Long id;
}
@@ -0,0 +1,13 @@
### 创建错误码
POST {{baseUrl}}/inra/error-code/create
Authorization: Bearer {{token}}
Content-Type: application/json
tenant-id: {{adminTenentId}}
{
"code": 200,
"message": "成功",
"group": "test",
"type": 1
}
@@ -0,0 +1,92 @@
package com.oneone.upms.controller.admin.errorcode;
import com.oneone.common.result.Result;
import com.oneone.common.result.PageResult;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.common.util.ExcelUtils;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.upms.controller.admin.errorcode.vo.*;
import com.oneone.upms.convert.errorcode.ErrorCodeConvert;
import com.oneone.upms.dal.dataobject.errorcode.ErrorCodeDO;
import com.oneone.upms.service.errorcode.ErrorCodeService;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 错误码")
@RestController
@RequestMapping("/system/error-code")
@Validated
public class ErrorCodeController {
@Resource
private ErrorCodeService errorCodeService;
@PostMapping("/create")
@Operation(summary = "创建错误码")
@RequiresPermissions("system:error-code:create")
public Result<Long> createErrorCode(@Valid @RequestBody ErrorCodeCreateReqVO createReqVO) {
return success(errorCodeService.createErrorCode(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新错误码")
@RequiresPermissions("system:error-code:update")
public Result<Boolean> updateErrorCode(@Valid @RequestBody ErrorCodeUpdateReqVO updateReqVO) {
errorCodeService.updateErrorCode(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除错误码")
@Parameter(name = "id", description = "编号", required = true)
@RequiresPermissions("system:error-code:delete")
public Result<Boolean> deleteErrorCode(@RequestParam("id") Long id) {
errorCodeService.deleteErrorCode(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得错误码")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@RequiresPermissions("system:error-code:query")
public Result<ErrorCodeRespVO> getErrorCode(@RequestParam("id") Long id) {
ErrorCodeDO errorCode = errorCodeService.getErrorCode(id);
return success(ErrorCodeConvert.INSTANCE.convert(errorCode));
}
@GetMapping("/page")
@Operation(summary = "获得错误码分页")
@RequiresPermissions("system:error-code:query")
public Result<PageResult<ErrorCodeRespVO>> getErrorCodePage(@Valid ErrorCodePageReqVO pageVO) {
PageResult<ErrorCodeDO> pageResult = errorCodeService.getErrorCodePage(pageVO);
return success(ErrorCodeConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出错误码 Excel")
@RequiresPermissions("system:error-code:export")
@ISysLog("导出错误码 Excel")
public void exportErrorCodeExcel(@Valid ErrorCodeExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<ErrorCodeDO> list = errorCodeService.getErrorCodeList(exportReqVO);
// 导出 Excel
List<ErrorCodeExcelVO> datas = ErrorCodeConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "错误码.xls", "数据", ErrorCodeExcelVO.class, datas);
}
}
@@ -0,0 +1,30 @@
package com.oneone.upms.controller.admin.errorcode.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 错误码 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ErrorCodeBaseVO {
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard")
@NotNull(message = "应用名不能为空")
private String applicationName;
@Schema(description = "错误码编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234")
@NotNull(message = "错误码编码不能为空")
private Integer code;
@Schema(description = "错误码错误提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "帅气")
@NotNull(message = "错误码错误提示不能为空")
private String message;
@Schema(description = "备注", example = "哈哈哈")
private String memo;
}
@@ -0,0 +1,15 @@
package com.oneone.upms.controller.admin.errorcode.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 错误码创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ErrorCodeCreateReqVO extends ErrorCodeBaseVO {
}
@@ -0,0 +1,36 @@
package com.oneone.upms.controller.admin.errorcode.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 错误码 Excel VO
*
*
*/
@Data
public class ErrorCodeExcelVO {
@ExcelProperty("错误码编号")
private Long id;
private Integer type;
@ExcelProperty("应用名")
private String applicationName;
@ExcelProperty("错误码编码")
private Integer code;
@ExcelProperty("错误码错误提示")
private String message;
@ExcelProperty("备注")
private String memo;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}
@@ -0,0 +1,31 @@
package com.oneone.upms.controller.admin.errorcode.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 错误码 Excel 导出 Request VO,参数和 InfErrorCodePageReqVO 是一致的")
@Data
public class ErrorCodeExportReqVO {
@Schema(description = "错误码类型", example = "1")
private Integer type;
@Schema(description = "应用名", example = "dashboard")
private String applicationName;
@Schema(description = "错误码编码", example = "1234")
private Integer code;
@Schema(description = "错误码错误提示", example = "帅气")
private String message;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建时间")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,36 @@
package com.oneone.upms.controller.admin.errorcode.vo;
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;
@Schema(description = "管理后台 - 错误码分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ErrorCodePageReqVO extends PageParam {
@Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", example = "1")
private Integer type;
@Schema(description = "应用名", example = "dashboard")
private String applicationName;
@Schema(description = "错误码编码", example = "1234")
private Integer code;
@Schema(description = "错误码错误提示", example = "帅气")
private String message;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建时间")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,25 @@
package com.oneone.upms.controller.admin.errorcode.vo;
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 ErrorCodeRespVO extends ErrorCodeBaseVO {
@Schema(description = "错误码编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}
@@ -0,0 +1,20 @@
package com.oneone.upms.controller.admin.errorcode.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 错误码更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ErrorCodeUpdateReqVO extends ErrorCodeBaseVO {
@Schema(description = "错误码编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "错误码编号不能为空")
private Long id;
}
@@ -0,0 +1,87 @@
package com.oneone.upms.controller.admin.file;
import com.oneone.common.result.Result;
import com.oneone.upms.service.file.ISysFileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 文件存储")
@RestController
@RequestMapping("/infra/file")
@Validated
@Slf4j
public class FileController {
@Autowired
private ISysFileService localSysFileByPathServiceImpl;
@PostMapping("/upload")
@Operation(summary = "上传文件")
public ResponseEntity<Result<String>> uploadFile(MultipartFile file) throws Exception {
String url = "";
try {
url = localSysFileByPathServiceImpl.uploadFile(file);
} catch (Exception e) {
log.error("上传文件失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Result.failed("上传文件失败!"));
}
return ResponseEntity.ok(success(url));
}
@PostMapping("/uploadByUrl")
@Operation(summary = "上传文件")
public Result<String> uploadFile(String url) throws Exception {
String result = localSysFileByPathServiceImpl.uploadFile(url);
return success(result);
}
// @DeleteMapping("/delete")
// @Operation(summary = "删除文件")
// @Parameter(name = "id", description = "编号", required = true)
// @RequiresPermissions("@ss.hasPermission('infra:file:delete')")
// public Result<Boolean> deleteFile(@RequestParam("id") Long id) throws Exception {
// fileService.deleteFile(id);
// return success(true);
// }
//
// @GetMapping("/{configId}/get/**")
// @PermitAll
// @Operation(summary = "下载文件")
// @Parameter(name = "configId", description = "配置编号", required = true)
// public void getFileContent(HttpServletRequest request,
// HttpServletResponse response,
// @PathVariable("configId") Long configId) throws Exception {
// // 获取请求的路径
// String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false);
// if (StrUtil.isEmpty(path)) {
// throw new IllegalArgumentException("结尾的 path 路径必须传递");
// }
//
// // 读取内容
// byte[] content = fileService.getFileContent(configId, path);
// if (content == null) {
// log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
// response.setStatus(HttpStatus.NOT_FOUND.value());
// return;
// }
// ServletUtils.writeAttachment(response, path, content);
// }
}
@@ -0,0 +1,18 @@
package com.oneone.upms.controller.admin.file.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 上传文件 Request VO")
@Data
public class FileUploadReqVO {
@Schema(description = "文件附件", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "文件附件不能为空")
private MultipartFile file;
@Schema(description = "文件附件", example = "yudaoyuanma.png")
private String path;
}
@@ -0,0 +1,24 @@
package com.oneone.upms.controller.admin.health;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description: 健康检查
* @author: jhaol
*/
@Tag(name = "system 模块 - 健康检查")
@RestController
@RequestMapping("/system/health")
@Validated
public class HealthController {
@GetMapping()
@Operation(summary = "健康检查")
public Integer health() {
return 0;
}
}
@@ -0,0 +1,5 @@
### 获得地区树
GET {{baseUrl}}/system/area/tree
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
@@ -0,0 +1,50 @@
package com.oneone.upms.controller.admin.ip;
import cn.hutool.core.lang.Assert;
import com.oneone.common.base.Area;
import com.oneone.common.result.Result;
import com.oneone.common.util.AreaUtils;
import com.oneone.common.util.BeanUtils;
import com.oneone.common.web.util.IPUtils;
import com.oneone.upms.controller.admin.ip.vo.AreaNodeRespVO;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 地区")
@RestController
@RequestMapping("/system/area")
@Validated
public class AreaController {
@GetMapping("/tree")
@Operation(summary = "获得地区树")
public Result<List<AreaNodeRespVO>> getAreaTree() {
Area area = AreaUtils.getArea(Area.ID_CHINA);
Assert.notNull(area, "获取不到中国");
return success(BeanUtils.toBean(area.getChildren(),AreaNodeRespVO.class));
}
@GetMapping("/get-by-ip")
@Operation(summary = "获得 IP 对应的地区名")
@Parameter(name = "ip", description = "IP", required = true)
public Result<String> getAreaByIp(@RequestParam("ip") String ip) {
// 获得城市
Area area = AreaUtils.getArea(ip);
if (area == null) {
return success("未知");
}
// 格式化返回
return success(AreaUtils.format(area.getId()));
}
}
@@ -0,0 +1,23 @@
package com.oneone.upms.controller.admin.ip.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 地区节点 Response VO")
@Data
public class AreaNodeRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京")
private String name;
/**
* 子节点
*/
private List<AreaNodeRespVO> children;
}
@@ -0,0 +1,57 @@
package com.oneone.upms.controller.admin.logger;
import com.oneone.common.result.Result;
import com.oneone.common.result.PageResult;
import com.oneone.common.util.ExcelUtils;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.logger.vo.loginlog.LoginLogExcelVO;
import com.oneone.upms.controller.admin.logger.vo.loginlog.LoginLogExportReqVO;
import com.oneone.upms.controller.admin.logger.vo.loginlog.LoginLogPageReqVO;
import com.oneone.upms.controller.admin.logger.vo.loginlog.LoginLogRespVO;
import com.oneone.upms.convert.logger.LoginLogConvert;
import com.oneone.upms.dal.dataobject.logger.LoginLogDO;
import com.oneone.upms.service.logger.LoginLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
@Tag(name = "管理后台 - 登录日志")
@RestController
@RequestMapping("/system/login-log")
@Validated
public class LoginLogController {
@Resource
private LoginLogService loginLogService;
@GetMapping("/page")
@Operation(summary = "获得登录日志分页列表")
@RequiresPermissions("system:login-log:query")
public Result<PageResult<LoginLogRespVO>> getLoginLogPage(@Valid LoginLogPageReqVO reqVO) {
PageResult<LoginLogDO> page = loginLogService.getLoginLogPage(reqVO);
return Result.success(LoginLogConvert.INSTANCE.convertPage(page));
}
@GetMapping("/export")
@Operation(summary = "导出登录日志 Excel")
@RequiresPermissions("system:login-log:export")
@ISysLog("导出登录日志 Excel")
public void exportLoginLog(HttpServletResponse response, @Valid LoginLogExportReqVO reqVO) throws IOException {
List<LoginLogDO> list = loginLogService.getLoginLogList(reqVO);
// 拼接数据
List<LoginLogExcelVO> data = LoginLogConvert.INSTANCE.convertList(list);
// 输出
ExcelUtils.write(response, "登录日志.xls", "数据列表", LoginLogExcelVO.class, data);
}
}
@@ -0,0 +1,4 @@
### 请求 /system/operate-log/demo 接口 => 成功
GET {{baseUrl}}/system/operate-log/demo
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
@@ -0,0 +1,84 @@
package com.oneone.upms.controller.admin.logger;
import com.oneone.common.result.Result;
import com.oneone.common.result.PageResult;
import com.oneone.common.util.collection.CollectionUtils;
import com.oneone.common.util.ExcelUtils;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.util.collection.MapUtils;
import com.oneone.common.web.security.annotation.RequiresPermissions;
import com.oneone.upms.controller.admin.logger.vo.operatelog.OperateLogExcelVO;
import com.oneone.upms.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
import com.oneone.upms.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
import com.oneone.upms.controller.admin.logger.vo.operatelog.OperateLogRespVO;
import com.oneone.upms.convert.logger.OperateLogConvert;
import com.oneone.upms.dal.dataobject.logger.OperateLogDO;
import com.oneone.upms.dal.dataobject.user.AdminUserDO;
import com.oneone.upms.service.logger.OperateLogService;
import com.oneone.upms.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static com.oneone.common.result.Result.success;
@Tag(name = "管理后台 - 操作日志")
@RestController
@RequestMapping("/system/operate-log")
@Validated
public class OperateLogController {
@Resource
private OperateLogService operateLogService;
@Resource
private AdminUserService userService;
@GetMapping("/page")
@Operation(summary = "查看操作日志分页列表")
@RequiresPermissions("system:operate-log:query')")
public Result<PageResult<OperateLogRespVO>> pageOperateLog(@Valid OperateLogPageReqVO reqVO) {
PageResult<OperateLogDO> pageResult = operateLogService.getOperateLogPage(reqVO);
// 获得拼接需要的数据
Collection<Long> userIds = CollectionUtils.convertList(pageResult.getList(), OperateLogDO::getUserId);
Map<Long, AdminUserDO> userMap = userService.getUserMap(userIds);
// 拼接数据
List<OperateLogRespVO> list = new ArrayList<>(pageResult.getList().size());
pageResult.getList().forEach(ISysLog -> {
OperateLogRespVO respVO = OperateLogConvert.INSTANCE.convert(ISysLog);
list.add(respVO);
// 拼接用户信息
MapUtils.findAndThen(userMap, ISysLog.getUserId(), user -> respVO.setUserNickname(user.getNickname()));
});
return success(new PageResult<>(list, pageResult.getTotal()));
}
@Operation(summary = "导出操作日志")
@GetMapping("/export")
@RequiresPermissions("system:operate-log:export')")
@ISysLog("导出操作日志")
public void exportOperateLog(HttpServletResponse response, @Valid OperateLogExportReqVO reqVO) throws IOException {
List<OperateLogDO> list = operateLogService.getOperateLogList(reqVO);
// 获得拼接需要的数据
Collection<Long> userIds = CollectionUtils.convertList(list, OperateLogDO::getUserId);
Map<Long, AdminUserDO> userMap = userService.getUserMap(userIds);
// 拼接数据
List<OperateLogExcelVO> excelDataList = OperateLogConvert.INSTANCE.convertList(list, userMap);
// 输出
ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogExcelVO.class, excelDataList);
}
}
@@ -0,0 +1,42 @@
package com.oneone.upms.controller.admin.logger.vo.loginlog;
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;
/**
* 登录日志 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class LoginLogBaseVO {
@Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "日志类型不能为空")
private Integer logType;
@Schema(description = "链路追踪编号", example = "89aca178-a370-411c-ae02-3f0d672be4ab")
@NotEmpty(message = "链路追踪编号不能为空")
private String traceId;
@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", example = "Mozilla/5.0")
private String userAgent;
}
@@ -0,0 +1,33 @@
package com.oneone.upms.controller.admin.logger.vo.loginlog;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 登录日志 Excel 导出响应 VO
*/
@Data
public class LoginLogExcelVO {
@ExcelProperty("日志主键")
private Long id;
@ExcelProperty("用户账号")
private String username;
private Integer logType;
private Integer result;
@ExcelProperty("登录 IP")
private String userIp;
@ExcelProperty("浏览器 UA")
private String userAgent;
@ExcelProperty("登录时间")
private LocalDateTime createTime;
}
@@ -0,0 +1,28 @@
package com.oneone.upms.controller.admin.logger.vo.loginlog;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 登录日志分页列表 Request VO")
@Data
public class LoginLogExportReqVO {
@Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1")
private String userIp;
@Schema(description = "用户账号,模拟匹配", example = "芋道")
private String username;
@Schema(description = "操作状态", example = "true")
private Boolean status;
@Schema(description = "登录时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,31 @@
package com.oneone.upms.controller.admin.logger.vo.loginlog;
import com.oneone.common.base.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 登录日志分页列表 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
public class LoginLogPageReqVO extends PageParam {
@Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1")
private String userIp;
@Schema(description = "用户账号,模拟匹配", example = "芋道")
private String username;
@Schema(description = "操作状态", example = "true")
private Boolean status;
@Schema(description = "登录时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime[] createTime;
}
@@ -0,0 +1,30 @@
package com.oneone.upms.controller.admin.logger.vo.loginlog;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 登录日志 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class LoginLogRespVO extends LoginLogBaseVO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@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)
private LocalDateTime createTime;
}

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