稳定组成这个文件优化
This commit is contained in:
4
app/.env
4
app/.env
@@ -11,9 +11,9 @@ zn_username=%E8%87%AA%E5%8A%A8%E5%8C%96_Robot
|
|||||||
client_name=ShuFuAI
|
client_name=ShuFuAI
|
||||||
|
|
||||||
|
|
||||||
# java_api_base=http://47.111.163.154:18080
|
java_api_base=http://47.111.163.154:18080
|
||||||
# java_api_base=http://127.0.0.1:18080
|
# java_api_base=http://127.0.0.1:18080
|
||||||
# java_api_base=http://8.136.19.173:18080
|
# java_api_base=http://8.136.19.173:18080
|
||||||
java_api_base=http://121.196.149.225:18080
|
# java_api_base=http://121.196.149.225:18080
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{aZ as r}from"./pywebview-BWNiqXug.js";const n="";function a(e){return r(`${n}/api/brand/expand-folder-recursive`,{folder:e})}export{a as e};
|
|
||||||
1
app/assets/convert-BKSNvX8i.css
Normal file
1
app/assets/convert-BKSNvX8i.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
app/assets/dedupe-DNlVfFj-.css
Normal file
1
app/assets/dedupe-DNlVfFj-.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
app/assets/patrol-delete-CBBdonF4.css
Normal file
1
app/assets/patrol-delete-CBBdonF4.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
app/assets/split-BoBVrLdC.css
Normal file
1
app/assets/split-BoBVrLdC.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,16 +1,16 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>格式转换 - 数富AI</title>
|
<title>格式转换 - 数富AI</title>
|
||||||
<script type="module" crossorigin src="/assets/convert.js"></script>
|
<script type="module" crossorigin src="/assets/convert.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BtdhG28Q.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-Lp7YWffz.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/convert-r7MSXq7I.css">
|
<link rel="stylesheet" crossorigin href="/assets/convert-BKSNvX8i.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
</body>
|
</html>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>数据去重 - 数富AI</title>
|
<title>数据去重 - 数富AI</title>
|
||||||
<script type="module" crossorigin src="/assets/dedupe.js"></script>
|
<script type="module" crossorigin src="/assets/dedupe.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BtdhG28Q.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-Lp7YWffz.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/dedupe-DMeaPUMZ.css">
|
<link rel="stylesheet" crossorigin href="/assets/dedupe-DNlVfFj-.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
</body>
|
</html>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>删除品牌 - 数富AI</title>
|
<title>删除品牌 - 数富AI</title>
|
||||||
<script type="module" crossorigin src="/assets/delete-brand.js"></script>
|
<script type="module" crossorigin src="/assets/delete-brand.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BtdhG28Q.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-Lp7YWffz.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/delete-brand-B5ChOXZY.css">
|
<link rel="stylesheet" crossorigin href="/assets/delete-brand-BfMLVSQU.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
</body>
|
</html>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>数据拆分 - 数富AI</title>
|
<title>数据拆分 - 数富AI</title>
|
||||||
<script type="module" crossorigin src="/assets/split.js"></script>
|
<script type="module" crossorigin src="/assets/split.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BtdhG28Q.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-Lp7YWffz.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/split-Cw6sXhAg.css">
|
<link rel="stylesheet" crossorigin href="/assets/split-BoBVrLdC.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
</body>
|
</html>
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ public class AppearancePatentTaskService {
|
|||||||
private static final String STATUS_SUCCESS = "SUCCESS";
|
private static final String STATUS_SUCCESS = "SUCCESS";
|
||||||
private static final String STATUS_FAILED = "FAILED";
|
private static final String STATUS_FAILED = "FAILED";
|
||||||
private static final String CONTENT_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
private static final String CONTENT_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||||
|
private static final int RESULT_ROWS_READ_RETRY_LIMIT = 3;
|
||||||
|
private static final long RESULT_ROWS_READ_RETRY_DELAY_MS = 500L;
|
||||||
private static final List<String> RESULT_HEADERS = List.of(
|
private static final List<String> RESULT_HEADERS = List.of(
|
||||||
"id",
|
"id",
|
||||||
"asin",
|
"asin",
|
||||||
@@ -759,12 +761,17 @@ public class AppearancePatentTaskService {
|
|||||||
}
|
}
|
||||||
String payloadJson = writeJson(rows == null ? List.of() : rows, "结果序列化失败");
|
String payloadJson = writeJson(rows == null ? List.of() : rows, "结果序列化失败");
|
||||||
payloadJson = writeJson(new ArrayList<>(persistedRows.values()), "appearance patent chunk payload merge failed");
|
payloadJson = writeJson(new ArrayList<>(persistedRows.values()), "appearance patent chunk payload merge failed");
|
||||||
String storedPayload = transientPayloadStorageService.storeChunkPayload(MODULE_TYPE, taskId, scopeHash, chunkIndex, payloadJson);
|
String oldPayload = chunk.getPayloadJson();
|
||||||
transientPayloadStorageService.deleteReplacedPayloadIfNeeded(chunk.getPayloadJson(), storedPayload);
|
String storedPayload = transientPayloadStorageService.storeChunkPayloadVersioned(MODULE_TYPE, taskId, scopeHash, chunkIndex, payloadJson);
|
||||||
chunk.setPayloadJson(storedPayload);
|
chunk.setPayloadJson(storedPayload);
|
||||||
chunk.setPayloadHash(DigestUtil.sha256Hex(payloadJson));
|
chunk.setPayloadHash(DigestUtil.sha256Hex(payloadJson));
|
||||||
chunk.setUpdatedAt(LocalDateTime.now());
|
chunk.setUpdatedAt(LocalDateTime.now());
|
||||||
taskChunkMapper.updateById(chunk);
|
int updated = taskChunkMapper.updateById(chunk);
|
||||||
|
if (updated <= 0) {
|
||||||
|
transientPayloadStorageService.deletePayloadIfPresent(storedPayload);
|
||||||
|
throw new IllegalStateException("appearance patent chunk payload update failed");
|
||||||
|
}
|
||||||
|
transientPayloadStorageService.deleteReplacedPayloadIfNeeded(oldPayload, storedPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AppearancePatentResultRowDto> expandRows(List<AppearancePatentResultRowDto> representatives,
|
private List<AppearancePatentResultRowDto> expandRows(List<AppearancePatentResultRowDto> representatives,
|
||||||
@@ -1122,7 +1129,7 @@ public class AppearancePatentTaskService {
|
|||||||
|
|
||||||
private void assembleResultWorkbook(FileTaskEntity task, FileResultEntity result) {
|
private void assembleResultWorkbook(FileTaskEntity task, FileResultEntity result) {
|
||||||
AppearancePatentParsedPayloadDto parsed = readParsedPayload(task);
|
AppearancePatentParsedPayloadDto parsed = readParsedPayload(task);
|
||||||
Map<String, AppearancePatentResultRowDto> resultMap = loadPersistedResultRows(task.getId());
|
Map<String, AppearancePatentResultRowDto> resultMap = loadPersistedResultRowsWithRetry(task.getId(), parsed.getAllItems().size());
|
||||||
long resolvedRows = parsed.getAllItems().stream()
|
long resolvedRows = parsed.getAllItems().stream()
|
||||||
.filter(row -> findResultRow(row, resultMap) != null || findResultRowByAsin(row.getAsin(), resultMap) != null)
|
.filter(row -> findResultRow(row, resultMap) != null || findResultRowByAsin(row.getAsin(), resultMap) != null)
|
||||||
.count();
|
.count();
|
||||||
@@ -1131,6 +1138,9 @@ public class AppearancePatentTaskService {
|
|||||||
.count();
|
.count();
|
||||||
log.info("[appearance-patent] assemble workbook taskId={} parsedRows={} resultRows={} resolvedRows={} reasonRows={}",
|
log.info("[appearance-patent] assemble workbook taskId={} parsedRows={} resultRows={} resolvedRows={} reasonRows={}",
|
||||||
task.getId(), parsed.getAllItems().size(), resultMap.size(), resolvedRows, reasonRows);
|
task.getId(), parsed.getAllItems().size(), resultMap.size(), resolvedRows, reasonRows);
|
||||||
|
if (!parsed.getAllItems().isEmpty() && resultMap.isEmpty()) {
|
||||||
|
throw new BusinessException("外观专利检测结果为空,请稍后重试生成结果文件");
|
||||||
|
}
|
||||||
File outputDir = new File(storageProperties.getLocalTempDir(), "appearance-patent-result");
|
File outputDir = new File(storageProperties.getLocalTempDir(), "appearance-patent-result");
|
||||||
if (!outputDir.exists() && !outputDir.mkdirs()) {
|
if (!outputDir.exists() && !outputDir.mkdirs()) {
|
||||||
throw new BusinessException("创建结果目录失败");
|
throw new BusinessException("创建结果目录失败");
|
||||||
@@ -1164,6 +1174,33 @@ public class AppearancePatentTaskService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, AppearancePatentResultRowDto> loadPersistedResultRowsWithRetry(Long taskId, int expectedParsedRows) {
|
||||||
|
Map<String, AppearancePatentResultRowDto> result = loadPersistedResultRows(taskId);
|
||||||
|
if (expectedParsedRows <= 0 || !result.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (int attempt = 1; attempt <= RESULT_ROWS_READ_RETRY_LIMIT && result.isEmpty(); attempt++) {
|
||||||
|
sleepBeforeResultRowsRetry(attempt);
|
||||||
|
result = loadPersistedResultRows(taskId);
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
log.info("[appearance-patent] result rows recovered after retry taskId={} attempt={} rows={}",
|
||||||
|
taskId, attempt, result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
log.warn("[appearance-patent] result rows still empty after retry taskId={} attempt={}/{}",
|
||||||
|
taskId, attempt, RESULT_ROWS_READ_RETRY_LIMIT);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sleepBeforeResultRowsRetry(int attempt) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(RESULT_ROWS_READ_RETRY_DELAY_MS * attempt);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void writeResultWorkbook(File xlsx, AppearancePatentParsedPayloadDto parsed, Map<String, AppearancePatentResultRowDto> resultMap) {
|
private void writeResultWorkbook(File xlsx, AppearancePatentParsedPayloadDto parsed, Map<String, AppearancePatentResultRowDto> resultMap) {
|
||||||
try (SXSSFWorkbook workbook = new SXSSFWorkbook(200); FileOutputStream fos = new FileOutputStream(xlsx)) {
|
try (SXSSFWorkbook workbook = new SXSSFWorkbook(200); FileOutputStream fos = new FileOutputStream(xlsx)) {
|
||||||
Sheet sheet = workbook.createSheet("外观专利检测结果");
|
Sheet sheet = workbook.createSheet("外观专利检测结果");
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ public class TransientPayloadStorageService {
|
|||||||
return store("task-chunk", moduleType, taskId, scopeHash, entryKey, content, true);
|
return store("task-chunk", moduleType, taskId, scopeHash, entryKey, content, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String storeChunkPayloadVersioned(String moduleType, Long taskId, String scopeHash, Integer chunkIndex, String content) {
|
||||||
|
String entryKey = chunkIndex == null
|
||||||
|
? UUID.randomUUID().toString()
|
||||||
|
: "chunk-" + chunkIndex + "-" + UUID.randomUUID();
|
||||||
|
return store("task-chunk", moduleType, taskId, scopeHash, entryKey, content, true);
|
||||||
|
}
|
||||||
|
|
||||||
public String resolvePayload(String value, String errorMessage) {
|
public String resolvePayload(String value, String errorMessage) {
|
||||||
String pointer = extractPointer(value);
|
String pointer = extractPointer(value);
|
||||||
if (pointer == null) {
|
if (pointer == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user