package com.emergencyrepair.system.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.emergencyrepair.business.entity.BaseEquipment; import com.emergencyrepair.business.entity.Contractor; import com.emergencyrepair.business.entity.EngineeringMajor; import com.emergencyrepair.business.entity.TeamMajor; import com.emergencyrepair.business.entity.ProductNode; import com.emergencyrepair.business.mapper.BaseEquipmentMapper; import com.emergencyrepair.business.mapper.ContractorMapper; import com.emergencyrepair.business.mapper.EngineeringMajorMapper; import com.emergencyrepair.business.mapper.ProductNodeMapper; import com.emergencyrepair.business.mapper.TeamMajorMapper; import com.emergencyrepair.common.BusinessException; import com.emergencyrepair.system.entity.SysMenu; import com.emergencyrepair.system.entity.SysRole; import com.emergencyrepair.system.entity.SysRoleMenu; import com.emergencyrepair.system.entity.SysRoleUser; import com.emergencyrepair.system.entity.SysTenantMenu; import com.emergencyrepair.system.mapper.SysMenuMapper; import com.emergencyrepair.system.mapper.SysRoleMapper; import com.emergencyrepair.system.mapper.SysRoleMenuMapper; import com.emergencyrepair.system.mapper.SysRoleUserMapper; import com.emergencyrepair.system.mapper.SysTenantMenuMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class SystemService { private final SysMenuMapper menuMapper; private final SysRoleMapper roleMapper; private final SysRoleMenuMapper roleMenuMapper; private final SysTenantMenuMapper tenantMenuMapper; private final SysRoleUserMapper roleUserMapper; private final ContractorMapper contractorMapper; private final EngineeringMajorMapper engineeringMajorMapper; private final TeamMajorMapper teamMajorMapper; private final ProductNodeMapper productNodeMapper; private final BaseEquipmentMapper baseEquipmentMapper; public List menuTree() { List menus = listMenus(); Map map = menus.stream().collect(Collectors.toMap(SysMenu::getId, item -> item)); List roots = new ArrayList<>(); for (SysMenu menu : menus) { if (menu.getPid() == null || menu.getPid() == 0L || !map.containsKey(menu.getPid())) { roots.add(menu); } else { map.get(menu.getPid()).getChildren().add(menu); } } sortTree(roots); return roots; } public List listMenus() { return menuMapper.selectList(Wrappers.lambdaQuery().orderByAsc(SysMenu::getSortNo)); } @Transactional public SysMenu saveMenu(SysMenu menu) { if (!StringUtils.hasText(menu.getName())) { throw new BusinessException("菜单名称不能为空"); } LocalDateTime now = LocalDateTime.now(); menu.setUpdateTime(now); if (menu.getId() == null) { menu.setCreateTime(now); if (menu.getVisible() == null) { menu.setVisible(1); } if (menu.getMenuType() == null) { menu.setMenuType(1); } menuMapper.insert(menu); } else { menuMapper.updateById(menu); } return menuMapper.selectById(menu.getId()); } @Transactional public void deleteMenu(Long id) { long children = menuMapper.selectCount(Wrappers.lambdaQuery().eq(SysMenu::getPid, id)); if (children > 0) { throw new BusinessException("请先删除下级菜单"); } menuMapper.deleteById(id); roleMenuMapper.delete(Wrappers.lambdaQuery().eq(SysRoleMenu::getMenuId, id)); tenantMenuMapper.delete(Wrappers.lambdaQuery().eq(SysTenantMenu::getMenuId, id)); } public List listRoles() { return roleMapper.selectList(Wrappers.lambdaQuery().orderByAsc(SysRole::getSortNo)); } @Transactional public SysRole saveRole(SysRole role) { if (!StringUtils.hasText(role.getName()) || !StringUtils.hasText(role.getCode())) { throw new BusinessException("角色名称和编码不能为空"); } LocalDateTime now = LocalDateTime.now(); role.setUpdateTime(now); if (role.getId() == null) { role.setCreateTime(now); roleMapper.insert(role); } else { roleMapper.updateById(role); } return roleMapper.selectById(role.getId()); } @Transactional public void deleteRole(Long id) { roleMapper.deleteById(id); roleMenuMapper.delete(Wrappers.lambdaQuery().eq(SysRoleMenu::getRoleId, id)); roleUserMapper.delete(Wrappers.lambdaQuery().eq(SysRoleUser::getRoleId, id)); } public List listContractors() { return contractorMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(Contractor::getSortNo).orderByAsc(Contractor::getId)); } @Transactional public Contractor saveContractor(Contractor contractor) { if (!StringUtils.hasText(contractor.getName())) { throw new BusinessException("承修单位名称不能为空"); } LocalDateTime now = LocalDateTime.now(); contractor.setUpdateTime(now); if (contractor.getId() == null) { contractor.setCreateTime(now); contractorMapper.insert(contractor); } else { contractorMapper.updateById(contractor); } return contractorMapper.selectById(contractor.getId()); } @Transactional public void deleteContractor(Long id) { contractorMapper.deleteById(id); } public List listEngineeringMajors() { return engineeringMajorMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(EngineeringMajor::getId)); } @Transactional public EngineeringMajor saveEngineeringMajor(EngineeringMajor major) { if (major == null || !StringUtils.hasText(major.getName())) { throw new BusinessException("工程专业名称不能为空"); } String name = major.getName().trim(); LambdaQueryWrapper duplicate = Wrappers.lambdaQuery() .eq(EngineeringMajor::getName, name); if (major.getId() != null) { duplicate.ne(EngineeringMajor::getId, major.getId()); } if (engineeringMajorMapper.selectCount(duplicate) > 0) { throw new BusinessException("工程专业名称已存在:" + name); } LocalDateTime now = LocalDateTime.now(); major.setName(name); major.setUpdateTime(now); if (major.getId() == null) { major.setCreateTime(now); engineeringMajorMapper.insert(major); } else { engineeringMajorMapper.updateById(major); } return engineeringMajorMapper.selectById(major.getId()); } @Transactional public void deleteEngineeringMajor(Long id) { engineeringMajorMapper.deleteById(id); } public List listTeamMajors() { return teamMajorMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(TeamMajor::getId)); } @Transactional public TeamMajor saveTeamMajor(TeamMajor major) { if (major == null || !StringUtils.hasText(major.getName())) { throw new BusinessException("T队专业名称不能为空"); } String name = major.getName().trim(); String category = StringUtils.hasText(major.getCategory()) ? major.getCategory().trim().toUpperCase() : ""; if (!"A".equals(category) && !"B".equals(category)) { throw new BusinessException("T队专业分类只能是A或B"); } LambdaQueryWrapper duplicate = Wrappers.lambdaQuery() .eq(TeamMajor::getName, name); if (major.getId() != null) { duplicate.ne(TeamMajor::getId, major.getId()); } if (teamMajorMapper.selectCount(duplicate) > 0) { throw new BusinessException("T队专业名称已存在:" + name); } LocalDateTime now = LocalDateTime.now(); major.setName(name); major.setCategory(category); major.setUpdateTime(now); if (major.getId() == null) { major.setCreateTime(now); teamMajorMapper.insert(major); } else { teamMajorMapper.updateById(major); } return teamMajorMapper.selectById(major.getId()); } @Transactional public void deleteTeamMajor(Long id) { teamMajorMapper.deleteById(id); } public List> tree(String type) { if ("product".equals(type)) { return productTree(); } if ("base".equals(type)) { return baseTree(); } throw new BusinessException("未知树类型"); } public List> productTree() { List nodes = productNodeMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(ProductNode::getNodeLevel).orderByAsc(ProductNode::getSortNo)); Map> map = new LinkedHashMap<>(); for (ProductNode node : nodes) { map.put(node.getId(), mapProduct(node)); } List> roots = new ArrayList<>(); for (ProductNode node : nodes) { Map target = map.get(node.getId()); if (node.getParentId() == null || node.getParentId() == 0L || !map.containsKey(node.getParentId())) { roots.add(target); } else { children(map.get(node.getParentId())).add(target); } } return roots; } public List> baseTree() { List nodes = baseEquipmentMapper.selectList(Wrappers.lambdaQuery() .orderByAsc(BaseEquipment::getNodeLevel).orderByAsc(BaseEquipment::getSortNo)); Map> map = new LinkedHashMap<>(); for (BaseEquipment node : nodes) { map.put(node.getId(), mapBase(node)); } List> roots = new ArrayList<>(); for (BaseEquipment node : nodes) { Map target = map.get(node.getId()); if (node.getParentId() == null || node.getParentId() == 0L || !map.containsKey(node.getParentId())) { roots.add(target); } else { children(map.get(node.getParentId())).add(target); } } return roots; } @Transactional public ProductNode saveProductNode(ProductNode node) { if (!StringUtils.hasText(node.getName()) || node.getNodeLevel() == null) { throw new BusinessException("节点名称和层级不能为空"); } LocalDateTime now = LocalDateTime.now(); node.setUpdateTime(now); if (node.getId() == null) { node.setCreateTime(now); productNodeMapper.insert(node); } else { productNodeMapper.updateById(node); } return productNodeMapper.selectById(node.getId()); } @Transactional public void deleteProductNode(Long id) { assertNoChildren(productNodeMapper.selectCount(Wrappers.lambdaQuery().eq(ProductNode::getParentId, id))); productNodeMapper.deleteById(id); } @Transactional public BaseEquipment saveBaseNode(BaseEquipment node) { if (!StringUtils.hasText(node.getName()) || node.getNodeLevel() == null) { throw new BusinessException("节点名称和层级不能为空"); } LocalDateTime now = LocalDateTime.now(); node.setUpdateTime(now); if (node.getId() == null) { node.setCreateTime(now); baseEquipmentMapper.insert(node); } else { baseEquipmentMapper.updateById(node); } return baseEquipmentMapper.selectById(node.getId()); } @Transactional public void deleteBaseNode(Long id) { assertNoChildren(baseEquipmentMapper.selectCount(Wrappers.lambdaQuery().eq(BaseEquipment::getParentId, id))); baseEquipmentMapper.deleteById(id); } public List> tenants() { return Collections.singletonList(row("id", 1L, "name", "临抢修租户")); } public Map menuPermissions(Long roleId, Long tenantId) { List roleMenuIds = roleMenuMapper.selectList(Wrappers.lambdaQuery() .eq(roleId != null, SysRoleMenu::getRoleId, roleId)) .stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()); List tenantMenuIds = tenantMenuMapper.selectList(Wrappers.lambdaQuery() .eq(tenantId != null, SysTenantMenu::getTenantId, tenantId)) .stream().map(SysTenantMenu::getMenuId).collect(Collectors.toList()); List effective = roleMenuIds.stream().filter(tenantMenuIds::contains).collect(Collectors.toList()); Map result = new LinkedHashMap<>(); result.put("roleMenuIds", roleMenuIds); result.put("tenantMenuIds", tenantMenuIds); result.put("effectiveMenuIds", effective); return result; } @Transactional public void saveMenuPermissions(Long roleId, Long tenantId, List roleMenuIds, List tenantMenuIds) { if (roleId == null || tenantId == null) { throw new BusinessException("请选择角色和租户"); } roleMenuMapper.delete(Wrappers.lambdaQuery().eq(SysRoleMenu::getRoleId, roleId)); tenantMenuMapper.delete(Wrappers.lambdaQuery().eq(SysTenantMenu::getTenantId, tenantId)); for (Long menuId : roleMenuIds == null ? Collections.emptyList() : roleMenuIds) { SysRoleMenu relation = new SysRoleMenu(); relation.setRoleId(roleId); relation.setMenuId(menuId); relation.setCreateTime(LocalDateTime.now()); roleMenuMapper.insert(relation); } for (Long menuId : tenantMenuIds == null ? Collections.emptyList() : tenantMenuIds) { SysTenantMenu relation = new SysTenantMenu(); relation.setTenantId(tenantId); relation.setMenuId(menuId); relation.setCreateTime(LocalDateTime.now()); tenantMenuMapper.insert(relation); } } public Map threeMemberOverview() { List roles = listRoles().stream() .filter(item -> Arrays.asList("SYSTEM_ADMIN", "SECURITY_ADMIN", "AUDIT_ADMIN").contains(item.getRoleType())) .collect(Collectors.toList()); Map result = new LinkedHashMap<>(); result.put("roles", roles); result.put("users", Collections.singletonList(row("id", 1L, "name", "admin", "realName", "系统管理员"))); result.put("assignments", roleUserMapper.selectList(null)); return result; } private List flatten(List menus, Long pid) { return menus.stream() .filter(item -> pid == null ? item.getPid() == null || item.getPid() == 0L : pid.equals(item.getPid())) .sorted(Comparator.comparing(SysMenu::getSortNo, Comparator.nullsLast(Integer::compareTo))) .collect(Collectors.toList()); } private void sortTree(List nodes) { nodes.sort(Comparator.comparing(SysMenu::getSortNo, Comparator.nullsLast(Integer::compareTo))); for (SysMenu node : nodes) { sortTree(node.getChildren()); } } private Map mapProduct(ProductNode node) { Map row = new LinkedHashMap<>(); row.put("id", String.valueOf(node.getId())); row.put("parentId", node.getParentId() == null ? null : String.valueOf(node.getParentId())); row.put("nodeLevel", node.getNodeLevel()); row.put("nodeType", node.getNodeType()); row.put("name", node.getName()); row.put("code", node.getCode()); row.put("baseEquipmentId", node.getBaseEquipmentId() == null ? null : String.valueOf(node.getBaseEquipmentId())); row.put("sortNo", node.getSortNo()); row.put("remark", node.getRemark()); row.put("children", new ArrayList<>()); return row; } private Map mapBase(BaseEquipment node) { Map row = new LinkedHashMap<>(); row.put("id", String.valueOf(node.getId())); row.put("parentId", node.getParentId() == null ? null : String.valueOf(node.getParentId())); row.put("nodeLevel", node.getNodeLevel()); row.put("nodeType", "BASE_" + node.getNodeLevel()); row.put("name", node.getName()); row.put("code", node.getCode()); row.put("sortNo", node.getSortNo()); row.put("remark", node.getRemark()); row.put("children", new ArrayList<>()); return row; } @SuppressWarnings("unchecked") private List> children(Map node) { return (List>) node.get("children"); } private void assertNoChildren(long count) { if (count > 0) { throw new BusinessException("请先删除下级节点"); } } private Map row(Object... values) { Map row = new LinkedHashMap<>(); for (int i = 0; i < values.length; i += 2) { row.put(String.valueOf(values[i]), values[i + 1]); } return row; } }