| | |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.core.utils.ip.IpUtils; |
| | | import com.xiaopeng.common.core.web.domain.AjaxResult; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import com.xiaopeng.operation.constant.I18nKeyConstant; |
| | | import com.xiaopeng.operation.dto.WhitelistAddDto; |
| | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | |
| | | @Override |
| | | public R addWhitelist(WhitelistAddDto dto, SysUser sysUser) { |
| | | XpWhitelist old = this.lambdaQuery().eq(XpWhitelist::getAccount, dto.getAccount()).last("limit 1").one(); |
| | | if (old != null) { |
| | | return R.fail("该账号已存在"); |
| | | List<String> accounts = Arrays.stream(dto.getAccount().split(",")) |
| | | .map(String::trim) |
| | | .filter(StringUtils::hasLength) |
| | | .collect(Collectors.toList()); |
| | | if (CollUtil.isEmpty(accounts)) { |
| | | return R.fail("所有帐号添加失败,请检查帐号格式或唯一性"); |
| | | } |
| | | |
| | | int sampleLimitPerReason = 20; |
| | | int totalCount = accounts.size(); |
| | | Map<String, Long> reasonCountMap = new HashMap<>(); |
| | | Map<String, LinkedHashSet<String>> reasonSampleMap = new HashMap<>(); |
| | | |
| | | Set<String> seenAccounts = new HashSet<>(); |
| | | List<String> candidates = new ArrayList<>(); |
| | | for (String account : accounts) { |
| | | if (!PhoneUtil.isMobile(account)) { |
| | | recordFail(reasonCountMap, reasonSampleMap, "帐号格式不正确", account, sampleLimitPerReason); |
| | | continue; |
| | | } |
| | | if (!seenAccounts.add(account)) { |
| | | recordFail(reasonCountMap, reasonSampleMap, "文件内重复", account, sampleLimitPerReason); |
| | | continue; |
| | | } |
| | | candidates.add(account); |
| | | } |
| | | |
| | | Set<String> existsAccounts = new HashSet<>(); |
| | | if (CollUtil.isNotEmpty(candidates)) { |
| | | existsAccounts = this.lambdaQuery() |
| | | .select(XpWhitelist::getAccount) |
| | | .in(XpWhitelist::getAccount, candidates) |
| | | .list() |
| | | .stream() |
| | | .map(XpWhitelist::getAccount) |
| | | .filter(StringUtils::hasLength) |
| | | .collect(Collectors.toSet()); |
| | | } |
| | | |
| | | List<XpWhitelist> addList = new ArrayList<>(); |
| | | List<String> accounts = Arrays.asList(dto.getAccount().split(",")); |
| | | if (CollUtil.isNotEmpty(accounts)) { |
| | | String notValidPhoneNumber = accounts.stream().filter(item -> !PhoneUtil.isPhone(item)).collect(Collectors.joining(",")); |
| | | if (org.apache.commons.lang3.StringUtils.isNotBlank(notValidPhoneNumber)) { |
| | | throw new ServiceException("以下帐号格式不正确:" + notValidPhoneNumber, I18nKeyConstant.ACCOUNT_FORMAT_ERROR, new Object[]{notValidPhoneNumber}); |
| | | for (String account : candidates) { |
| | | if (existsAccounts.contains(account)) { |
| | | recordFail(reasonCountMap, reasonSampleMap, "帐号已存在", account, sampleLimitPerReason); |
| | | continue; |
| | | } |
| | | StringBuilder operationContent = new StringBuilder("新增账号:"); |
| | | StringBuilder accountBuilder = new StringBuilder(); |
| | | for (String account : accounts) { |
| | | XpWhitelist xpWhitelist = new XpWhitelist(); |
| | | xpWhitelist.setAccount(account); |
| | | xpWhitelist.setStatus(true); |
| | | xpWhitelist.setIsPriorityDispatch(dto.getIsPriorityDispatch()); |
| | | xpWhitelist.setWhitelistSource(1); |
| | | xpWhitelist.setCreateBy(sysUser.getCreateBy()); |
| | | addList.add(xpWhitelist); |
| | | accountBuilder.append("\"").append(account).append("\"").append(","); |
| | | } |
| | | XpWhitelistOperlog xpWhitelistOperlog = new XpWhitelistOperlog(); |
| | | xpWhitelistOperlog.setOperationName(sysUser.getNickName()); |
| | | xpWhitelistOperlog.setOperationAccount(sysUser.getPhoneNumber()); |
| | | xpWhitelistOperlog.setOperationType(1); |
| | | xpWhitelistOperlog.setOperationIp(IpUtils.getIpAddr()); |
| | | xpWhitelistOperlog.setOperationAccountId(sysUser.getId()); |
| | | StringBuilder content = operationContent.append(accountBuilder.substring(0, accountBuilder.length() - 1)); |
| | | xpWhitelistOperlog.setOperationContent(content.toString()); |
| | | xpWhitelistOperlogMapper.insert(xpWhitelistOperlog); |
| | | this.saveBatch(addList); |
| | | XpWhitelist xpWhitelist = new XpWhitelist(); |
| | | xpWhitelist.setAccount(account); |
| | | xpWhitelist.setStatus(true); |
| | | xpWhitelist.setIsPriorityDispatch(dto.getIsPriorityDispatch()); |
| | | xpWhitelist.setWhitelistSource(1); |
| | | xpWhitelist.setCreateBy(sysUser.getNickName()); |
| | | addList.add(xpWhitelist); |
| | | } |
| | | return R.ok(); |
| | | |
| | | int successCount = addList.size(); |
| | | int failCount = totalCount - successCount; |
| | | |
| | | String message; |
| | | if (failCount == 0) { |
| | | message = "成功添加" + successCount + "条白名单记录"; |
| | | } else if (successCount == 0) { |
| | | message = "所有帐号添加失败,请检查帐号格式或唯一性"; |
| | | } else { |
| | | message = "成功加" + successCount + "条," + failCount + "条添加失败,失败原因:" + buildReasonDetail(reasonCountMap, reasonSampleMap); |
| | | } |
| | | |
| | | if (successCount == 0) { |
| | | return R.fail(message); |
| | | } |
| | | |
| | | this.saveBatch(addList); |
| | | |
| | | StringBuilder operationContent = new StringBuilder("新增账号:"); |
| | | StringBuilder accountBuilder = new StringBuilder(); |
| | | for (XpWhitelist item : addList) { |
| | | accountBuilder.append("\"").append(item.getAccount()).append("\"").append(","); |
| | | } |
| | | if (accountBuilder.length() > 0) { |
| | | operationContent.append(accountBuilder.substring(0, accountBuilder.length() - 1)); |
| | | } |
| | | if (failCount > 0) { |
| | | operationContent.append(";失败").append(failCount).append("条"); |
| | | operationContent.append(";原因").append(buildReasonSummary(reasonCountMap)); |
| | | } |
| | | |
| | | XpWhitelistOperlog xpWhitelistOperlog = new XpWhitelistOperlog(); |
| | | xpWhitelistOperlog.setOperationName(sysUser.getNickName()); |
| | | xpWhitelistOperlog.setOperationAccount(sysUser.getPhoneNumber()); |
| | | xpWhitelistOperlog.setOperationType(1); |
| | | xpWhitelistOperlog.setOperationIp(IpUtils.getIpAddr()); |
| | | xpWhitelistOperlog.setOperationAccountId(sysUser.getId()); |
| | | xpWhitelistOperlog.setOperationContent(truncate(operationContent.toString(), 200)); |
| | | xpWhitelistOperlogMapper.insert(xpWhitelistOperlog); |
| | | |
| | | return R.ok(null, message); |
| | | } |
| | | |
| | | private static void recordFail(Map<String, Long> reasonCountMap, |
| | | Map<String, LinkedHashSet<String>> reasonSampleMap, |
| | | String reason, |
| | | String sample, |
| | | int sampleLimitPerReason) { |
| | | reasonCountMap.merge(reason, 1L, Long::sum); |
| | | if (!StringUtils.hasLength(sample) || sampleLimitPerReason <= 0) { |
| | | return; |
| | | } |
| | | LinkedHashSet<String> samples = reasonSampleMap.computeIfAbsent(reason, k -> new LinkedHashSet<>()); |
| | | if (samples.size() >= sampleLimitPerReason) { |
| | | return; |
| | | } |
| | | samples.add(sample); |
| | | } |
| | | |
| | | private static String buildReasonSummary(Map<String, Long> reasonCountMap) { |
| | | if (reasonCountMap == null || reasonCountMap.isEmpty()) { |
| | | return "请检查帐号格式或唯一性"; |
| | | } |
| | | return reasonCountMap.entrySet().stream() |
| | | .sorted(Comparator.<Map.Entry<String, Long>>comparingLong(e -> e.getValue() == null ? 0L : e.getValue()) |
| | | .reversed() |
| | | .thenComparing(Map.Entry::getKey)) |
| | | .map(e -> e.getKey() + "(" + (e.getValue() == null ? 0L : e.getValue()) + ")") |
| | | .collect(Collectors.joining(",")); |
| | | } |
| | | |
| | | private static String buildReasonDetail(Map<String, Long> reasonCountMap, |
| | | Map<String, LinkedHashSet<String>> reasonSampleMap) { |
| | | if (reasonCountMap == null || reasonCountMap.isEmpty()) { |
| | | return "请检查帐号格式或唯一性"; |
| | | } |
| | | Map<String, LinkedHashSet<String>> safeSamples = reasonSampleMap == null ? new HashMap<>() : reasonSampleMap; |
| | | return reasonCountMap.entrySet().stream() |
| | | .sorted(Comparator.<Map.Entry<String, Long>>comparingLong(e -> e.getValue() == null ? 0L : e.getValue()) |
| | | .reversed() |
| | | .thenComparing(Map.Entry::getKey)) |
| | | .map(entry -> { |
| | | String reason = entry.getKey(); |
| | | long count = entry.getValue() == null ? 0L : entry.getValue(); |
| | | LinkedHashSet<String> samples = safeSamples.getOrDefault(reason, new LinkedHashSet<>()); |
| | | if (samples.isEmpty()) { |
| | | return reason + "(" + count + ")"; |
| | | } |
| | | long remaining = count - samples.size(); |
| | | String suffix = remaining > 0 ? "等" + remaining + "个" : ""; |
| | | String suffixPart = StringUtils.hasLength(suffix) ? ("," + suffix) : ""; |
| | | return reason + "(" + count + ")[" + String.join(",", samples) + suffixPart + "]"; |
| | | }) |
| | | .collect(Collectors.joining(";")); |
| | | } |
| | | |
| | | private static String truncate(String value, int maxLength) { |
| | | if (value == null || maxLength <= 0) { |
| | | return value; |
| | | } |
| | | if (value.length() <= maxLength) { |
| | | return value; |
| | | } |
| | | return value.substring(0, maxLength); |
| | | } |
| | | |
| | | @Override |