package com.tcm.training.admin.user.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.tcm.training.admin.common.PageResponse;
|
import com.tcm.training.admin.user.dto.RoleSaveRequest;
|
import com.tcm.training.admin.user.entity.SysMenu;
|
import com.tcm.training.admin.user.entity.SysRole;
|
import com.tcm.training.admin.user.entity.SysRoleMenu;
|
import com.tcm.training.admin.user.mapper.SysMenuMapper;
|
import com.tcm.training.admin.user.mapper.SysRoleMapper;
|
import com.tcm.training.admin.user.mapper.SysRoleMenuMapper;
|
import com.tcm.training.admin.user.row.RoleDetailRow;
|
import com.tcm.training.admin.user.row.RoleListRow;
|
import com.tcm.training.admin.user.vo.PermissionTreeNodeVO;
|
import com.tcm.training.admin.user.vo.RoleDetailVO;
|
import com.tcm.training.admin.user.vo.RoleListItemVO;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDateTime;
|
import java.util.ArrayList;
|
import java.util.LinkedHashMap;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.UUID;
|
|
@Service
|
public class RoleAppService {
|
|
private static final String SUPER_ADMIN_CODE = "SUPER_ADMIN";
|
|
private final SysRoleMapper sysRoleMapper;
|
private final SysMenuMapper sysMenuMapper;
|
private final SysRoleMenuMapper sysRoleMenuMapper;
|
|
public RoleAppService(
|
SysRoleMapper sysRoleMapper,
|
SysMenuMapper sysMenuMapper,
|
SysRoleMenuMapper sysRoleMenuMapper
|
) {
|
this.sysRoleMapper = sysRoleMapper;
|
this.sysMenuMapper = sysMenuMapper;
|
this.sysRoleMenuMapper = sysRoleMenuMapper;
|
}
|
|
public PageResponse<RoleListItemVO> page(int page, int pageSize, String roleName) {
|
IPage<RoleListRow> records = sysRoleMapper.selectRolePage(new Page<RoleListRow>(page, pageSize), roleName);
|
List<RoleListItemVO> list = new ArrayList<RoleListItemVO>();
|
for (RoleListRow row : records.getRecords()) {
|
RoleListItemVO item = new RoleListItemVO();
|
item.setId(row.getId());
|
item.setRoleName(row.getRoleName());
|
item.setAccountCount(row.getAccountCount() == null ? 0L : row.getAccountCount());
|
item.setCreatedAt(row.getCreatedAt());
|
item.setRemark(row.getRemark());
|
list.add(item);
|
}
|
return PageResponse.of(list, records.getTotal(), records.getCurrent(), records.getSize());
|
}
|
|
public RoleDetailVO detail(Long id) {
|
RoleDetailRow row = sysRoleMapper.selectRoleDetail(id);
|
if (row == null) {
|
throw new IllegalArgumentException("角色不存在");
|
}
|
RoleDetailVO vo = new RoleDetailVO();
|
vo.setId(row.getId());
|
vo.setRoleName(row.getRoleName());
|
vo.setRemark(row.getRemark());
|
vo.setAccountCount(row.getAccountCount() == null ? 0L : row.getAccountCount());
|
vo.setCreatedAt(row.getCreatedAt());
|
vo.setUpdatedAt(row.getUpdatedAt());
|
vo.setPermissionIds(sysRoleMapper.selectPermissionIdsByRoleId(id));
|
return vo;
|
}
|
|
public List<PermissionTreeNodeVO> permissionTree() {
|
List<SysMenu> menus = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>()
|
.eq(SysMenu::getDeleted, 0)
|
.eq(SysMenu::getStatus, 1)
|
.orderByAsc(SysMenu::getSort, SysMenu::getId));
|
Map<Long, PermissionTreeNodeVO> nodeMap = new LinkedHashMap<Long, PermissionTreeNodeVO>();
|
List<PermissionTreeNodeVO> roots = new ArrayList<PermissionTreeNodeVO>();
|
for (SysMenu menu : menus) {
|
PermissionTreeNodeVO node = new PermissionTreeNodeVO();
|
node.setId(menu.getId());
|
node.setParentId(menu.getParentId());
|
node.setName(menu.getName());
|
node.setType(menu.getType());
|
node.setPermissionKey(menu.getPermissionKey());
|
nodeMap.put(node.getId(), node);
|
}
|
for (SysMenu menu : menus) {
|
PermissionTreeNodeVO node = nodeMap.get(menu.getId());
|
PermissionTreeNodeVO parent = nodeMap.get(menu.getParentId());
|
if (parent == null || menu.getParentId() == null || menu.getParentId() == 0L) {
|
roots.add(node);
|
} else {
|
parent.getChildren().add(node);
|
}
|
}
|
return roots;
|
}
|
|
@Transactional
|
public RoleDetailVO create(RoleSaveRequest req) {
|
String roleName = req.getRoleName().trim();
|
ensureRoleNameUnique(roleName, null);
|
List<Long> permissionIds = normalizePermissionIds(req.getPermissionIds());
|
validatePermissionIds(permissionIds);
|
|
SysRole role = new SysRole();
|
role.setRoleName(roleName);
|
role.setRoleCode(generateRoleCode());
|
role.setRemark(normalizeRemark(req.getRemark()));
|
role.setStatus(1);
|
role.setDeleted(0);
|
role.setCreatedAt(LocalDateTime.now());
|
role.setUpdatedAt(LocalDateTime.now());
|
sysRoleMapper.insert(role);
|
|
saveRoleMenus(role.getId(), permissionIds);
|
return detail(role.getId());
|
}
|
|
@Transactional
|
public RoleDetailVO update(Long id, RoleSaveRequest req) {
|
SysRole role = requireRole(id);
|
String roleName = req.getRoleName().trim();
|
ensureRoleNameUnique(roleName, id);
|
List<Long> permissionIds = normalizePermissionIds(req.getPermissionIds());
|
validatePermissionIds(permissionIds);
|
|
role.setRoleName(roleName);
|
role.setRemark(normalizeRemark(req.getRemark()));
|
role.setUpdatedAt(LocalDateTime.now());
|
sysRoleMapper.updateById(role);
|
|
saveRoleMenus(id, permissionIds);
|
return detail(id);
|
}
|
|
@Transactional
|
public void delete(Long id) {
|
SysRole role = requireRole(id);
|
if (SUPER_ADMIN_CODE.equals(role.getRoleCode())) {
|
throw new IllegalArgumentException("超级管理员角色不允许删除");
|
}
|
long bindCount = sysRoleMapper.countAccountBindingsByRoleId(id);
|
if (bindCount > 0) {
|
throw new IllegalArgumentException("该角色已关联帐号,暂不允许删除");
|
}
|
|
role.setStatus(0);
|
role.setUpdatedAt(LocalDateTime.now());
|
sysRoleMapper.updateById(role);
|
sysRoleMapper.deleteById(id);
|
sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>()
|
.eq(SysRoleMenu::getRoleId, id));
|
}
|
|
private SysRole requireRole(Long id) {
|
SysRole role = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRole>()
|
.eq(SysRole::getId, id)
|
.eq(SysRole::getDeleted, 0)
|
.last("limit 1"));
|
if (role == null) {
|
throw new IllegalArgumentException("角色不存在");
|
}
|
return role;
|
}
|
|
private void ensureRoleNameUnique(String roleName, Long excludeId) {
|
LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<SysRole>()
|
.eq(SysRole::getRoleName, roleName)
|
.eq(SysRole::getDeleted, 0);
|
if (excludeId != null) {
|
wrapper.ne(SysRole::getId, excludeId);
|
}
|
SysRole exists = sysRoleMapper.selectOne(wrapper.last("limit 1"));
|
if (exists != null) {
|
throw new IllegalArgumentException("角色名称已存在");
|
}
|
}
|
|
private List<Long> normalizePermissionIds(List<Long> permissionIds) {
|
Set<Long> idSet = new LinkedHashSet<Long>();
|
if (permissionIds != null) {
|
for (Long permissionId : permissionIds) {
|
if (permissionId != null) {
|
idSet.add(permissionId);
|
}
|
}
|
}
|
return new ArrayList<Long>(idSet);
|
}
|
|
private void validatePermissionIds(List<Long> permissionIds) {
|
if (permissionIds.isEmpty()) {
|
throw new IllegalArgumentException("操作权限不能为空");
|
}
|
List<SysMenu> menus = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>()
|
.in(SysMenu::getId, permissionIds)
|
.eq(SysMenu::getDeleted, 0)
|
.eq(SysMenu::getStatus, 1));
|
if (menus.size() != permissionIds.size()) {
|
throw new IllegalArgumentException("存在无效的操作权限");
|
}
|
}
|
|
private void saveRoleMenus(Long roleId, List<Long> permissionIds) {
|
sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>()
|
.eq(SysRoleMenu::getRoleId, roleId));
|
LocalDateTime now = LocalDateTime.now();
|
for (Long permissionId : permissionIds) {
|
SysRoleMenu relation = new SysRoleMenu();
|
relation.setRoleId(roleId);
|
relation.setMenuId(permissionId);
|
relation.setCreatedAt(now);
|
sysRoleMenuMapper.insert(relation);
|
}
|
}
|
|
private String normalizeRemark(String remark) {
|
if (remark == null) {
|
return null;
|
}
|
String trimmed = remark.trim();
|
return trimmed.isEmpty() ? null : trimmed;
|
}
|
|
private String generateRoleCode() {
|
for (int i = 0; i < 10; i++) {
|
String code = "ROLE_" + UUID.randomUUID().toString().replace("-", "")
|
.substring(0, 12).toUpperCase();
|
SysRole exists = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRole>()
|
.eq(SysRole::getRoleCode, code)
|
.last("limit 1"));
|
if (exists == null) {
|
return code;
|
}
|
}
|
throw new IllegalStateException("角色编码生成失败");
|
}
|
}
|