| | |
| | | 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; |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.concurrent.ThreadLocalRandom; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | |
| | | /** 账户状态:欠款 */ |
| | | 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。 |
| | |
| | | @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); |
| | |
| | | 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 |