SystemRoleServiceImpl.java 6.38 KB
package com.diligrp.rider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.diligrp.rider.common.enums.AdminRoleScopeEnum;
import com.diligrp.rider.common.exception.BizException;
import com.diligrp.rider.dto.AdminRoleSaveDTO;
import com.diligrp.rider.entity.AdminUser;
import com.diligrp.rider.entity.Substation;
import com.diligrp.rider.entity.SysRole;
import com.diligrp.rider.entity.SysRoleMenu;
import com.diligrp.rider.mapper.AdminUserMapper;
import com.diligrp.rider.mapper.SubstationMapper;
import com.diligrp.rider.mapper.SysRoleMapper;
import com.diligrp.rider.mapper.SysRoleMenuMapper;
import com.diligrp.rider.service.SystemRoleService;
import com.diligrp.rider.vo.AdminRoleVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
@RequiredArgsConstructor
public class SystemRoleServiceImpl implements SystemRoleService {

    private static final Set<String> BUILT_IN_CODES = Set.of("platform_admin", "substation_admin");

    private final SysRoleMapper sysRoleMapper;
    private final SysRoleMenuMapper sysRoleMenuMapper;
    private final AdminUserMapper adminUserMapper;
    private final SubstationMapper substationMapper;

    @Override
    public List<AdminRoleVO> list(boolean includeDisabled) {
        List<SysRole> roles = sysRoleMapper.selectList(new LambdaQueryWrapper<SysRole>()
                .eq(!includeDisabled, SysRole::getStatus, 1)
                .orderByAsc(SysRole::getId));
        List<AdminRoleVO> result = new ArrayList<>();
        for (SysRole role : roles) {
            result.add(toVO(role));
        }
        return result;
    }

    @Override
    public void add(AdminRoleSaveDTO dto) {
        validateScope(dto.getRoleScope());
        ensureUniqueCode(dto.getCode(), null);

        SysRole role = new SysRole();
        role.setCode(dto.getCode().trim());
        role.setName(dto.getName().trim());
        role.setRoleScope(dto.getRoleScope());
        role.setStatus(1);
        role.setCreateTime(System.currentTimeMillis() / 1000);
        sysRoleMapper.insert(role);
    }

    @Override
    public void edit(AdminRoleSaveDTO dto) {
        if (dto.getId() == null || dto.getId() < 1) {
            throw new BizException("角色ID不能为空");
        }
        SysRole role = requireRole(dto.getId());
        if (isBuiltIn(role)) {
            throw new BizException("内置角色不允许编辑");
        }
        validateScope(dto.getRoleScope());
        if (!role.getRoleScope().equals(dto.getRoleScope())) {
            throw new BizException("角色范围不允许修改");
        }
        ensureUniqueCode(dto.getCode(), role.getId());
        role.setCode(dto.getCode().trim());
        role.setName(dto.getName().trim());
        sysRoleMapper.updateById(role);
    }

    @Override
    public void ban(Long id) {
        SysRole role = requireRole(id);
        if (isBuiltIn(role)) {
            throw new BizException("内置角色不允许禁用");
        }
        ensureNotBound(role.getId(), "当前角色已绑定账号,不能禁用");
        sysRoleMapper.update(null, new LambdaUpdateWrapper<SysRole>()
                .eq(SysRole::getId, id)
                .set(SysRole::getStatus, 0));
    }

    @Override
    public void cancelBan(Long id) {
        requireRole(id);
        sysRoleMapper.update(null, new LambdaUpdateWrapper<SysRole>()
                .eq(SysRole::getId, id)
                .set(SysRole::getStatus, 1));
    }

    @Override
    @Transactional
    public void del(Long id) {
        SysRole role = requireRole(id);
        if (isBuiltIn(role)) {
            throw new BizException("内置角色不允许删除");
        }
        ensureNotBound(role.getId(), "当前角色已绑定账号,不能删除");
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, role.getId()));
        sysRoleMapper.deleteById(role.getId());
    }

    private SysRole requireRole(Long id) {
        if (id == null || id < 1) {
            throw new BizException("角色ID不能为空");
        }
        SysRole role = sysRoleMapper.selectById(id);
        if (role == null) {
            throw new BizException("角色不存在");
        }
        return role;
    }

    private void validateScope(String scope) {
        for (AdminRoleScopeEnum value : AdminRoleScopeEnum.values()) {
            if (value.name().equals(scope)) {
                return;
            }
        }
        throw new BizException("角色范围不合法");
    }

    private void ensureUniqueCode(String code, Long excludeId) {
        SysRole duplicate = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRole>()
                .eq(SysRole::getCode, code.trim())
                .ne(excludeId != null, SysRole::getId, excludeId)
                .last("LIMIT 1"));
        if (duplicate != null) {
            throw new BizException("角色编码已存在");
        }
    }

    private void ensureNotBound(Long roleId, String message) {
        if (countAdminUsers(roleId) > 0 || countSubstations(roleId) > 0) {
            throw new BizException(message);
        }
    }

    private AdminRoleVO toVO(SysRole role) {
        AdminRoleVO vo = new AdminRoleVO();
        vo.setId(role.getId());
        vo.setCode(role.getCode());
        vo.setName(role.getName());
        vo.setRoleScope(role.getRoleScope());
        vo.setStatus(role.getStatus());
        vo.setBuiltIn(isBuiltIn(role));
        vo.setAdminUserCount(countAdminUsers(role.getId()));
        vo.setSubstationCount(countSubstations(role.getId()));
        vo.setCreateTime(role.getCreateTime());
        return vo;
    }

    private boolean isBuiltIn(SysRole role) {
        return BUILT_IN_CODES.contains(role.getCode());
    }

    private long countAdminUsers(Long roleId) {
        Long count = adminUserMapper.selectCount(new LambdaQueryWrapper<AdminUser>()
                .eq(AdminUser::getRoleId, roleId));
        return count == null ? 0L : count;
    }

    private long countSubstations(Long roleId) {
        Long count = substationMapper.selectCount(new LambdaQueryWrapper<Substation>()
                .eq(Substation::getRoleId, roleId));
        return count == null ? 0L : count;
    }
}