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"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:
|
||||
self.log(f"店铺 {shop_name} 国家处理完成,正在关闭店铺")
|
||||
@@ -1822,6 +1826,22 @@ class PatrolDeleteTask:
|
||||
del runing_shop[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]:
|
||||
error_info = ""
|
||||
driver: Optional[InventoryManage] = None
|
||||
@@ -1996,6 +2016,8 @@ class PatrolDeleteTask:
|
||||
"type": "completeDraft",
|
||||
"status": PatrolDeleteTask._string_result_field(item.get("tag")),
|
||||
"quantity": quantity,
|
||||
"deleteQuantity": "",
|
||||
"processStatus": "",
|
||||
}
|
||||
)
|
||||
self.log(f"trace_id={trace_id} 国家 {country_name} 补全草稿读取完成: rows={rows}")
|
||||
@@ -2032,6 +2054,7 @@ class PatrolDeleteTask:
|
||||
"status": status,
|
||||
"quantity": InventoryManage._normalize_quantity_text(item.get("quantity")),
|
||||
"deleteQuantity": str(deleted_count),
|
||||
"processStatus": "已完成" if deleted_count > 0 else "",
|
||||
}
|
||||
)
|
||||
section = {"country": country_name, "rows": rows} if rows else None
|
||||
@@ -2116,6 +2139,7 @@ class PatrolDeleteTask:
|
||||
cart_ratios: Optional[List[Dict[str, Any]]] = None,
|
||||
error: str = "",
|
||||
shop_done: bool = False,
|
||||
heartbeat_only: bool = False,
|
||||
):
|
||||
"""回传巡店删除结果到 Java API。"""
|
||||
from config import DELETE_BRAND_API_BASE
|
||||
@@ -2130,6 +2154,8 @@ class PatrolDeleteTask:
|
||||
}
|
||||
if error:
|
||||
shop_payload["error"] = error
|
||||
elif heartbeat_only:
|
||||
shop_payload["heartbeatOnly"] = True
|
||||
else:
|
||||
shop_payload["countrySections"] = self._normalize_country_sections_for_result(country_sections)
|
||||
shop_payload["cartRatios"] = self._normalize_cart_ratios_for_result(cart_ratios)
|
||||
@@ -2217,9 +2243,12 @@ class PatrolDeleteTask:
|
||||
rows = []
|
||||
for row in section.get("rows") or []:
|
||||
if cls._is_complete_draft_result_row(row):
|
||||
delete_quantity = cls._string_result_field(row.get("deleteQuantity"))
|
||||
normalized_row = {
|
||||
"status": cls._complete_draft_result_status(row),
|
||||
"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:
|
||||
normalized_row = {
|
||||
@@ -2255,6 +2284,19 @@ class PatrolDeleteTask:
|
||||
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"
|
||||
|
||||
@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
|
||||
def _replace_complete_draft_rows(
|
||||
cls,
|
||||
|
||||
@@ -27,9 +27,9 @@ def _resolve_asset_filename(filename):
|
||||
"""Resolve hashed Vite assets without maintaining hardcoded alias tables."""
|
||||
safe_name = os.path.basename(filename)
|
||||
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')),
|
||||
ASSETS_DIR,
|
||||
]
|
||||
for asset_dir in asset_dirs:
|
||||
exact_path = os.path.join(asset_dir, safe_name)
|
||||
@@ -153,9 +153,9 @@ def serve_assets(filename):
|
||||
"""提供 static 目录及子目录下的静态文件访问。"""
|
||||
filename = _resolve_asset_filename(filename)
|
||||
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(ASSETS_DIR),
|
||||
]
|
||||
for static_abs in candidate_dirs:
|
||||
filepath = os.path.normpath(os.path.join(static_abs, filename))
|
||||
|
||||
+1
-1
@@ -7,13 +7,13 @@ import json
|
||||
import sys
|
||||
import shutil
|
||||
import os
|
||||
from amazon.main import TaskMonitor
|
||||
os.makedirs(cache_path,exist_ok=True)
|
||||
if not debug:
|
||||
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.stderr = sys.stdout
|
||||
|
||||
from amazon.main import TaskMonitor
|
||||
import webview
|
||||
import threading
|
||||
import time
|
||||
|
||||
@@ -105,7 +105,7 @@ def test_patrol_delete_task_post_result_retries_business_failure(monkeypatch):
|
||||
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(
|
||||
[
|
||||
{
|
||||
@@ -132,7 +132,7 @@ def test_normalize_country_sections_omits_status_fields_for_complete_draft_rows(
|
||||
{
|
||||
"country": "意大利",
|
||||
"rows": [
|
||||
{"quantity": "12", "deleteQuantity": "3"},
|
||||
{"status": "商品信息草稿", "quantity": "12", "deleteQuantity": "3", "processStatus": "已完成"},
|
||||
{"status": "缺少的信息", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||
],
|
||||
}
|
||||
@@ -150,8 +150,8 @@ def test_replace_complete_draft_rows_uses_quick_view_rows():
|
||||
complete_draft_section = {
|
||||
"country": "西班牙",
|
||||
"rows": [
|
||||
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1"},
|
||||
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0"},
|
||||
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0", "processStatus": ""},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -161,8 +161,8 @@ def test_replace_complete_draft_rows_uses_quick_view_rows():
|
||||
"country": "西班牙",
|
||||
"rows": [
|
||||
{"status": "全部", "quantity": "6230", "deleteQuantity": "0", "processStatus": "无可删商品"},
|
||||
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1"},
|
||||
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0"},
|
||||
{"type": "completeDraft", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||
{"type": "completeDraft", "quantity": "0", "deleteQuantity": "0", "processStatus": ""},
|
||||
],
|
||||
}
|
||||
assert PatrolDeleteTask._normalize_country_sections_for_result([merged]) == [
|
||||
@@ -170,8 +170,8 @@ def test_replace_complete_draft_rows_uses_quick_view_rows():
|
||||
"country": "西班牙",
|
||||
"rows": [
|
||||
{"status": "全部", "quantity": "6230", "deleteQuantity": "0", "processStatus": "无可删商品"},
|
||||
{"quantity": "1", "deleteQuantity": "1"},
|
||||
{"quantity": "0", "deleteQuantity": "0"},
|
||||
{"status": "商品信息草稿", "quantity": "1", "deleteQuantity": "1", "processStatus": "已完成"},
|
||||
{"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 "郭亚芳" not in runing_shop
|
||||
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,
|
||||
"shop_name": "郭亚芳",
|
||||
@@ -377,16 +389,28 @@ def test_delete_complete_draft_country_section_reports_delete_quantity(monkeypat
|
||||
assert result["countrySection"] == {
|
||||
"country": "德国",
|
||||
"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"]]) == [
|
||||
{
|
||||
"country": "德国",
|
||||
"rows": [
|
||||
{"quantity": "0", "deleteQuantity": "3"},
|
||||
{"quantity": "2", "deleteQuantity": "0"},
|
||||
{"status": "未提交的草稿", "quantity": "0", "deleteQuantity": "3", "processStatus": "已完成"},
|
||||
{"status": "已提交:提供缺少的信息", "quantity": "2", "deleteQuantity": "0", "processStatus": ""},
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
@@ -60,7 +60,12 @@
|
||||
</el-table>
|
||||
</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-input-row">
|
||||
<el-input
|
||||
@@ -823,13 +828,14 @@ async function refreshActiveTaskProgress(taskIds?: number[]) {
|
||||
),
|
||||
);
|
||||
if (!ids.length) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
const batch = await getPatrolDeleteTaskProgressBatch(ids);
|
||||
mergeHistoryProgressItems(batch.items || []);
|
||||
if ((batch.missingTaskIds || []).length) {
|
||||
await loadHistory();
|
||||
}
|
||||
return batch.missingTaskIds || [];
|
||||
}
|
||||
|
||||
function startHistoryPolling() {
|
||||
@@ -1029,7 +1035,11 @@ async function waitForTaskTerminal(taskId: number) {
|
||||
if (disposed) return "STOPPED";
|
||||
if (activeTaskId.value !== taskId) return "DELETED";
|
||||
try {
|
||||
await refreshActiveTaskProgress([taskId]);
|
||||
const missingTaskIds = await refreshActiveTaskProgress([taskId]);
|
||||
if (missingTaskIds.includes(taskId)) {
|
||||
clearActiveQueueTask();
|
||||
return "DELETED";
|
||||
}
|
||||
if (activeTaskId.value !== taskId) return "DELETED";
|
||||
if (transientErrorCount > 0) {
|
||||
queuePushResult.value = `任务 ${taskId} 后端已恢复,继续等待执行结果...`;
|
||||
@@ -1236,6 +1246,8 @@ onUnmounted(() => {
|
||||
.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; }
|
||||
.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; }
|
||||
.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; }
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>外观专利检测</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>外观专利检测</title>
|
||||
<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/brand-BZije8D7.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/appearance-patent-BPCrG75P.css">
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.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/appearance-patent-TI-osB39.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</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
+15
-15
@@ -1,16 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>格式转换 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>格式转换 - 数富AI</title>
|
||||
<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/brand-BZije8D7.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/convert-BKSNvX8i.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/convert-r7MSXq7I.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
+15
-15
@@ -1,16 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>数据去重 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>数据去重 - 数富AI</title>
|
||||
<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/brand-BZije8D7.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/dedupe-DNlVfFj-.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/dedupe-DMeaPUMZ.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>删除品牌 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>删除品牌 - 数富AI</title>
|
||||
<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/brand-BZije8D7.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/delete-brand-BP3XWKAC.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.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/delete-brand-B5ChOXZY.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>巡店删除 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>巡店删除 - 数富AI</title>
|
||||
<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/zh-cn-CuE9Zzgz.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/patrol-delete-CSekhzSS.css">
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/zh-cn-BbuLS91u.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/patrol-delete-DyumfGaZ.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>跟价 - 数富AI</title>
|
||||
<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/brand-BZije8D7.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/price-track-z8RU_FlW.css">
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.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/price-track-DMhhVz4u.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||
</head>
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>商品风险解决 - 数富AI</title>
|
||||
<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="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/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-input-xaztPnzw.css">
|
||||
</head>
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>巡店删除 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>巡店删除 - 数富AI</title>
|
||||
<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/zh-cn-CuE9Zzgz.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/query-asin-Bv7Jtgqa.css">
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/zh-cn-BbuLS91u.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/query-asin-Bw6BQsRN.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/el-input-xaztPnzw.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>匹配店铺 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>匹配店铺 - 数富AI</title>
|
||||
<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/zh-cn-CuE9Zzgz.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/zh-cn-BbuLS91u.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/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-input-xaztPnzw.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
+15
-15
@@ -1,16 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>数据拆分 - 数富AI</title>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>数据拆分 - 数富AI</title>
|
||||
<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/brand-BZije8D7.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/split-BoBVrLdC.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
<link rel="modulepreload" crossorigin href="/assets/pywebview-BWNiqXug.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/brand-CABpTGPu.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/pywebview-BFZO8_3q.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/split-Cw6sXhAg.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"version": "1.0.56"}
|
||||
Reference in New Issue
Block a user