package com.labelsys.backend.service; import java.util.List; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.labelsys.backend.common.ResultCode; import com.labelsys.backend.common.exception.BusinessException; import com.labelsys.backend.common.exception.ForbiddenException; import com.labelsys.backend.context.LoginUser; import com.labelsys.backend.dto.request.CreateCompanyAdminRequest; import com.labelsys.backend.dto.request.CreateSystemEngineerAdminRequest; import com.labelsys.backend.dto.request.CreateUserRequest; import com.labelsys.backend.dto.request.UpdateUserAssignmentRequest; import com.labelsys.backend.dto.request.UpdateUserStatusRequest; import com.labelsys.backend.entity.SysCompany; import com.labelsys.backend.entity.SysUser; import com.labelsys.backend.enums.CompanyStatus; import com.labelsys.backend.enums.UserPosition; import com.labelsys.backend.enums.UserRole; import com.labelsys.backend.enums.UserStatus; import com.labelsys.backend.mapper.SysCompanyMapper; import com.labelsys.backend.mapper.SysUserMapper; import com.labelsys.backend.service.session.TokenSessionRepository; import com.labelsys.backend.util.IdGenerator; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class UserService { private static final String DEFAULT_PASSWORD = "123456"; private final SysUserMapper sysUserMapper; private final SysCompanyMapper sysCompanyMapper; private final PasswordEncoder passwordEncoder; private final TokenSessionRepository tokenSessionRepository; public List listAllUsers(LoginUser currentUser) { assertSystemAdmin(currentUser); LambdaQueryWrapper wrapper = new LambdaQueryWrapper().orderByAsc(SysUser::getId); return sysUserMapper.selectList(wrapper); } public List listCompanyUsers(LoginUser currentUser) { assertCompanyAdmin(currentUser); LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .eq(SysUser::getCompanyId, currentUser.companyId()).orderByAsc(SysUser::getId); return sysUserMapper.selectList(wrapper); } public List listCompanyAdmins(LoginUser currentUser, Long companyId) { assertSystemAdmin(currentUser); return sysUserMapper.listCompanyAdmins(companyId); } public SysUser createCompanyAdmin(LoginUser currentUser, CreateCompanyAdminRequest request) { assertSystemAdmin(currentUser); ensureEnabledCompany(request.companyId()); return createUser(request.companyId(), new CreateUserRequest(request.phone(), request.username(), request.realName(), UserRole.EMPLOYEE, UserPosition.ADMIN)); } public SysUser createSystemEngineerAdmin(LoginUser currentUser, CreateSystemEngineerAdminRequest request) { assertSystemAdmin(currentUser); Long systemCompanyId = 1L; ensureEnabledCompany(systemCompanyId); if (sysUserMapper.findByCompanyIdAndPhone(systemCompanyId, request.phone()) != null) { throw new BusinessException(ResultCode.CONFLICT, "同一公司内手机号已存在"); } SysUser user = SysUser.builder().id(IdGenerator.nextId()).companyId(systemCompanyId).phone(request.phone()) .username(request.username()).realName(request.realName()).role(UserRole.ENGINEER) .position(UserPosition.SUPER_ADMIN).passwordHash(passwordEncoder.encode(DEFAULT_PASSWORD)) .mustChangePassword(true).status(UserStatus.ENABLED).sessionVersion(1).build(); sysUserMapper.insert(user); return user; } public SysUser createCompanyUser(LoginUser currentUser, CreateUserRequest request) { assertCompanyAdmin(currentUser); return createUser(currentUser.companyId(), request); } public SysUser createCompanyUser(LoginUser currentUser, Long companyId, CreateUserRequest request) { assertSystemAdmin(currentUser); ensureEnabledCompany(companyId); return createUser(companyId, request); } @Transactional public void updateAssignment(LoginUser currentUser, Long userId, UpdateUserAssignmentRequest request) { assertCompanyAdmin(currentUser); if (sysUserMapper.updateAssignment(userId, currentUser.companyId(), request.role(), request.position()) == 0) { throw new BusinessException(ResultCode.NOT_FOUND, "用户不存在"); } tokenSessionRepository.removeAll(userId); } @Transactional public void updateStatus(LoginUser currentUser, Long userId, UpdateUserStatusRequest request) { assertCompanyAdmin(currentUser); if (sysUserMapper.updateStatus(userId, currentUser.companyId(), request.status()) == 0) { throw new BusinessException(ResultCode.NOT_FOUND, "用户不存在"); } tokenSessionRepository.removeAll(userId); } @Transactional public void updateCompanyAdminStatus(LoginUser currentUser, Long companyId, Long userId, UpdateUserStatusRequest request) { assertSystemAdmin(currentUser); if (sysUserMapper.updateStatus(userId, companyId, request.status()) == 0) { throw new BusinessException(ResultCode.NOT_FOUND, "用户不存在"); } tokenSessionRepository.removeAll(userId); } private SysUser createUser(Long companyId, CreateUserRequest request) { if (sysUserMapper.findByCompanyIdAndPhone(companyId, request.phone()) != null) { throw new BusinessException(ResultCode.CONFLICT, "同一公司内手机号已存在"); } SysUser user = SysUser.builder().id(IdGenerator.nextId()).companyId(companyId).phone(request.phone()) .username(request.username()).realName(request.realName()).role(request.role()).position(request.position()) .passwordHash(passwordEncoder.encode(DEFAULT_PASSWORD)).mustChangePassword(true).status(UserStatus.ENABLED) .sessionVersion(1).build(); sysUserMapper.insert(user); return user; } private void ensureEnabledCompany(Long companyId) { SysCompany company = sysCompanyMapper.selectById(companyId); if (company == null || company.getStatus() != CompanyStatus.ENABLED) { throw new BusinessException(ResultCode.NOT_FOUND, "公司不存在或已禁用"); } } // private void assertPlatformAdmin(LoginUser currentUser) { // if (!currentUser.isPlatformAdmin()) { // throw new ForbiddenException("仅平台管理员可操作"); // } // } private void assertSystemAdmin(LoginUser currentUser) { if (!currentUser.isSuperAdmin()) { throw new ForbiddenException("仅超级管理员可操作"); } } private void assertCompanyAdmin(LoginUser currentUser) { if (currentUser.isSuperAdmin() || currentUser.position() != UserPosition.ADMIN) { throw new ForbiddenException("仅公司管理员可操作"); } } }