提交一些更改

This commit is contained in:
super
2026-05-20 09:05:28 +08:00
parent a2ebfc0b81
commit 73d25fcbcb
28 changed files with 1620 additions and 8062 deletions
@@ -0,0 +1,114 @@
package com.nanri.aiimage.common.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
public final class FailedStatusRowFilter {
private static final String STATUS_HEADER_CN = "\u72b6\u6001";
private static final String FAILED_STATUS_ERROR = "\u9519\u8bef";
private static final String FAILED_STATUS_FAILED_CN = "\u5931\u8d25";
private static final String FAILED_STATUS_FAILED_EN = "failed";
private static final String NO_MATCHED_ROWS_MESSAGE =
"\u72b6\u6001\u5217\u8fc7\u6ee4\u540e\u672a\u627e\u5230 \u9519\u8bef/\u5931\u8d25/FAILED \u6570\u636e";
private static final Set<String> STATUS_HEADER_ALIASES = Set.of(
normalizeHeader(STATUS_HEADER_CN),
normalizeHeader("status")
);
private static final Set<String> FAILED_STATUS_VALUES = Set.of(
normalizeValue(FAILED_STATUS_ERROR),
normalizeValue(FAILED_STATUS_FAILED_CN),
normalizeValue(FAILED_STATUS_FAILED_EN)
);
private FailedStatusRowFilter() {
}
public static int findStatusColumnIndex(List<String> headers) {
if (headers == null || headers.isEmpty()) {
return -1;
}
for (int i = 0; i < headers.size(); i++) {
if (STATUS_HEADER_ALIASES.contains(normalizeHeader(headers.get(i)))) {
return i;
}
}
return -1;
}
public static boolean matchesFailedStatus(String value) {
return FAILED_STATUS_VALUES.contains(normalizeValue(value));
}
public static boolean isBlankStatus(String value) {
return normalizeValue(value).isBlank();
}
public static String noMatchedRowsMessage() {
return NO_MATCHED_ROWS_MESSAGE;
}
/**
* 暴露表头归一化逻辑给其它模块复用,避免每个模块各自维护一份规则。
* 处理:去 BOM、全角空格转半角、首尾 trim、连续空白合一、转小写,
* 并剥除常见分隔符(含中文全角括号、方括号、冒号)。
*/
public static String canonicalizeHeader(String value) {
return normalizeHeader(value);
}
public static <T> FilterResult<T> retainFailedRows(List<T> rows,
boolean statusFilteringEnabled,
Function<T, String> statusReader) {
return retainRows(rows, statusFilteringEnabled, statusReader, FailedStatusRowFilter::matchesFailedStatus);
}
public static <T> FilterResult<T> retainRows(List<T> rows,
boolean statusFilteringEnabled,
Function<T, String> statusReader,
Predicate<String> statusMatcher) {
List<T> safeRows = rows == null ? List.of() : rows;
if (!statusFilteringEnabled) {
return new FilterResult<>(false, safeRows, 0);
}
List<T> filteredRows = new ArrayList<>();
int filteredCount = 0;
for (T row : safeRows) {
String status = statusReader == null ? "" : statusReader.apply(row);
boolean matched = statusMatcher != null && statusMatcher.test(status);
if (matched) {
filteredRows.add(row);
} else {
filteredCount++;
}
}
return new FilterResult<>(true, filteredRows, filteredCount);
}
private static String normalizeHeader(String value) {
// 扩展:兼容中文全角括号 ()、中文方括号 【】、中文冒号 :,避免
// "状态(结果)"、"标题维度(商标)" 等全角括号表头被识别失败。
return normalizeValue(value).replaceAll("[\\s_\\-()\\[\\]{}::()【】]+", "");
}
private static String normalizeValue(String value) {
if (value == null) {
return "";
}
return value
.replace(String.valueOf((char) 0xFEFF), "")
.replace((char) 0x3000, ' ')
.trim()
.replaceAll("\\s+", " ")
.toLowerCase(Locale.ROOT);
}
public record FilterResult<T>(boolean filterApplied, List<T> rows, int filteredCount) {
}
}