删除中间表实体类,添加菜单功能
This commit is contained in:
parent
ee7e0a44c4
commit
3517f38282
@ -37,7 +37,7 @@ public class UserApiController extends BaseController<User, UserDTO, Long, UserQ
|
||||
@Operation(summary = "获取当前用户信息")
|
||||
@GetMapping("/current")
|
||||
public Response<LoginResponse> getCurrentUser() {
|
||||
return Response.success(userService.getCurrentUser());
|
||||
return Response.success(userService.getCurrentUserResponse());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -3,19 +3,23 @@ package com.qqchen.deploy.backend.converter;
|
||||
import com.qqchen.deploy.backend.entity.Menu;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import com.qqchen.deploy.backend.model.MenuDTO;
|
||||
import com.qqchen.deploy.backend.model.request.MenuRequest;
|
||||
import com.qqchen.deploy.backend.model.response.MenuResponse;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper(config = BaseConverter.class)
|
||||
public interface MenuConverter extends BaseConverter<Menu, MenuDTO> {
|
||||
|
||||
MenuDTO requestToDto(MenuRequest request);
|
||||
@Override
|
||||
MenuDTO toDto(Menu entity);
|
||||
|
||||
MenuResponse toResponse(Menu menu);
|
||||
@Override
|
||||
List<MenuDTO> toDtoList(List<Menu> entityList);
|
||||
|
||||
List<MenuResponse> toResponseList(List<MenuDTO> dtos);
|
||||
@Mapping(target = "children", expression = "java(toResponseList(dto.getChildren()))")
|
||||
MenuResponse toResponse(MenuDTO dto);
|
||||
|
||||
List<MenuResponse> toResponseList(List<MenuDTO> dtoList);
|
||||
}
|
||||
@ -12,8 +12,14 @@ public interface UserConverter extends BaseConverter<User, UserDTO> {
|
||||
// MapStruct 会自动实现所有方法
|
||||
|
||||
@Mapping(target = "token", ignore = true)
|
||||
@Mapping(target = "id", ignore = true)
|
||||
LoginResponse toLoginResponse(User user);
|
||||
|
||||
@Mapping(target = "token", source = "token")
|
||||
@Mapping(target = "id", ignore = true)
|
||||
LoginResponse toLoginResponse(User user, String token);
|
||||
|
||||
@Mapping(target = "token", ignore = true)
|
||||
@Mapping(target = "id", ignore = true)
|
||||
LoginResponse toLoginResponse(UserDTO userDTO);
|
||||
}
|
||||
@ -3,9 +3,12 @@ package com.qqchen.deploy.backend.entity;
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@Data
|
||||
@ -67,4 +70,16 @@ public class Menu extends Entity<Long> {
|
||||
* 是否启用(true:启用 false:禁用)
|
||||
*/
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* 菜单关联的角色列表
|
||||
*/
|
||||
@ManyToMany(mappedBy = "menus")
|
||||
private Set<Role> roles = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 菜单关联的权限模板列表
|
||||
*/
|
||||
@ManyToMany(mappedBy = "menus")
|
||||
private Set<PermissionTemplate> templates = new HashSet<>();
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.qqchen.deploy.backend.entity;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 权限模板实体
|
||||
*/
|
||||
@Data
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "sys_permission_template")
|
||||
public class PermissionTemplate extends Entity<Long> {
|
||||
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
@Column(nullable = false, length = 100)
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 模板名称
|
||||
*/
|
||||
@Column(nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 模板类型(1:系统模板 2:自定义模板)
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 模板描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* 模板包含的菜单列表
|
||||
*/
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(
|
||||
name = "sys_template_menu",
|
||||
joinColumns = @JoinColumn(name = "template_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "menu_id")
|
||||
)
|
||||
private Set<Menu> menus = new HashSet<>();
|
||||
}
|
||||
@ -3,6 +3,9 @@ package com.qqchen.deploy.backend.entity;
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
@ -12,6 +15,9 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* 角色实体
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@jakarta.persistence.Entity
|
||||
@ -19,20 +25,68 @@ import java.util.Set;
|
||||
@LogicDelete
|
||||
public class Role extends Entity<Long> {
|
||||
|
||||
@NotBlank(message = "角色名称不能为空")
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
@NotBlank(message = "角色编码不能为空")
|
||||
@Column(nullable = false, unique = true)
|
||||
@Column(nullable = false, length = 100, unique = true)
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 角色名称
|
||||
*/
|
||||
@NotBlank(message = "角色名称不能为空")
|
||||
@Column(nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 角色类型(1:系统角色 2:自定义角色)
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 角色描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
@Column(nullable = false)
|
||||
private Integer sort = 0;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* 角色关联的用户列表
|
||||
*/
|
||||
@ManyToMany(mappedBy = "roles")
|
||||
private Set<User> users = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 角色关联的菜单列表
|
||||
*/
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(
|
||||
name = "sys_role_menu",
|
||||
joinColumns = @JoinColumn(name = "role_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "menu_id")
|
||||
)
|
||||
private Set<Menu> menus = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 角色关联的标签列表
|
||||
*/
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(
|
||||
name = "sys_role_tag_relation",
|
||||
joinColumns = @JoinColumn(name = "role_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "tag_id")
|
||||
)
|
||||
private Set<RoleTag> tags = new HashSet<>();
|
||||
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.qqchen.deploy.backend.entity;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "sys_role_menu")
|
||||
@LogicDelete
|
||||
public class RoleMenu extends Entity<Long> {
|
||||
|
||||
@Column(name = "role_id")
|
||||
private Long roleId;
|
||||
|
||||
@Column(name = "menu_id")
|
||||
private Long menuId;
|
||||
|
||||
protected RoleMenu() {
|
||||
}
|
||||
|
||||
public RoleMenu(Long roleId, Long menuId) {
|
||||
this.roleId = roleId;
|
||||
this.menuId = menuId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.qqchen.deploy.backend.entity;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 角色标签实体
|
||||
*/
|
||||
@Data
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "sys_role_tag")
|
||||
public class RoleTag extends Entity<Long> {
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
@Column(nullable = false, length = 50)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 标签颜色(十六进制颜色码)
|
||||
*/
|
||||
@Column(length = 20)
|
||||
private String color;
|
||||
|
||||
/**
|
||||
* 关联的角色列表
|
||||
*/
|
||||
@ManyToMany(mappedBy = "tags")
|
||||
private Set<Role> roles = new HashSet<>();
|
||||
}
|
||||
@ -38,15 +38,9 @@ public class User extends Entity<Long> {
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(
|
||||
name = "sys_user_role", // 中间表名称
|
||||
joinColumns = @JoinColumn(
|
||||
name = "user_id", // 中间表中关联当前实体的外键名
|
||||
referencedColumnName = "id" // 当前实体的主键
|
||||
),
|
||||
inverseJoinColumns = @JoinColumn(
|
||||
name = "role_id", // 中间表中关联目标实体的外键名
|
||||
referencedColumnName = "id" // 目标实体的主键
|
||||
)
|
||||
name = "sys_user_role",
|
||||
joinColumns = @JoinColumn(name = "user_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "role_id")
|
||||
)
|
||||
private Set<Role> roles = new HashSet<>();
|
||||
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
package com.qqchen.deploy.backend.entity;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "sys_user_department")
|
||||
@LogicDelete
|
||||
public class UserDepartment extends Entity<Long> {
|
||||
|
||||
@Column(name = "user_id")
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "dept_id")
|
||||
private Long deptId;
|
||||
|
||||
protected UserDepartment() {
|
||||
// JPA需要无参构造函数
|
||||
}
|
||||
|
||||
public UserDepartment(Long userId, Long deptId) {
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
//package com.qqchen.deploy.backend.entity;
|
||||
//
|
||||
//import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
//import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
//import jakarta.persistence.Column;
|
||||
//import jakarta.persistence.Table;
|
||||
//import lombok.Data;
|
||||
//import lombok.EqualsAndHashCode;
|
||||
//
|
||||
//@Data
|
||||
//@EqualsAndHashCode(callSuper = true)
|
||||
//@jakarta.persistence.Entity
|
||||
//@Table(name = "sys_user_role")
|
||||
//@LogicDelete
|
||||
//public class UserRole extends Entity<Long> {
|
||||
//
|
||||
// @Column(name = "user_id")
|
||||
// private Long userId;
|
||||
//
|
||||
// @Column(name = "role_id")
|
||||
// private Long roleId;
|
||||
//
|
||||
// // 添加构造方法
|
||||
// protected UserRole() {
|
||||
// // JPA需要无参构造方法
|
||||
// }
|
||||
//
|
||||
// public UserRole(Long userId, Long roleId) {
|
||||
// this.userId = userId;
|
||||
// this.roleId = roleId;
|
||||
// }
|
||||
//}
|
||||
@ -33,10 +33,18 @@ public enum ResponseCode {
|
||||
EMAIL_EXISTS(2005, "user.email.exists"),
|
||||
LOGIN_ERROR(2006, "user.login.error"),
|
||||
|
||||
// JWT相关错误码 (2100-2199)
|
||||
JWT_EXPIRED(2100, "jwt.token.expired"),
|
||||
JWT_INVALID(2101, "jwt.token.invalid"),
|
||||
JWT_MISSING(2102, "jwt.token.missing");
|
||||
// 角色相关错误码 (2100-2199)
|
||||
ROLE_NOT_FOUND(2100, "role.not.found"),
|
||||
ROLE_CODE_EXISTS(2101, "role.code.exists"),
|
||||
ROLE_NAME_EXISTS(2102, "role.name.exists"),
|
||||
ROLE_IN_USE(2103, "role.in.use"),
|
||||
ROLE_ADMIN_CANNOT_DELETE(2104, "role.admin.cannot.delete"),
|
||||
ROLE_ADMIN_CANNOT_UPDATE(2105, "role.admin.cannot.update"),
|
||||
|
||||
// JWT相关错误码 (2200-2299)
|
||||
JWT_EXPIRED(2200, "jwt.token.expired"),
|
||||
JWT_INVALID(2201, "jwt.token.invalid"),
|
||||
JWT_MISSING(2202, "jwt.token.missing");
|
||||
|
||||
private final int code;
|
||||
private final String messageKey; // 国际化消息key
|
||||
|
||||
@ -9,8 +9,11 @@ import io.jsonwebtoken.MalformedJwtException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import java.security.SignatureException;
|
||||
|
||||
@ -33,18 +36,12 @@ public class GlobalExceptionHandler {
|
||||
return Response.error(ResponseCode.ERROR);
|
||||
}
|
||||
|
||||
@ExceptionHandler(org.springframework.security.authentication.BadCredentialsException.class)
|
||||
public Response<?> handleBadCredentialsException(org.springframework.security.authentication.BadCredentialsException e) {
|
||||
@ExceptionHandler(BadCredentialsException.class)
|
||||
public Response<?> handleBadCredentialsException(BadCredentialsException e) {
|
||||
log.warn("Login failed: Bad credentials", e);
|
||||
return Response.error(ResponseCode.LOGIN_ERROR);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Response<?> handleException(Exception e) {
|
||||
log.error("Unexpected error occurred", e);
|
||||
return Response.error(ResponseCode.ERROR);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ExpiredJwtException.class)
|
||||
public Response<?> handleExpiredJwtException(ExpiredJwtException e) {
|
||||
log.warn("JWT token expired", e);
|
||||
@ -56,4 +53,27 @@ public class GlobalExceptionHandler {
|
||||
log.warn("Invalid JWT token", e);
|
||||
return Response.error(ResponseCode.JWT_INVALID);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
|
||||
public Response<?> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
|
||||
String message = String.format("参数[%s]类型错误, 期望类型: %s, 实际值: %s",
|
||||
e.getName(),
|
||||
e.getRequiredType().getSimpleName(),
|
||||
e.getValue());
|
||||
log.warn("Parameter type mismatch: {}", message);
|
||||
return Response.error(ResponseCode.INVALID_PARAM, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoHandlerFoundException.class)
|
||||
public Response<?> handleNoHandlerFoundException(NoHandlerFoundException e) {
|
||||
String message = String.format("接口不存在: %s %s", e.getHttpMethod(), e.getRequestURL());
|
||||
log.warn("API not found: {}", message);
|
||||
return Response.error(ResponseCode.NOT_FOUND, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Response<?> handleException(Exception e) {
|
||||
log.error("Unexpected error occurred", e);
|
||||
return Response.error(ResponseCode.ERROR);
|
||||
}
|
||||
}
|
||||
@ -315,13 +315,18 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, I
|
||||
return PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "createTime"));
|
||||
}
|
||||
|
||||
// 处理分页参数
|
||||
int pageNum = query.getPageNum() != null ? Math.max(1, query.getPageNum()) : 1;
|
||||
int pageSize = query.getPageSize() != null ? Math.max(1, Math.min(query.getPageSize(), 100)) : 10;
|
||||
|
||||
// 处理排序
|
||||
Sort sort = StringUtils.hasText(query.getSortField()) ?
|
||||
Sort.by(Sort.Direction.fromString(query.getSortOrder()), query.getSortField()) :
|
||||
Sort.by(Sort.Direction.DESC, "createTime");
|
||||
|
||||
return PageRequest.of(
|
||||
query.getPageNum() - 1,
|
||||
query.getPageSize(),
|
||||
pageNum - 1, // 转换为从0开始的页码
|
||||
pageSize,
|
||||
sort
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,11 +8,15 @@ import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RoleDTO extends BaseDTO {
|
||||
|
||||
private String name;
|
||||
|
||||
private String code;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private Boolean enabled;
|
||||
}
|
||||
@ -9,6 +9,9 @@ import java.util.Set;
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserDTO extends BaseDTO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String nickname;
|
||||
|
||||
@ -9,6 +9,8 @@ import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserResponse extends BaseResponse {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String email;
|
||||
|
||||
@ -1,29 +1,39 @@
|
||||
package com.qqchen.deploy.backend.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.Menu;
|
||||
import com.qqchen.deploy.backend.entity.User;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface IMenuRepository extends IBaseRepository<Menu, Long> {
|
||||
|
||||
/**
|
||||
* 查询所有未删除的菜单,按排序字段排序
|
||||
*/
|
||||
List<Menu> findByDeletedFalseOrderBySort();
|
||||
|
||||
List<Menu> findByParentIdAndDeletedFalseOrderBySort(Long parentId);
|
||||
/**
|
||||
* 根据角色ID列表查询对应的菜单
|
||||
*/
|
||||
@Query(value = "SELECT DISTINCT m.* FROM sys_menu m " +
|
||||
"INNER JOIN sys_role_menu rm ON m.id = rm.menu_id " +
|
||||
"WHERE rm.role_id IN :roleIds " +
|
||||
"AND m.enabled = true " +
|
||||
"AND m.deleted = false " +
|
||||
"ORDER BY m.sort", nativeQuery = true)
|
||||
List<Menu> findByRoleIdsAndEnabledTrue(@Param("roleIds") List<Long> roleIds);
|
||||
|
||||
List<Menu> findByTypeAndDeletedFalseOrderBySort(Integer type);
|
||||
/**
|
||||
* 检查菜单编码是否存在
|
||||
*/
|
||||
boolean existsByPermissionAndDeletedFalse(String permission);
|
||||
|
||||
List<Menu> findByIdInAndDeletedFalseOrderBySort(List<Long> ids);
|
||||
|
||||
List<Menu> findByPermissionLikeAndDeletedFalse(String permission);
|
||||
|
||||
List<Menu> findByTypeAndPermissionIsNotNullAndDeletedFalse(Integer type);
|
||||
|
||||
List<Menu> findByParentIdAndDeletedFalse(Long parentId);
|
||||
|
||||
List<Menu> findByTypeInAndDeletedFalseOrderBySort(List<Integer> types);
|
||||
|
||||
List<Menu> findByEnabledAndDeletedFalseOrderBySort(Boolean enabled);
|
||||
/**
|
||||
* 检查同级菜单下是否存在相同名称的菜单
|
||||
*/
|
||||
boolean existsByNameAndParentIdAndDeletedFalse(String name, Long parentId);
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.qqchen.deploy.backend.repository;
|
||||
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.entity.RoleMenu;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface IRoleMenuRepository extends IBaseRepository<RoleMenu, Long> {
|
||||
|
||||
@Query("SELECT rm.roleId FROM RoleMenu rm where rm.roleId = :roleId")
|
||||
List<Long> findByRoleId(Long roleId);
|
||||
//
|
||||
// void deleteByRoleId(Long roleId);
|
||||
//
|
||||
// List<RoleMenu> findByRoleIdIn(List<Long> roleIds);
|
||||
// 通过角色ID查询
|
||||
}
|
||||
@ -1,21 +1,30 @@
|
||||
package com.qqchen.deploy.backend.repository;
|
||||
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.entity.Role;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface IRoleRepository extends IBaseRepository<Role, Long> {
|
||||
|
||||
List<Role> findByDeletedFalseOrderBySort();
|
||||
|
||||
/**
|
||||
* 检查角色编码是否存在(排除已删除的)
|
||||
*/
|
||||
boolean existsByCodeAndDeletedFalse(String code);
|
||||
|
||||
/**
|
||||
* 检查角色名称是否存在(排除已删除的)
|
||||
*/
|
||||
boolean existsByNameAndDeletedFalse(String name);
|
||||
|
||||
Optional<Role> findByCodeAndDeletedFalse(String code);
|
||||
/**
|
||||
* 获取用户的所有角色ID
|
||||
*/
|
||||
@Query(value = "SELECT role_id FROM sys_user_role WHERE user_id = :userId AND deleted = false",
|
||||
nativeQuery = true)
|
||||
List<Long> findRoleIdsByUserId(@Param("userId") Long userId);
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//package com.qqchen.deploy.backend.repository;
|
||||
//
|
||||
//
|
||||
//import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
//import com.qqchen.deploy.backend.entity.UserRole;
|
||||
//import org.springframework.data.jpa.repository.Modifying;
|
||||
//import org.springframework.data.jpa.repository.Query;
|
||||
//import org.springframework.data.repository.query.Param;
|
||||
//import org.springframework.stereotype.Repository;
|
||||
//
|
||||
//import java.util.Set;
|
||||
//
|
||||
//@Repository
|
||||
//public interface IUserRoleRepository extends IBaseRepository<UserRole, Long> {
|
||||
//
|
||||
// @Query("SELECT ur FROM UserRole ur WHERE ur.userId = :userId")
|
||||
// Set<UserRole> findByUserId(@Param("userId") Long userId);
|
||||
//
|
||||
// @Modifying
|
||||
// @Query("DELETE FROM UserRole ur WHERE ur.userId = :userId AND ur.roleId = :roleId")
|
||||
// void deleteByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
|
||||
//
|
||||
//
|
||||
// @Query("SELECT COUNT(ur) > 0 FROM UserRole ur WHERE ur.userId = :userId AND ur.roleId = :roleId")
|
||||
// boolean existsByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
|
||||
//
|
||||
//}
|
||||
@ -1,18 +1,29 @@
|
||||
//package com.qqchen.deploy.backend.service;
|
||||
//
|
||||
//
|
||||
//import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
//import com.qqchen.deploy.backend.entity.Role;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//public interface IRoleService extends IBaseService<Role, Long> {
|
||||
//
|
||||
// void validateCode(String code);
|
||||
//
|
||||
// void validateName(String name);
|
||||
//
|
||||
// List<Long> getRoleMenuIds(Long roleId);
|
||||
//
|
||||
// void updateRoleMenus(Long roleId, List<Long> menuIds);
|
||||
//}
|
||||
package com.qqchen.deploy.backend.service;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import com.qqchen.deploy.backend.entity.Role;
|
||||
import com.qqchen.deploy.backend.model.RoleDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IRoleService extends IBaseService<Role, RoleDTO, Long> {
|
||||
|
||||
/**
|
||||
* 验证角色编码是否存在
|
||||
* @param code 角色编码
|
||||
*/
|
||||
void validateCode(String code);
|
||||
|
||||
/**
|
||||
* 验证角色名称是否存在
|
||||
* @param name 角色名称
|
||||
*/
|
||||
void validateName(String name);
|
||||
|
||||
/**
|
||||
* 获取用户的所有角色ID
|
||||
* @param userId 用户ID
|
||||
* @return 角色ID列表
|
||||
*/
|
||||
List<Long> getUserRoleIds(Long userId);
|
||||
}
|
||||
@ -24,6 +24,18 @@ public interface IUserService extends IBaseService<User, UserDTO, Long> {
|
||||
@Audited(action = "CHANGE_PASSWORD", detail = "修改密码")
|
||||
void changePassword(Long userId, String oldPassword, String newPassword);
|
||||
|
||||
/**
|
||||
* 获取当前用户信息(内部服务使用)
|
||||
* @return 当前用户DTO,包含完整信息
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
LoginResponse getCurrentUser();
|
||||
@Audited(action = "GET_CURRENT_USER", detail = "获取当前用户信息")
|
||||
UserDTO getCurrentUser();
|
||||
|
||||
/**
|
||||
* 获取当前用户信息(前端使用)
|
||||
* @return 当前用户响应,不包含敏感信息
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
LoginResponse getCurrentUserResponse();
|
||||
}
|
||||
@ -9,11 +9,13 @@ import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.qqchen.deploy.backend.model.MenuDTO;
|
||||
import com.qqchen.deploy.backend.model.UserDTO;
|
||||
import com.qqchen.deploy.backend.model.response.LoginResponse;
|
||||
import com.qqchen.deploy.backend.model.response.MenuResponse;
|
||||
import com.qqchen.deploy.backend.repository.IMenuRepository;
|
||||
import com.qqchen.deploy.backend.service.IMenuService;
|
||||
import com.qqchen.deploy.backend.service.IUserService;
|
||||
import com.qqchen.deploy.backend.service.IRoleService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -21,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Comparator;
|
||||
|
||||
import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;
|
||||
|
||||
@ -38,6 +41,9 @@ public class MenuServiceImpl extends BaseServiceImpl<Menu, MenuDTO, Long> implem
|
||||
@Resource
|
||||
private IUserService userService;
|
||||
|
||||
@Resource
|
||||
private IRoleService roleService;
|
||||
|
||||
@Override
|
||||
public List<MenuResponse> getMenuTree() {
|
||||
List<Menu> allMenus = repository.findByDeletedFalseOrderBySort();
|
||||
@ -48,21 +54,37 @@ public class MenuServiceImpl extends BaseServiceImpl<Menu, MenuDTO, Long> implem
|
||||
|
||||
@Override
|
||||
public List<MenuResponse> getUserMenus() {
|
||||
LoginResponse user = userService.getCurrentUser();
|
||||
// TODO: 根据用户角色获取菜单
|
||||
return getMenuTree();
|
||||
// 1. 获取当前用户信息(使用内部服务方法)
|
||||
UserDTO user = userService.getCurrentUser();
|
||||
|
||||
// 2. 通过roleService获取用户的所有角色ID
|
||||
List<Long> roleIds = roleService.getUserRoleIds(user.getId());
|
||||
|
||||
// 3. 获取这些角色关联的所有菜单
|
||||
List<Menu> userMenus = repository.findByRoleIdsAndEnabledTrue(roleIds);
|
||||
|
||||
// 4. 转换为DTO并构建树形结构
|
||||
List<MenuDTO> menuDTOs = converter.toDtoList(userMenus);
|
||||
List<MenuDTO> menuTree = buildMenuTree(menuDTOs);
|
||||
|
||||
// 5. 转换为响应对象
|
||||
return converter.toResponseList(menuTree);
|
||||
}
|
||||
|
||||
private List<MenuDTO> buildMenuTree(List<MenuDTO> menus) {
|
||||
// 使用Map存储所有菜单,便于查找
|
||||
Map<Long, MenuDTO> menuMap = menus.stream()
|
||||
.collect(Collectors.toMap(MenuDTO::getId, menu -> menu));
|
||||
|
||||
List<MenuDTO> rootMenus = new ArrayList<>();
|
||||
|
||||
// 遍历所有菜单,构建树形结构
|
||||
for (MenuDTO menu : menus) {
|
||||
if (menu.getParentId() == null || menu.getParentId() == 0) {
|
||||
// 如果是根菜单,直接添加到结果列表
|
||||
rootMenus.add(menu);
|
||||
} else {
|
||||
// 如果不是根菜单,找到其父菜单并添加到children中
|
||||
MenuDTO parent = menuMap.get(menu.getParentId());
|
||||
if (parent != null) {
|
||||
if (parent.getChildren() == null) {
|
||||
@ -73,6 +95,25 @@ public class MenuServiceImpl extends BaseServiceImpl<Menu, MenuDTO, Long> implem
|
||||
}
|
||||
}
|
||||
|
||||
// 对每一级菜单进行排序
|
||||
sortMenuTree(rootMenus);
|
||||
|
||||
return rootMenus;
|
||||
}
|
||||
|
||||
private void sortMenuTree(List<MenuDTO> menus) {
|
||||
if (menus == null || menus.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据sort字段排序
|
||||
menus.sort(Comparator.comparing(MenuDTO::getSort));
|
||||
|
||||
// 递归排序子菜单
|
||||
for (MenuDTO menu : menus) {
|
||||
if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
|
||||
sortMenuTree(menu.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,139 +1,45 @@
|
||||
//package com.qqchen.deploy.backend.service.impl;
|
||||
//
|
||||
//import com.qqchen.application.query.RoleQuery;
|
||||
//import com.qqchen.application.service.RoleService;
|
||||
//import com.qqchen.common.exception.ApiException;
|
||||
//import com.qqchen.common.service.impl.BaseServiceImpl;
|
||||
//import com.qqchen.domain.entity.Role;
|
||||
//import com.qqchen.domain.entity.RoleMenu;
|
||||
//import com.qqchen.domain.repository.RoleMenuRepository;
|
||||
//import com.qqchen.domain.repository.RoleRepository;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.data.jpa.repository.JpaRepository;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.List;
|
||||
//import java.util.stream.Collectors;
|
||||
//
|
||||
//@Slf4j
|
||||
//@Service
|
||||
//@RequiredArgsConstructor
|
||||
//public class RoleServiceImpl extends BaseServiceImpl<Role, RoleQuery> implements RoleService {
|
||||
//
|
||||
// private final RoleRepository roleRepository;
|
||||
// private final RoleMenuRepository roleMenuRepository;
|
||||
//
|
||||
// @Override
|
||||
// protected JpaRepository<Role, Long> getRepository() {
|
||||
// return roleRepository;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public List<Long> getRoleMenuIds(Long roleId) {
|
||||
// return roleMenuRepository.findByRoleId(roleId)
|
||||
// .stream()
|
||||
// .map(RoleMenu::getMenuId)
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// @Transactional
|
||||
// public void updateRoleMenus(Long roleId, List<Long> menuIds) {
|
||||
// // 验证角色是否存在
|
||||
// Role role = findById(roleId)
|
||||
// .orElseThrow(() -> new ApiException("角色不存在"));
|
||||
//
|
||||
// // 不允许修改超级管理员的权限
|
||||
// if ("ROLE_ADMIN".equals(role.getCode())) {
|
||||
// throw new ApiException("不能修改超级管理员的权限");
|
||||
// }
|
||||
//
|
||||
// // 删除原有权限
|
||||
// roleMenuRepository.deleteByRoleId(roleId);
|
||||
//
|
||||
// // 保存新的权限
|
||||
// if (menuIds != null && !menuIds.isEmpty()) {
|
||||
// List<RoleMenu> roleMenus = menuIds.stream()
|
||||
// .map(menuId -> {
|
||||
// RoleMenu roleMenu = new RoleMenu();
|
||||
// roleMenu.setRoleId(roleId);
|
||||
// roleMenu.setMenuId(menuId);
|
||||
// return roleMenu;
|
||||
// })
|
||||
// .collect(Collectors.toList());
|
||||
// roleMenuRepository.saveAll(roleMenus);
|
||||
// }
|
||||
//
|
||||
// log.info("角色 {} 的权限已更新", role.getName());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// @Transactional
|
||||
// public void delete(Long id) {
|
||||
// Role role = findById(id)
|
||||
// .orElseThrow(() -> new ApiException("角色不存在"));
|
||||
//
|
||||
// // 不允许删除超级管理员角色
|
||||
// if ("ROLE_ADMIN".equals(role.getCode())) {
|
||||
// throw new ApiException("不能删除超级管理员角色");
|
||||
// }
|
||||
//
|
||||
// // 执行软删除
|
||||
// role.setDeleted(true);
|
||||
// roleRepository.save(role);
|
||||
// log.info("角色 {} 已删除", role.getName());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// @Transactional
|
||||
// public Role save(Role entity) {
|
||||
// validateCode(entity.getCode());
|
||||
// validateName(entity.getName());
|
||||
// entity.setDeleted(false);
|
||||
// return super.save(entity);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// @Transactional
|
||||
// public Role update(Long id, Role entity) {
|
||||
// Role existing = findById(id)
|
||||
// .orElseThrow(() -> new ApiException("角色不存在"));
|
||||
//
|
||||
// // 不允许修改超级管理员角色的编码
|
||||
// if ("ROLE_ADMIN".equals(existing.getCode()) && !existing.getCode().equals(entity.getCode())) {
|
||||
// throw new ApiException("不能修改超级管理员角色的编码");
|
||||
// }
|
||||
//
|
||||
// if (!existing.getCode().equals(entity.getCode())) {
|
||||
// validateCode(entity.getCode());
|
||||
// }
|
||||
// if (!existing.getName().equals(entity.getName())) {
|
||||
// validateName(entity.getName());
|
||||
// }
|
||||
//
|
||||
// entity.setVersion(existing.getVersion());
|
||||
// entity.setDeleted(existing.getDeleted());
|
||||
// return super.update(id, entity);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void validateCode(String code) {
|
||||
// if (roleRepository.existsByCodeAndDeletedFalse(code)) {
|
||||
// throw new ApiException("角色编码已存在");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void validateName(String name) {
|
||||
// if (roleRepository.existsByNameAndDeletedFalse(name)) {
|
||||
// throw new ApiException("角色名称已存在");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public List<Role> findAll() {
|
||||
// return roleRepository.findByDeletedFalseOrderBySort();
|
||||
// }
|
||||
//}
|
||||
package com.qqchen.deploy.backend.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.Role;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.model.RoleDTO;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.qqchen.deploy.backend.repository.IRoleRepository;
|
||||
import com.qqchen.deploy.backend.service.IRoleService;
|
||||
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ServiceType(DATABASE)
|
||||
public class RoleServiceImpl extends BaseServiceImpl<Role, RoleDTO, Long> implements IRoleService {
|
||||
|
||||
@Resource
|
||||
private IRoleRepository repository;
|
||||
|
||||
@Override
|
||||
public List<Long> getUserRoleIds(Long userId) {
|
||||
return repository.findRoleIdsByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateCode(String code) {
|
||||
if (repository.existsByCodeAndDeletedFalse(code)) {
|
||||
throw new BusinessException(ResponseCode.ROLE_CODE_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateName(String name) {
|
||||
if (repository.existsByNameAndDeletedFalse(name)) {
|
||||
throw new BusinessException(ResponseCode.ROLE_NAME_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,13 +132,20 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
@Audited(action = "GET_CURRENT_USER", detail = "获取当前用户信息")
|
||||
public LoginResponse getCurrentUser() {
|
||||
public UserDTO getCurrentUser() {
|
||||
String username = SecurityUtils.getCurrentUsername();
|
||||
User user = userRepository.findByUsernameAndDeletedFalse(username)
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
|
||||
|
||||
LoginResponse response = userConverter.toLoginResponse(user);
|
||||
log.debug("获取当前用户信息: {}", user.getUsername());
|
||||
return response;
|
||||
return userConverter.toDto(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public LoginResponse getCurrentUserResponse() {
|
||||
// 复用getCurrentUser方法,直接转换DTO为LoginResponse
|
||||
UserDTO userDTO = getCurrentUser();
|
||||
return userConverter.toLoginResponse(userDTO);
|
||||
}
|
||||
}
|
||||
@ -77,3 +77,101 @@ CREATE TABLE sys_menu (
|
||||
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用(0禁用 1启用)'
|
||||
) COMMENT '菜单表';
|
||||
|
||||
-- 角色表
|
||||
CREATE TABLE sys_role (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
create_by VARCHAR(255),
|
||||
create_time DATETIME(6),
|
||||
deleted BIT NOT NULL DEFAULT 0,
|
||||
update_by VARCHAR(255),
|
||||
update_time DATETIME(6),
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
code VARCHAR(100) NOT NULL COMMENT '角色编码',
|
||||
name VARCHAR(100) NOT NULL COMMENT '角色名称',
|
||||
type INT NOT NULL DEFAULT 2 COMMENT '角色类型(1:系统角色 2:自定义角色)',
|
||||
description VARCHAR(255) COMMENT '角色描述',
|
||||
sort INT NOT NULL DEFAULT 0 COMMENT '显示顺序',
|
||||
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
|
||||
|
||||
CONSTRAINT UK_role_code UNIQUE (code)
|
||||
) COMMENT '角色表';
|
||||
|
||||
-- 角色标签表
|
||||
CREATE TABLE sys_role_tag (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
create_by VARCHAR(255),
|
||||
create_time DATETIME(6),
|
||||
deleted BIT NOT NULL DEFAULT 0,
|
||||
update_by VARCHAR(255),
|
||||
update_time DATETIME(6),
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
name VARCHAR(50) NOT NULL COMMENT '标签名称',
|
||||
color VARCHAR(20) COMMENT '标签颜色'
|
||||
) COMMENT '角色标签表';
|
||||
|
||||
-- 角色标签关联表
|
||||
CREATE TABLE sys_role_tag_relation (
|
||||
role_id BIGINT NOT NULL COMMENT '角色ID',
|
||||
tag_id BIGINT NOT NULL COMMENT '标签ID',
|
||||
PRIMARY KEY (role_id, tag_id),
|
||||
CONSTRAINT FK_role_tag_role FOREIGN KEY (role_id) REFERENCES sys_role (id),
|
||||
CONSTRAINT FK_role_tag_tag FOREIGN KEY (tag_id) REFERENCES sys_role_tag (id)
|
||||
) COMMENT '角色标签关联表';
|
||||
|
||||
-- 用户角色关联表
|
||||
CREATE TABLE sys_user_role (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
create_by VARCHAR(255),
|
||||
create_time DATETIME(6),
|
||||
deleted BIT NOT NULL DEFAULT 0,
|
||||
update_by VARCHAR(255),
|
||||
update_time DATETIME(6),
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
role_id BIGINT NOT NULL COMMENT '角色ID',
|
||||
|
||||
CONSTRAINT UK_user_role UNIQUE (user_id, role_id),
|
||||
CONSTRAINT FK_user_role_user FOREIGN KEY (user_id) REFERENCES sys_user (id),
|
||||
CONSTRAINT FK_user_role_role FOREIGN KEY (role_id) REFERENCES sys_role (id)
|
||||
) COMMENT '用户角色关联表';
|
||||
|
||||
-- 角色菜单关联表
|
||||
CREATE TABLE sys_role_menu (
|
||||
role_id BIGINT NOT NULL COMMENT '角色ID',
|
||||
menu_id BIGINT NOT NULL COMMENT '菜单ID',
|
||||
PRIMARY KEY (role_id, menu_id),
|
||||
CONSTRAINT FK_role_menu_role FOREIGN KEY (role_id) REFERENCES sys_role (id),
|
||||
CONSTRAINT FK_role_menu_menu FOREIGN KEY (menu_id) REFERENCES sys_menu (id)
|
||||
) COMMENT '角色菜单关联表';
|
||||
|
||||
-- 权限模板表
|
||||
CREATE TABLE sys_permission_template (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
create_by VARCHAR(255),
|
||||
create_time DATETIME(6),
|
||||
deleted BIT NOT NULL DEFAULT 0,
|
||||
update_by VARCHAR(255),
|
||||
update_time DATETIME(6),
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
|
||||
code VARCHAR(100) NOT NULL COMMENT '模板编码',
|
||||
name VARCHAR(100) NOT NULL COMMENT '模板名称',
|
||||
type INT NOT NULL DEFAULT 1 COMMENT '模板类型(1:系统模板 2:自定义模板)',
|
||||
description VARCHAR(255) COMMENT '模板描述',
|
||||
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
|
||||
|
||||
CONSTRAINT UK_template_code UNIQUE (code)
|
||||
) COMMENT '权限模板表';
|
||||
|
||||
-- 模板菜单关联表
|
||||
CREATE TABLE sys_template_menu (
|
||||
template_id BIGINT NOT NULL COMMENT '模板ID',
|
||||
menu_id BIGINT NOT NULL COMMENT '菜单ID',
|
||||
PRIMARY KEY (template_id, menu_id),
|
||||
CONSTRAINT FK_template_menu_template FOREIGN KEY (template_id) REFERENCES sys_permission_template (id),
|
||||
CONSTRAINT FK_template_menu_menu FOREIGN KEY (menu_id) REFERENCES sys_menu (id)
|
||||
) COMMENT '模板菜单关联表';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
-- 插入初始租户
|
||||
-- 初始化租户
|
||||
INSERT INTO sys_tenant
|
||||
(create_by, create_time, deleted, update_by, update_time, version,
|
||||
address, code, contact_name, contact_phone, email, enabled, name)
|
||||
@ -7,56 +7,92 @@ VALUES
|
||||
'北京市朝阳区望京SOHO T1 C座', 'default', '张三', '13900000001',
|
||||
'admin@deploy-ease.com', 1, '默认租户');
|
||||
|
||||
-- 插入管理员用户
|
||||
INSERT INTO sys_user
|
||||
(create_by, create_time, deleted, update_by, update_time, version,
|
||||
email, enabled, nickname, password, phone, username)
|
||||
VALUES
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'admin@deploy-ease.com', 1, '系统管理员',
|
||||
'$2a$10$B5qWUPyWyXxfm6Jq4JKcAOp/XcQLjtv3jifafsqPqZvzY9owae2ve', -- 密码: admin123
|
||||
'13800138000', 'admin');
|
||||
|
||||
-- 系统参数初始化
|
||||
INSERT INTO sys_param (code, name, value, type, description, enabled, create_by, create_time)
|
||||
INSERT INTO sys_param (code, name, value, type, description, enabled, create_by, create_time, deleted, version)
|
||||
VALUES
|
||||
('SYSTEM_NAME', '系统名称', 'DevOps平台', 'TEXT', '系统显示名称', 1, 'system', '2024-01-01 00:00:00'),
|
||||
('SYSTEM_LOGO', '系统Logo', '/logo.png', 'TEXT', '系统Logo路径', 1, 'system', '2024-01-01 00:00:00'),
|
||||
('GENDER_ENUM', '性别枚举', '[{"code":"1","name":"男"},{"code":"2","name":"女"}]', 'ENUM', '性别枚举值', 1, 'system', '2024-01-01 00:00:00'),
|
||||
('USER_STATUS_ENUM', '用户状态枚举', '[{"code":"0","name":"禁用"},{"code":"1","name":"启用"}]', 'ENUM', '用户状态枚举值', 1, 'system', '2024-01-01 00:00:00');
|
||||
('SYSTEM_NAME', '系统名称', 'DevOps平台', 'TEXT', '系统显示名称', 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
('SYSTEM_LOGO', '系统Logo', '/logo.png', 'TEXT', '系统Logo路径', 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
('GENDER_ENUM', '性别枚举', '[{"code":"1","name":"男"},{"code":"2","name":"女"}]', 'ENUM', '性别枚举值', 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
('USER_STATUS_ENUM', '用户状态枚举', '[{"code":"0","name":"禁用"},{"code":"1","name":"启用"}]', 'ENUM', '用户状态枚举值', 1, 'system', '2024-01-01 00:00:00', 0, 0);
|
||||
|
||||
-- 初始化系统管理菜单
|
||||
INSERT INTO sys_menu (create_by, create_time, deleted, update_by, update_time, version,
|
||||
INSERT INTO sys_menu (id, create_by, create_time, deleted, update_by, update_time, version,
|
||||
name, path, component, icon, type, parent_id, sort, hidden, enabled)
|
||||
VALUES
|
||||
-- 系统管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(1, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'系统管理', '/system', null, 'setting', 1, null, 1, 0, 1),
|
||||
|
||||
-- 用户管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(2, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'用户管理', '/system/user', '/System/User', 'user', 2, 1, 1, 0, 1),
|
||||
|
||||
-- 角色管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(3, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'角色管理', '/system/role', '/System/Role', 'team', 2, 1, 2, 0, 1),
|
||||
|
||||
-- 菜单管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(4, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'菜单管理', '/system/menu', '/System/Menu', 'menu', 2, 1, 3, 0, 1),
|
||||
|
||||
-- 部门管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(5, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'部门管理', '/system/department', '/System/Department', 'apartment', 2, 1, 4, 0, 1),
|
||||
|
||||
-- 租户管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(6, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'租户管理', '/system/tenant', '/System/Tenant', 'cluster', 2, 1, 5, 0, 1),
|
||||
|
||||
-- Jenkins管理
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(7, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'Jenkins管理', '/system/jenkins', '/System/Jenkins', 'cloud-server', 2, 1, 6, 0, 1),
|
||||
|
||||
-- 代码仓库
|
||||
('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
(8, 'system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
|
||||
'代码仓库', '/system/repository', '/System/Repository', 'code', 2, 1, 7, 0, 1);
|
||||
|
||||
-- 初始化角色标签
|
||||
INSERT INTO sys_role_tag (id, name, color, create_by, create_time, deleted, version) VALUES
|
||||
(1, '研发', '#1890FF', 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(2, '运维', '#52C41A', 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(3, '安全', '#FF4D4F', 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(4, '临时', '#FAAD14', 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(5, '外部', '#722ED1', 'system', '2024-01-01 00:00:00', 0, 0);
|
||||
|
||||
-- 初始化用户
|
||||
INSERT INTO sys_user (id, username, password, nickname, email, phone, enabled, create_by, create_time, deleted, version)
|
||||
VALUES
|
||||
(1, 'admin', '$2a$10$zXuXOF3C.w/ZpjayaE1P/eFRov/3vJAAOBs.uy2kHUoK3SyuR/Wte', '超级管理员', 'admin@deploy-ease.com', '13800138000', 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(2, 'dev_manager', '$2a$10$zXuXOF3C.w/ZpjayaE1P/eFRov/3vJAAOBs.uy2kHUoK3SyuR/Wte', '开发主管', 'dev@deploy-ease.com', '13800138001', 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(3, 'ops_manager', '$2a$10$zXuXOF3C.w/ZpjayaE1P/eFRov/3vJAAOBs.uy2kHUoK3SyuR/Wte', '运维主管', 'ops@deploy-ease.com', '13800138002', 1, 'system', '2024-01-01 00:00:00', 0, 0);
|
||||
|
||||
-- 初始化角色
|
||||
INSERT INTO sys_role (id, code, name, type, description, sort, enabled, create_by, create_time, deleted, version)
|
||||
VALUES
|
||||
(1, 'SUPER_ADMIN', '超级管理员', 1, '系统超级管理员', 1, 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(2, 'DEV_MANAGER', '开发主管', 2, '开发团队主管', 2, 1, 'system', '2024-01-01 00:00:00', 0, 0),
|
||||
(3, 'OPS_MANAGER', '运维主管', 2, '运维团队主管', 3, 1, 'system', '2024-01-01 00:00:00', 0, 0);
|
||||
|
||||
-- 用户角色关联
|
||||
INSERT INTO sys_user_role (user_id, role_id, create_by, create_time)
|
||||
VALUES
|
||||
(1, 1, 'system', '2024-01-01 00:00:00'), -- 超级管理员 -> 超级管理员角色
|
||||
(2, 2, 'system', '2024-01-01 00:00:00'), -- 开发主管 -> 开发主管角色
|
||||
(3, 3, 'system', '2024-01-01 00:00:00'); -- 运维主管 -> 运维主管角色
|
||||
|
||||
-- 角色菜单关联
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
VALUES
|
||||
-- 超级管理员拥有所有菜单权限
|
||||
(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8),
|
||||
-- 开发主管权限
|
||||
(2, 7), (2, 8),
|
||||
-- 运维主管权限
|
||||
(3, 7), (3, 8);
|
||||
|
||||
-- 角色标签关联
|
||||
INSERT INTO sys_role_tag_relation (role_id, tag_id)
|
||||
VALUES
|
||||
(1, 3), -- 超级管理员 -> 安全标签
|
||||
(2, 1), -- 开发主管 -> 研发标签
|
||||
(3, 2); -- 运维主管 -> 运维标签
|
||||
@ -39,3 +39,11 @@ dependency.injection.entitypath.failed=初始化实体 {0} 的EntityPath失败:
|
||||
jwt.token.expired=登录已过期,请重新登录
|
||||
jwt.token.invalid=无效的登录凭证
|
||||
jwt.token.missing=未提供登录凭证
|
||||
|
||||
# 角色相关错误消息
|
||||
role.not.found=角色不存在
|
||||
role.code.exists=角色编码已存在
|
||||
role.name.exists=角色名称已存在
|
||||
role.in.use=角色正在使用中,无法删除
|
||||
role.admin.cannot.delete=不能删除超级管理员角色
|
||||
role.admin.cannot.update=不能修改超级管理员角色
|
||||
@ -39,3 +39,11 @@ dependency.injection.entitypath.failed=Failed to initialize EntityPath for entit
|
||||
jwt.token.expired=Login expired, please login again
|
||||
jwt.token.invalid=Invalid token
|
||||
jwt.token.missing=No token provided
|
||||
|
||||
# Role related error messages
|
||||
role.not.found=Role not found
|
||||
role.code.exists=Role code already exists
|
||||
role.name.exists=Role name already exists
|
||||
role.in.use=Role is in use and cannot be deleted
|
||||
role.admin.cannot.delete=Cannot delete admin role
|
||||
role.admin.cannot.update=Cannot update admin role
|
||||
@ -34,3 +34,14 @@ dependency.injection.service.not.found=找不到实体 {0} 对应的服务 (尝
|
||||
dependency.injection.repository.not.found=找不到实体 {0} 对应的Repository: {1}
|
||||
dependency.injection.converter.not.found=找不到实体 {0} 对应的Converter: {1}
|
||||
dependency.injection.entitypath.failed=初始化实体 {0} 的EntityPath失败: {1}
|
||||
|
||||
# 角色相关错误消息
|
||||
role.not.found=角色不存在
|
||||
role.code.exists=角色编码已存在
|
||||
role.name.exists=角色名称已存在
|
||||
role.in.use=角色正在使用中,无法删除
|
||||
role.admin.cannot.delete=不能删除超级管理员角色
|
||||
role.admin.cannot.update=不能修改超级管理员角色
|
||||
|
||||
# 请求相关错误消息
|
||||
request.api.not.found=请求的API不存在: {0}
|
||||
Loading…
Reference in New Issue
Block a user