Merge branch 'refs/heads/develop' into feature/zijie

# Conflicts:
#	tashow-module/tashow-module-app/pom.xml
#	tashow-module/tashow-module-system/src/main/resources/application-local.yaml
This commit is contained in:
2025-06-09 14:58:46 +08:00
344 changed files with 16517 additions and 49973 deletions

View File

@@ -1,5 +1,9 @@
package com.tashow.cloud.system.controller.admin.auth;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.common.util.collection.CollectionUtils.convertSet;
import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.enums.CommonStatusEnum;
@@ -19,21 +23,20 @@ import com.tashow.cloud.system.convert.auth.AuthConvert;
import com.tashow.cloud.system.dal.dataobject.permission.MenuDO;
import com.tashow.cloud.system.dal.dataobject.permission.RoleDO;
import com.tashow.cloud.system.dal.dataobject.user.AdminUserDO;
import com.tashow.cloud.systemapi.enums.logger.LoginLogTypeEnum;
import com.tashow.cloud.system.service.auth.AdminAuthService;
import com.tashow.cloud.system.service.permission.MenuService;
import com.tashow.cloud.system.service.permission.PermissionService;
import com.tashow.cloud.system.service.permission.RoleService;
import com.tashow.cloud.system.service.social.SocialClientService;
import com.tashow.cloud.system.service.user.AdminUserService;
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 com.tashow.cloud.systemapi.enums.logger.LoginLogTypeEnum;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
@@ -43,142 +46,125 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.common.util.collection.CollectionUtils.convertSet;
import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;
@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;
@Resource
private SocialClientService socialClientService;
@Resource private AdminAuthService authService;
@Resource private AdminUserService userService;
@Resource private RoleService roleService;
@Resource private MenuService menuService;
@Resource private PermissionService permissionService;
@Resource private SocialClientService socialClientService;
@Resource
private SecurityProperties securityProperties;
@Resource private SecurityProperties securityProperties;
@PostMapping("/login")
@PermitAll
@Operation(summary = "使用账号密码登录")
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
return success(authService.login(reqVO));
/** 使用账号密码登录 */
@PostMapping("/login")
@PermitAll
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
return success(authService.login(reqVO));
}
/** 登出系统 */
@PostMapping("/logout")
@PermitAll
public CommonResult<Boolean> logout(HttpServletRequest request) {
String token =
SecurityFrameworkUtils.obtainAuthorization(
request, securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
if (StrUtil.isNotBlank(token)) {
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
}
return success(true);
}
/** 刷新令牌 */
@PostMapping("/refresh-token")
@PermitAll
public CommonResult<AuthLoginRespVO> refreshToken(
@RequestParam("refreshToken") String refreshToken) {
return success(authService.refreshToken(refreshToken));
}
/** 获取登录用户的权限信息 */
@GetMapping("/get-permission-info")
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
// 1.1 获得用户信息
AdminUserDO user = userService.getUser(getLoginUserId());
if (user == null) {
return success(null);
}
@PostMapping("/logout")
@PermitAll
@Operation(summary = "登出系统")
public CommonResult<Boolean> logout(HttpServletRequest request) {
String token = SecurityFrameworkUtils.obtainAuthorization(request,
securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
if (StrUtil.isNotBlank(token)) {
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
}
return success(true);
// 1.2 获得角色列表
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
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())); // 移除禁用的角色
@PostMapping("/refresh-token")
@PermitAll
@Operation(summary = "刷新令牌")
@Parameter(name = "refreshToken", description = "刷新令牌", required = true)
public CommonResult<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
return success(authService.refreshToken(refreshToken));
}
// 1.3 获得菜单列表
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
List<MenuDO> menuList = menuService.getMenuList(menuIds);
menuList = menuService.filterDisableMenus(menuList);
@GetMapping("/get-permission-info")
@Operation(summary = "获取登录用户的权限信息")
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
// 1.1 获得用户信息
AdminUserDO user = userService.getUser(getLoginUserId());
if (user == null) {
return success(null);
}
// 2. 拼接结果返回
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
}
// 1.2 获得角色列表
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
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())); // 移除禁用的角色
/** 注册用户 */
@PostMapping("/register")
@PermitAll
public CommonResult<AuthLoginRespVO> register(
@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
return success(authService.register(registerReqVO));
}
// 1.3 获得菜单列表
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
List<MenuDO> menuList = menuService.getMenuList(menuIds);
menuList = menuService.filterDisableMenus(menuList);
// ========== 短信登录相关 ==========
/** 使用短信验证码登录 */
@PostMapping("/sms-login")
@PermitAll
public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
return success(authService.smsLogin(reqVO));
}
// 2. 拼接结果返回
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
}
/** 发送手机验证码 */
@PostMapping("/send-sms-code")
@PermitAll
public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
authService.sendSmsCode(reqVO);
return success(true);
}
@PostMapping("/register")
@PermitAll
@Operation(summary = "注册用户")
public CommonResult<AuthLoginRespVO> register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
return success(authService.register(registerReqVO));
}
/** 重置密码 */
@PostMapping("/reset-password")
@PermitAll
public CommonResult<Boolean> resetPassword(@RequestBody @Valid AuthResetPasswordReqVO reqVO) {
authService.resetPassword(reqVO);
return success(true);
}
// ========== 短信登录相关 ==========
@PostMapping("/sms-login")
@PermitAll
@Operation(summary = "使用短信验证码登录")
public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
return success(authService.smsLogin(reqVO));
}
@PostMapping("/send-sms-code")
@PermitAll
@Operation(summary = "发送手机验证码")
public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
authService.sendSmsCode(reqVO);
return success(true);
}
@PostMapping("/reset-password")
@PermitAll
@Operation(summary = "重置密码")
public CommonResult<Boolean> resetPassword(@RequestBody @Valid AuthResetPasswordReqVO reqVO) {
authService.resetPassword(reqVO);
return success(true);
}
// ========== 社交登录相关 ==========
@GetMapping("/social-auth-redirect")
@PermitAll
@Operation(summary = "社交授权的跳转")
@Parameters({
@Parameter(name = "type", description = "社交类型", required = true),
@Parameter(name = "redirectUri", description = "回调路径")
})
public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
@RequestParam("redirectUri") String redirectUri) {
return success(socialClientService.getAuthorizeUrl(
type, UserTypeEnum.ADMIN.getValue(), redirectUri));
}
@PostMapping("/social-login")
@PermitAll
@Operation(summary = "社交快捷登录,使用 code 授权码", description = "适合未登录的用户,但是社交账号已绑定用户")
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
return success(authService.socialLogin(reqVO));
}
// ========== 社交登录相关 ==========
/** 社交授权的跳转 */
@GetMapping("/social-auth-redirect")
@PermitAll
public CommonResult<String> socialLogin(
@RequestParam("type") Integer type, @RequestParam("redirectUri") String redirectUri) {
return success(
socialClientService.getAuthorizeUrl(type, UserTypeEnum.ADMIN.getValue(), redirectUri));
}
/** 社交快捷登录,使用 code 授权码", description = "适合未登录的用户,但是社交账号已绑定用户 */
@PostMapping("/social-login")
@PermitAll
public CommonResult<AuthLoginRespVO> socialQuickLogin(
@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
return success(authService.socialLogin(reqVO));
}
}

View File

@@ -3,8 +3,6 @@ package com.tashow.cloud.system.controller.admin.auth.vo;
import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.systemapi.enums.social.SocialTypeEnum;
import com.tashow.cloud.systemapi.enums.social.SocialTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
@@ -14,44 +12,43 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
@Schema(description = "管理后台 - 账号密码登录 Request VO如果登录并绑定社交用户需要传递 social 开头的参数")
/** 管理后台 - 账号密码登录 Request VO如果登录并绑定社交用户需要传递 social 开头的参数 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginReqVO extends CaptchaVerificationReqVO {
@Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
private String username;
/** 账号" */
@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;
/** 密码" */
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
// ========== 绑定社交登录时,需要传递如下参数 ==========
// ========== 绑定社交登录时,需要传递如下参数 ==========
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@InEnum(SocialTypeEnum.class)
private Integer socialType;
/** 社交平台的类型,参见 SocialTypeEnum 枚举值" */
@InEnum(SocialTypeEnum.class)
private Integer socialType;
@Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String socialCode;
/** 授权码" */
private String socialCode;
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
private String socialState;
/** state" */
private String socialState;
@AssertTrue(message = "授权码不能为空")
public boolean isSocialCodeValid() {
return socialType == null || StrUtil.isNotEmpty(socialCode);
}
@AssertTrue(message = "授权 state 不能为空")
public boolean isSocialState() {
return socialType == null || StrUtil.isNotEmpty(socialState);
}
@AssertTrue(message = "授权码不能为空")
public boolean isSocialCodeValid() {
return socialType == null || StrUtil.isNotEmpty(socialCode);
}
@AssertTrue(message = "授权 state 不能为空")
public boolean isSocialState() {
return socialType == null || StrUtil.isNotEmpty(socialState);
}
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -8,23 +7,22 @@ import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 登录 Response VO")
/** 管理后台 - 登录 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthLoginRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId;
/** 用户编号" */
private Long userId;
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "happy")
private String accessToken;
/** 访问令牌" */
private String accessToken;
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
private String refreshToken;
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime expiresTime;
/** 刷新令牌" */
private String refreshToken;
/** 过期时间 */
private LocalDateTime expiresTime;
}

View File

@@ -1,53 +1,48 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")
/** 管理后台 - 登录用户的菜单信息 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthMenuRespVO {
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private Long id;
/** 菜单名称", example = "芋道 */
private Long id;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long parentId;
/** 父菜单 ID" */
private Long parentId;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
/** 菜单名称", example = "芋道 */
private String name;
@Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post")
private String path;
/** 路由地址,仅菜单类型为菜单或者目录时,才需要传 */
private String path;
@Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index")
private String component;
/** 组件路径,仅菜单类型为菜单时,才需要传 */
private String component;
@Schema(description = "组件名", example = "SystemUser")
private String componentName;
/** 组件名 */
private String componentName;
@Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list")
private String icon;
/** 菜单图标,仅菜单类型为菜单或者目录时,才需要传 */
private String icon;
@Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean visible;
/** 是否可见" */
private Boolean visible;
@Schema(description = "是否缓存", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean keepAlive;
/** 是否缓存" */
private Boolean keepAlive;
@Schema(description = "是否总是显示", example = "false")
private Boolean alwaysShow;
/**
* 子路由
*/
private List<AuthMenuRespVO> children;
/** 是否总是显示 */
private Boolean alwaysShow;
/** 子路由 */
private List<AuthMenuRespVO> children;
}

View File

@@ -1,96 +1,97 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Set;
@Schema(description = "管理后台 - 登录用户的权限信息 Response VO额外包括用户信息和角色列表")
/** 管理后台 - 登录用户的权限信息 Response VO额外包括用户信息和角色列表 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthPermissionInfoRespVO {
@Schema(description = "用户信息", requiredMode = Schema.RequiredMode.REQUIRED)
private UserVO user;
/**
* 用户信息
*/
private UserVO user;
@Schema(description = "角色标识数组", requiredMode = Schema.RequiredMode.REQUIRED)
private Set<String> roles;
/**
* 角色标识数组
*/
private Set<String> roles;
@Schema(description = "操作权限数组", requiredMode = Schema.RequiredMode.REQUIRED)
private Set<String> permissions;
/**
* 操作权限数组
*/
private Set<String> permissions;
@Schema(description = "菜单树", requiredMode = Schema.RequiredMode.REQUIRED)
private List<MenuVO> menus;
/**
* 菜单树
*/
private List<MenuVO> menus;
@Schema(description = "用户信息 VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class UserVO {
/** 用户信息 VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class UserVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/** 用户编号" */
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String nickname;
/** 用户昵称", example = "芋道源码 */
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg")
private String avatar;
/** 用户头像" */
private String avatar;
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long deptId;
/** 部门编号" */
private Long deptId;
}
}
/** 管理后台 - 登录用户的菜单信息 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class MenuVO {
@Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class MenuVO {
/** 菜单名称", example = "芋道 */
private Long id;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private Long id;
/** 父菜单 ID" */
private Long parentId;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long parentId;
/** 菜单名称", example = "芋道 */
private String name;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
/** 路由地址,仅菜单类型为菜单或者目录时,才需要传 */
private String path;
@Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post")
private String path;
/** 组件路径,仅菜单类型为菜单时,才需要传 */
private String component;
@Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index")
private String component;
/** 组件名 */
private String componentName;
@Schema(description = "组件名", example = "SystemUser")
private String componentName;
/** 菜单图标,仅菜单类型为菜单或者目录时,才需要传 */
private String icon;
@Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list")
private String icon;
/** 是否可见" */
private Boolean visible;
@Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean visible;
/** 是否缓存" */
private Boolean keepAlive;
@Schema(description = "是否缓存", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
private Boolean keepAlive;
@Schema(description = "是否总是显示", example = "false")
private Boolean alwaysShow;
/**
* 子路由
*/
private List<MenuVO> children;
}
/** 是否总是显示 */
private Boolean alwaysShow;
/** 子路由 */
private List<MenuVO> children;
}
}

View File

@@ -1,7 +1,5 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
@@ -9,23 +7,23 @@ import jakarta.validation.constraints.Size;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
@Schema(description = "管理后台 - Register Request VO")
/** 管理后台 - Register Request VO */
@Data
public class AuthRegisterReqVO extends CaptchaVerificationReqVO {
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotBlank(message = "用户账号不能为空")
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成")
@Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符")
private String username;
/** 用户账号" */
@NotBlank(message = "用户账号不能为空")
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成")
@Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符")
private String username;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@NotBlank(message = "用户昵称不能为空")
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
private String nickname;
/** 用户昵称", example = "芋艿 */
@NotBlank(message = "用户昵称不能为空")
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
private String nickname;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
/** 密码" */
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
}

View File

@@ -1,7 +1,7 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import com.tashow.cloud.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -9,24 +9,24 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
@Schema(description = "管理后台 - 短信重置账号密码 Request VO")
/** 管理后台 - 短信重置账号密码 Request VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthResetPasswordReqVO {
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234")
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
/** 密码" */
@NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13312341234")
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
/** 手机号" */
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
@Schema(description = "手机短信验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotEmpty(message = "手机手机短信验证码不能为空")
private String code;
/** 手机短信验证码" */
@NotEmpty(message = "手机手机短信验证码不能为空")
private String code;
}

View File

@@ -1,27 +1,25 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import com.tashow.cloud.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 短信验证码的登录 Request VO")
/** 管理后台 - 短信验证码的登录 Request VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSmsLoginReqVO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
@Schema(description = "短信验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotEmpty(message = "验证码不能为空")
private String code;
/** 手机号" */
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
/** 短信验证码" */
@NotEmpty(message = "验证码不能为空")
private String code;
}

View File

@@ -3,8 +3,6 @@ package com.tashow.cloud.system.controller.admin.auth.vo;
import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.common.validation.Mobile;
import com.tashow.cloud.systemapi.enums.sms.SmsSceneEnum;
import com.tashow.cloud.systemapi.enums.sms.SmsSceneEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
@@ -12,21 +10,20 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 发送手机验证码 Request VO")
/** 管理后台 - 发送手机验证码 Request VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSmsSendReqVO extends CaptchaVerificationReqVO {
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
@Schema(description = "短信场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "发送场景不能为空")
@InEnum(SmsSceneEnum.class)
private Integer scene;
/** 手机号" */
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
/** 短信场景" */
@NotNull(message = "发送场景不能为空")
@InEnum(SmsSceneEnum.class)
private Integer scene;
}

View File

@@ -2,8 +2,6 @@ package com.tashow.cloud.system.controller.admin.auth.vo;
import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.systemapi.enums.social.SocialTypeEnum;
import com.tashow.cloud.systemapi.enums.social.SocialTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
@@ -11,24 +9,23 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 社交绑定登录 Request VO使用 code 授权码 + 账号密码")
/** 管理后台 - 社交绑定登录 Request VO使用 code 授权码 + 账号密码 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AuthSocialLoginReqVO {
@Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@InEnum(SocialTypeEnum.class)
@NotNull(message = "社交平台的类型不能为空")
private Integer type;
/** 社交平台的类型,参见 UserSocialTypeEnum 枚举值" */
@InEnum(SocialTypeEnum.class)
@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;
/** 授权码" */
@NotEmpty(message = "授权码不能为空")
private String code;
/** state" */
@NotEmpty(message = "state 不能为空")
private String state;
}

View File

@@ -1,22 +1,16 @@
package com.tashow.cloud.system.controller.admin.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
@Schema(description = "管理后台 - 验证码 Request VO")
/** 管理后台 - 验证码 Request VO */
@Data
public class CaptchaVerificationReqVO {
// ========== 图片验证码相关 ==========
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
private String captchaVerification;
// ========== 图片验证码相关 ==========
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
private String captchaVerification;
/**
* 开启验证码的 Group
*/
public interface CodeEnableGroup {
}
/** 开启验证码的 Group */
public interface CodeEnableGroup {}
}

View File

@@ -5,49 +5,44 @@ import com.tashow.cloud.common.util.servlet.ServletUtils;
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 jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
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 jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
@Tag(name = "管理后台 - 验证码")
/** 管理后台 - 验证码 */
@RestController("adminCaptchaController")
@RequestMapping("/system/captcha")
public class CaptchaController {
@Resource
private CaptchaService captchaService;
@Resource private CaptchaService captchaService;
@PostMapping({"/get"})
@Operation(summary = "获得验证码")
@PermitAll
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
assert request.getRemoteHost() != null;
data.setBrowserInfo(getRemoteId(request));
return captchaService.get(data);
/** 获得验证码 */
@PostMapping({"/get"})
@PermitAll
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
assert request.getRemoteHost() != null;
data.setBrowserInfo(getRemoteId(request));
return captchaService.get(data);
}
/** 校验验证码 */
@PostMapping("/check")
@PermitAll
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
data.setBrowserInfo(getRemoteId(request));
return captchaService.check(data);
}
public static String getRemoteId(HttpServletRequest request) {
String ip = ServletUtils.getClientIP(request);
String ua = request.getHeader("user-agent");
if (StrUtil.isNotBlank(ip)) {
return ip + ua;
}
@PostMapping("/check")
@Operation(summary = "校验验证码")
@PermitAll
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
data.setBrowserInfo(getRemoteId(request));
return captchaService.check(data);
}
public static String getRemoteId(HttpServletRequest request) {
String ip = ServletUtils.getClientIP(request);
String ua = request.getHeader("user-agent");
if (StrUtil.isNotBlank(ip)) {
return ip + ua;
}
return request.getRemoteAddr() + ua;
}
return request.getRemoteAddr() + ua;
}
}

View File

@@ -1,5 +1,7 @@
package com.tashow.cloud.system.controller.admin.dept;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.util.object.BeanUtils;
@@ -9,76 +11,66 @@ import com.tashow.cloud.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import com.tashow.cloud.system.controller.admin.dept.vo.dept.DeptSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.dept.DeptDO;
import com.tashow.cloud.system.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 jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 部门")
/** 管理后台 - 部门 */
@RestController
@RequestMapping("/system/dept")
@Validated
public class DeptController {
@Resource
private DeptService deptService;
@Resource private DeptService deptService;
@PostMapping("create")
@Operation(summary = "创建部门")
@PreAuthorize("@ss.hasPermission('system:dept:create')")
public CommonResult<Long> createDept(@Valid @RequestBody DeptSaveReqVO createReqVO) {
Long deptId = deptService.createDept(createReqVO);
return success(deptId);
}
/** 创建部门 */
@PostMapping("create")
@PreAuthorize("@ss.hasPermission('system:dept:create')")
public CommonResult<Long> createDept(@Valid @RequestBody DeptSaveReqVO createReqVO) {
Long deptId = deptService.createDept(createReqVO);
return success(deptId);
}
@PutMapping("update")
@Operation(summary = "更新部门")
@PreAuthorize("@ss.hasPermission('system:dept:update')")
public CommonResult<Boolean> updateDept(@Valid @RequestBody DeptSaveReqVO updateReqVO) {
deptService.updateDept(updateReqVO);
return success(true);
}
/** 更新部门 */
@PutMapping("update")
@PreAuthorize("@ss.hasPermission('system:dept:update')")
public CommonResult<Boolean> updateDept(@Valid @RequestBody DeptSaveReqVO updateReqVO) {
deptService.updateDept(updateReqVO);
return success(true);
}
@DeleteMapping("delete")
@Operation(summary = "删除部门")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dept:delete')")
public CommonResult<Boolean> deleteDept(@RequestParam("id") Long id) {
deptService.deleteDept(id);
return success(true);
}
/** 删除部门 */
@DeleteMapping("delete")
@PreAuthorize("@ss.hasPermission('system:dept:delete')")
public CommonResult<Boolean> deleteDept(@RequestParam("id") Long id) {
deptService.deleteDept(id);
return success(true);
}
@GetMapping("/list")
@Operation(summary = "获取部门列表")
@PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<List<DeptRespVO>> getDeptList(DeptListReqVO reqVO) {
List<DeptDO> list = deptService.getDeptList(reqVO);
return success(BeanUtils.toBean(list, DeptRespVO.class));
}
/** 获取部门列表 */
@GetMapping("/list")
@PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<List<DeptRespVO>> getDeptList(DeptListReqVO reqVO) {
List<DeptDO> list = deptService.getDeptList(reqVO);
return success(BeanUtils.toBean(list, DeptRespVO.class));
}
@GetMapping(value = {"/list-all-simple", "/simple-list"})
@Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项")
public CommonResult<List<DeptSimpleRespVO>> getSimpleDeptList() {
List<DeptDO> list = deptService.getDeptList(
new DeptListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
return success(BeanUtils.toBean(list, DeptSimpleRespVO.class));
}
@GetMapping("/get")
@Operation(summary = "获得部门信息")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<DeptRespVO> getDept(@RequestParam("id") Long id) {
DeptDO dept = deptService.getDept(id);
return success(BeanUtils.toBean(dept, DeptRespVO.class));
}
/** 获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项 */
@GetMapping(value = {"/list-all-simple", "/simple-list"})
public CommonResult<List<DeptSimpleRespVO>> getSimpleDeptList() {
List<DeptDO> list =
deptService.getDeptList(new DeptListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
return success(BeanUtils.toBean(list, DeptSimpleRespVO.class));
}
/** 获得部门信息 */
@GetMapping("/get")
@PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<DeptRespVO> getDept(@RequestParam("id") Long id) {
DeptDO dept = deptService.getDept(id);
return success(BeanUtils.toBean(dept, DeptRespVO.class));
}
}

View File

@@ -1,6 +1,8 @@
package com.tashow.cloud.system.controller.admin.dept;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
@@ -13,97 +15,87 @@ import com.tashow.cloud.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.tashow.cloud.system.controller.admin.dept.vo.post.PostSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.dept.PostDO;
import com.tashow.cloud.system.service.dept.PostService;
import com.tashow.cloud.system.controller.admin.dept.vo.post.PostPageReqVO;
import com.tashow.cloud.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.tashow.cloud.system.controller.admin.dept.vo.post.PostSimpleRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 岗位")
/** 管理后台 - 岗位 */
@RestController
@RequestMapping("/system/post")
@Validated
public class PostController {
@Resource
private PostService postService;
@Resource private PostService postService;
@PostMapping("/create")
@Operation(summary = "创建岗位")
@PreAuthorize("@ss.hasPermission('system:post:create')")
public CommonResult<Long> createPost(@Valid @RequestBody PostSaveReqVO createReqVO) {
Long postId = postService.createPost(createReqVO);
return success(postId);
}
/** 创建岗位 */
@PostMapping("/create")
@PreAuthorize("@ss.hasPermission('system:post:create')")
public CommonResult<Long> createPost(@Valid @RequestBody PostSaveReqVO createReqVO) {
Long postId = postService.createPost(createReqVO);
return success(postId);
}
@PutMapping("/update")
@Operation(summary = "修改岗位")
@PreAuthorize("@ss.hasPermission('system:post:update')")
public CommonResult<Boolean> updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) {
postService.updatePost(updateReqVO);
return success(true);
}
/** 修改岗位 */
@PutMapping("/update")
@PreAuthorize("@ss.hasPermission('system:post:update')")
public CommonResult<Boolean> updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) {
postService.updatePost(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除岗位")
@PreAuthorize("@ss.hasPermission('system:post:delete')")
public CommonResult<Boolean> deletePost(@RequestParam("id") Long id) {
postService.deletePost(id);
return success(true);
}
/** 删除岗位 */
@DeleteMapping("/delete")
@PreAuthorize("@ss.hasPermission('system:post:delete')")
public CommonResult<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")
@PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PostRespVO> getPost(@RequestParam("id") Long id) {
PostDO post = postService.getPost(id);
return success(BeanUtils.toBean(post, PostRespVO.class));
}
/** 获得岗位信息 */
@GetMapping(value = "/get")
@PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PostRespVO> getPost(@RequestParam("id") Long id) {
PostDO post = postService.getPost(id);
return success(BeanUtils.toBean(post, PostRespVO.class));
}
@GetMapping(value = {"/list-all-simple", "simple-list"})
@Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项")
public CommonResult<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));
}
/** 获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项 */
@GetMapping(value = {"/list-all-simple", "simple-list"})
public CommonResult<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 = "获得岗位分页列表")
@PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO pageReqVO) {
PageResult<PostDO> pageResult = postService.getPostPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, PostRespVO.class));
}
@GetMapping("/export")
@Operation(summary = "岗位管理")
@PreAuthorize("@ss.hasPermission('system:post:export')")
@ApiAccessLog(operateType = EXPORT)
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));
}
/** 获得岗位分页列表 */
@GetMapping("/page")
@PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO pageReqVO) {
PageResult<PostDO> pageResult = postService.getPostPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, PostRespVO.class));
}
/** 岗位管理 */
@GetMapping("/export")
@PreAuthorize("@ss.hasPermission('system:post:export')")
@ApiAccessLog(operateType = EXPORT)
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));
}
}

View File

@@ -1,16 +1,14 @@
package com.tashow.cloud.system.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 部门列表 Request VO")
/** 管理后台 - 部门列表 Request VO */
@Data
public class DeptListReqVO {
@Schema(description = "部门名称,模糊匹配", example = "芋道")
private String name;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
/** 部门名称,模糊匹配 */
private String name;
/** 展示状态,参见 CommonStatusEnum 枚举类 */
private Integer status;
}

View File

@@ -1,39 +1,37 @@
package com.tashow.cloud.system.controller.admin.dept.vo.dept;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 部门信息 Response VO")
/** 管理后台 - 部门信息 Response VO */
@Data
public class DeptRespVO {
@Schema(description = "部门编号", example = "1024")
private Long id;
/** 部门编号 */
private Long id;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
/** 部门名称", example = "芋道 */
private String name;
@Schema(description = "父部门 ID", example = "1024")
private Long parentId;
/** 父部门 ID */
private Long parentId;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer sort;
/** 显示顺序" */
private Integer sort;
@Schema(description = "负责人的用户编号", example = "2048")
private Long leaderUserId;
/** 负责人的用户编号 */
private Long leaderUserId;
@Schema(description = "联系电话", example = "15601691000")
private String phone;
/** 联系电话 */
private String phone;
@Schema(description = "邮箱", example = "yudao@iocoder.cn")
private String email;
/** 邮箱 */
private String email;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
private LocalDateTime createTime;
/** 状态,见 CommonStatusEnum 枚举" */
private Integer status;
/** 创建时间", example = "时间戳格式 */
private LocalDateTime createTime;
}

View File

@@ -2,47 +2,45 @@ package com.tashow.cloud.system.controller.admin.dept.vo.dept;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 部门创建/修改 Request VO")
/** 管理后台 - 部门创建/修改 Request VO */
@Data
public class DeptSaveReqVO {
@Schema(description = "部门编号", example = "1024")
private Long id;
/** 部门编号 */
private Long id;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@NotBlank(message = "部门名称不能为空")
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
private String name;
/** 部门名称", example = "芋道 */
@NotBlank(message = "部门名称不能为空")
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
private String name;
@Schema(description = "父部门 ID", example = "1024")
private Long parentId;
/** 父部门 ID */
private Long parentId;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "显示顺序不能为空")
private Integer sort;
/** 显示顺序" */
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "负责人的用户编号", example = "2048")
private Long leaderUserId;
/** 负责人的用户编号 */
private Long leaderUserId;
@Schema(description = "联系电话", example = "15601691000")
@Size(max = 11, message = "联系电话长度不能超过11个字符")
private String phone;
/** 联系电话 */
@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;
/** 邮箱 */
@Email(message = "邮箱格式不正确")
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
private String email;
/** 状态,见 CommonStatusEnum 枚举" */
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
}

View File

@@ -1,23 +1,21 @@
package com.tashow.cloud.system.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")
/** 管理后台 - 部门精简信息 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptSimpleRespVO {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/** 部门编号" */
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;
/** 部门名称", example = "芋道 */
private String name;
/** 父部门 ID" */
private Long parentId;
}

View File

@@ -1,22 +1,28 @@
package com.tashow.cloud.system.controller.admin.dept.vo.post;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 岗位分页 Request VO")
/**
* 管理后台 - 岗位分页 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")
/**
* 展示状态,参见 CommonStatusEnum 枚举类
*/
private Integer status;
}

View File

@@ -1,46 +1,59 @@
package com.tashow.cloud.system.controller.admin.dept.vo.post;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.excel.excel.core.annotations.DictFormat;
import com.tashow.cloud.excel.excel.core.convert.DictConvert;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 岗位信息 Response VO")
/**
* 管理后台 - 岗位信息 Response VO
*/
@Data
@ExcelIgnoreUnannotated
public class PostRespVO {
@Schema(description = "岗位序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 岗位序号"
*/
@ExcelProperty("岗位序号")
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
/**
* 岗位名称", example = "小土豆
*/
@ExcelProperty("岗位名称")
private String name;
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
/**
* 岗位编码"
*/
@ExcelProperty("岗位编码")
private String code;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 显示顺序"
*/
@ExcelProperty("岗位排序")
private Integer sort;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举类"
*/
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
/**
* 备注
*/
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -2,38 +2,50 @@ package com.tashow.cloud.system.controller.admin.dept.vo.post;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 岗位创建/修改 Request VO")
/**
* 管理后台 - 岗位创建/修改 Request VO
*/
@Data
public class PostSaveReqVO {
@Schema(description = "岗位编号", example = "1024")
/**
* 岗位编号
*/
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
/**
* 岗位名称", 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")
/**
* 状态"
*/
@InEnum(CommonStatusEnum.class)
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
/**
* 备注
*/
private String remark;
}

View File

@@ -1,19 +1,23 @@
package com.tashow.cloud.system.controller.admin.dept.vo.post;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 岗位信息的精简 Response VO")
/**
* 管理后台 - 岗位信息的精简 Response VO
*/
@Data
public class PostSimpleRespVO {
@Schema(description = "岗位序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 岗位序号"
*/
@ExcelProperty("岗位序号")
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆")
/**
* 岗位名称", example = "小土豆
*/
@ExcelProperty("岗位名称")
private String name;
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.dict;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
@@ -13,13 +12,7 @@ import com.tashow.cloud.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
import com.tashow.cloud.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.dict.DictDataDO;
import com.tashow.cloud.system.service.dict.DictDataService;
import com.tashow.cloud.system.controller.admin.dict.vo.data.DictDataPageReqVO;
import com.tashow.cloud.system.controller.admin.dict.vo.data.DictDataRespVO;
import com.tashow.cloud.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
import com.tashow.cloud.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -30,10 +23,12 @@ import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 字典数据")
/**
* 管理后台 - 字典数据
*/
@RestController
@RequestMapping("/system/dict-data")
@Validated
@@ -42,67 +37,85 @@ public class DictDataController {
@Resource
private DictDataService dictDataService;
/**
* 新增字典数据
*/
@PostMapping("/create")
@Operation(summary = "新增字典数据")
@PreAuthorize("@ss.hasPermission('system:dict:create')")
public CommonResult<Long> createDictData(@Valid @RequestBody DictDataSaveReqVO createReqVO) {
Long dictDataId = dictDataService.createDictData(createReqVO);
return success(dictDataId);
}
/**
* 修改字典数据
*/
@PutMapping("/update")
@Operation(summary = "修改字典数据")
@PreAuthorize("@ss.hasPermission('system:dict:update')")
public CommonResult<Boolean> updateDictData(@Valid @RequestBody DictDataSaveReqVO updateReqVO) {
dictDataService.updateDictData(updateReqVO);
return success(true);
}
/**
* 删除字典数据
*/
@DeleteMapping("/delete")
@Operation(summary = "删除字典数据")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dict:delete')")
public CommonResult<Boolean> deleteDictData(Long id) {
dictDataService.deleteDictData(id);
return success(true);
}
/**
* 获得全部字典数据列表", description = "一般用于管理后台缓存字典数据在本地
*/
@GetMapping(value = {"/list-all-simple", "simple-list"})
@Operation(summary = "获得全部字典数据列表", description = "一般用于管理后台缓存字典数据在本地")
// 无需添加权限认证,因为前端全局都需要
public CommonResult<List<DictDataSimpleRespVO>> getSimpleDictDataList() {
List<DictDataDO> list = dictDataService.getDictDataList(
CommonStatusEnum.ENABLE.getStatus(), null);
List<DictDataDO> list =
dictDataService.getDictDataList(CommonStatusEnum.ENABLE.getStatus(), null);
return success(BeanUtils.toBean(list, DictDataSimpleRespVO.class));
}
/**
* /获得字典类型的分页列表
*/
@GetMapping("/page")
@Operation(summary = "/获得字典类型的分页列表")
@PreAuthorize("@ss.hasPermission('system:dict:query')")
public CommonResult<PageResult<DictDataRespVO>> getDictTypePage(@Valid DictDataPageReqVO pageReqVO) {
public CommonResult<PageResult<DictDataRespVO>> getDictTypePage(
@Valid DictDataPageReqVO pageReqVO) {
PageResult<DictDataDO> pageResult = dictDataService.getDictDataPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, DictDataRespVO.class));
}
/**
* /查询字典数据详细
*/
@GetMapping(value = "/get")
@Operation(summary = "/查询字典数据详细")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dict:query')")
public CommonResult<DictDataRespVO> getDictData(@RequestParam("id") Long id) {
DictDataDO dictData = dictDataService.getDictData(id);
return success(BeanUtils.toBean(dictData, DictDataRespVO.class));
}
/**
* 导出字典数据
*/
@GetMapping("/export")
@Operation(summary = "导出字典数据")
@PreAuthorize("@ss.hasPermission('system:dict:export')")
@ApiAccessLog(operateType = EXPORT)
public void export(HttpServletResponse response, @Valid DictDataPageReqVO exportReqVO) throws IOException {
public void export(HttpServletResponse response, @Valid DictDataPageReqVO exportReqVO)
throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<DictDataDO> list = dictDataService.getDictDataPage(exportReqVO).getList();
// 输出
ExcelUtils.write(response, "字典数据.xls", "数据", DictDataRespVO.class,
ExcelUtils.write(
response,
"字典数据.xls",
"数据",
DictDataRespVO.class,
BeanUtils.toBean(list, DictDataRespVO.class));
}
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.dict;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.pojo.PageResult;
@@ -12,13 +11,7 @@ import com.tashow.cloud.system.controller.admin.dict.vo.type.DictTypeSaveReqVO;
import com.tashow.cloud.system.controller.admin.dict.vo.type.DictTypeSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.dict.DictTypeDO;
import com.tashow.cloud.system.service.dict.DictTypeService;
import com.tashow.cloud.system.controller.admin.dict.vo.type.DictTypePageReqVO;
import com.tashow.cloud.system.controller.admin.dict.vo.type.DictTypeRespVO;
import com.tashow.cloud.system.controller.admin.dict.vo.type.DictTypeSaveReqVO;
import com.tashow.cloud.system.controller.admin.dict.vo.type.DictTypeSimpleRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -29,10 +22,12 @@ import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 字典类型")
/**
* 管理后台 - 字典类型
*/
@RestController
@RequestMapping("/system/dict-type")
@Validated
@@ -41,41 +36,50 @@ public class DictTypeController {
@Resource
private DictTypeService dictTypeService;
/**
* 创建字典类型
*/
@PostMapping("/create")
@Operation(summary = "创建字典类型")
@PreAuthorize("@ss.hasPermission('system:dict:create')")
public CommonResult<Long> createDictType(@Valid @RequestBody DictTypeSaveReqVO createReqVO) {
Long dictTypeId = dictTypeService.createDictType(createReqVO);
return success(dictTypeId);
}
/**
* 修改字典类型
*/
@PutMapping("/update")
@Operation(summary = "修改字典类型")
@PreAuthorize("@ss.hasPermission('system:dict:update')")
public CommonResult<Boolean> updateDictType(@Valid @RequestBody DictTypeSaveReqVO updateReqVO) {
dictTypeService.updateDictType(updateReqVO);
return success(true);
}
/**
* 删除字典类型
*/
@DeleteMapping("/delete")
@Operation(summary = "删除字典类型")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:dict:delete')")
public CommonResult<Boolean> deleteDictType(Long id) {
dictTypeService.deleteDictType(id);
return success(true);
}
/**
* 获得字典类型的分页列表
*/
@GetMapping("/page")
@Operation(summary = "获得字典类型的分页列表")
@PreAuthorize("@ss.hasPermission('system:dict:query')")
public CommonResult<PageResult<DictTypeRespVO>> pageDictTypes(@Valid DictTypePageReqVO pageReqVO) {
public CommonResult<PageResult<DictTypeRespVO>> pageDictTypes(
@Valid DictTypePageReqVO pageReqVO) {
PageResult<DictTypeDO> pageResult = dictTypeService.getDictTypePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, DictTypeRespVO.class));
}
@Operation(summary = "/查询字典类型详细")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
/**
* /查询字典类型详细
*/
@GetMapping(value = "/get")
@PreAuthorize("@ss.hasPermission('system:dict:query')")
public CommonResult<DictTypeRespVO> getDictType(@RequestParam("id") Long id) {
@@ -83,24 +87,32 @@ public class DictTypeController {
return success(BeanUtils.toBean(dictType, DictTypeRespVO.class));
}
@GetMapping(value = {"/list-all-simple", "simple-list"})
@Operation(summary = "获得全部字典类型列表", description = "包括开启 + 禁用的字典类型,主要用于前端的下拉选项")
/**
* 获得全部字典类型列表", description = "包括开启 + 禁用的字典类型,主要用于前端的下拉选项
*/
// 无需添加权限认证,因为前端全局都需要
@GetMapping(value = {"/list-all-simple", "simple-list"})
public CommonResult<List<DictTypeSimpleRespVO>> getSimpleDictTypeList() {
List<DictTypeDO> list = dictTypeService.getDictTypeList();
return success(BeanUtils.toBean(list, DictTypeSimpleRespVO.class));
}
@Operation(summary = "导出数据类型")
/**
* 导出数据类型
*/
@GetMapping("/export")
@PreAuthorize("@ss.hasPermission('system:dict:query')")
@ApiAccessLog(operateType = EXPORT)
public void export(HttpServletResponse response, @Valid DictTypePageReqVO exportReqVO) throws IOException {
public void export(HttpServletResponse response, @Valid DictTypePageReqVO exportReqVO)
throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<DictTypeDO> list = dictTypeService.getDictTypePage(exportReqVO).getList();
// 导出
ExcelUtils.write(response, "字典类型.xls", "数据", DictTypeRespVO.class,
ExcelUtils.write(
response,
"字典类型.xls",
"数据",
DictTypeRespVO.class,
BeanUtils.toBean(list, DictTypeRespVO.class));
}
}

View File

@@ -3,26 +3,32 @@ package com.tashow.cloud.system.controller.admin.dict.vo.data;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 字典类型分页列表 Request VO")
/**
* 管理后台 - 字典类型分页列表 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")
/**
* 展示状态,参见 CommonStatusEnum 枚举类
*/
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
}

View File

@@ -1,56 +1,75 @@
package com.tashow.cloud.system.controller.admin.dict.vo.data;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.excel.excel.core.annotations.DictFormat;
import com.tashow.cloud.excel.excel.core.convert.DictConvert;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典数据信息 Response VO")
/**
* 管理后台 - 字典数据信息 Response VO
*/
@Data
@ExcelIgnoreUnannotated
public class DictDataRespVO {
@Schema(description = "字典数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 字典数据编号"
*/
@ExcelProperty("字典编码")
private Long id;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 显示顺序"
*/
@ExcelProperty("字典排序")
private Integer sort;
@Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
/**
* 字典标签", example = "芋道
*/
@ExcelProperty("字典标签")
private String label;
@Schema(description = "字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "iocoder")
/**
* 字典值"
*/
@ExcelProperty("字典键值")
private String value;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
/**
* 字典类型"
*/
@ExcelProperty("字典类型")
private String dictType;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,见 CommonStatusEnum 枚举"
*/
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
/**
* 颜色类型,default、primary、success、info、warning、danger
*/
private String colorType;
@Schema(description = "css 样式", example = "btn-visible")
/**
* css 样式
*/
private String cssClass;
@Schema(description = "备注", example = "我是一个角色")
/**
* 备注
*/
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
/**
* 创建时间", example = "时间戳格式
*/
private LocalDateTime createTime;
}

View File

@@ -2,50 +2,48 @@ package com.tashow.cloud.system.controller.admin.dict.vo.data;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 字典数据创建/修改 Request VO")
/** 管理后台 - 字典数据创建/修改 Request VO */
@Data
public class DictDataSaveReqVO {
@Schema(description = "字典数据编号", example = "1024")
private Long id;
/** 字典数据编号 */
private Long id;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "显示顺序不能为空")
private Integer sort;
/** 显示顺序" */
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@NotBlank(message = "字典标签不能为空")
@Size(max = 100, message = "字典标签长度不能超过100个字符")
private String label;
/** 字典标签", 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;
/** 字典值" */
@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;
/** 字典类型" */
@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;
/** 状态,见 CommonStatusEnum 枚举" */
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
@Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default")
private String colorType;
/** 颜色类型,default、primary、success、info、warning、danger */
private String colorType;
@Schema(description = "css 样式", example = "btn-visible")
private String cssClass;
@Schema(description = "备注", example = "我是一个角色")
private String remark;
/** css 样式 */
private String cssClass;
/** 备注 */
private String remark;
}

View File

@@ -1,25 +1,35 @@
package com.tashow.cloud.system.controller.admin.dict.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 数据字典精简 Response VO")
/**
* 管理后台 - 数据字典精简 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 = "")
/**
* 字典标签", example = "男
*/
private String label;
@Schema(description = "颜色类型default、primary、success、info、warning、danger", example = "default")
/**
* 颜色类型default、primary、success、info、warning、danger
*/
private String colorType;
@Schema(description = "css 样式", example = "btn-visible")
/**
* css 样式
*/
private String cssClass;
}

View File

@@ -1,33 +1,39 @@
package com.tashow.cloud.system.controller.admin.dict.vo.type;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 字典类型分页列表 Request VO")
/**
* 管理后台 - 字典类型分页列表 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")
/**
* 展示状态,参见 CommonStatusEnum 枚举类
*/
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "创建时间")
/** 创建时间 */
private LocalDateTime[] createTime;
}

View File

@@ -1,42 +1,38 @@
package com.tashow.cloud.system.controller.admin.dict.vo.type;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.excel.excel.core.annotations.DictFormat;
import com.tashow.cloud.excel.excel.core.convert.DictConvert;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 字典类型信息 Response VO")
/** 管理后台 - 字典类型信息 Response VO */
@Data
@ExcelIgnoreUnannotated
public class DictTypeRespVO {
@Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("字典主键")
private Long id;
/** 字典类型编号" */
@ExcelProperty("字典主键")
private Long id;
@Schema(description = "字典名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "性别")
@ExcelProperty("字典名称")
private String name;
/** 字典名称", example = "性别 */
@ExcelProperty("字典名称")
private String name;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
@ExcelProperty("字典类型")
private String type;
/** 字典类型" */
@ExcelProperty("字典类型")
private String type;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
/** 状态,参见 CommonStatusEnum 枚举类" */
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
private LocalDateTime createTime;
/** 备注 */
private String remark;
/** 创建时间", example = "时间戳格式 */
private LocalDateTime createTime;
}

View File

@@ -1,34 +1,43 @@
package com.tashow.cloud.system.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 字典类型创建/修改 Request VO")
/**
* 管理后台 - 字典类型创建/修改 Request VO
*/
@Data
public class DictTypeSaveReqVO {
@Schema(description = "字典类型编号", example = "1024")
/**
* 字典类型编号
*/
private Long id;
@Schema(description = "字典名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "性别")
/**
* 字典名称", example = "性别
*/
@NotBlank(message = "字典名称不能为空")
@Size(max = 100, message = "字典类型名称长度不能超过100个字符")
private String name;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
/**
* 字典类型"
*/
@NotNull(message = "字典类型不能为空")
@Size(max = 100, message = "字典类型类型长度不能超过 100 个字符")
private String type;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举类"
*/
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "备注", example = "快乐的备注")
/**
* 备注
*/
private String remark;
}

View File

@@ -1,19 +1,25 @@
package com.tashow.cloud.system.controller.admin.dict.vo.type;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 字典类型精简信息 Response VO")
/**
* 管理后台 - 字典类型精简信息 Response VO
*/
@Data
public class DictTypeSimpleRespVO {
@Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 字典类型编号"
*/
private Long id;
@Schema(description = "字典类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
/**
* 字典类型名称", example = "芋道
*/
private String name;
@Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex")
/**
* 字典类型"
*/
private String type;
}

View File

@@ -7,9 +7,6 @@ import com.tashow.cloud.common.util.ip.AreaUtils;
import com.tashow.cloud.common.util.ip.IPUtils;
import com.tashow.cloud.common.util.object.BeanUtils;
import com.tashow.cloud.system.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;
@@ -20,23 +17,28 @@ import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 地区")
/**
* 管理后台 - 地区
*/
@RestController
@RequestMapping("/system/area")
@Validated
public class AreaController {
/**
* 获得地区树
*/
@GetMapping("/tree")
@Operation(summary = "获得地区树")
public CommonResult<List<AreaNodeRespVO>> getAreaTree() {
Area area = AreaUtils.getArea(Area.ID_CHINA);
Assert.notNull(area, "获取不到中国");
return success(BeanUtils.toBean(area.getChildren(), AreaNodeRespVO.class));
}
/**
* 获得 IP 对应的地区名
*/
@GetMapping("/get-by-ip")
@Operation(summary = "获得 IP 对应的地区名")
@Parameter(name = "ip", description = "IP", required = true)
public CommonResult<String> getAreaByIp(@RequestParam("ip") String ip) {
// 获得城市
Area area = IPUtils.getArea(ip);
@@ -46,5 +48,4 @@ public class AreaController {
// 格式化返回
return success(AreaUtils.format(area.getId()));
}
}

View File

@@ -1,23 +1,18 @@
package com.tashow.cloud.system.controller.admin.ip.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 地区节点 Response VO")
/** 管理后台 - 地区节点 Response VO */
@Data
public class AreaNodeRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer id;
/** 编号" */
private Integer id;
@Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "北京")
private String name;
/**
* 子节点
*/
private List<AreaNodeRespVO> children;
/** 名字", example = "北京 */
private String name;
/** 子节点 */
private List<AreaNodeRespVO> children;
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.logger;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.pojo.PageResult;
@@ -10,8 +9,7 @@ import com.tashow.cloud.system.controller.admin.logger.vo.loginlog.LoginLogPageR
import com.tashow.cloud.system.controller.admin.logger.vo.loginlog.LoginLogRespVO;
import com.tashow.cloud.system.dal.dataobject.logger.LoginLogDO;
import com.tashow.cloud.system.service.logger.LoginLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -24,10 +22,12 @@ import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 登录日志")
/**
* 管理后台 - 登录日志
*/
@RestController
@RequestMapping("/system/login-log")
@Validated
@@ -36,24 +36,33 @@ public class LoginLogController {
@Resource
private LoginLogService loginLogService;
/**
* 获得登录日志分页列表
*/
@GetMapping("/page")
@Operation(summary = "获得登录日志分页列表")
@PreAuthorize("@ss.hasPermission('system:login-log:query')")
public CommonResult<PageResult<LoginLogRespVO>> getLoginLogPage(@Valid LoginLogPageReqVO pageReqVO) {
public CommonResult<PageResult<LoginLogRespVO>> getLoginLogPage(
@Valid LoginLogPageReqVO pageReqVO) {
PageResult<LoginLogDO> pageResult = loginLogService.getLoginLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, LoginLogRespVO.class));
}
/**
* 导出登录日志 Excel
*/
@GetMapping("/export")
@Operation(summary = "导出登录日志 Excel")
@PreAuthorize("@ss.hasPermission('system:login-log:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportLoginLog(HttpServletResponse response, @Valid LoginLogPageReqVO exportReqVO) throws IOException {
public void exportLoginLog(HttpServletResponse response, @Valid LoginLogPageReqVO exportReqVO)
throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<LoginLogDO> list = loginLogService.getLoginLogPage(exportReqVO).getList();
// 输出
ExcelUtils.write(response, "登录日志.xls", "数据列表", LoginLogRespVO.class,
ExcelUtils.write(
response,
"登录日志.xls",
"数据列表",
LoginLogRespVO.class,
BeanUtils.toBean(list, LoginLogRespVO.class));
}
}

View File

@@ -1,18 +1,16 @@
package com.tashow.cloud.system.controller.admin.logger;
import com.tashow.cloud.mybatis.translate.core.TranslateUtils;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.common.util.object.BeanUtils;
import com.tashow.cloud.excel.excel.core.util.ExcelUtils;
import com.tashow.cloud.mybatis.translate.core.TranslateUtils;
import com.tashow.cloud.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
import com.tashow.cloud.system.controller.admin.logger.vo.operatelog.OperateLogRespVO;
import com.tashow.cloud.system.dal.dataobject.logger.OperateLogDO;
import com.tashow.cloud.system.service.logger.OperateLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -25,10 +23,12 @@ import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 操作日志")
/**
* 管理后台 - 操作日志
*/
@RestController
@RequestMapping("/system/operate-log")
@Validated
@@ -37,23 +37,32 @@ public class OperateLogController {
@Resource
private OperateLogService operateLogService;
/**
* 查看操作日志分页列表
*/
@GetMapping("/page")
@Operation(summary = "查看操作日志分页列表")
@PreAuthorize("@ss.hasPermission('system:operate-log:query')")
public CommonResult<PageResult<OperateLogRespVO>> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) {
public CommonResult<PageResult<OperateLogRespVO>> pageOperateLog(
@Valid OperateLogPageReqVO pageReqVO) {
PageResult<OperateLogDO> pageResult = operateLogService.getOperateLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, OperateLogRespVO.class));
}
@Operation(summary = "导出操作日志")
/**
* 导出操作日志
*/
@GetMapping("/export")
@PreAuthorize("@ss.hasPermission('system:operate-log:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException {
public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO)
throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<OperateLogDO> list = operateLogService.getOperateLogPage(exportReqVO).getList();
ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class,
ExcelUtils.write(
response,
"操作日志.xls",
"数据列表",
OperateLogRespVO.class,
TranslateUtils.translate(BeanUtils.toBean(list, OperateLogRespVO.class)));
}
}

View File

@@ -1,7 +1,6 @@
package com.tashow.cloud.system.controller.admin.logger.vo.loginlog;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
@@ -10,22 +9,31 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 登录日志分页列表 Request VO")
/**
* 管理后台 - 登录日志分页列表 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class LoginLogPageReqVO extends PageParam {
@Schema(description = "用户 IP模拟匹配", example = "127.0.0.1")
/**
* 用户 IP模拟匹配
*/
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 = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -1,58 +1,77 @@
package com.tashow.cloud.system.controller.admin.logger.vo.loginlog;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.excel.excel.core.annotations.DictFormat;
import com.tashow.cloud.excel.excel.core.convert.DictConvert;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 登录日志 Response VO")
/**
* 管理后台 - 登录日志 Response VO
*/
@Data
@ExcelIgnoreUnannotated
public class LoginLogRespVO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 日志编号"
*/
@ExcelProperty("日志主键")
private Long id;
@Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 日志类型,参见 LoginLogTypeEnum 枚举类"
*/
@ExcelProperty(value = "日志类型", converter = DictConvert.class)
@DictFormat(DictTypeConstants.LOGIN_TYPE)
private Integer logType;
@Schema(description = "用户编号", example = "666")
/**
* 用户编号
*/
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
/**
* 用户类型,参见 UserTypeEnum 枚举"
*/
private Integer userType;
@Schema(description = "链路追踪编号", example = "89aca178-a370-411c-ae02-3f0d672be4ab")
/**
* 链路追踪编号
*/
private String traceId;
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
/**
* 用户账号"
*/
@ExcelProperty("用户账号")
private String username;
@Schema(description = "登录结果,参见 LoginResultEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 登录结果,参见 LoginResultEnum 枚举类"
*/
@ExcelProperty(value = "登录结果", converter = DictConvert.class)
@DictFormat(DictTypeConstants.LOGIN_RESULT)
private Integer result;
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
/**
* 用户 IP"
*/
@ExcelProperty("登录 IP")
private String userIp;
@Schema(description = "浏览器 UserAgent", example = "Mozilla/5.0")
/**
* 浏览器 UserAgent
*/
@ExcelProperty("浏览器 UA")
private String userAgent;
@Schema(description = "登录时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 登录时间
*/
@ExcelProperty("登录时间")
private LocalDateTime createTime;
}

View File

@@ -1,7 +1,6 @@
package com.tashow.cloud.system.controller.admin.logger.vo.operatelog;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@@ -9,27 +8,40 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 操作日志分页列表 Request VO")
/**
* 管理后台 - 操作日志分页列表 Request VO
*/
@Data
public class OperateLogPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "芋道")
/**
* 用户编号
*/
private Long userId;
@Schema(description = "操作模块业务编号", example = "1")
/**
* 操作模块业务编号
*/
private Long bizId;
@Schema(description = "操作模块,模拟匹配", example = "订单")
/**
* 操作模块,模拟匹配
*/
private String type;
@Schema(description = "操作名,模拟匹配", example = "创建订单")
/**
* 操作名,模拟匹配
*/
private String subType;
@Schema(description = "操作明细,模拟匹配", example = "修改编号为 1 的用户信息")
/**
* 操作明细,模拟匹配
*/
private String action;
@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;
}

View File

@@ -1,68 +1,68 @@
package com.tashow.cloud.system.controller.admin.logger.vo.operatelog;
import com.tashow.cloud.system.dal.dataobject.user.AdminUserDO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema;
import com.tashow.cloud.system.dal.dataobject.user.AdminUserDO;
import jakarta.validation.constraints.NotEmpty;
import java.time.LocalDateTime;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 操作日志 Response VO")
/** 管理后台 - 操作日志 Response VO */
@Data
@ExcelIgnoreUnannotated
public class OperateLogRespVO implements VO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("日志编号")
private Long id;
/** 日志编号" */
@ExcelProperty("日志编号")
private Long id;
@Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
private String traceId;
/** 链路追踪编号" */
private String traceId;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userName")
private Long userId;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@ExcelProperty("操作人")
private String userName;
/** 用户编号" */
@Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userName")
private Long userId;
@Schema(description = "操作模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
@ExcelProperty("操作模块类型")
private String type;
/** 用户昵称", example = "芋艿 */
@ExcelProperty("操作")
private String userName;
@Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单")
@ExcelProperty("操作")
private String subType;
/** 操作模块类型", example = "订单 */
@ExcelProperty("操作模块类型")
private String type;
@Schema(description = "操作模块业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("操作模块业务编号")
private Long bizId;
/** 操作名", example = "创建订单 */
@ExcelProperty("操作")
private String subType;
@Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
private String action;
/** 操作模块业务编号" */
@ExcelProperty("操作模块业务编号")
private Long bizId;
@Schema(description = "拓展字段", example = "{'orderId': 1}")
private String extra;
/** 操作明细 */
private String action;
@Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET")
@NotEmpty(message = "请求方法名不能为空")
private String requestMethod;
/** 拓展字段 */
private String extra;
@Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy")
private String requestUrl;
/** 请求方法名" */
@NotEmpty(message = "请求方法名不能为空")
private String requestMethod;
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
private String userIp;
/** 请求地址", example = "/xxx/yyy */
private String requestUrl;
@Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0")
private String userAgent;
/** 用户 IP" */
private String userIp;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
/** 浏览器 UserAgent" */
private String userAgent;
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.mail;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.common.util.object.BeanUtils;
@@ -10,19 +9,18 @@ import com.tashow.cloud.system.controller.admin.mail.vo.account.MailAccountSaveR
import com.tashow.cloud.system.controller.admin.mail.vo.account.MailAccountSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.mail.MailAccountDO;
import com.tashow.cloud.system.service.mail.MailAccountService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 邮箱账号")
/**
* 管理后台 - 邮箱账号
*/
@RestController
@RequestMapping("/system/mail-account")
public class MailAccountController {
@@ -30,52 +28,64 @@ public class MailAccountController {
@Resource
private MailAccountService mailAccountService;
/**
* 创建邮箱账号
*/
@PostMapping("/create")
@Operation(summary = "创建邮箱账号")
@PreAuthorize("@ss.hasPermission('system:mail-account:create')")
public CommonResult<Long> createMailAccount(@Valid @RequestBody MailAccountSaveReqVO createReqVO) {
public CommonResult<Long> createMailAccount(
@Valid @RequestBody MailAccountSaveReqVO createReqVO) {
return success(mailAccountService.createMailAccount(createReqVO));
}
/**
* 修改邮箱账号
*/
@PutMapping("/update")
@Operation(summary = "修改邮箱账号")
@PreAuthorize("@ss.hasPermission('system:mail-account:update')")
public CommonResult<Boolean> updateMailAccount(@Valid @RequestBody MailAccountSaveReqVO updateReqVO) {
public CommonResult<Boolean> updateMailAccount(
@Valid @RequestBody MailAccountSaveReqVO updateReqVO) {
mailAccountService.updateMailAccount(updateReqVO);
return success(true);
}
/**
* 删除邮箱账号
*/
@DeleteMapping("/delete")
@Operation(summary = "删除邮箱账号")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:mail-account:delete')")
public CommonResult<Boolean> deleteMailAccount(@RequestParam Long id) {
mailAccountService.deleteMailAccount(id);
return success(true);
}
/**
* 获得邮箱账号
*/
@GetMapping("/get")
@Operation(summary = "获得邮箱账号")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:mail-account:query')")
public CommonResult<MailAccountRespVO> getMailAccount(@RequestParam("id") Long id) {
MailAccountDO account = mailAccountService.getMailAccount(id);
return success(BeanUtils.toBean(account, MailAccountRespVO.class));
}
/**
* 获得邮箱账号分页
*/
@GetMapping("/page")
@Operation(summary = "获得邮箱账号分页")
@PreAuthorize("@ss.hasPermission('system:mail-account:query')")
public CommonResult<PageResult<MailAccountRespVO>> getMailAccountPage(@Valid MailAccountPageReqVO pageReqVO) {
public CommonResult<PageResult<MailAccountRespVO>> getMailAccountPage(
@Valid MailAccountPageReqVO pageReqVO) {
PageResult<MailAccountDO> pageResult = mailAccountService.getMailAccountPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, MailAccountRespVO.class));
}
/**
* 获得邮箱账号精简列表
*/
@GetMapping({"/list-all-simple", "simple-list"})
@Operation(summary = "获得邮箱账号精简列表")
public CommonResult<List<MailAccountSimpleRespVO>> getSimpleMailAccountList() {
List<MailAccountDO> list = mailAccountService.getMailAccountList();
return success(BeanUtils.toBean(list, MailAccountSimpleRespVO.class));
}
}

View File

@@ -7,21 +7,19 @@ import com.tashow.cloud.system.controller.admin.mail.vo.log.MailLogPageReqVO;
import com.tashow.cloud.system.controller.admin.mail.vo.log.MailLogRespVO;
import com.tashow.cloud.system.dal.dataobject.mail.MailLogDO;
import com.tashow.cloud.system.service.mail.MailLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
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 jakarta.annotation.Resource;
import jakarta.validation.Valid;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 邮件日志")
/**
* 管理后台 - 邮件日志
*/
@RestController
@RequestMapping("/system/mail-log")
public class MailLogController {
@@ -29,21 +27,23 @@ public class MailLogController {
@Resource
private MailLogService mailLogService;
/**
* 获得邮箱日志分页
*/
@GetMapping("/page")
@Operation(summary = "获得邮箱日志分页")
@PreAuthorize("@ss.hasPermission('system:mail-log:query')")
public CommonResult<PageResult<MailLogRespVO>> getMailLogPage(@Valid MailLogPageReqVO pageVO) {
PageResult<MailLogDO> pageResult = mailLogService.getMailLogPage(pageVO);
return success(BeanUtils.toBean(pageResult, MailLogRespVO.class));
}
/**
* 获得邮箱日志
*/
@GetMapping("/get")
@Operation(summary = "获得邮箱日志")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:mail-log:query')")
public CommonResult<MailLogRespVO> getMailTemplate(@RequestParam("id") Long id) {
MailLogDO log = mailLogService.getMailLog(id);
return success(BeanUtils.toBean(log, MailLogRespVO.class));
}
}

View File

@@ -7,20 +7,19 @@ import com.tashow.cloud.system.controller.admin.mail.vo.template.*;
import com.tashow.cloud.system.dal.dataobject.mail.MailTemplateDO;
import com.tashow.cloud.system.service.mail.MailSendService;
import com.tashow.cloud.system.service.mail.MailTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 邮件模版")
/**
* 管理后台 - 邮件模版
*/
@RestController
@RequestMapping("/system/mail-template")
public class MailTemplateController {
@@ -30,60 +29,78 @@ public class MailTemplateController {
@Resource
private MailSendService mailSendService;
/**
* 创建邮件模版
*/
@PostMapping("/create")
@Operation(summary = "创建邮件模版")
@PreAuthorize("@ss.hasPermission('system:mail-template:create')")
public CommonResult<Long> createMailTemplate(@Valid @RequestBody MailTemplateSaveReqVO createReqVO){
public CommonResult<Long> createMailTemplate(
@Valid @RequestBody MailTemplateSaveReqVO createReqVO) {
return success(mailTempleService.createMailTemplate(createReqVO));
}
/**
* 修改邮件模版
*/
@PutMapping("/update")
@Operation(summary = "修改邮件模版")
@PreAuthorize("@ss.hasPermission('system:mail-template:update')")
public CommonResult<Boolean> updateMailTemplate(@Valid @RequestBody MailTemplateSaveReqVO updateReqVO){
public CommonResult<Boolean> updateMailTemplate(
@Valid @RequestBody MailTemplateSaveReqVO updateReqVO) {
mailTempleService.updateMailTemplate(updateReqVO);
return success(true);
}
/**
* 删除邮件模版
*/
@DeleteMapping("/delete")
@Operation(summary = "删除邮件模版")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:mail-template:delete')")
public CommonResult<Boolean> deleteMailTemplate(@RequestParam("id") Long id) {
mailTempleService.deleteMailTemplate(id);
return success(true);
}
/**
* 获得邮件模版
*/
@GetMapping("/get")
@Operation(summary = "获得邮件模版")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:mail-template:query')")
public CommonResult<MailTemplateRespVO> getMailTemplate(@RequestParam("id") Long id) {
MailTemplateDO template = mailTempleService.getMailTemplate(id);
return success(BeanUtils.toBean(template, MailTemplateRespVO.class));
}
/**
* 获得邮件模版分页
*/
@GetMapping("/page")
@Operation(summary = "获得邮件模版分页")
@PreAuthorize("@ss.hasPermission('system:mail-template:query')")
public CommonResult<PageResult<MailTemplateRespVO>> getMailTemplatePage(@Valid MailTemplatePageReqVO pageReqVO) {
public CommonResult<PageResult<MailTemplateRespVO>> getMailTemplatePage(
@Valid MailTemplatePageReqVO pageReqVO) {
PageResult<MailTemplateDO> pageResult = mailTempleService.getMailTemplatePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, MailTemplateRespVO.class));
}
/**
* 获得邮件模版精简列表
*/
@GetMapping({"/list-all-simple", "simple-list"})
@Operation(summary = "获得邮件模版精简列表")
public CommonResult<List<MailTemplateSimpleRespVO>> getSimpleTemplateList() {
List<MailTemplateDO> list = mailTempleService.getMailTemplateList();
return success(BeanUtils.toBean(list, MailTemplateSimpleRespVO.class));
}
/**
* 发送短信
*/
@PostMapping("/send-mail")
@Operation(summary = "发送短信")
@PreAuthorize("@ss.hasPermission('system:mail-template:send-mail')")
public CommonResult<Long> sendMail(@Valid @RequestBody MailTemplateSendReqVO sendReqVO) {
return success(mailSendService.sendSingleMailToAdmin(sendReqVO.getMail(), getLoginUserId(),
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
return success(
mailSendService.sendSingleMailToAdmin(
sendReqVO.getMail(),
getLoginUserId(),
sendReqVO.getTemplateCode(),
sendReqVO.getTemplateParams()));
}
}

View File

@@ -1,21 +1,25 @@
package com.tashow.cloud.system.controller.admin.mail.vo.account;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 邮箱账号分页 Request VO")
/**
* 管理后台 - 邮箱账号分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MailAccountPageReqVO extends PageParam {
@Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma@123.com")
/**
* 邮箱"
*/
private String mail;
@Schema(description = "用户名" , requiredMode = Schema.RequiredMode.REQUIRED , example = "yudao")
/**
* 用户名"
*/
private String username;
}

View File

@@ -1,39 +1,57 @@
package com.tashow.cloud.system.controller.admin.mail.vo.account;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 邮箱账号 Response VO")
/**
* 管理后台 - 邮箱账号 Response VO
*/
@Data
public class MailAccountRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 编号"
*/
private Long id;
@Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma@123.com")
/**
* 邮箱"
*/
private String mail;
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
/**
* 用户名"
*/
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
/**
* 密码"
*/
private String password;
@Schema(description = "SMTP 服务器域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "www.iocoder.cn")
/**
* SMTP 服务器域名"
*/
private String host;
@Schema(description = "SMTP 服务器端口", requiredMode = Schema.RequiredMode.REQUIRED, example = "80")
/**
* SMTP 服务器端口"
*/
private Integer port;
@Schema(description = "是否开启 ssl", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
/**
* 是否开启 ssl"
*/
private Boolean sslEnable;
@Schema(description = "是否开启 starttls", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
/**
* 是否开启 starttls"
*/
private Boolean starttlsEnable;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -1,44 +1,42 @@
package com.tashow.cloud.system.controller.admin.mail.vo.account;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 邮箱账号创建/修改 Request VO")
/** 管理后台 - 邮箱账号创建/修改 Request VO */
@Data
public class MailAccountSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
/** 编号 */
private Long id;
@Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma@123.com")
@NotNull(message = "邮箱不能为空")
@Email(message = "必须是 Email 格式")
private String mail;
/** 邮箱" */
@NotNull(message = "邮箱不能为空")
@Email(message = "必须是 Email 格式")
private String mail;
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotNull(message = "用户名不能为空")
private String username;
/** 用户名" */
@NotNull(message = "用户名不能为空")
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@NotNull(message = "密码必填")
private String password;
/** 密码" */
@NotNull(message = "密码必填")
private String password;
@Schema(description = "SMTP 服务器域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "www.iocoder.cn")
@NotNull(message = "SMTP 服务器域名不能为空")
private String host;
/** SMTP 服务器域名" */
@NotNull(message = "SMTP 服务器域名不能为空")
private String host;
@Schema(description = "SMTP 服务器端口", requiredMode = Schema.RequiredMode.REQUIRED, example = "80")
@NotNull(message = "SMTP 服务器端口不能为空")
private Integer port;
/** SMTP 服务器端口" */
@NotNull(message = "SMTP 服务器端口不能为空")
private Integer port;
@Schema(description = "是否开启 ssl", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否开启 ssl 必填")
private Boolean sslEnable;
@Schema(description = "是否开启 starttls", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否开启 starttls 必填")
private Boolean starttlsEnable;
/** 是否开启 ssl" */
@NotNull(message = "是否开启 ssl 必填")
private Boolean sslEnable;
/** 是否开启 starttls" */
@NotNull(message = "是否开启 starttls 必填")
private Boolean starttlsEnable;
}

View File

@@ -1,16 +1,20 @@
package com.tashow.cloud.system.controller.admin.mail.vo.account;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 邮箱账号的精简 Response VO")
/**
* 管理后台 - 邮箱账号的精简 Response VO
*/
@Data
public class MailAccountSimpleRespVO {
@Schema(description = "邮箱编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 邮箱编号"
*/
private Long id;
@Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "768541388@qq.com")
/**
* 邮箱"
*/
private String mail;
}

View File

@@ -1,42 +1,39 @@
package com.tashow.cloud.system.controller.admin.mail.vo.log;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 邮箱日志分页 Request VO")
/** 管理后台 - 邮箱日志分页 Request VO */
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MailLogPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "30883")
private Long userId;
/** 用户编号 */
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2")
private Integer userType;
/** 用户类型,参见 UserTypeEnum 枚举 */
private Integer userType;
@Schema(description = "接收邮箱地址,模糊匹配", example = "76854@qq.com")
private String toMail;
/** 接收邮箱地址,模糊匹配 */
private String toMail;
@Schema(description = "邮箱账号编号", example = "18107")
private Long accountId;
/** 邮箱账号编号 */
private Long accountId;
@Schema(description = "模板编号", example = "5678")
private Long templateId;
/** 模板编号 */
private Long templateId;
@Schema(description = "发送状态,参见 MailSendStatusEnum 枚举", example = "1")
private Integer sendStatus;
@Schema(description = "发送时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] sendTime;
/** 发送状态,参见 MailSendStatusEnum 枚举 */
private Integer sendStatus;
/** 发送时间 */
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] sendTime;
}

View File

@@ -1,64 +1,98 @@
package com.tashow.cloud.system.controller.admin.mail.vo.log;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
@Schema(description = "管理后台 - 邮件日志 Response VO")
/**
* 管理后台 - 邮件日志 Response VO
*/
@Data
public class MailLogRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31020")
/**
* 编号"
*/
private Long id;
@Schema(description = "用户编号", example = "30883")
/**
* 用户编号
*/
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2")
/**
* 用户类型,参见 UserTypeEnum 枚举
*/
private Byte userType;
@Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "76854@qq.com")
/**
* 接收邮箱地址"
*/
private String toMail;
@Schema(description = "邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18107")
/**
* 邮箱账号编号"
*/
private Long accountId;
@Schema(description = "发送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "85757@qq.com")
/**
* 发送邮箱地址"
*/
private String fromMail;
@Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5678")
/**
* 模板编号"
*/
private Long templateId;
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
/**
* 模板编码"
*/
private String templateCode;
@Schema(description = "模版发送人名称", example = "李四")
/**
* 模版发送人名称
*/
private String templateNickname;
@Schema(description = "邮件标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试标题")
/**
* 邮件标题", example = "测试标题
*/
private String templateTitle;
@Schema(description = "邮件内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试内容")
/**
* 邮件内容", example = "测试内容
*/
private String templateContent;
@Schema(description = "邮件参数", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 邮件参数
*/
private Map<String, Object> templateParams;
@Schema(description = "发送状态,参见 MailSendStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 发送状态,参见 MailSendStatusEnum 枚举"
*/
private Byte sendStatus;
@Schema(description = "发送时间")
/**
* 发送时间
*/
private LocalDateTime sendTime;
@Schema(description = "发送返回的消息 ID", example = "28568")
/**
* 发送返回的消息 ID
*/
private String sendMessageId;
@Schema(description = "发送异常")
/**
* 发送异常
*/
private String sendException;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -1,7 +1,6 @@
package com.tashow.cloud.system.controller.admin.mail.vo.template;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -11,26 +10,37 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 邮件模版分页 Request VO")
/**
* 管理后台 - 邮件模版分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MailTemplatePageReqVO extends PageParam {
@Schema(description = "状态,参见 CommonStatusEnum 枚举", example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举
*/
private Integer status;
@Schema(description = "标识,模糊匹配", example = "code_1024")
/**
* 标识,模糊匹配
*/
private String code;
@Schema(description = "名称,模糊匹配", example = "芋头")
/**
* 名称,模糊匹配
*/
private String name;
@Schema(description = "账号编号", example = "2048")
/**
* 账号编号
*/
private Long accountId;
@Schema(description = "创建时间")
/**
* 创建时间
*/
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -1,46 +1,68 @@
package com.tashow.cloud.system.controller.admin.mail.vo.template;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 邮件末班 Response VO")
/**
* 管理后台 - 邮件末班 Response VO
*/
@Data
public class MailTemplateRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 编号"
*/
private Long id;
@Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试名字")
/**
* 模版名称", example = "测试名字
*/
private String name;
@Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
/**
* 模版编号"
*/
private String code;
@Schema(description = "发送的邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 发送的邮箱账号编号"
*/
private Long accountId;
@Schema(description = "发送人名称", example = "芋头")
/**
* 发送人名称
*/
private String nickname;
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "注册成功")
/**
* 标题", example = "注册成功
*/
private String title;
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,注册成功啦")
/**
* 内容", example = "你好,注册成功啦
*/
private String content;
@Schema(description = "参数数组", example = "name,code")
/**
* 参数数组
*/
private List<String> params;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举"
*/
private Integer status;
@Schema(description = "备注", example = "奥特曼")
/**
* 备注
*/
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -1,46 +1,63 @@
package com.tashow.cloud.system.controller.admin.mail.vo.template;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 邮件模版创建/修改 Request VO")
/**
* 管理后台 - 邮件模版创建/修改 Request VO
*/
@Data
public class MailTemplateSaveReqVO {
@Schema(description = "编号", example = "1024")
/**
* 编号
*/
private Long id;
@Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试名字")
/**
* 模版名称", example = "测试名字
*/
@NotNull(message = "名称不能为空")
private String name;
@Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "test")
/**
* 模版编号"
*/
@NotNull(message = "模版编号不能为空")
private String code;
@Schema(description = "发送的邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 发送的邮箱账号编号"
*/
@NotNull(message = "发送的邮箱账号编号不能为空")
private Long accountId;
@Schema(description = "发送人名称", example = "芋头")
/**
* 发送人名称
*/
private String nickname;
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "注册成功")
/**
* 标题", example = "注册成功
*/
@NotEmpty(message = "标题不能为空")
private String title;
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,注册成功啦")
/**
* 内容", example = "你好,注册成功啦
*/
@NotEmpty(message = "内容不能为空")
private String content;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举"
*/
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "备注", example = "奥特曼")
/**
* 备注
*/
private String remark;
}

View File

@@ -1,25 +1,31 @@
package com.tashow.cloud.system.controller.admin.mail.vo.template;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.Map;
@Schema(description = "管理后台 - 邮件发送 Req VO")
/**
* 管理后台 - 邮件发送 Req VO
*/
@Data
public class MailTemplateSendReqVO {
@Schema(description = "接收邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "7685413@qq.com")
/**
* 接收邮箱"
*/
@NotEmpty(message = "接收邮箱不能为空")
private String mail;
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
/**
* 模板编码"
*/
@NotNull(message = "模板编码不能为空")
private String templateCode;
@Schema(description = "模板参数")
/**
* 模板参数
*/
private Map<String, Object> templateParams;
}

View File

@@ -1,16 +1,20 @@
package com.tashow.cloud.system.controller.admin.mail.vo.template;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 邮件模版的精简 Response VO")
/**
* 管理后台 - 邮件模版的精简 Response VO
*/
@Data
public class MailTemplateSimpleRespVO {
@Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 模版编号"
*/
private Long id;
@Schema(description = "模版名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "哒哒哒")
/**
* 模版名字", example = "哒哒哒
*/
private String name;
}

View File

@@ -11,21 +11,17 @@ import com.tashow.cloud.system.controller.admin.notice.vo.NoticeRespVO;
import com.tashow.cloud.system.controller.admin.notice.vo.NoticeSaveReqVO;
import com.tashow.cloud.system.dal.dataobject.notice.NoticeDO;
import com.tashow.cloud.system.service.notice.NoticeService;
import com.tashow.cloud.system.controller.admin.notice.vo.NoticePageReqVO;
import com.tashow.cloud.system.controller.admin.notice.vo.NoticeRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 通知公告")
/**
* 管理后台 - 通知公告
*/
@RestController
@RequestMapping("/system/notice")
@Validated
@@ -37,51 +33,61 @@ public class NoticeController {
@Resource
private WebSocketSenderApi webSocketSenderApi;
/**
* 创建通知公告
*/
@PostMapping("/create")
@Operation(summary = "创建通知公告")
@PreAuthorize("@ss.hasPermission('system:notice:create')")
public CommonResult<Long> createNotice(@Valid @RequestBody NoticeSaveReqVO createReqVO) {
Long noticeId = noticeService.createNotice(createReqVO);
return success(noticeId);
}
/**
* 修改通知公告
*/
@PutMapping("/update")
@Operation(summary = "修改通知公告")
@PreAuthorize("@ss.hasPermission('system:notice:update')")
public CommonResult<Boolean> updateNotice(@Valid @RequestBody NoticeSaveReqVO updateReqVO) {
noticeService.updateNotice(updateReqVO);
return success(true);
}
/**
* 删除通知公告
*/
@DeleteMapping("/delete")
@Operation(summary = "删除通知公告")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:notice:delete')")
public CommonResult<Boolean> deleteNotice(@RequestParam("id") Long id) {
noticeService.deleteNotice(id);
return success(true);
}
/**
* 获取通知公告列表
*/
@GetMapping("/page")
@Operation(summary = "获取通知公告列表")
@PreAuthorize("@ss.hasPermission('system:notice:query')")
public CommonResult<PageResult<NoticeRespVO>> getNoticePage(@Validated NoticePageReqVO pageReqVO) {
public CommonResult<PageResult<NoticeRespVO>> getNoticePage(
@Validated NoticePageReqVO pageReqVO) {
PageResult<NoticeDO> pageResult = noticeService.getNoticePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, NoticeRespVO.class));
}
/**
* 获得通知公告
*/
@GetMapping("/get")
@Operation(summary = "获得通知公告")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:notice:query')")
public CommonResult<NoticeRespVO> getNotice(@RequestParam("id") Long id) {
NoticeDO notice = noticeService.getNotice(id);
return success(BeanUtils.toBean(notice, NoticeRespVO.class));
}
/**
* 推送通知公告"
*/
@PostMapping("/push")
@Operation(summary = "推送通知公告", description = "只发送给 websocket 连接在线的用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:notice:update')")
public CommonResult<Boolean> push(@RequestParam("id") Long id) {
NoticeDO notice = noticeService.getNotice(id);
@@ -90,5 +96,4 @@ public class NoticeController {
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), "notice-push", notice);
return success(true);
}
}

View File

@@ -1,19 +1,17 @@
package com.tashow.cloud.system.controller.admin.notice.vo;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 通知公告分页 Request VO")
/** 管理后台 - 通知公告分页 Request VO */
@Data
@EqualsAndHashCode(callSuper = true)
public class NoticePageReqVO extends PageParam {
@Schema(description = "通知公告名称,模糊匹配", example = "芋道")
private String title;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
/** 通知公告名称,模糊匹配 */
private String title;
/** 展示状态,参见 CommonStatusEnum 枚举类 */
private Integer status;
}

View File

@@ -1,30 +1,42 @@
package com.tashow.cloud.system.controller.admin.notice.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 通知公告信息 Response VO")
/**
* 管理后台 - 通知公告信息 Response VO
*/
@Data
public class NoticeRespVO {
@Schema(description = "通知公告序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 通知公告序号"
*/
private Long id;
@Schema(description = "公告标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主")
/**
* 公告标题", example = "小博主
*/
private String title;
@Schema(description = "公告类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主")
/**
* 公告类型", example = "小博主
*/
private Integer type;
@Schema(description = "公告内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "半生编码")
/**
* 公告内容", example = "半生编码
*/
private String content;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举类"
*/
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
/**
* 创建时间", example = "时间戳格式
*/
private LocalDateTime createTime;
}

View File

@@ -1,32 +1,29 @@
package com.tashow.cloud.system.controller.admin.notice.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 通知公告创建/修改 Request VO")
/** 管理后台 - 通知公告创建/修改 Request VO */
@Data
public class NoticeSaveReqVO {
@Schema(description = "岗位公告编号", example = "1024")
private Long id;
/** 岗位公告编号 */
private Long id;
@Schema(description = "公告标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主")
@NotBlank(message = "公告标题不能为空")
@Size(max = 50, message = "公告标题不能超过50个字符")
private String title;
/** 公告标题", example = "小博主 */
@NotBlank(message = "公告标题不能为空")
@Size(max = 50, message = "公告标题不能超过50个字符")
private String title;
@Schema(description = "公告类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主")
@NotNull(message = "公告类型不能为空")
private Integer type;
/** 公告类型", example = "小博主 */
@NotNull(message = "公告类型不能为空")
private Integer type;
@Schema(description = "公告内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "半生编码")
private String content;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
/** 公告内容", example = "半生编码 */
private String content;
/** 状态,参见 CommonStatusEnum 枚举类" */
private Integer status;
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.notify;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.enums.UserTypeEnum;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult;
@@ -10,24 +9,21 @@ import com.tashow.cloud.system.controller.admin.notify.vo.message.NotifyMessageP
import com.tashow.cloud.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import com.tashow.cloud.system.dal.dataobject.notify.NotifyMessageDO;
import com.tashow.cloud.system.service.notify.NotifyMessageService;
import com.tashow.cloud.system.controller.admin.notify.vo.message.NotifyMessageMyPageReqVO;
import com.tashow.cloud.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO;
import com.tashow.cloud.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 我的站内信")
/**
* 管理后台 - 我的站内信
*/
@RestController
@RequestMapping("/system/notify-message")
@Validated
@@ -38,64 +34,81 @@ public class NotifyMessageController {
// ========== 管理所有的站内信 ==========
/**
* 获得站内信
*/
@GetMapping("/get")
@Operation(summary = "获得站内信")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:notify-message:query')")
public CommonResult<NotifyMessageRespVO> getNotifyMessage(@RequestParam("id") Long id) {
NotifyMessageDO message = notifyMessageService.getNotifyMessage(id);
return success(BeanUtils.toBean(message, NotifyMessageRespVO.class));
}
/**
* 获得站内信分页
*/
@GetMapping("/page")
@Operation(summary = "获得站内信分页")
@PreAuthorize("@ss.hasPermission('system:notify-message:query')")
public CommonResult<PageResult<NotifyMessageRespVO>> getNotifyMessagePage(@Valid NotifyMessagePageReqVO pageVO) {
public CommonResult<PageResult<NotifyMessageRespVO>> getNotifyMessagePage(
@Valid NotifyMessagePageReqVO pageVO) {
PageResult<NotifyMessageDO> pageResult = notifyMessageService.getNotifyMessagePage(pageVO);
return success(BeanUtils.toBean(pageResult, NotifyMessageRespVO.class));
}
// ========== 查看自己的站内信 ==========
/**
* 获得我的站内信分页
*/
@GetMapping("/my-page")
@Operation(summary = "获得我的站内信分页")
public CommonResult<PageResult<NotifyMessageRespVO>> getMyMyNotifyMessagePage(@Valid NotifyMessageMyPageReqVO pageVO) {
PageResult<NotifyMessageDO> pageResult = notifyMessageService.getMyMyNotifyMessagePage(pageVO,
getLoginUserId(), UserTypeEnum.ADMIN.getValue());
public CommonResult<PageResult<NotifyMessageRespVO>> getMyMyNotifyMessagePage(
@Valid NotifyMessageMyPageReqVO pageVO) {
PageResult<NotifyMessageDO> pageResult =
notifyMessageService.getMyMyNotifyMessagePage(
pageVO, getLoginUserId(), UserTypeEnum.ADMIN.getValue());
return success(BeanUtils.toBean(pageResult, NotifyMessageRespVO.class));
}
/**
* 标记站内信为已读
*/
@PutMapping("/update-read")
@Operation(summary = "标记站内信为已读")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
public CommonResult<Boolean> updateNotifyMessageRead(@RequestParam("ids") List<Long> ids) {
notifyMessageService.updateNotifyMessageRead(ids, getLoginUserId(), UserTypeEnum.ADMIN.getValue());
notifyMessageService.updateNotifyMessageRead(
ids, getLoginUserId(), UserTypeEnum.ADMIN.getValue());
return success(Boolean.TRUE);
}
/**
* 标记所有站内信为已读
*/
@PutMapping("/update-all-read")
@Operation(summary = "标记所有站内信为已读")
public CommonResult<Boolean> updateAllNotifyMessageRead() {
notifyMessageService.updateAllNotifyMessageRead(getLoginUserId(), UserTypeEnum.ADMIN.getValue());
notifyMessageService.updateAllNotifyMessageRead(
getLoginUserId(), UserTypeEnum.ADMIN.getValue());
return success(Boolean.TRUE);
}
/**
* 获取当前用户的最新站内信列表,默认 10 条
*/
@GetMapping("/get-unread-list")
@Operation(summary = "获取当前用户的最新站内信列表,默认 10 条")
@Parameter(name = "size", description = "10")
public CommonResult<List<NotifyMessageRespVO>> getUnreadNotifyMessageList(
@RequestParam(name = "size", defaultValue = "10") Integer size) {
List<NotifyMessageDO> list = notifyMessageService.getUnreadNotifyMessageList(
getLoginUserId(), UserTypeEnum.ADMIN.getValue(), size);
List<NotifyMessageDO> list =
notifyMessageService.getUnreadNotifyMessageList(
getLoginUserId(), UserTypeEnum.ADMIN.getValue(), size);
return success(BeanUtils.toBean(list, NotifyMessageRespVO.class));
}
/**
* 获得当前用户的未读站内信数量
*/
@GetMapping("/get-unread-count")
@Operation(summary = "获得当前用户的未读站内信数量")
@ApiAccessLog(enable = false) // 由于前端会不断轮询该接口,记录日志没有意义
public CommonResult<Long> getUnreadNotifyMessageCount() {
return success(notifyMessageService.getUnreadNotifyMessageCount(
getLoginUserId(), UserTypeEnum.ADMIN.getValue()));
return success(
notifyMessageService.getUnreadNotifyMessageCount(
getLoginUserId(), UserTypeEnum.ADMIN.getValue()));
}
}

View File

@@ -11,19 +11,17 @@ import com.tashow.cloud.system.controller.admin.notify.vo.template.NotifyTemplat
import com.tashow.cloud.system.dal.dataobject.notify.NotifyTemplateDO;
import com.tashow.cloud.system.service.notify.NotifySendService;
import com.tashow.cloud.system.service.notify.NotifyTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 站内信模版")
/**
* 管理后台 - 站内信模版
*/
@RestController
@RequestMapping("/system/notify-template")
@Validated
@@ -35,57 +33,72 @@ public class NotifyTemplateController {
@Resource
private NotifySendService notifySendService;
/**
* 创建站内信模版
*/
@PostMapping("/create")
@Operation(summary = "创建站内信模版")
@PreAuthorize("@ss.hasPermission('system:notify-template:create')")
public CommonResult<Long> createNotifyTemplate(@Valid @RequestBody NotifyTemplateSaveReqVO createReqVO) {
public CommonResult<Long> createNotifyTemplate(
@Valid @RequestBody NotifyTemplateSaveReqVO createReqVO) {
return success(notifyTemplateService.createNotifyTemplate(createReqVO));
}
/**
* 更新站内信模版
*/
@PutMapping("/update")
@Operation(summary = "更新站内信模版")
@PreAuthorize("@ss.hasPermission('system:notify-template:update')")
public CommonResult<Boolean> updateNotifyTemplate(@Valid @RequestBody NotifyTemplateSaveReqVO updateReqVO) {
public CommonResult<Boolean> updateNotifyTemplate(
@Valid @RequestBody NotifyTemplateSaveReqVO updateReqVO) {
notifyTemplateService.updateNotifyTemplate(updateReqVO);
return success(true);
}
/**
* 删除站内信模版
*/
@DeleteMapping("/delete")
@Operation(summary = "删除站内信模版")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:notify-template:delete')")
public CommonResult<Boolean> deleteNotifyTemplate(@RequestParam("id") Long id) {
notifyTemplateService.deleteNotifyTemplate(id);
return success(true);
}
/**
* 获得站内信模版
*/
@GetMapping("/get")
@Operation(summary = "获得站内信模版")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:notify-template:query')")
public CommonResult<NotifyTemplateRespVO> getNotifyTemplate(@RequestParam("id") Long id) {
NotifyTemplateDO template = notifyTemplateService.getNotifyTemplate(id);
return success(BeanUtils.toBean(template, NotifyTemplateRespVO.class));
}
/**
* 获得站内信模版分页
*/
@GetMapping("/page")
@Operation(summary = "获得站内信模版分页")
@PreAuthorize("@ss.hasPermission('system:notify-template:query')")
public CommonResult<PageResult<NotifyTemplateRespVO>> getNotifyTemplatePage(@Valid NotifyTemplatePageReqVO pageVO) {
public CommonResult<PageResult<NotifyTemplateRespVO>> getNotifyTemplatePage(
@Valid NotifyTemplatePageReqVO pageVO) {
PageResult<NotifyTemplateDO> pageResult = notifyTemplateService.getNotifyTemplatePage(pageVO);
return success(BeanUtils.toBean(pageResult, NotifyTemplateRespVO.class));
}
/**
* 发送站内信
*/
@PostMapping("/send-notify")
@Operation(summary = "发送站内信")
@PreAuthorize("@ss.hasPermission('system:notify-template:send-notify')")
public CommonResult<Long> sendNotify(@Valid @RequestBody NotifyTemplateSendReqVO sendReqVO) {
if (UserTypeEnum.MEMBER.getValue().equals(sendReqVO.getUserType())) {
return success(notifySendService.sendSingleNotifyToMember(sendReqVO.getUserId(),
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
return success(
notifySendService.sendSingleNotifyToMember(
sendReqVO.getUserId(), sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
} else {
return success(notifySendService.sendSingleNotifyToAdmin(sendReqVO.getUserId(),
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
return success(
notifySendService.sendSingleNotifyToAdmin(
sendReqVO.getUserId(), sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
}
}
}

View File

@@ -1,7 +1,7 @@
package com.tashow.cloud.system.controller.admin.notify.vo.message;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -11,16 +11,22 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 站内信分页 Request VO")
/**
* 管理后台 - 站内信分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class NotifyMessageMyPageReqVO extends PageParam {
@Schema(description = "是否已读", example = "true")
/**
* 是否已读
*/
private Boolean readStatus;
@Schema(description = "创建时间")
/**
* 创建时间
*/
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@@ -1,7 +1,7 @@
package com.tashow.cloud.system.controller.admin.notify.vo.message;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -11,25 +11,37 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 站内信分页 Request VO")
/**
* 管理后台 - 站内信分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class NotifyMessagePageReqVO extends PageParam {
@Schema(description = "用户编号", example = "25025")
/**
* 用户编号
*/
private Long userId;
@Schema(description = "用户类型", example = "1")
/**
* 用户类型
*/
private Integer userType;
@Schema(description = "模板编码", example = "test_01")
/**
* 模板编码
*/
private String templateCode;
@Schema(description = "模版类型", example = "2")
/**
* 模版类型
*/
private Integer templateType;
@Schema(description = "创建时间")
/**
* 创建时间
*/
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@@ -1,49 +1,50 @@
package com.tashow.cloud.system.controller.admin.notify.vo.message;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
import lombok.Data;
@Schema(description = "管理后台 - 站内信 Response VO")
/** 管理后台 - 站内信 Response VO */
@Data
public class NotifyMessageRespVO {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/** ID" */
private Long id;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25025")
private Long userId;
/** 用户编号" */
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Byte userType;
/** 用户类型,参见 UserTypeEnum 枚举" */
private Byte userType;
@Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13013")
private Long templateId;
/** 模版编号" */
private Long templateId;
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
private String templateCode;
/** 模板编码" */
private String templateCode;
@Schema(description = "模版发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String templateNickname;
/** 模版发送人名称", example = "芋艿 */
private String templateNickname;
@Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试内容")
private String templateContent;
/** 模版内容", example = "测试内容 */
private String templateContent;
@Schema(description = "模版类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer templateType;
/** 模版类型" */
private Integer templateType;
@Schema(description = "模版参数", requiredMode = Schema.RequiredMode.REQUIRED)
private Map<String, Object> templateParams;
/**
* 模版参数
*/
private Map<String, Object> templateParams;
@Schema(description = "是否已读", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean readStatus;
/** 是否已读" */
private Boolean readStatus;
@Schema(description = "阅读时间")
private LocalDateTime readTime;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
/** 阅读时间 */
private LocalDateTime readTime;
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -1,7 +1,7 @@
package com.tashow.cloud.system.controller.admin.notify.vo.template;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -11,22 +11,32 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 站内信模版分页 Request VO")
/**
* 管理后台 - 站内信模版分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class NotifyTemplatePageReqVO extends PageParam {
@Schema(description = "模版编码", example = "test_01")
/**
* 模版编码
*/
private String code;
@Schema(description = "模版名称", example = "我是名称")
/**
* 模版名称
*/
private String name;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举类
*/
private Integer status;
@Schema(description = "创建时间")
/**
* 创建时间
*/
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;

View File

@@ -1,43 +1,42 @@
package com.tashow.cloud.system.controller.admin.notify.vo.template;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
@Schema(description = "管理后台 - 站内信模版 Response VO")
/** 管理后台 - 站内信模版 Response VO */
@Data
public class NotifyTemplateRespVO {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/** ID" */
private Long id;
@Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版")
private String name;
/** 模版名称", example = "测试模版 */
private String name;
@Schema(description = "模版编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SEND_TEST")
private String code;
/** 模版编码" */
private String code;
@Schema(description = "模版类型,对应 system_notify_template_type 字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
/** 模版类型,对应 system_notify_template_type 字典" */
private Integer type;
@Schema(description = "发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆")
private String nickname;
/** 发送人名称", example = "土豆 */
private String nickname;
@Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是模版内容")
private String content;
/** 模版内容", example = "我是模版内容 */
private String content;
@Schema(description = "参数数组", example = "name,code")
private List<String> params;
/** 参数数组 */
private List<String> params;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
/** 状态,参见 CommonStatusEnum 枚举" */
private Integer status;
@Schema(description = "备注", example = "我是备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
/** 备注 */
private String remark;
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -2,45 +2,63 @@ package com.tashow.cloud.system.controller.admin.notify.vo.template;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
@Schema(description = "管理后台 - 站内信模版创建/修改 Request VO")
/**
* 管理后台 - 站内信模版创建/修改 Request VO
*/
@Data
public class NotifyTemplateSaveReqVO {
@Schema(description = "ID", example = "1024")
/**
* ID
*/
private Long id;
@Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版")
/**
* 模版名称", example = "测试模版
*/
@NotEmpty(message = "模版名称不能为空")
private String name;
@Schema(description = "模版编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SEND_TEST")
/**
* 模版编码"
*/
@NotNull(message = "模版编码不能为空")
private String code;
@Schema(description = "模版类型,对应 system_notify_template_type 字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 模版类型,对应 system_notify_template_type 字典"
*/
@NotNull(message = "模版类型不能为空")
private Integer type;
@Schema(description = "发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆")
/**
* 发送人名称", example = "土豆
*/
@NotEmpty(message = "发送人名称不能为空")
private String nickname;
@Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是模版内容")
/**
* 模版内容", example = "我是模版内容
*/
@NotEmpty(message = "模版内容不能为空")
private String content;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举"
*/
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
@Schema(description = "备注", example = "我是备注")
/**
* 备注
*/
private String remark;
}

View File

@@ -1,29 +1,39 @@
package com.tashow.cloud.system.controller.admin.notify.vo.template;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.Map;
@Schema(description = "管理后台 - 站内信模板的发送 Request VO")
/**
* 管理后台 - 站内信模板的发送 Request VO
*/
@Data
public class NotifyTemplateSendReqVO {
@Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "01")
/**
* 用户id"
*/
@NotNull(message = "用户id不能为空")
private Long userId;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 用户类型"
*/
@NotNull(message = "用户类型不能为空")
private Integer userType;
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "01")
/**
* 模板编码"
*/
@NotEmpty(message = "模板编码不能为空")
private String templateCode;
@Schema(description = "模板参数")
/**
* 模板参数
*/
private Map<String, Object> templateParams;
}

View File

@@ -8,20 +8,17 @@ import com.tashow.cloud.system.controller.admin.oauth2.vo.client.OAuth2ClientRes
import com.tashow.cloud.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO;
import com.tashow.cloud.system.dal.dataobject.oauth2.OAuth2ClientDO;
import com.tashow.cloud.system.service.oauth2.OAuth2ClientService;
import com.tashow.cloud.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - OAuth2 客户端")
/**
* 管理后台 - OAuth2 客户端
*/
@RestController
@RequestMapping("/system/oauth2-client")
@Validated
@@ -30,45 +27,55 @@ public class OAuth2ClientController {
@Resource
private OAuth2ClientService oAuth2ClientService;
/**
* 创建 OAuth2 客户端
*/
@PostMapping("/create")
@Operation(summary = "创建 OAuth2 客户端")
@PreAuthorize("@ss.hasPermission('system:oauth2-client:create')")
public CommonResult<Long> createOAuth2Client(@Valid @RequestBody OAuth2ClientSaveReqVO createReqVO) {
public CommonResult<Long> createOAuth2Client(
@Valid @RequestBody OAuth2ClientSaveReqVO createReqVO) {
return success(oAuth2ClientService.createOAuth2Client(createReqVO));
}
/**
* 更新 OAuth2 客户端
*/
@PutMapping("/update")
@Operation(summary = "更新 OAuth2 客户端")
@PreAuthorize("@ss.hasPermission('system:oauth2-client:update')")
public CommonResult<Boolean> updateOAuth2Client(@Valid @RequestBody OAuth2ClientSaveReqVO updateReqVO) {
public CommonResult<Boolean> updateOAuth2Client(
@Valid @RequestBody OAuth2ClientSaveReqVO updateReqVO) {
oAuth2ClientService.updateOAuth2Client(updateReqVO);
return success(true);
}
/**
* 删除 OAuth2 客户端
*/
@DeleteMapping("/delete")
@Operation(summary = "删除 OAuth2 客户端")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:oauth2-client:delete')")
public CommonResult<Boolean> deleteOAuth2Client(@RequestParam("id") Long id) {
oAuth2ClientService.deleteOAuth2Client(id);
return success(true);
}
/**
* 获得 OAuth2 客户端
*/
@GetMapping("/get")
@Operation(summary = "获得 OAuth2 客户端")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:oauth2-client:query')")
public CommonResult<OAuth2ClientRespVO> getOAuth2Client(@RequestParam("id") Long id) {
OAuth2ClientDO client = oAuth2ClientService.getOAuth2Client(id);
return success(BeanUtils.toBean(client, OAuth2ClientRespVO.class));
}
/**
* 获得 OAuth2 客户端分页
*/
@GetMapping("/page")
@Operation(summary = "获得 OAuth2 客户端分页")
@PreAuthorize("@ss.hasPermission('system:oauth2-client:query')")
public CommonResult<PageResult<OAuth2ClientRespVO>> getOAuth2ClientPage(@Valid OAuth2ClientPageReqVO pageVO) {
public CommonResult<PageResult<OAuth2ClientRespVO>> getOAuth2ClientPage(
@Valid OAuth2ClientPageReqVO pageVO) {
PageResult<OAuth2ClientDO> pageResult = oAuth2ClientService.getOAuth2ClientPage(pageVO);
return success(BeanUtils.toBean(pageResult, OAuth2ClientRespVO.class));
}
}

View File

@@ -15,24 +15,19 @@ import com.tashow.cloud.system.convert.oauth2.OAuth2OpenConvert;
import com.tashow.cloud.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.tashow.cloud.system.dal.dataobject.oauth2.OAuth2ApproveDO;
import com.tashow.cloud.system.dal.dataobject.oauth2.OAuth2ClientDO;
import com.tashow.cloud.systemapi.enums.oauth2.OAuth2GrantTypeEnum;
import com.tashow.cloud.system.service.oauth2.OAuth2ApproveService;
import com.tashow.cloud.system.service.oauth2.OAuth2ClientService;
import com.tashow.cloud.system.service.oauth2.OAuth2GrantService;
import com.tashow.cloud.system.service.oauth2.OAuth2TokenService;
import com.tashow.cloud.system.util.oauth2.OAuth2Utils;
import com.tashow.cloud.systemapi.enums.oauth2.OAuth2GrantTypeEnum;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -46,16 +41,20 @@ import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserI
/**
* 提供给外部应用调用为主
*
* 一般来说,管理后台的 /system-api/* 是不直接提供给外部应用使用,主要是外部应用能够访问的数据与接口是有限的,而管理后台的 RBAC 无法很好的控制。
* <p>一般来说,管理后台的 /system-api/* 是不直接提供给外部应用使用,主要是外部应用能够访问的数据与接口是有限的,而管理后台的 RBAC 无法很好的控制。
* 参考大量的开放平台,都是独立的一套 OpenAPI对应到【本系统】就是在 Controller 下新建 open 包,实现 /open-api/* 接口,然后通过 scope 进行控制。
* 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id 产生信任授权。
* 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id
* 产生信任授权。
*
* 考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。
* scope 的使用示例,可见 {@link OAuth2UserController} 类
* <p>考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。
* scope 的使用示例,可见 {@link com.tashow.cloud.system.controller.admin.oauth2.OAuth2UserController} 类
*
* @author 芋道源码
*/
@Tag(name = "管理后台 - OAuth2.0 授权")
/**
* 管理后台 - OAuth2.0 授权
*/
@RestController
@RequestMapping("/system/oauth2")
@Validated
@@ -74,36 +73,27 @@ public class OAuth2OpenController {
/**
* 对应 Spring Security OAuth 的 TokenEndpoint 类的 postAccessToken 方法
*
* 授权码 authorization_code 模式时code + redirectUri + state 参数
* 密码 password 模式时username + password + scope 参数
* 刷新 refresh_token 模式时refreshToken 参数
* 客户端 client_credentials 模式scope 参数
* 简化 implicit 模式时:不支持
* <p>授权码 authorization_code 模式时code + redirectUri + state 参数 密码 password 模式时username + password
* + scope 参数 刷新 refresh_token 模式时refreshToken 参数 客户端 client_credentials 模式scope 参数 简化 implicit
* 模式时:不支持
*
* 注意,默认需要传递 client_id + client_secret 参数
* <p>注意,默认需要传递 client_id + client_secret 参数
*/
/**
* 获得访问令牌", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用
*/
@PostMapping("/token")
@PermitAll
@Operation(summary = "获得访问令牌", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
@Parameters({
@Parameter(name = "grant_type", required = true, description = "授权类型", example = "code"),
@Parameter(name = "code", description = "授权范围", example = "userinfo.read"),
@Parameter(name = "redirect_uri", description = "重定向 URI", example = "https://www.iocoder.cn"),
@Parameter(name = "state", description = "状态", example = "1"),
@Parameter(name = "username", example = "tudou"),
@Parameter(name = "password", example = "cai"), // 多个使用空格分隔
@Parameter(name = "scope", example = "user_info"),
@Parameter(name = "refresh_token", example = "123424233"),
})
public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request,
@RequestParam("grant_type") String grantType,
@RequestParam(value = "code", required = false) String code, // 授权码模式
@RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式
@RequestParam(value = "state", required = false) String state, // 授权码模式
@RequestParam(value = "username", required = false) String username, // 密码模式
@RequestParam(value = "password", required = false) String password, // 密码模式
@RequestParam(value = "scope", required = false) String scope, // 密码模式
@RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式
public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(
HttpServletRequest request,
@RequestParam("grant_type") String grantType,
@RequestParam(value = "code", required = false) String code, // 授权码模式
@RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式
@RequestParam(value = "state", required = false) String state, // 授权码模式
@RequestParam(value = "username", required = false) String username, // 密码模式
@RequestParam(value = "password", required = false) String password, // 密码模式
@RequestParam(value = "scope", required = false) String scope, // 密码模式
@RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式
List<String> scopes = OAuth2Utils.buildScopes(scope);
// 1.1 校验授权类型
OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGrantType(grantType);
@@ -116,17 +106,21 @@ public class OAuth2OpenController {
// 1.2 校验客户端
String[] clientIdAndSecret = obtainBasicAuthorization(request);
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
grantType, scopes, redirectUri);
OAuth2ClientDO client =
oauth2ClientService.validOAuthClientFromCache(
clientIdAndSecret[0], clientIdAndSecret[1], grantType, scopes, redirectUri);
// 2. 根据授权模式,获取访问令牌
OAuth2AccessTokenDO accessTokenDO;
switch (grantTypeEnum) {
case AUTHORIZATION_CODE:
accessTokenDO = oauth2GrantService.grantAuthorizationCodeForAccessToken(client.getClientId(), code, redirectUri, state);
accessTokenDO =
oauth2GrantService.grantAuthorizationCodeForAccessToken(
client.getClientId(), code, redirectUri, state);
break;
case PASSWORD:
accessTokenDO = oauth2GrantService.grantPassword(username, password, client.getClientId(), scopes);
accessTokenDO =
oauth2GrantService.grantPassword(username, password, client.getClientId(), scopes);
break;
case CLIENT_CREDENTIALS:
accessTokenDO = oauth2GrantService.grantClientCredentials(client.getClientId(), scopes);
@@ -141,34 +135,35 @@ public class OAuth2OpenController {
return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
}
/**
* 删除访问令牌
*/
@DeleteMapping("/token")
@PermitAll
@Operation(summary = "删除访问令牌")
@Parameter(name = "token", required = true, description = "访问令牌", example = "biu")
public CommonResult<Boolean> revokeToken(HttpServletRequest request,
@RequestParam("token") String token) {
public CommonResult<Boolean> revokeToken(
HttpServletRequest request, @RequestParam("token") String token) {
// 校验客户端
String[] clientIdAndSecret = obtainBasicAuthorization(request);
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
null, null, null);
OAuth2ClientDO client =
oauth2ClientService.validOAuthClientFromCache(
clientIdAndSecret[0], clientIdAndSecret[1], null, null, null);
// 删除访问令牌
return success(oauth2GrantService.revokeToken(client.getClientId(), token));
}
/** 校验访问令牌 */
/**
* 对应 Spring Security OAuth 的 CheckTokenEndpoint 类的 checkToken 方法
*/
@PostMapping("/check-token")
@PermitAll
@Operation(summary = "校验访问令牌")
@Parameter(name = "token", required = true, description = "访问令牌", example = "biu")
public CommonResult<OAuth2OpenCheckTokenRespVO> checkToken(HttpServletRequest request,
@RequestParam("token") String token) {
public CommonResult<OAuth2OpenCheckTokenRespVO> checkToken(
HttpServletRequest request, @RequestParam("token") String token) {
// 校验客户端
String[] clientIdAndSecret = obtainBasicAuthorization(request);
oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
null, null, null);
oauth2ClientService.validOAuthClientFromCache(
clientIdAndSecret[0], clientIdAndSecret[1], null, null, null);
// 校验令牌
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.checkAccessToken(token);
@@ -176,19 +171,20 @@ public class OAuth2OpenController {
return success(OAuth2OpenConvert.INSTANCE.convert2(accessTokenDO));
}
/** 获得授权信息", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用 */
/**
* 对应 Spring Security OAuth 的 AuthorizationEndpoint 类的 authorize 方法
*/
@GetMapping("/authorize")
@Operation(summary = "获得授权信息", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
@Parameter(name = "clientId", required = true, description = "客户端编号", example = "tudou")
public CommonResult<OAuth2OpenAuthorizeInfoRespVO> authorize(@RequestParam("clientId") String clientId) {
public CommonResult<OAuth2OpenAuthorizeInfoRespVO> authorize(
@RequestParam("clientId") String clientId) {
// 0. 校验用户已经登录。通过 Spring Security 实现
// 1. 获得 Client 客户端的信息
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId);
// 2. 获得用户已经授权的信息
List<OAuth2ApproveDO> approves = oauth2ApproveService.getApproveList(getLoginUserId(), getUserType(), clientId);
List<OAuth2ApproveDO> approves =
oauth2ApproveService.getApproveList(getLoginUserId(), getUserType(), clientId);
// 拼接返回
return success(OAuth2OpenConvert.INSTANCE.convert(client, approves));
}
@@ -196,29 +192,23 @@ public class OAuth2OpenController {
/**
* 对应 Spring Security OAuth 的 AuthorizationEndpoint 类的 approveOrDeny 方法
*
* 场景一:【自动授权 autoApprove = true】
* 刚进入 sso.vue 界面,调用该接口,用户历史已经给该应用做过对应的授权,或者 OAuth2Client 支持该 scope 的自动授权
* 场景二:【手动授权 autoApprove = false
* 在 sso.vue 界面,用户选择好 scope 授权范围调用该接口进行授权。此时approved 为 true 或者 false
* <p>场景一:【自动授权 autoApprove = true】 刚进入 sso.vue 界面,调用该接口,用户历史已经给该应用做过对应的授权,或者 OAuth2Client 支持该
* scope 的自动授权 场景二:【手动授权 autoApprove = false】 在 sso.vue 界面,用户选择好 scope 授权范围调用该接口进行授权。此时approved
* 为 true 或者 false
*
* 因为前后端分离Axios 无法很好的处理 302 重定向,所以和 Spring Security OAuth 略有不同,返回结果是重定向的 URL剩余交给前端处理
* <p>因为前后端分离Axios 无法很好的处理 302 重定向,所以和 Spring Security OAuth 略有不同,返回结果是重定向的 URL剩余交给前端处理
*/
/**
* 申请授权", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【提交】调用
*/
@PostMapping("/authorize")
@Operation(summary = "申请授权", description = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【提交】调用")
@Parameters({
@Parameter(name = "response_type", required = true, description = "响应类型", example = "code"),
@Parameter(name = "client_id", required = true, description = "客户端编号", example = "tudou"),
@Parameter(name = "scope", description = "授权范围", example = "userinfo.read"), // 使用 Map<String, Boolean> 格式Spring MVC 暂时不支持这么接收参数
@Parameter(name = "redirect_uri", required = true, description = "重定向 URI", example = "https://www.iocoder.cn"),
@Parameter(name = "auto_approve", required = true, description = "用户是否接受", example = "true"),
@Parameter(name = "state", example = "1")
})
public CommonResult<String> approveOrDeny(@RequestParam("response_type") String responseType,
@RequestParam("client_id") String clientId,
@RequestParam(value = "scope", required = false) String scope,
@RequestParam("redirect_uri") String redirectUri,
@RequestParam(value = "auto_approve") Boolean autoApprove,
@RequestParam(value = "state", required = false) String state) {
public CommonResult<String> approveOrDeny(
@RequestParam("response_type") String responseType,
@RequestParam("client_id") String clientId,
@RequestParam(value = "scope", required = false) String scope,
@RequestParam("redirect_uri") String redirectUri,
@RequestParam(value = "auto_approve") Boolean autoApprove,
@RequestParam(value = "state", required = false) String state) {
@SuppressWarnings("unchecked")
Map<String, Boolean> scopes = JsonUtils.parseObject(scope, Map.class);
scopes = ObjectUtil.defaultIfNull(scopes, Collections.emptyMap());
@@ -227,30 +217,38 @@ public class OAuth2OpenController {
// 1.1 校验 responseType 是否满足 code 或者 token 值
OAuth2GrantTypeEnum grantTypeEnum = getGrantTypeEnum(responseType);
// 1.2 校验 redirectUri 重定向域名是否合法 + 校验 scope 是否在 Client 授权范围内
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, null,
grantTypeEnum.getGrantType(), scopes.keySet(), redirectUri);
OAuth2ClientDO client =
oauth2ClientService.validOAuthClientFromCache(
clientId, null, grantTypeEnum.getGrantType(), scopes.keySet(), redirectUri);
// 2.1 假设 approved 为 null说明是场景一
if (Boolean.TRUE.equals(autoApprove)) {
// 如果无法自动授权通过,则返回空 url前端不进行跳转
if (!oauth2ApproveService.checkForPreApproval(getLoginUserId(), getUserType(), clientId, scopes.keySet())) {
if (!oauth2ApproveService.checkForPreApproval(
getLoginUserId(), getUserType(), clientId, scopes.keySet())) {
return success(null);
}
} else { // 2.2 假设 approved 非 null说明是场景二
// 如果计算后不通过,则跳转一个错误链接
if (!oauth2ApproveService.updateAfterApproval(getLoginUserId(), getUserType(), clientId, scopes)) {
return success(OAuth2Utils.buildUnsuccessfulRedirect(redirectUri, responseType, state,
"access_denied", "User denied access"));
if (!oauth2ApproveService.updateAfterApproval(
getLoginUserId(), getUserType(), clientId, scopes)) {
return success(
OAuth2Utils.buildUnsuccessfulRedirect(
redirectUri, responseType, state, "access_denied", "User denied access"));
}
}
// 3.1 如果是 code 授权码模式,则发放 code 授权码,并重定向
List<String> approveScopes = convertList(scopes.entrySet(), Map.Entry::getKey, Map.Entry::getValue);
List<String> approveScopes =
convertList(scopes.entrySet(), Map.Entry::getKey, Map.Entry::getValue);
if (grantTypeEnum == OAuth2GrantTypeEnum.AUTHORIZATION_CODE) {
return success(getAuthorizationCodeRedirect(getLoginUserId(), client, approveScopes, redirectUri, state));
return success(
getAuthorizationCodeRedirect(
getLoginUserId(), client, approveScopes, redirectUri, state));
}
// 3.2 如果是 token 则是 implicit 简化模式,则发送 accessToken 访问令牌,并重定向
return success(getImplicitGrantRedirect(getLoginUserId(), client, approveScopes, redirectUri, state));
return success(
getImplicitGrantRedirect(getLoginUserId(), client, approveScopes, redirectUri, state));
}
private static OAuth2GrantTypeEnum getGrantTypeEnum(String responseType) {
@@ -263,22 +261,29 @@ public class OAuth2OpenController {
throw exception0(BAD_REQUEST.getCode(), "response_type 参数值只允许 code 和 token");
}
private String getImplicitGrantRedirect(Long userId, OAuth2ClientDO client,
List<String> scopes, String redirectUri, String state) {
private String getImplicitGrantRedirect(
Long userId, OAuth2ClientDO client, List<String> scopes, String redirectUri, String state) {
// 1. 创建 access token 访问令牌
OAuth2AccessTokenDO accessTokenDO = oauth2GrantService.grantImplicit(userId, getUserType(), client.getClientId(), scopes);
OAuth2AccessTokenDO accessTokenDO =
oauth2GrantService.grantImplicit(userId, getUserType(), client.getClientId(), scopes);
Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
// 2. 拼接重定向的 URL
// noinspection unchecked
return OAuth2Utils.buildImplicitRedirectUri(redirectUri, accessTokenDO.getAccessToken(), state, accessTokenDO.getExpiresTime(),
scopes, JsonUtils.parseObject(client.getAdditionalInformation(), Map.class));
return OAuth2Utils.buildImplicitRedirectUri(
redirectUri,
accessTokenDO.getAccessToken(),
state,
accessTokenDO.getExpiresTime(),
scopes,
JsonUtils.parseObject(client.getAdditionalInformation(), Map.class));
}
private String getAuthorizationCodeRedirect(Long userId, OAuth2ClientDO client,
List<String> scopes, String redirectUri, String state) {
private String getAuthorizationCodeRedirect(
Long userId, OAuth2ClientDO client, List<String> scopes, String redirectUri, String state) {
// 1. 创建 code 授权码
String authorizationCode = oauth2GrantService.grantAuthorizationCodeForCode(userId, getUserType(), client.getClientId(), scopes,
redirectUri, state);
String authorizationCode =
oauth2GrantService.grantAuthorizationCodeForCode(
userId, getUserType(), client.getClientId(), scopes, redirectUri, state);
// 2. 拼接重定向的 URL
return OAuth2Utils.buildAuthorizationCodeRedirectUri(redirectUri, authorizationCode, state);
}
@@ -294,5 +299,4 @@ public class OAuth2OpenController {
}
return clientIdAndSecret;
}
}

View File

@@ -6,22 +6,19 @@ import com.tashow.cloud.common.util.object.BeanUtils;
import com.tashow.cloud.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
import com.tashow.cloud.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenRespVO;
import com.tashow.cloud.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.tashow.cloud.systemapi.enums.logger.LoginLogTypeEnum;
import com.tashow.cloud.system.service.auth.AdminAuthService;
import com.tashow.cloud.system.service.oauth2.OAuth2TokenService;
import com.tashow.cloud.systemapi.enums.logger.LoginLogTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - OAuth2.0 令牌")
/**
* 管理后台 - OAuth2.0 令牌
*/
@RestController
@RequestMapping("/system/oauth2-token")
public class OAuth2TokenController {
@@ -31,21 +28,24 @@ public class OAuth2TokenController {
@Resource
private AdminAuthService authService;
/**
* 获得访问令牌分页", description = "只返回有效期内的
*/
@GetMapping("/page")
@Operation(summary = "获得访问令牌分页", description = "只返回有效期内的")
@PreAuthorize("@ss.hasPermission('system:oauth2-token:page')")
public CommonResult<PageResult<OAuth2AccessTokenRespVO>> getAccessTokenPage(@Valid OAuth2AccessTokenPageReqVO reqVO) {
public CommonResult<PageResult<OAuth2AccessTokenRespVO>> getAccessTokenPage(
@Valid OAuth2AccessTokenPageReqVO reqVO) {
PageResult<OAuth2AccessTokenDO> pageResult = oauth2TokenService.getAccessTokenPage(reqVO);
return success(BeanUtils.toBean(pageResult, OAuth2AccessTokenRespVO.class));
}
/**
* 删除访问令牌
*/
@DeleteMapping("/delete")
@Operation(summary = "删除访问令牌")
@Parameter(name = "accessToken", description = "访问令牌", required = true, example = "tudou")
@PreAuthorize("@ss.hasPermission('system:oauth2-token:delete')")
public CommonResult<Boolean> deleteAccessToken(@RequestParam("accessToken") String accessToken) {
authService.logout(accessToken, LoginLogTypeEnum.LOGOUT_DELETE.getType());
return success(true);
}
}

View File

@@ -12,16 +12,13 @@ import com.tashow.cloud.system.dal.dataobject.user.AdminUserDO;
import com.tashow.cloud.system.service.dept.DeptService;
import com.tashow.cloud.system.service.dept.PostService;
import com.tashow.cloud.system.service.user.AdminUserService;
import com.tashow.cloud.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@@ -30,12 +27,16 @@ import static com.tashow.cloud.web.web.core.util.WebFrameworkUtils.getLoginUserI
/**
* 提供给外部应用调用为主
*
* 1. 在 getUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.read')") 注解,声明需要满足 scope = user.read
* 2. 在 updateUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.write')") 注解,声明需要满足 scope = user.write
* <p>1. 在 getUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.read')") 注解,声明需要满足 scope = user.read
* 2. 在 updateUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.write')") 注解,声明需要满足 scope =
* user.write
*
* @author 芋道源码
*/
@Tag(name = "管理后台 - OAuth2.0 用户")
/**
* 管理后台 - OAuth2.0 用户
*/
@RestController
@RequestMapping("/system/oauth2/user")
@Validated
@@ -49,8 +50,10 @@ public class OAuth2UserController {
@Resource
private PostService postService;
/**
* 获得用户基本信息
*/
@GetMapping("/get")
@Operation(summary = "获得用户基本信息")
@PreAuthorize("@ss.hasScope('user.read')") //
public CommonResult<OAuth2UserInfoRespVO> getUserInfo() {
// 获得用户基本信息
@@ -69,14 +72,16 @@ public class OAuth2UserController {
return success(resp);
}
/**
* 更新用户基本信息
*/
@PutMapping("/update")
@Operation(summary = "更新用户基本信息")
@PreAuthorize("@ss.hasScope('user.write')")
public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody OAuth2UserUpdateReqVO reqVO) {
// 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。
// 主要是AdminUserService 没有自己的 BO 对象,所以复用只能这么做
userService.updateUserProfile(getLoginUserId(), BeanUtils.toBean(reqVO, UserProfileUpdateReqVO.class));
userService.updateUserProfile(
getLoginUserId(), BeanUtils.toBean(reqVO, UserProfileUpdateReqVO.class));
return success(true);
}
}

View File

@@ -1,21 +1,25 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.client;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - OAuth2 客户端分页 Request VO")
/**
* 管理后台 - OAuth2 客户端分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class OAuth2ClientPageReqVO extends PageParam {
@Schema(description = "应用名,模糊匹配", example = "土豆")
/**
* 应用名,模糊匹配
*/
private String name;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举
*/
private Integer status;
}

View File

@@ -1,64 +1,98 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.client;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - OAuth2 客户端 Response VO")
/**
* 管理后台 - OAuth2 客户端 Response VO
*/
@Data
public class OAuth2ClientRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 编号"
*/
private Long id;
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
/**
* 客户端编号"
*/
private String clientId;
@Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "fan")
/**
* 客户端密钥"
*/
private String secret;
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆")
/**
* 应用名", example = "土豆
*/
private String name;
@Schema(description = "应用图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
/**
* 应用图标"
*/
private String logo;
@Schema(description = "应用描述", example = "我是一个应用")
/**
* 应用描述
*/
private String description;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,参见 CommonStatusEnum 枚举"
*/
private Integer status;
@Schema(description = "访问令牌的有效期", requiredMode = Schema.RequiredMode.REQUIRED, example = "8640")
/**
* 访问令牌的有效期"
*/
private Integer accessTokenValiditySeconds;
@Schema(description = "刷新令牌的有效期", requiredMode = Schema.RequiredMode.REQUIRED, example = "8640000")
/**
* 刷新令牌的有效期"
*/
private Integer refreshTokenValiditySeconds;
@Schema(description = "可重定向的 URI 地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
/**
* 可重定向的 URI 地址"
*/
private List<String> redirectUris;
@Schema(description = "授权类型,参见 OAuth2GrantTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "password")
/**
* 授权类型,参见 OAuth2GrantTypeEnum 枚举"
*/
private List<String> authorizedGrantTypes;
@Schema(description = "授权范围", example = "user_info")
/**
* 授权范围
*/
private List<String> scopes;
@Schema(description = "自动通过的授权范围", example = "user_info")
/**
* 自动通过的授权范围
*/
private List<String> autoApproveScopes;
@Schema(description = "权限", example = "system:user:query")
/**
* 权限
*/
private List<String> authorities;
@Schema(description = "资源", example = "1024")
/**
* 资源
*/
private List<String> resourceIds;
@Schema(description = "附加信息", example = "{yunai: true}")
/**
* 附加信息
*/
private String additionalInformation;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@@ -2,80 +2,78 @@ package com.tashow.cloud.system.controller.admin.oauth2.vo.client;
import cn.hutool.core.util.StrUtil;
import com.tashow.cloud.common.util.json.JsonUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.Data;
import org.hibernate.validator.constraints.URL;
@Schema(description = "管理后台 - OAuth2 客户端创建/修改 Request VO")
/** 管理后台 - OAuth2 客户端创建/修改 Request VO */
@Data
public class OAuth2ClientSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
/** 编号 */
private Long id;
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
@NotNull(message = "客户端编号不能为空")
private String clientId;
/** 客户端编号" */
@NotNull(message = "客户端编号不能为空")
private String clientId;
@Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "fan")
@NotNull(message = "客户端密钥不能为空")
private String secret;
/** 客户端密钥" */
@NotNull(message = "客户端密钥不能为空")
private String secret;
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆")
@NotNull(message = "应用名不能为空")
private String name;
/** 应用名", example = "土豆 */
@NotNull(message = "应用名不能为空")
private String name;
@Schema(description = "应用图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
@NotNull(message = "应用图标不能为空")
@URL(message = "应用图标的地址不正确")
private String logo;
/** 应用图标" */
@NotNull(message = "应用图标不能为空")
@URL(message = "应用图标的地址不正确")
private String logo;
@Schema(description = "应用描述", example = "我是一个应用")
private String description;
/** 应用描述 */
private String description;
@Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
/** 状态,参见 CommonStatusEnum 枚举" */
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "访问令牌的有效期", requiredMode = Schema.RequiredMode.REQUIRED, example = "8640")
@NotNull(message = "访问令牌的有效期不能为空")
private Integer accessTokenValiditySeconds;
/** 访问令牌的有效期" */
@NotNull(message = "访问令牌的有效期不能为空")
private Integer accessTokenValiditySeconds;
@Schema(description = "刷新令牌的有效期", requiredMode = Schema.RequiredMode.REQUIRED, example = "8640000")
@NotNull(message = "刷新令牌的有效期不能为空")
private Integer refreshTokenValiditySeconds;
/** 刷新令牌的有效期" */
@NotNull(message = "刷新令牌的有效期不能为空")
private Integer refreshTokenValiditySeconds;
@Schema(description = "可重定向的 URI 地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn")
@NotNull(message = "可重定向的 URI 地址不能为空")
private List<@NotEmpty(message = "重定向的 URI 不能为空") @URL(message = "重定向的 URI 格式不正确") String> redirectUris;
/** 可重定向的 URI 地址" */
@NotNull(message = "可重定向的 URI 地址不能为空")
private List<@NotEmpty(message = "重定向的 URI 不能为空") @URL(message = "重定向的 URI 格式不正确") String>
redirectUris;
@Schema(description = "授权类型,参见 OAuth2GrantTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "password")
@NotNull(message = "授权类型不能为空")
private List<String> authorizedGrantTypes;
/** 授权类型,参见 OAuth2GrantTypeEnum 枚举" */
@NotNull(message = "授权类型不能为空")
private List<String> authorizedGrantTypes;
@Schema(description = "授权范围", example = "user_info")
private List<String> scopes;
/** 授权范围 */
private List<String> scopes;
@Schema(description = "自动通过的授权范围", example = "user_info")
private List<String> autoApproveScopes;
/** 自动通过的授权范围 */
private List<String> autoApproveScopes;
@Schema(description = "权限", example = "system:user:query")
private List<String> authorities;
/** 权限 */
private List<String> authorities;
@Schema(description = "资源", example = "1024")
private List<String> resourceIds;
/** 资源 */
private List<String> resourceIds;
@Schema(description = "附加信息", example = "{yunai: true}")
private String additionalInformation;
@AssertTrue(message = "附加信息必须是 JSON 格式")
public boolean isAdditionalInformationJson() {
return StrUtil.isEmpty(additionalInformation) || JsonUtils.isJson(additionalInformation);
}
/** 附加信息 */
private String additionalInformation;
@AssertTrue(message = "附加信息必须是 JSON 格式")
public boolean isAdditionalInformationJson() {
return StrUtil.isEmpty(additionalInformation) || JsonUtils.isJson(additionalInformation);
}
}

View File

@@ -1,34 +1,32 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.open;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 【开放接口】访问令牌 Response VO")
/** 管理后台 - 【开放接口】访问令牌 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OAuth2OpenAccessTokenRespVO {
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
@JsonProperty("access_token")
private String accessToken;
/** 访问令牌" */
@JsonProperty("access_token")
private String accessToken;
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
@JsonProperty("refresh_token")
private String refreshToken;
/** 刷新令牌" */
@JsonProperty("refresh_token")
private String refreshToken;
@Schema(description = "令牌类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "bearer")
@JsonProperty("token_type")
private String tokenType;
/** 令牌类型" */
@JsonProperty("token_type")
private String tokenType;
@Schema(description = "过期时间,单位:秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "42430")
@JsonProperty("expires_in")
private Long expiresIn;
@Schema(description = "授权范围,如果多个授权范围,使用空格分隔", example = "user_info")
private String scope;
/** 过期时间,单位:秒" */
@JsonProperty("expires_in")
private Long expiresIn;
/** 授权范围,如果多个授权范围,使用空格分隔 */
private String scope;
}

View File

@@ -1,14 +1,15 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.open;
import com.tashow.cloud.common.core.KeyValue;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Schema(description = "管理后台 - 授权页的信息 Response VO")
/**
* 管理后台 - 授权页的信息 Response VO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@@ -19,7 +20,6 @@ public class OAuth2OpenAuthorizeInfoRespVO {
*/
private Client client;
@Schema(description = "scope 的选中信息,使用 List 保证有序性Key 是 scopeValue 为是否选中", requiredMode = Schema.RequiredMode.REQUIRED)
private List<KeyValue<String, Boolean>> scopes;
@Data
@@ -27,12 +27,14 @@ public class OAuth2OpenAuthorizeInfoRespVO {
@AllArgsConstructor
public static class Client {
@Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆")
/**
* 应用名", example = "土豆
*/
private String name;
@Schema(description = "应用图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
/**
* 应用图标"
*/
private String logo;
}
}

View File

@@ -1,40 +1,40 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.open;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Schema(description = "管理后台 - 【开放接口】校验令牌 Response VO")
/** 管理后台 - 【开放接口】校验令牌 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OAuth2OpenCheckTokenRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
@JsonProperty("user_id")
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@JsonProperty("user_type")
private Integer userType;
@Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@JsonProperty("tenant_id")
private Long tenantId;
/** 用户编号" */
@JsonProperty("user_id")
private Long userId;
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "car")
@JsonProperty("client_id")
private String clientId;
@Schema(description = "授权范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "user_info")
private List<String> scopes;
/** 用户类型,参见 UserTypeEnum 枚举" */
@JsonProperty("user_type")
private Integer userType;
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
@JsonProperty("access_token")
private String accessToken;
/** 租户编号" */
@JsonProperty("tenant_id")
private Long tenantId;
@Schema(description = "过期时间,时间戳 / 1000即单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1593092157")
private Long exp;
/** 客户端编号" */
@JsonProperty("client_id")
private String clientId;
/** 授权范围" */
private List<String> scopes;
/** 访问令牌" */
@JsonProperty("access_token")
private String accessToken;
/** 过期时间,时间戳 / 1000即单位秒" */
private Long exp;
}

View File

@@ -1,22 +1,28 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.token;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Schema(description = "管理后台 - 访问令牌分页 Request VO")
/**
* 管理后台 - 访问令牌分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OAuth2AccessTokenPageReqVO extends PageParam {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
/**
* 用户编号"
*/
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
/**
* 用户类型,参见 UserTypeEnum 枚举"
*/
private Integer userType;
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
/**
* 客户端编号"
*/
private String clientId;
}

View File

@@ -1,40 +1,56 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.token;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 访问令牌 Response VO")
/**
* 管理后台 - 访问令牌 Response VO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OAuth2AccessTokenRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 编号"
*/
private Long id;
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou")
/**
* 访问令牌"
*/
private String accessToken;
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
/**
* 刷新令牌"
*/
private String refreshToken;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
/**
* 用户编号"
*/
private Long userId;
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
/**
* 用户类型,参见 UserTypeEnum 枚举"
*/
private Integer userType;
@Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
/**
* 客户端编号"
*/
private String clientId;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 创建时间
*/
private LocalDateTime createTime;
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
/**
* 过期时间
*/
private LocalDateTime expiresTime;
}

View File

@@ -1,70 +1,62 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Schema(description = "管理后台 - OAuth2 获得用户基本信息 Response VO")
/** 管理后台 - OAuth2 获得用户基本信息 Response VO */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OAuth2UserInfoRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/** 用户编号" */
private Long id;
/** 用户账号", example = "芋艿 */
private String username;
/** 用户昵称", example = "芋道 */
private String nickname;
/** 用户邮箱 */
private String email;
/** 手机号码 */
private String mobile;
/** 用户性别,参见 SexEnum 枚举类 */
private Integer sex;
/** 用户头像 */
private String avatar;
/** 所在部门 */
private Dept dept;
/** 所属岗位数组 */
private List<Post> posts;
/** 部门 */
@Data
public static class Dept {
/** 部门编号" */
private Long id;
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String username;
/** 部门名称", example = "研发部 */
private String name;
}
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String nickname;
/** 岗位 */
@Data
public static class Post {
@Schema(description = "用户邮箱", example = "yudao@iocoder.cn")
private String email;
@Schema(description = "手机号码", example = "15601691300")
private String mobile;
@Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
private Integer sex;
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
private String avatar;
/**
* 所在部门
*/
private Dept dept;
/**
* 所属岗位数组
*/
private List<Post> posts;
@Schema(description = "部门")
@Data
public static class Dept {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部")
private String name;
}
@Schema(description = "岗位")
@Data
public static class Post {
@Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "开发")
private String name;
}
/** 岗位编号" */
private Long id;
/** 岗位名称", example = "开发 */
private String name;
}
}

View File

@@ -1,34 +1,41 @@
package com.tashow.cloud.system.controller.admin.oauth2.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Size;
@Schema(description = "管理后台 - OAuth2 更新用户基本信息 Request VO")
/**
* 管理后台 - OAuth2 更新用户基本信息 Request VO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OAuth2UserUpdateReqVO {
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
/**
* 用户昵称", example = "芋艿
*/
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
private String nickname;
@Schema(description = "用户邮箱", example = "yudao@iocoder.cn")
/**
* 用户邮箱
*/
@Email(message = "邮箱格式不正确")
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
private String email;
@Schema(description = "手机号码", example = "15601691300")
/**
* 手机号码
*/
@Length(min = 11, max = 11, message = "手机号长度必须 11 位")
private String mobile;
@Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
/**
* 用户性别,参见 SexEnum 枚举类
*/
private Integer sex;
}

View File

@@ -9,21 +9,20 @@ import com.tashow.cloud.system.controller.admin.permission.vo.menu.MenuSaveVO;
import com.tashow.cloud.system.controller.admin.permission.vo.menu.MenuSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.permission.MenuDO;
import com.tashow.cloud.system.service.permission.MenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.Comparator;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 菜单")
/**
* 管理后台 - 菜单
*/
@RestController
@RequestMapping("/system/menu")
@Validated
@@ -32,33 +31,40 @@ public class MenuController {
@Resource
private MenuService menuService;
/**
* 创建菜单
*/
@PostMapping("/create")
@Operation(summary = "创建菜单")
@PreAuthorize("@ss.hasPermission('system:menu:create')")
public CommonResult<Long> createMenu(@Valid @RequestBody MenuSaveVO createReqVO) {
Long menuId = menuService.createMenu(createReqVO);
return success(menuId);
}
/**
* 修改菜单
*/
@PutMapping("/update")
@Operation(summary = "修改菜单")
@PreAuthorize("@ss.hasPermission('system:menu:update')")
public CommonResult<Boolean> updateMenu(@Valid @RequestBody MenuSaveVO updateReqVO) {
menuService.updateMenu(updateReqVO);
return success(true);
}
/**
* 删除菜单
*/
@DeleteMapping("/delete")
@Operation(summary = "删除菜单")
@Parameter(name = "id", description = "菜单编号", required= true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:menu:delete')")
public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
menuService.deleteMenu(id);
return success(true);
}
/**
* 获取菜单列表", description = "用于【菜单管理】界面
*/
@GetMapping("/list")
@Operation(summary = "获取菜单列表", description = "用于【菜单管理】界面")
@PreAuthorize("@ss.hasPermission('system:menu:query')")
public CommonResult<List<MenuRespVO>> getMenuList(MenuListReqVO reqVO) {
List<MenuDO> list = menuService.getMenuList(reqVO);
@@ -66,23 +72,26 @@ public class MenuController {
return success(BeanUtils.toBean(list, MenuRespVO.class));
}
/**
* 获取菜单精简信息列表
*/
@GetMapping({"/list-all-simple", "simple-list"})
@Operation(summary = "获取菜单精简信息列表", description = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" +
"在多租户的场景下,会只返回租户所在套餐有的菜单")
public CommonResult<List<MenuSimpleRespVO>> getSimpleMenuList() {
List<MenuDO> list = menuService.getMenuListByTenant(
new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
List<MenuDO> list =
menuService.getMenuListByTenant(
new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
list = menuService.filterDisableMenus(list);
list.sort(Comparator.comparing(MenuDO::getSort));
return success(BeanUtils.toBean(list, MenuSimpleRespVO.class));
}
/**
* 获取菜单信息
*/
@GetMapping("/get")
@Operation(summary = "获取菜单信息")
@PreAuthorize("@ss.hasPermission('system:menu:query')")
public CommonResult<MenuRespVO> getMenu(Long id) {
MenuDO menu = menuService.getMenu(id);
return success(BeanUtils.toBean(menu, MenuRespVO.class));
}
}

View File

@@ -7,15 +7,12 @@ import com.tashow.cloud.system.controller.admin.permission.vo.permission.Permiss
import com.tashow.cloud.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
import com.tashow.cloud.system.service.permission.PermissionService;
import com.tashow.cloud.system.service.tenant.TenantService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.Set;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@@ -25,7 +22,10 @@ import static com.tashow.cloud.common.pojo.CommonResult.success;
*
* @author 芋道源码
*/
@Tag(name = "管理后台 - 权限")
/**
* 管理后台 - 权限
*/
@RestController
@RequestMapping("/system/permission")
public class PermissionController {
@@ -35,48 +35,60 @@ public class PermissionController {
@Resource
private TenantService tenantService;
@Operation(summary = "获得角色拥有的菜单编号")
@Parameter(name = "roleId", description = "角色编号", required = true)
/**
* 获得角色拥有的菜单编号
*/
@GetMapping("/list-role-menus")
@PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
public CommonResult<Set<Long>> getRoleMenuList(Long roleId) {
return success(permissionService.getRoleMenuListByRoleId(roleId));
}
/**
* 赋予角色菜单
*/
@PostMapping("/assign-role-menu")
@Operation(summary = "赋予角色菜单")
@PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) {
public CommonResult<Boolean> assignRoleMenu(
@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) {
// 开启多租户的情况下,需要过滤掉未开通的菜单
tenantService.handleTenantMenu(menuIds -> reqVO.getMenuIds().removeIf(menuId -> !CollUtil.contains(menuIds, menuId)));
tenantService.handleTenantMenu(
menuIds -> reqVO.getMenuIds().removeIf(menuId -> !CollUtil.contains(menuIds, menuId)));
// 执行菜单的分配
permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds());
return success(true);
}
/**
* 赋予角色数据权限
*/
@PostMapping("/assign-role-data-scope")
@Operation(summary = "赋予角色数据权限")
@PreAuthorize("@ss.hasPermission('system:permission:assign-role-data-scope')")
public CommonResult<Boolean> assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) {
permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds());
public CommonResult<Boolean> assignRoleDataScope(
@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) {
permissionService.assignRoleDataScope(
reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds());
return success(true);
}
@Operation(summary = "获得管理员拥有的角色编号列表")
@Parameter(name = "userId", description = "用户编号", required = true)
/**
* 获得管理员拥有的角色编号列表
*/
@GetMapping("/list-user-roles")
@PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) {
return success(permissionService.getUserRoleIdListByUserId(userId));
}
@Operation(summary = "赋予用户角色")
/**
* 赋予用户角色
*/
@PostMapping("/assign-user-role")
@PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
public CommonResult<Boolean> assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) {
public CommonResult<Boolean> assignUserRole(
@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) {
permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds());
return success(true);
}
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.permission;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
@@ -12,9 +11,7 @@ import com.tashow.cloud.system.controller.admin.permission.vo.role.RoleRespVO;
import com.tashow.cloud.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import com.tashow.cloud.system.dal.dataobject.permission.RoleDO;
import com.tashow.cloud.system.service.permission.RoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -26,11 +23,13 @@ import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static java.util.Collections.singleton;
@Tag(name = "管理后台 - 角色")
/**
* 管理后台 - 角色
*/
@RestController
@RequestMapping("/system/role")
@Validated
@@ -39,64 +38,78 @@ public class RoleController {
@Resource
private RoleService roleService;
/**
* 创建角色
*/
@PostMapping("/create")
@Operation(summary = "创建角色")
@PreAuthorize("@ss.hasPermission('system:role:create')")
public CommonResult<Long> createRole(@Valid @RequestBody RoleSaveReqVO createReqVO) {
return success(roleService.createRole(createReqVO, null));
}
/**
* 修改角色
*/
@PutMapping("/update")
@Operation(summary = "修改角色")
@PreAuthorize("@ss.hasPermission('system:role:update')")
public CommonResult<Boolean> updateRole(@Valid @RequestBody RoleSaveReqVO updateReqVO) {
roleService.updateRole(updateReqVO);
return success(true);
}
/**
* 删除角色
*/
@DeleteMapping("/delete")
@Operation(summary = "删除角色")
@Parameter(name = "id", description = "角色编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:role:delete')")
public CommonResult<Boolean> deleteRole(@RequestParam("id") Long id) {
roleService.deleteRole(id);
return success(true);
}
/**
* 获得角色信息
*/
@GetMapping("/get")
@Operation(summary = "获得角色信息")
@PreAuthorize("@ss.hasPermission('system:role:query')")
public CommonResult<RoleRespVO> getRole(@RequestParam("id") Long id) {
RoleDO role = roleService.getRole(id);
return success(BeanUtils.toBean(role, RoleRespVO.class));
}
/**
* 获得角色分页
*/
@GetMapping("/page")
@Operation(summary = "获得角色分页")
@PreAuthorize("@ss.hasPermission('system:role:query')")
public CommonResult<PageResult<RoleRespVO>> getRolePage(RolePageReqVO pageReqVO) {
PageResult<RoleDO> pageResult = roleService.getRolePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RoleRespVO.class));
}
/**
* 获取角色精简信息列表", description = "只包含被开启的角色,主要用于前端的下拉选项
*/
@GetMapping({"/list-all-simple", "/simple-list"})
@Operation(summary = "获取角色精简信息列表", description = "只包含被开启的角色,主要用于前端的下拉选项")
public CommonResult<List<RoleRespVO>> getSimpleRoleList() {
List<RoleDO> list = roleService.getRoleListByStatus(singleton(CommonStatusEnum.ENABLE.getStatus()));
List<RoleDO> list =
roleService.getRoleListByStatus(singleton(CommonStatusEnum.ENABLE.getStatus()));
list.sort(Comparator.comparing(RoleDO::getSort));
return success(BeanUtils.toBean(list, RoleRespVO.class));
}
/**
* 导出角色 Excel
*/
@GetMapping("/export-excel")
@Operation(summary = "导出角色 Excel")
@ApiAccessLog(operateType = EXPORT)
@PreAuthorize("@ss.hasPermission('system:role:export')")
public void export(HttpServletResponse response, @Validated RolePageReqVO exportReqVO) throws IOException {
public void export(HttpServletResponse response, @Validated RolePageReqVO exportReqVO)
throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RoleDO> list = roleService.getRolePage(exportReqVO).getList();
// 输出
ExcelUtils.write(response, "角色数据.xls", "数据", RoleRespVO.class,
BeanUtils.toBean(list, RoleRespVO.class));
ExcelUtils.write(
response, "角色数据.xls", "数据", RoleRespVO.class, BeanUtils.toBean(list, RoleRespVO.class));
}
}

View File

@@ -1,16 +1,14 @@
package com.tashow.cloud.system.controller.admin.permission.vo.menu;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 菜单列表 Request VO")
/** 管理后台 - 菜单列表 Request VO */
@Data
public class MenuListReqVO {
@Schema(description = "菜单名称,模糊匹配", example = "芋道")
private String name;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
/** 菜单名称,模糊匹配 */
private String name;
/** 展示状态,参见 CommonStatusEnum 枚举类 */
private Integer status;
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.permission.vo.menu;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
@@ -8,62 +7,93 @@ import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 菜单信息 Response VO")
/**
* 管理后台 - 菜单信息 Response VO
*/
@Data
public class MenuRespVO {
@Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 菜单编号"
*/
private Long id;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
/**
* 菜单名称", example = "芋道
*/
@NotBlank(message = "菜单名称不能为空")
@Size(max = 50, message = "菜单名称长度不能超过50个字符")
private String name;
@Schema(description = "权限标识,仅菜单类型为按钮时,才需要传递", example = "sys:menu:add")
/**
* 权限标识,仅菜单类型为按钮时,才需要传递
*/
@Size(max = 100)
private String permission;
@Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 类型,参见 MenuTypeEnum 枚举类"
*/
@NotNull(message = "菜单类型不能为空")
private Integer type;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 显示顺序"
*/
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 父菜单 ID"
*/
@NotNull(message = "父菜单 ID 不能为空")
private Long parentId;
@Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post")
/**
* 路由地址,仅菜单类型为菜单或者目录时,才需要传
*/
@Size(max = 200, message = "路由地址不能超过200个字符")
private String path;
@Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list")
/**
* 菜单图标,仅菜单类型为菜单或者目录时,才需要传
*/
private String icon;
@Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index")
/**
* 组件路径,仅菜单类型为菜单时,才需要传
*/
@Size(max = 200, message = "组件路径不能超过255个字符")
private String component;
@Schema(description = "组件名", example = "SystemUser")
/**
* 组件名
*/
private String componentName;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,见 CommonStatusEnum 枚举"
*/
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "是否可见", example = "false")
/**
* 是否可见
*/
private Boolean visible;
@Schema(description = "是否缓存", example = "false")
/**
* 是否缓存
*/
private Boolean keepAlive;
@Schema(description = "是否总是显示", example = "false")
/**
* 是否总是显示
*/
private Boolean alwaysShow;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
/**
* 创建时间", example = "时间戳格式
*/
private LocalDateTime createTime;
}

View File

@@ -1,64 +1,92 @@
package com.tashow.cloud.system.controller.admin.permission.vo.menu;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 菜单创建/修改 Request VO")
/**
* 管理后台 - 菜单创建/修改 Request VO
*/
@Data
public class MenuSaveVO {
@Schema(description = "菜单编号", example = "1024")
/**
* 菜单编号
*/
private Long id;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
/**
* 菜单名称", example = "芋道
*/
@NotBlank(message = "菜单名称不能为空")
@Size(max = 50, message = "菜单名称长度不能超过50个字符")
private String name;
@Schema(description = "权限标识,仅菜单类型为按钮时,才需要传递", example = "sys:menu:add")
/**
* 权限标识,仅菜单类型为按钮时,才需要传递
*/
@Size(max = 100)
private String permission;
@Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 类型,参见 MenuTypeEnum 枚举类"
*/
@NotNull(message = "菜单类型不能为空")
private Integer type;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 显示顺序"
*/
@NotNull(message = "显示顺序不能为空")
private Integer sort;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 父菜单 ID"
*/
@NotNull(message = "父菜单 ID 不能为空")
private Long parentId;
@Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post")
/**
* 路由地址,仅菜单类型为菜单或者目录时,才需要传
*/
@Size(max = 200, message = "路由地址不能超过200个字符")
private String path;
@Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list")
/**
* 菜单图标,仅菜单类型为菜单或者目录时,才需要传
*/
private String icon;
@Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index")
/**
* 组件路径,仅菜单类型为菜单时,才需要传
*/
@Size(max = 200, message = "组件路径不能超过255个字符")
private String component;
@Schema(description = "组件名", example = "SystemUser")
/**
* 组件名
*/
private String componentName;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 状态,见 CommonStatusEnum 枚举"
*/
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "是否可见", example = "false")
/**
* 是否可见
*/
private Boolean visible;
@Schema(description = "是否缓存", example = "false")
/**
* 是否缓存
*/
private Boolean keepAlive;
@Schema(description = "是否总是显示", example = "false")
/**
* 是否总是显示
*/
private Boolean alwaysShow;
}

View File

@@ -1,22 +1,20 @@
package com.tashow.cloud.system.controller.admin.permission.vo.menu;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 菜单精简信息 Response VO")
/** 管理后台 - 菜单精简信息 Response VO */
@Data
public class MenuSimpleRespVO {
@Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/** 菜单编号" */
private Long id;
@Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
/** 菜单名称", example = "芋道 */
private String name;
@Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long parentId;
@Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
/** 父菜单 ID" */
private Long parentId;
/** 类型,参见 MenuTypeEnum 枚举类" */
private Integer type;
}

View File

@@ -2,28 +2,33 @@ package com.tashow.cloud.system.controller.admin.permission.vo.permission;
import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.systemapi.enums.permission.DataScopeEnum;
import com.tashow.cloud.systemapi.enums.permission.DataScopeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.util.Collections;
import java.util.Set;
@Schema(description = "管理后台 - 赋予角色数据权限 Request VO")
/**
* 管理后台 - 赋予角色数据权限 Request VO
*/
@Data
public class PermissionAssignRoleDataScopeReqVO {
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 角色编号"
*/
@NotNull(message = "角色编号不能为空")
private Long roleId;
@Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 数据范围,参见 DataScopeEnum 枚举类"
*/
@NotNull(message = "数据范围不能为空")
@InEnum(value = DataScopeEnum.class, message = "数据范围必须是 {value}")
private Integer dataScope;
@Schema(description = "部门编号列表,只有范围类型为 DEPT_CUSTOM 时,该字段才需要", example = "1,3,5")
/**
* 部门编号列表,只有范围类型为 DEPT_CUSTOM 时,该字段才需要
*/
private Set<Long> dataScopeDeptIds = Collections.emptySet(); // 兜底
}

View File

@@ -1,21 +1,25 @@
package com.tashow.cloud.system.controller.admin.permission.vo.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.util.Collections;
import java.util.Set;
@Schema(description = "管理后台 - 赋予角色菜单 Request VO")
/**
* 管理后台 - 赋予角色菜单 Request VO
*/
@Data
public class PermissionAssignRoleMenuReqVO {
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
/**
* 角色编号"
*/
@NotNull(message = "角色编号不能为空")
private Long roleId;
@Schema(description = "菜单编号列表", example = "1,3,5")
/**
* 菜单编号列表
*/
private Set<Long> menuIds = Collections.emptySet(); // 兜底
}

View File

@@ -1,21 +1,18 @@
package com.tashow.cloud.system.controller.admin.permission.vo.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
import java.util.Collections;
import java.util.Set;
import lombok.Data;
@Schema(description = "管理后台 - 赋予用户角色 Request VO")
/** 管理后台 - 赋予用户角色 Request VO */
@Data
public class PermissionAssignUserRoleReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "角色编号列表", example = "1,3,5")
private Set<Long> roleIds = Collections.emptySet(); // 兜底
/** 用户编号" */
@NotNull(message = "用户编号不能为空")
private Long userId;
/** 角色编号列表 */
private Set<Long> roleIds = Collections.emptySet(); // 兜底
}

View File

@@ -1,31 +1,28 @@
package com.tashow.cloud.system.controller.admin.permission.vo.role;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 角色分页 Request VO")
/** 管理后台 - 角色分页 Request VO */
@Data
@EqualsAndHashCode(callSuper = true)
public class RolePageReqVO extends PageParam {
@Schema(description = "角色名称,模糊匹配", example = "芋道")
private String name;
/** 角色名称,模糊匹配 */
private String name;
@Schema(description = "角色标识,模糊匹配", example = "yudao")
private String code;
/** 角色标识,模糊匹配 */
private String code;
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
private Integer status;
@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;
/** 展示状态,参见 CommonStatusEnum 枚举类 */
private Integer status;
/** 创建时间 */
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -1,60 +1,56 @@
package com.tashow.cloud.system.controller.admin.permission.vo.role;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.excel.excel.core.annotations.DictFormat;
import com.tashow.cloud.excel.excel.core.convert.DictConvert;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.tashow.cloud.systemapi.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Set;
import lombok.Data;
@Schema(description = "管理后台 - 角色信息 Response VO")
/** 管理后台 - 角色信息 Response VO */
@Data
@ExcelIgnoreUnannotated
public class RoleRespVO {
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("角色序号")
private Long id;
/** 角色编号" */
@ExcelProperty("角色序号")
private Long id;
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "管理员")
@ExcelProperty("角色名称")
private String name;
/** 角色名称", example = "管理员 */
@ExcelProperty("角色名称")
private String name;
@Schema(description = "角色标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin")
@NotBlank(message = "角色标志不能为空")
@ExcelProperty("角色标志")
private String code;
/** 角色标志" */
@NotBlank(message = "角色标志不能为空")
@ExcelProperty("角色标志")
private String code;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("角色排序")
private Integer sort;
/** 显示顺序" */
@ExcelProperty("角色排序")
private Integer sort;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "角色状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
/** 状态,参见 CommonStatusEnum 枚举类" */
@ExcelProperty(value = "角色状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@Schema(description = "角色类型,参见 RoleTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
/** 角色类型,参见 RoleTypeEnum 枚举类" */
private Integer type;
@Schema(description = "备注", example = "我是一个角色")
private String remark;
/** 备注 */
private String remark;
@Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "数据范围", converter = DictConvert.class)
@DictFormat(DictTypeConstants.DATA_SCOPE)
private Integer dataScope;
/** 数据范围,参见 DataScopeEnum 枚举类" */
@ExcelProperty(value = "数据范围", converter = DictConvert.class)
@DictFormat(DictTypeConstants.DATA_SCOPE)
private Integer dataScope;
@Schema(description = "数据范围(指定部门数组)", example = "1")
private Set<Long> dataScopeDeptIds;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
private LocalDateTime createTime;
/** 数据范围(指定部门数组) */
private Set<Long> dataScopeDeptIds;
/** 创建时间", example = "时间戳格式 */
private LocalDateTime createTime;
}

View File

@@ -1,47 +1,45 @@
package com.tashow.cloud.system.controller.admin.permission.vo.role;
import com.mzt.logapi.starter.annotation.DiffLogField;
import com.tashow.cloud.common.enums.CommonStatusEnum;
import com.tashow.cloud.common.validation.InEnum;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - 角色创建/更新 Request VO")
/** 管理后台 - 角色创建/更新 Request VO */
@Data
public class RoleSaveReqVO {
@Schema(description = "角色编号", example = "1")
private Long id;
/** 角色编号 */
private Long id;
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "管理员")
@NotBlank(message = "角色名称不能为空")
@Size(max = 30, message = "角色名称长度不能超过 30 个字符")
@DiffLogField(name = "角色名称")
private String name;
/** 角色名称", example = "管理员 */
@NotBlank(message = "角色名称不能为空")
@Size(max = 30, message = "角色名称长度不能超过 30 个字符")
@DiffLogField(name = "角色名称")
private String name;
@NotBlank(message = "角色标志不能为空")
@Size(max = 100, message = "角色标志长度不能超过 100 个字符")
@Schema(description = "角色标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ADMIN")
@DiffLogField(name = "角色标志")
private String code;
@NotBlank(message = "角色标志不能为空")
@Size(max = 100, message = "角色标志长度不能超过 100 个字符")
/** 角色标志" */
@DiffLogField(name = "角色标志")
private String code;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "显示顺序不能为空")
@DiffLogField(name = "显示顺序")
private Integer sort;
/** 显示顺序" */
@NotNull(message = "显示顺序不能为空")
@DiffLogField(name = "显示顺序")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@DiffLogField(name = "状态")
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
@Schema(description = "备注", example = "我是一个角色")
@Size(max = 500, message = "备注长度不能超过 500 个字符")
@DiffLogField(name = "备注")
private String remark;
/** 状态" */
@DiffLogField(name = "状态")
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
/** 备注 */
@Size(max = 500, message = "备注长度不能超过 500 个字符")
@DiffLogField(name = "备注")
private String remark;
}

View File

@@ -1,16 +1,20 @@
package com.tashow.cloud.system.controller.admin.permission.vo.role;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 角色精简信息 Response VO")
/**
* 管理后台 - 角色精简信息 Response VO
*/
@Data
public class RoleSimpleRespVO {
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
/**
* 角色编号"
*/
private Long id;
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
/**
* 角色名称", example = "芋道
*/
private String name;
}

View File

@@ -4,17 +4,19 @@ import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.util.servlet.ServletUtils;
import com.tashow.cloud.system.framework.sms.core.enums.SmsChannelEnum;
import com.tashow.cloud.system.service.sms.SmsSendService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
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 static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 短信回调")
/**
* 管理后台 - 短信回调
*/
@RestController
@RequestMapping("/system/sms/callback")
public class SmsCallbackController {
@@ -22,39 +24,48 @@ public class SmsCallbackController {
@Resource
private SmsSendService smsSendService;
/**
* 阿里云短信的回调", description = "参见 https://help.aliyun.com/document_detail/120998.html 文档
*/
@PostMapping("/aliyun")
@PermitAll
@Operation(summary = "阿里云短信的回调", description = "参见 https://help.aliyun.com/document_detail/120998.html 文档")
public CommonResult<Boolean> receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable {
String text = ServletUtils.getBody(request);
smsSendService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text);
return success(true);
}
/**
* 腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/52077 文档
*/
@PostMapping("/tencent")
@PermitAll
@Operation(summary = "腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/52077 文档")
public CommonResult<Boolean> receiveTencentSmsStatus(HttpServletRequest request) throws Throwable {
public CommonResult<Boolean> receiveTencentSmsStatus(HttpServletRequest request)
throws Throwable {
String text = ServletUtils.getBody(request);
smsSendService.receiveSmsStatus(SmsChannelEnum.TENCENT.getCode(), text);
return success(true);
}
/**
* 华为云短信的回调", description = "参见 https://support.huaweicloud.com/api-msgsms/sms_05_0003.html 文档
*/
@PostMapping("/huawei")
@PermitAll
@Operation(summary = "华为云短信的回调", description = "参见 https://support.huaweicloud.com/api-msgsms/sms_05_0003.html 文档")
public CommonResult<Boolean> receiveHuaweiSmsStatus(@RequestBody String requestBody) throws Throwable {
public CommonResult<Boolean> receiveHuaweiSmsStatus(@RequestBody String requestBody)
throws Throwable {
smsSendService.receiveSmsStatus(SmsChannelEnum.HUAWEI.getCode(), requestBody);
return success(true);
}
/**
* 七牛云短信的回调", description = "参见 https://developer.qiniu.com/sms/5910/message-push 文档
*/
@PostMapping("/qiniu")
@PermitAll
@Operation(summary = "七牛云短信的回调", description = "参见 https://developer.qiniu.com/sms/5910/message-push 文档")
public CommonResult<Boolean> receiveQiniuSmsStatus(@RequestBody String requestBody) throws Throwable {
public CommonResult<Boolean> receiveQiniuSmsStatus(@RequestBody String requestBody)
throws Throwable {
smsSendService.receiveSmsStatus(SmsChannelEnum.QINIU.getCode(), requestBody);
return success(true);
}
}

View File

@@ -9,20 +9,19 @@ import com.tashow.cloud.system.controller.admin.sms.vo.channel.SmsChannelSaveReq
import com.tashow.cloud.system.controller.admin.sms.vo.channel.SmsChannelSimpleRespVO;
import com.tashow.cloud.system.dal.dataobject.sms.SmsChannelDO;
import com.tashow.cloud.system.service.sms.SmsChannelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.Comparator;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 短信渠道")
/**
* 管理后台 - 短信渠道
*/
@RestController
@RequestMapping("system/sms-channel")
public class SmsChannelController {
@@ -30,53 +29,64 @@ public class SmsChannelController {
@Resource
private SmsChannelService smsChannelService;
/**
* 创建短信渠道
*/
@PostMapping("/create")
@Operation(summary = "创建短信渠道")
@PreAuthorize("@ss.hasPermission('system:sms-channel:create')")
public CommonResult<Long> createSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO createReqVO) {
return success(smsChannelService.createSmsChannel(createReqVO));
}
/**
* 更新短信渠道
*/
@PutMapping("/update")
@Operation(summary = "更新短信渠道")
@PreAuthorize("@ss.hasPermission('system:sms-channel:update')")
public CommonResult<Boolean> updateSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO updateReqVO) {
public CommonResult<Boolean> updateSmsChannel(
@Valid @RequestBody SmsChannelSaveReqVO updateReqVO) {
smsChannelService.updateSmsChannel(updateReqVO);
return success(true);
}
/**
* 删除短信渠道
*/
@DeleteMapping("/delete")
@Operation(summary = "删除短信渠道")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:sms-channel:delete')")
public CommonResult<Boolean> deleteSmsChannel(@RequestParam("id") Long id) {
smsChannelService.deleteSmsChannel(id);
return success(true);
}
/**
* 获得短信渠道
*/
@GetMapping("/get")
@Operation(summary = "获得短信渠道")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
public CommonResult<SmsChannelRespVO> getSmsChannel(@RequestParam("id") Long id) {
SmsChannelDO channel = smsChannelService.getSmsChannel(id);
return success(BeanUtils.toBean(channel, SmsChannelRespVO.class));
}
/**
* 获得短信渠道分页
*/
@GetMapping("/page")
@Operation(summary = "获得短信渠道分页")
@PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
public CommonResult<PageResult<SmsChannelRespVO>> getSmsChannelPage(@Valid SmsChannelPageReqVO pageVO) {
public CommonResult<PageResult<SmsChannelRespVO>> getSmsChannelPage(
@Valid SmsChannelPageReqVO pageVO) {
PageResult<SmsChannelDO> pageResult = smsChannelService.getSmsChannelPage(pageVO);
return success(BeanUtils.toBean(pageResult, SmsChannelRespVO.class));
}
/**
* 获得短信渠道精简列表", description = "包含被禁用的短信渠道
*/
@GetMapping({"/list-all-simple", "/simple-list"})
@Operation(summary = "获得短信渠道精简列表", description = "包含被禁用的短信渠道")
public CommonResult<List<SmsChannelSimpleRespVO>> getSimpleSmsChannelList() {
List<SmsChannelDO> list = smsChannelService.getSmsChannelList();
list.sort(Comparator.comparing(SmsChannelDO::getId));
return success(BeanUtils.toBean(list, SmsChannelSimpleRespVO.class));
}
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.sms;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.pojo.PageResult;
@@ -10,8 +9,7 @@ import com.tashow.cloud.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
import com.tashow.cloud.system.controller.admin.sms.vo.log.SmsLogRespVO;
import com.tashow.cloud.system.dal.dataobject.sms.SmsLogDO;
import com.tashow.cloud.system.service.sms.SmsLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -24,10 +22,12 @@ import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 短信日志")
/**
* 管理后台 - 短信日志
*/
@RestController
@RequestMapping("/system/sms-log")
@Validated
@@ -36,25 +36,28 @@ public class SmsLogController {
@Resource
private SmsLogService smsLogService;
/**
* 获得短信日志分页
*/
@GetMapping("/page")
@Operation(summary = "获得短信日志分页")
@PreAuthorize("@ss.hasPermission('system:sms-log:query')")
public CommonResult<PageResult<SmsLogRespVO>> getSmsLogPage(@Valid SmsLogPageReqVO pageReqVO) {
PageResult<SmsLogDO> pageResult = smsLogService.getSmsLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, SmsLogRespVO.class));
}
/**
* 导出短信日志 Excel
*/
@GetMapping("/export-excel")
@Operation(summary = "导出短信日志 Excel")
@PreAuthorize("@ss.hasPermission('system:sms-log:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportSmsLogExcel(@Valid SmsLogPageReqVO exportReqVO,
HttpServletResponse response) throws IOException {
public void exportSmsLogExcel(@Valid SmsLogPageReqVO exportReqVO, HttpServletResponse response)
throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<SmsLogDO> list = smsLogService.getSmsLogPage(exportReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "短信日志.xls", "数据", SmsLogRespVO.class,
BeanUtils.toBean(list, SmsLogRespVO.class));
ExcelUtils.write(
response, "短信日志.xls", "数据", SmsLogRespVO.class, BeanUtils.toBean(list, SmsLogRespVO.class));
}
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.system.controller.admin.sms;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageParam;
import com.tashow.cloud.common.pojo.PageResult;
@@ -13,9 +12,7 @@ import com.tashow.cloud.system.controller.admin.sms.vo.template.SmsTemplateSendR
import com.tashow.cloud.system.dal.dataobject.sms.SmsTemplateDO;
import com.tashow.cloud.system.service.sms.SmsSendService;
import com.tashow.cloud.system.service.sms.SmsTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import com.tashow.cloud.web.apilog.core.annotation.ApiAccessLog;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@@ -25,10 +22,12 @@ import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.tashow.cloud.common.pojo.CommonResult.success;
import static com.tashow.cloud.web.apilog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 短信模板")
/**
* 管理后台 - 短信模板
*/
@RestController
@RequestMapping("/system/sms-template")
public class SmsTemplateController {
@@ -38,66 +37,88 @@ public class SmsTemplateController {
@Resource
private SmsSendService smsSendService;
/**
* 创建短信模板
*/
@PostMapping("/create")
@Operation(summary = "创建短信模板")
@PreAuthorize("@ss.hasPermission('system:sms-template:create')")
public CommonResult<Long> createSmsTemplate(@Valid @RequestBody SmsTemplateSaveReqVO createReqVO) {
public CommonResult<Long> createSmsTemplate(
@Valid @RequestBody SmsTemplateSaveReqVO createReqVO) {
return success(smsTemplateService.createSmsTemplate(createReqVO));
}
/**
* 更新短信模板
*/
@PutMapping("/update")
@Operation(summary = "更新短信模板")
@PreAuthorize("@ss.hasPermission('system:sms-template:update')")
public CommonResult<Boolean> updateSmsTemplate(@Valid @RequestBody SmsTemplateSaveReqVO updateReqVO) {
public CommonResult<Boolean> updateSmsTemplate(
@Valid @RequestBody SmsTemplateSaveReqVO updateReqVO) {
smsTemplateService.updateSmsTemplate(updateReqVO);
return success(true);
}
/**
* 删除短信模板
*/
@DeleteMapping("/delete")
@Operation(summary = "删除短信模板")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('system:sms-template:delete')")
public CommonResult<Boolean> deleteSmsTemplate(@RequestParam("id") Long id) {
smsTemplateService.deleteSmsTemplate(id);
return success(true);
}
/**
* 获得短信模板
*/
@GetMapping("/get")
@Operation(summary = "获得短信模板")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:sms-template:query')")
public CommonResult<SmsTemplateRespVO> getSmsTemplate(@RequestParam("id") Long id) {
SmsTemplateDO template = smsTemplateService.getSmsTemplate(id);
return success(BeanUtils.toBean(template, SmsTemplateRespVO.class));
}
/**
* 获得短信模板分页
*/
@GetMapping("/page")
@Operation(summary = "获得短信模板分页")
@PreAuthorize("@ss.hasPermission('system:sms-template:query')")
public CommonResult<PageResult<SmsTemplateRespVO>> getSmsTemplatePage(@Valid SmsTemplatePageReqVO pageVO) {
public CommonResult<PageResult<SmsTemplateRespVO>> getSmsTemplatePage(
@Valid SmsTemplatePageReqVO pageVO) {
PageResult<SmsTemplateDO> pageResult = smsTemplateService.getSmsTemplatePage(pageVO);
return success(BeanUtils.toBean(pageResult, SmsTemplateRespVO.class));
}
/**
* 导出短信模板 Excel
*/
@GetMapping("/export-excel")
@Operation(summary = "导出短信模板 Excel")
@PreAuthorize("@ss.hasPermission('system:sms-template:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportSmsTemplateExcel(@Valid SmsTemplatePageReqVO exportReqVO,
HttpServletResponse response) throws IOException {
public void exportSmsTemplateExcel(
@Valid SmsTemplatePageReqVO exportReqVO, HttpServletResponse response) throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<SmsTemplateDO> list = smsTemplateService.getSmsTemplatePage(exportReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "短信模板.xls", "数据", SmsTemplateRespVO.class,
ExcelUtils.write(
response,
"短信模板.xls",
"数据",
SmsTemplateRespVO.class,
BeanUtils.toBean(list, SmsTemplateRespVO.class));
}
/**
* 发送短信
*/
@PostMapping("/send-sms")
@Operation(summary = "发送短信")
@PreAuthorize("@ss.hasPermission('system:sms-template:send-sms')")
public CommonResult<Long> sendSms(@Valid @RequestBody SmsTemplateSendReqVO sendReqVO) {
return success(smsSendService.sendSingleSmsToAdmin(sendReqVO.getMobile(), null,
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
return success(
smsSendService.sendSingleSmsToAdmin(
sendReqVO.getMobile(),
null,
sendReqVO.getTemplateCode(),
sendReqVO.getTemplateParams()));
}
}

View File

@@ -1,7 +1,6 @@
package com.tashow.cloud.system.controller.admin.sms.vo.channel;
import com.tashow.cloud.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -11,20 +10,25 @@ import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 短信渠道分页 Request VO")
/**
* 管理后台 - 短信渠道分页 Request VO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SmsChannelPageReqVO extends PageParam {
@Schema(description = "任务状态", example = "1")
/**
* 任务状态
*/
private Integer status;
@Schema(description = "短信签名,模糊匹配", example = "芋道源码")
/**
* 短信签名,模糊匹配
*/
private String signature;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Schema(description = "创建时间")
/** 创建时间 */
private LocalDateTime[] createTime;
}

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