fix: update patrol delete progress handling
This commit is contained in:
@@ -1792,6 +1792,10 @@ class PatrolDeleteTask:
|
|||||||
f"国家 {country_name} 处理结束,success={country_result['success']},"
|
f"国家 {country_name} 处理结束,success={country_result['success']},"
|
||||||
f"deleted={country_result['deletedCount']},reopenRequired={requires_browser_reset}"
|
f"deleted={country_result['deletedCount']},reopenRequired={requires_browser_reset}"
|
||||||
)
|
)
|
||||||
|
self._post_progress_result_safely(
|
||||||
|
task_id=task_id,
|
||||||
|
shop_name=shop_name,
|
||||||
|
)
|
||||||
|
|
||||||
if driver is not None:
|
if driver is not None:
|
||||||
self.log(f"店铺 {shop_name} 国家处理完成,正在关闭店铺")
|
self.log(f"店铺 {shop_name} 国家处理完成,正在关闭店铺")
|
||||||
@@ -1822,6 +1826,22 @@ class PatrolDeleteTask:
|
|||||||
del runing_shop[shop_name]
|
del runing_shop[shop_name]
|
||||||
self.log(f"店铺 {shop_name} 已从执行列表中移除")
|
self.log(f"店铺 {shop_name} 已从执行列表中移除")
|
||||||
|
|
||||||
|
def _post_progress_result_safely(
|
||||||
|
self,
|
||||||
|
task_id: int,
|
||||||
|
shop_name: str,
|
||||||
|
) -> None:
|
||||||
|
"""Submit a heartbeat-only payload so Java does not append duplicate result rows."""
|
||||||
|
try:
|
||||||
|
self.post_result(
|
||||||
|
task_id=task_id,
|
||||||
|
shop_name=shop_name,
|
||||||
|
shop_done=False,
|
||||||
|
heartbeat_only=True,
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
self.log(f"店铺 {shop_name} 中间结果回传失败,继续执行: {str(exc)}", "WARNING")
|
||||||
|
|
||||||
def open_shop(self, max_retries: int, company_name: str, shop_name: str, iskill: bool = False) -> Optional[InventoryManage]:
|
def open_shop(self, max_retries: int, company_name: str, shop_name: str, iskill: bool = False) -> Optional[InventoryManage]:
|
||||||
error_info = ""
|
error_info = ""
|
||||||
driver: Optional[InventoryManage] = None
|
driver: Optional[InventoryManage] = None
|
||||||
@@ -1996,6 +2016,8 @@ class PatrolDeleteTask:
|
|||||||
"type": "completeDraft",
|
"type": "completeDraft",
|
||||||
"status": PatrolDeleteTask._string_result_field(item.get("tag")),
|
"status": PatrolDeleteTask._string_result_field(item.get("tag")),
|
||||||
"quantity": quantity,
|
"quantity": quantity,
|
||||||
|
"deleteQuantity": "",
|
||||||
|
"processStatus": "",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.log(f"trace_id={trace_id} 国家 {country_name} 补全草稿读取完成: rows={rows}")
|
self.log(f"trace_id={trace_id} 国家 {country_name} 补全草稿读取完成: rows={rows}")
|
||||||
@@ -2032,6 +2054,7 @@ class PatrolDeleteTask:
|
|||||||
"status": status,
|
"status": status,
|
||||||
"quantity": InventoryManage._normalize_quantity_text(item.get("quantity")),
|
"quantity": InventoryManage._normalize_quantity_text(item.get("quantity")),
|
||||||
"deleteQuantity": str(deleted_count),
|
"deleteQuantity": str(deleted_count),
|
||||||
|
"processStatus": "已完成" if deleted_count > 0 else "",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
section = {"country": country_name, "rows": rows} if rows else None
|
section = {"country": country_name, "rows": rows} if rows else None
|
||||||
@@ -2116,6 +2139,7 @@ class PatrolDeleteTask:
|
|||||||
cart_ratios: Optional[List[Dict[str, Any]]] = None,
|
cart_ratios: Optional[List[Dict[str, Any]]] = None,
|
||||||
error: str = "",
|
error: str = "",
|
||||||
shop_done: bool = False,
|
shop_done: bool = False,
|
||||||
|
heartbeat_only: bool = False,
|
||||||
):
|
):
|
||||||
"""回传巡店删除结果到 Java API。"""
|
"""回传巡店删除结果到 Java API。"""
|
||||||
from config import DELETE_BRAND_API_BASE
|
from config import DELETE_BRAND_API_BASE
|
||||||
@@ -2130,6 +2154,8 @@ class PatrolDeleteTask:
|
|||||||
}
|
}
|
||||||
if error:
|
if error:
|
||||||
shop_payload["error"] = error
|
shop_payload["error"] = error
|
||||||
|
elif heartbeat_only:
|
||||||
|
shop_payload["heartbeatOnly"] = True
|
||||||
else:
|
else:
|
||||||
shop_payload["countrySections"] = self._normalize_country_sections_for_result(country_sections)
|
shop_payload["countrySections"] = self._normalize_country_sections_for_result(country_sections)
|
||||||
shop_payload["cartRatios"] = self._normalize_cart_ratios_for_result(cart_ratios)
|
shop_payload["cartRatios"] = self._normalize_cart_ratios_for_result(cart_ratios)
|
||||||
@@ -2217,9 +2243,12 @@ class PatrolDeleteTask:
|
|||||||
rows = []
|
rows = []
|
||||||
for row in section.get("rows") or []:
|
for row in section.get("rows") or []:
|
||||||
if cls._is_complete_draft_result_row(row):
|
if cls._is_complete_draft_result_row(row):
|
||||||
|
delete_quantity = cls._string_result_field(row.get("deleteQuantity"))
|
||||||
normalized_row = {
|
normalized_row = {
|
||||||
|
"status": cls._complete_draft_result_status(row),
|
||||||
"quantity": cls._string_result_field(row.get("quantity")),
|
"quantity": cls._string_result_field(row.get("quantity")),
|
||||||
"deleteQuantity": cls._string_result_field(row.get("deleteQuantity")),
|
"deleteQuantity": delete_quantity,
|
||||||
|
"processStatus": cls._complete_draft_process_status(row, delete_quantity),
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
normalized_row = {
|
normalized_row = {
|
||||||
@@ -2255,6 +2284,19 @@ class PatrolDeleteTask:
|
|||||||
row_type = str(row.get("type") or row.get("kind") or row.get("_kind") or "").strip()
|
row_type = str(row.get("type") or row.get("kind") or row.get("_kind") or "").strip()
|
||||||
return status in {"补全草稿", "商品信息草稿"} or tag == "补全草稿" or row_type == "completeDraft"
|
return status in {"补全草稿", "商品信息草稿"} or tag == "补全草稿" or row_type == "completeDraft"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _complete_draft_result_status(row: Dict[str, Any]) -> str:
|
||||||
|
status = PatrolDeleteTask._string_result_field(row.get("status") or row.get("tag")).strip()
|
||||||
|
return status or "商品信息草稿"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _complete_draft_process_status(row: Dict[str, Any], delete_quantity: str) -> str:
|
||||||
|
process_status = PatrolDeleteTask._string_result_field(row.get("processStatus")).strip()
|
||||||
|
if process_status:
|
||||||
|
return process_status
|
||||||
|
match = re.search(r"\d+", str(delete_quantity or ""))
|
||||||
|
return "已完成" if match and int(match.group(0)) > 0 else ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _replace_complete_draft_rows(
|
def _replace_complete_draft_rows(
|
||||||
cls,
|
cls,
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ def _resolve_asset_filename(filename):
|
|||||||
"""Resolve hashed Vite assets without maintaining hardcoded alias tables."""
|
"""Resolve hashed Vite assets without maintaining hardcoded alias tables."""
|
||||||
safe_name = os.path.basename(filename)
|
safe_name = os.path.basename(filename)
|
||||||
asset_dirs = [
|
asset_dirs = [
|
||||||
ASSETS_DIR,
|
|
||||||
os.path.abspath(os.path.join(BASE_DIR, 'new_web_source', 'assets')),
|
os.path.abspath(os.path.join(BASE_DIR, 'new_web_source', 'assets')),
|
||||||
os.path.abspath(os.path.join(BASE_DIR, '..', 'new_web_source', 'assets')),
|
os.path.abspath(os.path.join(BASE_DIR, '..', 'new_web_source', 'assets')),
|
||||||
|
ASSETS_DIR,
|
||||||
]
|
]
|
||||||
for asset_dir in asset_dirs:
|
for asset_dir in asset_dirs:
|
||||||
exact_path = os.path.join(asset_dir, safe_name)
|
exact_path = os.path.join(asset_dir, safe_name)
|
||||||
@@ -153,9 +153,9 @@ def serve_assets(filename):
|
|||||||
"""提供 static 目录及子目录下的静态文件访问。"""
|
"""提供 static 目录及子目录下的静态文件访问。"""
|
||||||
filename = _resolve_asset_filename(filename)
|
filename = _resolve_asset_filename(filename)
|
||||||
candidate_dirs = [
|
candidate_dirs = [
|
||||||
os.path.abspath(ASSETS_DIR),
|
|
||||||
os.path.abspath(os.path.join(BASE_DIR, 'new_web_source', 'assets')),
|
os.path.abspath(os.path.join(BASE_DIR, 'new_web_source', 'assets')),
|
||||||
os.path.abspath(os.path.join(BASE_DIR, '..', 'new_web_source', 'assets')),
|
os.path.abspath(os.path.join(BASE_DIR, '..', 'new_web_source', 'assets')),
|
||||||
|
os.path.abspath(ASSETS_DIR),
|
||||||
]
|
]
|
||||||
for static_abs in candidate_dirs:
|
for static_abs in candidate_dirs:
|
||||||
filepath = os.path.normpath(os.path.join(static_abs, filename))
|
filepath = os.path.normpath(os.path.join(static_abs, filename))
|
||||||
|
|||||||
+1
-1
@@ -7,13 +7,13 @@ import json
|
|||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
from amazon.main import TaskMonitor
|
|
||||||
os.makedirs(cache_path,exist_ok=True)
|
os.makedirs(cache_path,exist_ok=True)
|
||||||
if not debug:
|
if not debug:
|
||||||
today = datetime.datetime.now().strftime("%Y_%m_%d")
|
today = datetime.datetime.now().strftime("%Y_%m_%d")
|
||||||
sys.stdout = open(os.path.join(cache_path,f'{today}.log'), 'a',buffering=1,encoding='utf-8')
|
sys.stdout = open(os.path.join(cache_path,f'{today}.log'), 'a',buffering=1,encoding='utf-8')
|
||||||
sys.stderr = sys.stdout
|
sys.stderr = sys.stdout
|
||||||
|
|
||||||
|
from amazon.main import TaskMonitor
|
||||||
import webview
|
import webview
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ def test_patrol_delete_task_post_result_retries_business_failure(monkeypatch):
|
|||||||
assert len(calls) == 3
|
assert len(calls) == 3
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_country_sections_omits_status_fields_for_complete_draft_rows():
|
def test_normalize_country_sections_keeps_status_fields_for_complete_draft_rows():
|
||||||
rows = PatrolDeleteTask._normalize_country_sections_for_result(
|
rows = PatrolDeleteTask._normalize_country_sections_for_result(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -132,7 +132,7 @@ def test_normalize_country_sections_omits_status_fields_for_complete_draft_rows(
|
|||||||
{
|
{
|
||||||
"country": "意大利",
|
"country": "意大利",
|
||||||
"rows": [
|
"rows": [
|
||||||
{"quantity": "12", "deleteQuantity": "3"},
|
{"status": "商品信息草稿", "quantity": "12", "deleteQuantity": "3", "processStatus": "已完成"},
|
||||||
{"status": "缺少的信息", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
{"status": "缺少的信息", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -150,8 +150,8 @@ def test_replace_complete_draft_rows_uses_quick_view_rows():
|
|||||||
complete_draft_section = {
|
complete_draft_section = {
|
||||||
"country": "西班牙",
|
"country": "西班牙",
|
||||||
"rows": [
|
"rows": [
|
||||||
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1"},
|
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||||
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0"},
|
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0", "processStatus": ""},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,8 +161,8 @@ def test_replace_complete_draft_rows_uses_quick_view_rows():
|
|||||||
"country": "西班牙",
|
"country": "西班牙",
|
||||||
"rows": [
|
"rows": [
|
||||||
{"status": "全部", "quantity": "6230", "deleteQuantity": "0", "processStatus": "无可删商品"},
|
{"status": "全部", "quantity": "6230", "deleteQuantity": "0", "processStatus": "无可删商品"},
|
||||||
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1"},
|
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||||
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0"},
|
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0", "processStatus": ""},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
assert PatrolDeleteTask._normalize_country_sections_for_result([merged]) == [
|
assert PatrolDeleteTask._normalize_country_sections_for_result([merged]) == [
|
||||||
@@ -170,8 +170,8 @@ def test_replace_complete_draft_rows_uses_quick_view_rows():
|
|||||||
"country": "西班牙",
|
"country": "西班牙",
|
||||||
"rows": [
|
"rows": [
|
||||||
{"status": "全部", "quantity": "6230", "deleteQuantity": "0", "processStatus": "无可删商品"},
|
{"status": "全部", "quantity": "6230", "deleteQuantity": "0", "processStatus": "无可删商品"},
|
||||||
{"quantity": "1", "deleteQuantity": "1"},
|
{"status": "商品信息草稿", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||||
{"quantity": "0", "deleteQuantity": "0"},
|
{"status": "商品信息草稿", "quantity": "0", "deleteQuantity": "0", "processStatus": ""},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -261,6 +261,18 @@ def test_patrol_delete_task_process_task_aggregates_country_results(monkeypatch)
|
|||||||
assert runing_task[1]["deleted_listings_count"] == 2
|
assert runing_task[1]["deleted_listings_count"] == 2
|
||||||
assert "郭亚芳" not in runing_shop
|
assert "郭亚芳" not in runing_shop
|
||||||
assert calls == [
|
assert calls == [
|
||||||
|
{
|
||||||
|
"task_id": 1,
|
||||||
|
"shop_name": "郭亚芳",
|
||||||
|
"shop_done": False,
|
||||||
|
"heartbeat_only": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": 1,
|
||||||
|
"shop_name": "郭亚芳",
|
||||||
|
"shop_done": False,
|
||||||
|
"heartbeat_only": True,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"task_id": 1,
|
"task_id": 1,
|
||||||
"shop_name": "郭亚芳",
|
"shop_name": "郭亚芳",
|
||||||
@@ -377,16 +389,28 @@ def test_delete_complete_draft_country_section_reports_delete_quantity(monkeypat
|
|||||||
assert result["countrySection"] == {
|
assert result["countrySection"] == {
|
||||||
"country": "德国",
|
"country": "德国",
|
||||||
"rows": [
|
"rows": [
|
||||||
{"type": "completeDraft", "status": "未提交的草稿", "quantity": "0", "deleteQuantity": "3"},
|
{
|
||||||
{"type": "completeDraft", "status": "已提交:提供缺少的信息", "quantity": "2", "deleteQuantity": "0"},
|
"type": "completeDraft",
|
||||||
|
"status": "未提交的草稿",
|
||||||
|
"quantity": "0",
|
||||||
|
"deleteQuantity": "3",
|
||||||
|
"processStatus": "已完成",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "completeDraft",
|
||||||
|
"status": "已提交:提供缺少的信息",
|
||||||
|
"quantity": "2",
|
||||||
|
"deleteQuantity": "0",
|
||||||
|
"processStatus": "",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
assert PatrolDeleteTask._normalize_country_sections_for_result([result["countrySection"]]) == [
|
assert PatrolDeleteTask._normalize_country_sections_for_result([result["countrySection"]]) == [
|
||||||
{
|
{
|
||||||
"country": "德国",
|
"country": "德国",
|
||||||
"rows": [
|
"rows": [
|
||||||
{"quantity": "0", "deleteQuantity": "3"},
|
{"status": "未提交的草稿", "quantity": "0", "deleteQuantity": "3", "processStatus": "已完成"},
|
||||||
{"quantity": "2", "deleteQuantity": "0"},
|
{"status": "已提交:提供缺少的信息", "quantity": "2", "deleteQuantity": "0", "processStatus": ""},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -60,7 +60,12 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section-title">删除条件</div>
|
<div class="section-title condition-title">
|
||||||
|
<span>删除条件</span>
|
||||||
|
<span class="condition-title-hint">
|
||||||
|
注意删除条件的描述需要和页面描述一致
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="condition-panel">
|
<div class="condition-panel">
|
||||||
<div class="condition-input-row">
|
<div class="condition-input-row">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -823,13 +828,14 @@ async function refreshActiveTaskProgress(taskIds?: number[]) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
return;
|
return [];
|
||||||
}
|
}
|
||||||
const batch = await getPatrolDeleteTaskProgressBatch(ids);
|
const batch = await getPatrolDeleteTaskProgressBatch(ids);
|
||||||
mergeHistoryProgressItems(batch.items || []);
|
mergeHistoryProgressItems(batch.items || []);
|
||||||
if ((batch.missingTaskIds || []).length) {
|
if ((batch.missingTaskIds || []).length) {
|
||||||
await loadHistory();
|
await loadHistory();
|
||||||
}
|
}
|
||||||
|
return batch.missingTaskIds || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function startHistoryPolling() {
|
function startHistoryPolling() {
|
||||||
@@ -1029,7 +1035,11 @@ async function waitForTaskTerminal(taskId: number) {
|
|||||||
if (disposed) return "STOPPED";
|
if (disposed) return "STOPPED";
|
||||||
if (activeTaskId.value !== taskId) return "DELETED";
|
if (activeTaskId.value !== taskId) return "DELETED";
|
||||||
try {
|
try {
|
||||||
await refreshActiveTaskProgress([taskId]);
|
const missingTaskIds = await refreshActiveTaskProgress([taskId]);
|
||||||
|
if (missingTaskIds.includes(taskId)) {
|
||||||
|
clearActiveQueueTask();
|
||||||
|
return "DELETED";
|
||||||
|
}
|
||||||
if (activeTaskId.value !== taskId) return "DELETED";
|
if (activeTaskId.value !== taskId) return "DELETED";
|
||||||
if (transientErrorCount > 0) {
|
if (transientErrorCount > 0) {
|
||||||
queuePushResult.value = `任务 ${taskId} 后端已恢复,继续等待执行结果...`;
|
queuePushResult.value = `任务 ${taskId} 后端已恢复,继续等待执行结果...`;
|
||||||
@@ -1236,6 +1246,8 @@ onUnmounted(() => {
|
|||||||
.left-panel { width: 400px; background: #1e1e1e; padding: 20px; overflow-y: auto; border-right: 1px solid #2a2a2a; }
|
.left-panel { width: 400px; background: #1e1e1e; padding: 20px; overflow-y: auto; border-right: 1px solid #2a2a2a; }
|
||||||
.right-panel { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #1a1a1a; }
|
.right-panel { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #1a1a1a; }
|
||||||
.section-title { font-size: 13px; color: #bbb; margin-bottom: 10px; }
|
.section-title { font-size: 13px; color: #bbb; margin-bottom: 10px; }
|
||||||
|
.condition-title { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
||||||
|
.condition-title-hint { flex: 1; min-width: 0; color: #d6a95a; font-size: 12px; text-align: right; line-height: 1.35; }
|
||||||
.input-zone { border: 1px dashed #3a3a3a; border-radius: 10px; padding: 16px; background: #252525; margin-bottom: 20px; }
|
.input-zone { border: 1px dashed #3a3a3a; border-radius: 10px; padding: 16px; background: #252525; margin-bottom: 20px; }
|
||||||
.hint { color: #888; font-size: 12px; margin-bottom: 12px; line-height: 1.5; text-align: left; }
|
.hint { color: #888; font-size: 12px; margin-bottom: 12px; line-height: 1.5; text-align: left; }
|
||||||
.input-row { display: flex; gap: 10px; align-items: center; }
|
.input-row { display: flex; gap: 10px; align-items: center; }
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>外观专利检测</title>
|
<title>外观专利检测</title>
|
||||||
<script type="module" crossorigin src="/assets/appearance-patent.js"></script>
|
<script type="module" crossorigin src="/assets/appearance-patent.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-BZije8D7.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/appearance-patent-BPCrG75P.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/appearance-patent-TI-osB39.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
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};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
const r=new Map;function c(n){let t=r.get(n);return t||(t=new Map,r.set(n,t)),t}function u(n,t){const e=r.get(n);e&&(e.delete(t),e.size||r.delete(n))}function l(n,t,e){const i=window.setTimeout(()=>{u(n,i),t()},e);return c(n).set(i,{id:i,kind:"timeout",category:n}),i}function a(n,t,e){const i=window.setInterval(t,e);return c(n).set(i,{id:i,kind:"interval",category:n}),i}function f(n,t){if(t==null)return;const i=r.get(n)?.get(t);i?.kind==="interval"?window.clearInterval(t):window.clearTimeout(t),i?.cancel?.(),u(n,t)}function s(n){const t=r.get(n);if(t){for(const e of t.values())e.kind==="interval"?window.clearInterval(e.id):window.clearTimeout(e.id),e.cancel?.();r.delete(n)}}function d(n,t){return new Promise(e=>{const i=window.setTimeout(()=>{u(n,i),e()},t);c(n).set(i,{id:i,kind:"timeout",category:n,cancel:e})})}function m(n){const t=`${n}:`;for(const e of Array.from(r.keys()))(e===n||e.startsWith(t))&&s(e)}function w(n){const t=e=>`${n}:${e}`;return{setTimeout(e,i,o){return l(t(e),i,o)},setInterval(e,i,o){return a(t(e),i,o)},clearTimer(e,i){f(t(e),i)},clearCategory(e){s(t(e))},clearScope(){m(n)},sleep(e,i){return d(t(e),i)}}}export{w as c};
|
||||||
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
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
@@ -5,10 +5,10 @@
|
|||||||
<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-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-BZije8D7.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/convert-BKSNvX8i.css">
|
<link rel="stylesheet" crossorigin href="/assets/convert-r7MSXq7I.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
<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-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-BZije8D7.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/dedupe-DNlVfFj-.css">
|
<link rel="stylesheet" crossorigin href="/assets/dedupe-DMeaPUMZ.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
<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-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-BZije8D7.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/delete-brand-BP3XWKAC.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/delete-brand-B5ChOXZY.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
<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/patrol-delete.js"></script>
|
<script type="module" crossorigin src="/assets/patrol-delete.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/zh-cn-CuE9Zzgz.js">
|
<link rel="modulepreload" crossorigin href="/assets/zh-cn-BbuLS91u.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/patrol-delete-CSekhzSS.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/patrol-delete-DyumfGaZ.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
<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/price-track.js"></script>
|
<script type="module" crossorigin src="/assets/price-track.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-BZije8D7.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/price-track-z8RU_FlW.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/price-track-DMhhVz4u.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
<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/product-risk.js"></script>
|
<script type="module" crossorigin src="/assets/product-risk.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/listingFilters-BpGOU_pJ.js">
|
<link rel="modulepreload" crossorigin href="/assets/listingFilters-BpGOU_pJ.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<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/listingFilters-CK58rX4v.css">
|
<link rel="stylesheet" crossorigin href="/assets/listingFilters-CK58rX4v.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/product-risk-eXMv239F.css">
|
<link rel="stylesheet" crossorigin href="/assets/product-risk-CI6qY5U2.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
<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/query-asin.js"></script>
|
<script type="module" crossorigin src="/assets/query-asin.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/zh-cn-CuE9Zzgz.js">
|
<link rel="modulepreload" crossorigin href="/assets/zh-cn-BbuLS91u.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="modulepreload" crossorigin href="/assets/categorized-timers-JPA-olTr.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/query-asin-Bv7Jtgqa.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/query-asin-Bw6BQsRN.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -5,12 +5,13 @@
|
|||||||
<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/shop-match.js"></script>
|
<script type="module" crossorigin src="/assets/shop-match.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/zh-cn-CuE9Zzgz.js">
|
<link rel="modulepreload" crossorigin href="/assets/zh-cn-BbuLS91u.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/listingFilters-BpGOU_pJ.js">
|
<link rel="modulepreload" crossorigin href="/assets/listingFilters-BpGOU_pJ.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<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/listingFilters-CK58rX4v.css">
|
<link rel="stylesheet" crossorigin href="/assets/listingFilters-CK58rX4v.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/shop-match-BiZP8IGM.css">
|
<link rel="stylesheet" crossorigin href="/assets/shop-match-CxCKUsqS.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
<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-C66x_2Dh.js">
|
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/brand-BZije8D7.js">
|
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/split-BoBVrLdC.css">
|
<link rel="stylesheet" crossorigin href="/assets/split-Cw6sXhAg.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{"version": "1.0.56"}
|
||||||
Reference in New Issue
Block a user