puzhibing
4 天以前 a0e03b646f2c444b0f09687d24e9995112b99017
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TGroupCompanyServiceImpl.java
@@ -33,8 +33,11 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
@@ -44,6 +47,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/**
@@ -87,6 +91,21 @@
    /** 账户状态:欠款 */
    private static final int ACCOUNT_STATUS_OVERDUE = 2;
    /** 公司登录账号前缀:admin */
    private static final String ACCOUNT_PREFIX = "admin";
    /** 公司登录账号随机数字位数 */
    private static final int ACCOUNT_RANDOM_DIGITS = 4;
    /** 账号生成查重重试上限 */
    private static final int ACCOUNT_GENERATE_MAX_ATTEMPTS = 20;
    /** 新增公司初始密码(明文,落库前按登录口径 HMAC-MD5 处理) */
    private static final String DEFAULT_INITIAL_PASSWORD = "123456";
    /** 密码传输 HMAC 密钥(与前端 CryptoJS.HmacMD5(password, 'password') 口径一致) */
    private static final String PASSWORD_HMAC_KEY = "password";
    /**
     * 车队 Mapper。
@@ -387,30 +406,21 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addCompany(TGroupCompany company) {
        if (!StringUtils.hasText(company.getAccount())) {
            return AjaxResult.error("登录账号不能为空");
        }
        // 登录账号由系统自动生成:admin + 4位随机数字,前端不可指定、不可修改
        String account = generateCompanyAccount();
        company.setAccount(account);
        // 添加企业弹窗不再配置账户模式:未指定时按共享模式建档,后续可在“账户模式”弹窗切换
        if (company.getAccountMode() == null) {
            company.setAccountMode(ACCOUNT_MODE_SHARED);
        }
        if (!StringUtils.hasText(company.getPassword())) {
            return AjaxResult.error("登录密码不能为空");
        }
        if (accountExists(company.getAccount(), null)) {
            return AjaxResult.error("登录账号不能重复");
        }
        R<SysUser> existR = sysUserClient.queryUserByUserName(company.getAccount());
        SysUser existUser = existR == null ? null : existR.getData();
        if (existUser != null) {
            return AjaxResult.error("登录账号不能重复");
        }
        // 初始密码固定 123456,按登录口径 HMAC-MD5 后由 system 侧 BCrypt 落库
        String password = hmacMd5(DEFAULT_INITIAL_PASSWORD, PASSWORD_HMAC_KEY);
        Long roleId = resolveCompanyRoleId();
        SysUser user = new SysUser();
        user.setUserName(company.getAccount());
        user.setUserName(account);
        user.setNickName(company.getName());
        user.setPhonenumber(company.getContactPhone());
        user.setPassword(company.getPassword());
        user.setPassword(password);
        user.setStatus("0");
        user.setDelFlag("0");
        user.setRoleId(roleId);
@@ -428,7 +438,47 @@
            created.setObjectId(company.getId());
            sysUserClient.updateUser(created);
        }
        return AjaxResult.success();
        // 返回生成的登录账号,供添加页回显(初始密码为固定 123456)
        return AjaxResult.success("操作成功", account);
    }
    /**
     * 生成公司登录账号:admin + 4位随机数字,公司表与 sys_user 双查重,冲突重试
     */
    private String generateCompanyAccount() {
        int start = (int) Math.pow(10, ACCOUNT_RANDOM_DIGITS - 1);
        int bound = (int) Math.pow(10, ACCOUNT_RANDOM_DIGITS) - start;
        for (int i = 0; i < ACCOUNT_GENERATE_MAX_ATTEMPTS; i++) {
            String candidate = ACCOUNT_PREFIX + (start + ThreadLocalRandom.current().nextInt(bound));
            if (accountExists(candidate, null)) {
                continue;
            }
            R<SysUser> existR = sysUserClient.queryUserByUserName(candidate);
            SysUser existUser = existR == null ? null : existR.getData();
            if (existUser == null) {
                return candidate;
            }
        }
        throw new ServiceException("登录账号生成失败,请稍后重试");
    }
    /**
     * HMAC-MD5(小写 Hex),与前端 CryptoJS.HmacMD5(text, key) 口径一致
     */
    private String hmacMd5(String text, String key) {
        try {
            Mac mac = Mac.getInstance("HmacMD5");
            mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacMD5"));
            byte[] bytes = mac.doFinal(text.getBytes(StandardCharsets.UTF_8));
            StringBuilder hex = new StringBuilder(bytes.length * 2);
            for (byte b : bytes) {
                hex.append(Character.forDigit((b >> 4) & 0xF, 16));
                hex.append(Character.forDigit(b & 0xF, 16));
            }
            return hex.toString();
        } catch (Exception e) {
            throw new ServiceException("密码处理失败: " + e.getMessage());
        }
    }
    @Override