fix: update frontend
This commit is contained in:
BIN
__pycache__/ts.cpython-39.pyc
Normal file
BIN
__pycache__/ts.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/approve.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/approve.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/asin_status.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/asin_status.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/base.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/base.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/del_brand.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/del_brand.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/detail_spider.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/detail_spider.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/main.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/main.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/match_action.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/match_action.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/patrol_delete.cpython-314.pyc
Normal file
BIN
app/amazon/__pycache__/patrol_delete.cpython-314.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/patrol_delete.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/patrol_delete.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/price_match.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/price_match.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/amazon/__pycache__/tool.cpython-39.pyc
Normal file
BIN
app/amazon/__pycache__/tool.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/admin.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/admin.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/auth.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/auth.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/brand.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/brand.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/communication.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/communication.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/image.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/image.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/blueprints/__pycache__/main.cpython-39.pyc
Normal file
BIN
app/blueprints/__pycache__/main.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/brand_spider/__pycache__/main.cpython-39.pyc
Normal file
BIN
app/brand_spider/__pycache__/main.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/brand_spider/__pycache__/web_dec.cpython-39.pyc
Normal file
BIN
app/brand_spider/__pycache__/web_dec.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/tests/__pycache__/conftest.cpython-39-pytest-8.4.2.pyc
Normal file
BIN
app/tests/__pycache__/conftest.cpython-39-pytest-8.4.2.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app/tests/__pycache__/test_patrol_delete.cpython-39.pyc
Normal file
BIN
app/tests/__pycache__/test_patrol_delete.cpython-39.pyc
Normal file
Binary file not shown.
BIN
app/tool/__pycache__/devices.cpython-39.pyc
Normal file
BIN
app/tool/__pycache__/devices.cpython-39.pyc
Normal file
Binary file not shown.
17
new_web_source/appearance-patent.html
Normal file
17
new_web_source/appearance-patent.html
Normal file
@@ -0,0 +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>外观专利检测</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="stylesheet" crossorigin href="/assets/el-table-column-Cy4YJvw0.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
new_web_source/assets/appearance-patent-BPCrG75P.css
Normal file
1
new_web_source/assets/appearance-patent-BPCrG75P.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.module-page[data-v-d71413c4]{min-height:100vh;background:#1a1a1a}.main-content[data-v-d71413c4]{display:flex;height:calc(100vh - 56px);min-height:calc(100vh - 56px)}.left-panel[data-v-d71413c4]{width:400px;background:#1e1e1e;padding:20px;overflow-y:auto;border-right:1px solid #2a2a2a}.right-panel[data-v-d71413c4]{flex:1;min-width:0;background:#1a1a1a;display:flex;flex-direction:column}.section-title[data-v-d71413c4],.subsection-title[data-v-d71413c4]{font-size:13px;color:#bbb;margin-bottom:10px}.upload-zone[data-v-d71413c4]{border:1px dashed #3a3a3a;border-radius:10px;padding:18px;background:#252525;margin-bottom:18px}.hint[data-v-d71413c4],.loading-msg[data-v-d71413c4],.files[data-v-d71413c4],.muted[data-v-d71413c4]{color:#888;font-size:12px;line-height:1.5}.link[data-v-d71413c4]{color:#6ea8fe;text-decoration:none}.link[data-v-d71413c4]:hover{color:#9fc5ff}.btns[data-v-d71413c4],.run-row[data-v-d71413c4]{display:flex;gap:10px;flex-wrap:wrap}.opt-btn[data-v-d71413c4],.btn-run[data-v-d71413c4],.btn-delete[data-v-d71413c4],.download[data-v-d71413c4]{border:none;cursor:pointer;border-radius:7px}.opt-btn[data-v-d71413c4]{padding:8px 14px;color:#ccc;background:#2a2a2a;border:1px solid #3a3a3a}.btn-run[data-v-d71413c4]{padding:10px 18px;color:#fff;background:#3498db;font-weight:600}.btn-queue[data-v-d71413c4]{background:#27ae60}.btn-run[data-v-d71413c4]:disabled{opacity:.55;cursor:not-allowed}.selected-files[data-v-d71413c4]{margin-top:14px;color:#999;font-size:12px;word-break:break-all}.selected-files span[data-v-d71413c4]{display:block;margin:4px 0}.prompt-card[data-v-d71413c4]{margin-bottom:18px}.prompt-input[data-v-d71413c4]{width:100%;box-sizing:border-box;resize:vertical;min-height:180px;padding:10px 12px;border:1px solid #333;border-radius:8px;background:#202020;color:#d8d8d8;font-size:12px;line-height:1.6;outline:none}.prompt-input[data-v-d71413c4]:focus{border-color:#3498db}.prompt-default-label[data-v-d71413c4]{margin-top:10px;color:#8d8d8d;font-size:12px}.prompt-preview[data-v-d71413c4]{margin-top:10px;padding:12px;border:1px solid #2a2a2a;border-radius:8px;background:#202020;color:#9ea7b3;font-size:12px;line-height:1.6;white-space:pre-wrap}.parse-card[data-v-d71413c4],.queue-payload[data-v-d71413c4]{margin-top:14px;padding:12px;border:1px solid #2a2a2a;border-radius:8px;background:#202020;color:#b8c1cc;font-size:12px}.queue-payload[data-v-d71413c4]{max-height:220px;overflow:auto;color:#8fd3ff;white-space:pre-wrap}.panel-header[data-v-d71413c4]{padding:16px 20px;border-bottom:1px solid #2a2a2a;font-size:15px;font-weight:600;color:#ddd}.task-list-wrap[data-v-d71413c4]{flex:1;padding:16px 20px;overflow:auto}.clean-result-summary[data-v-d71413c4]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:16px}.summary-card[data-v-d71413c4]{padding:14px 16px;border:1px solid #2a2a2a;border-radius:8px;background:#1e1e1e}.summary-card strong[data-v-d71413c4]{display:block;margin-top:8px;color:#eaf4ff;font-size:22px}.summary-label[data-v-d71413c4]{color:#8d8d8d;font-size:12px}.result-list-wrap[data-v-d71413c4]{border:1px solid #2a2a2a;border-radius:8px;background:#1e1e1e;min-height:180px;margin:0 0 16px}.result-list-header[data-v-d71413c4]{display:flex;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #2a2a2a;color:#ddd;font-size:14px}.empty-tasks[data-v-d71413c4]{color:#666;font-size:13px;padding:18px;text-align:center}.result-table[data-v-d71413c4]{--el-table-bg-color: #222;--el-table-tr-bg-color: #222;--el-table-header-bg-color: #2a2a2a;--el-table-text-color: #ccc;--el-table-border-color: #333}.task-list[data-v-d71413c4]{list-style:none;margin:0;padding:12px}.task-item[data-v-d71413c4]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:12px 14px;border:1px solid #2a2a2a;border-radius:8px;margin-bottom:8px;background:#222}.left[data-v-d71413c4]{flex:1;min-width:0}.id[data-v-d71413c4]{color:#e0e0e0;font-size:13px;font-weight:600}.task-right[data-v-d71413c4]{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.status[data-v-d71413c4]{padding:4px 10px;border-radius:6px;font-size:12px}.status.success[data-v-d71413c4]{background:#2ecc712e;color:#2ecc71}.status.failed[data-v-d71413c4]{background:#e74c3c2e;color:#ff6b6b}.status.running[data-v-d71413c4]{background:#3498db2e;color:#3498db}.result-hint[data-v-d71413c4]{margin-top:6px;color:#e0b96d}.download[data-v-d71413c4]{padding:6px 10px;color:#d6ecff;background:#3498db2e}.btn-delete[data-v-d71413c4]{padding:6px 10px;color:#ff8f8f;background:#e74c3c1f}@media(max-width:1100px){.main-content[data-v-d71413c4]{flex-direction:column;height:auto}.left-panel[data-v-d71413c4]{width:100%;border-right:none;border-bottom:1px solid #2a2a2a}.clean-result-summary[data-v-d71413c4]{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||||
6
new_web_source/assets/appearance-patent.js
Normal file
6
new_web_source/assets/appearance-patent.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/brand-BZije8D7.js
Normal file
1
new_web_source/assets/brand-BZije8D7.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import{aZ as r}from"./pywebview-C66x_2Dh.js";const n="";function a(e){return r(`${n}/api/brand/expand-folder-recursive`,{folder:e})}export{a as e};
|
||||||
1
new_web_source/assets/convert-BKSNvX8i.css
Normal file
1
new_web_source/assets/convert-BKSNvX8i.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/convert.js
Normal file
1
new_web_source/assets/convert.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/dedupe-DNlVfFj-.css
Normal file
1
new_web_source/assets/dedupe-DNlVfFj-.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/dedupe.js
Normal file
1
new_web_source/assets/dedupe.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/delete-brand-BP3XWKAC.css
Normal file
1
new_web_source/assets/delete-brand-BP3XWKAC.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/delete-brand.js
Normal file
1
new_web_source/assets/delete-brand.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/el-input-xaztPnzw.css
Normal file
1
new_web_source/assets/el-input-xaztPnzw.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/el-table-column-Cy4YJvw0.css
Normal file
1
new_web_source/assets/el-table-column-Cy4YJvw0.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/listingFilters-BpGOU_pJ.js
Normal file
1
new_web_source/assets/listingFilters-BpGOU_pJ.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
const e=[{value:"SearchSuppressed",label:"在搜索结果中禁止显示"},{value:"ApprovalRequired",label:"需要批准"},{value:"Active",label:"在售"},{value:"DetailPageRemoved",label:"详情页面已删除"}];export{e as L};
|
||||||
1
new_web_source/assets/listingFilters-CK58rX4v.css
Normal file
1
new_web_source/assets/listingFilters-CK58rX4v.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/patrol-delete-CSekhzSS.css
Normal file
1
new_web_source/assets/patrol-delete-CSekhzSS.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/patrol-delete.js
Normal file
1
new_web_source/assets/patrol-delete.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/price-track-z8RU_FlW.css
Normal file
1
new_web_source/assets/price-track-z8RU_FlW.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/price-track.js
Normal file
1
new_web_source/assets/price-track.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/product-risk-eXMv239F.css
Normal file
1
new_web_source/assets/product-risk-eXMv239F.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/product-risk.js
Normal file
1
new_web_source/assets/product-risk.js
Normal file
File diff suppressed because one or more lines are too long
55
new_web_source/assets/pywebview-C66x_2Dh.js
Normal file
55
new_web_source/assets/pywebview-C66x_2Dh.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/pywebview-Dp5dN8OO.css
Normal file
1
new_web_source/assets/pywebview-Dp5dN8OO.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/query-asin-Bv7Jtgqa.css
Normal file
1
new_web_source/assets/query-asin-Bv7Jtgqa.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/query-asin.js
Normal file
1
new_web_source/assets/query-asin.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/shop-match-BiZP8IGM.css
Normal file
1
new_web_source/assets/shop-match-BiZP8IGM.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/shop-match.js
Normal file
1
new_web_source/assets/shop-match.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/split-BoBVrLdC.css
Normal file
1
new_web_source/assets/split-BoBVrLdC.css
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/split.js
Normal file
1
new_web_source/assets/split.js
Normal file
File diff suppressed because one or more lines are too long
1
new_web_source/assets/zh-cn-CuE9Zzgz.js
Normal file
1
new_web_source/assets/zh-cn-CuE9Zzgz.js
Normal file
File diff suppressed because one or more lines are too long
@@ -10,7 +10,7 @@
|
|||||||
<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="stylesheet" crossorigin href="/assets/pywebview-Dp5dN8OO.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-BmHsgsuC.css">
|
<link rel="stylesheet" crossorigin href="/assets/shop-match-BiZP8IGM.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>
|
||||||
|
|||||||
321
ts.py
Normal file
321
ts.py
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
ROOT_DIR = Path(__file__).resolve().parent
|
||||||
|
APP_DIR = ROOT_DIR / "app"
|
||||||
|
sys.path.insert(0, str(APP_DIR))
|
||||||
|
|
||||||
|
from amazon.main import TaskMonitor # noqa: E402
|
||||||
|
from amazon.patrol_delete import InventoryManage, PatrolDeleteTask # noqa: E402
|
||||||
|
from config import ( # noqa: E402
|
||||||
|
DELETE_BRAND_API_BASE,
|
||||||
|
JAVA_API_BASE,
|
||||||
|
JSON_TASK_QUEUE,
|
||||||
|
ZN_COMPANY,
|
||||||
|
ZN_PASSWORD,
|
||||||
|
ZN_USERNAME,
|
||||||
|
runing_task,
|
||||||
|
)
|
||||||
|
from main import WindowAPI # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
|
SHOP_NAME = "郭亚芳"
|
||||||
|
USER_ID = 1
|
||||||
|
COUNTRIES = [item.strip() for item in os.environ.get("PATROL_COUNTRIES", "德国,西班牙,意大利").split(",") if item.strip()]
|
||||||
|
TS_MODE = os.environ.get("TS_MODE", "full").strip().lower()
|
||||||
|
|
||||||
|
|
||||||
|
class EventSlot:
|
||||||
|
def __iadd__(self, handler):
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
class DummyWindow:
|
||||||
|
def __init__(self):
|
||||||
|
self.events = SimpleNamespace(maximized=EventSlot(), restored=EventSlot())
|
||||||
|
|
||||||
|
|
||||||
|
def log(message, payload=None):
|
||||||
|
print(f"[ts] {message}", flush=True)
|
||||||
|
if payload is not None:
|
||||||
|
print(json.dumps(payload, ensure_ascii=False, indent=2), flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
def unwrap(response):
|
||||||
|
log(f"HTTP {response.request.method} {response.url} -> {response.status_code}")
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
if not data.get("success"):
|
||||||
|
raise RuntimeError(data.get("message") or data.get("error") or response.text)
|
||||||
|
return data.get("data")
|
||||||
|
|
||||||
|
|
||||||
|
def get_match_item():
|
||||||
|
data = unwrap(
|
||||||
|
requests.post(
|
||||||
|
f"{JAVA_API_BASE}/api/patrol-delete/match-shops",
|
||||||
|
json={"user_id": USER_ID, "shop_names": [SHOP_NAME]},
|
||||||
|
timeout=40,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
items = data.get("items") or []
|
||||||
|
if not items:
|
||||||
|
raise RuntimeError("match-shops did not return any items")
|
||||||
|
|
||||||
|
item = items[0]
|
||||||
|
log("match result", item)
|
||||||
|
if not item.get("matched"):
|
||||||
|
raise RuntimeError(f"shop is not matched: {item}")
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
def create_java_task(match_item):
|
||||||
|
country_sections = [
|
||||||
|
{
|
||||||
|
"country": country,
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"status": "全部",
|
||||||
|
"quantity": "",
|
||||||
|
"deleteQuantity": "",
|
||||||
|
"processStatus": "",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
for country in COUNTRIES
|
||||||
|
]
|
||||||
|
cart_ratios = [{"country": country, "ratio": ""} for country in COUNTRIES]
|
||||||
|
task_item = {
|
||||||
|
"shopName": match_item.get("shopName") or SHOP_NAME,
|
||||||
|
"matched": bool(match_item.get("matched")),
|
||||||
|
"shopId": match_item.get("shopId"),
|
||||||
|
"platform": match_item.get("platform"),
|
||||||
|
"companyName": match_item.get("companyName"),
|
||||||
|
"matchStatus": match_item.get("matchStatus"),
|
||||||
|
"matchMessage": match_item.get("matchMessage"),
|
||||||
|
"countrySections": country_sections,
|
||||||
|
"cartRatios": cart_ratios,
|
||||||
|
}
|
||||||
|
data = unwrap(
|
||||||
|
requests.post(
|
||||||
|
f"{JAVA_API_BASE}/api/patrol-delete/tasks",
|
||||||
|
json={"user_id": USER_ID, "items": [task_item]},
|
||||||
|
timeout=40,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
log("created task", data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def build_queue_payload(created_task):
|
||||||
|
task_id = created_task["taskId"]
|
||||||
|
created_item = (created_task.get("items") or [])[0]
|
||||||
|
sections = created_item.get("countrySections") or []
|
||||||
|
ratios = created_item.get("cartRatios") or []
|
||||||
|
payload = {
|
||||||
|
"type": "patrol-delete-run",
|
||||||
|
"ts": int(time.time() * 1000),
|
||||||
|
"data": {
|
||||||
|
"taskId": task_id,
|
||||||
|
"user_id": USER_ID,
|
||||||
|
"source": "ts-real-patrol-delete",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"shopName": created_item.get("shopName") or SHOP_NAME,
|
||||||
|
"shopId": created_item.get("shopId"),
|
||||||
|
"platform": created_item.get("platform"),
|
||||||
|
"companyName": created_item.get("companyName"),
|
||||||
|
"matched": created_item.get("matched"),
|
||||||
|
"matchStatus": created_item.get("matchStatus"),
|
||||||
|
"matchMessage": created_item.get("matchMessage"),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"template_rows": [
|
||||||
|
{
|
||||||
|
"shopName": created_item.get("shopName") or SHOP_NAME,
|
||||||
|
"countries": [
|
||||||
|
{
|
||||||
|
"country": section.get("country"),
|
||||||
|
"status": (section.get("rows") or [{}])[0].get("status", ""),
|
||||||
|
"quantity": (section.get("rows") or [{}])[0].get("quantity", ""),
|
||||||
|
"deleteQuantity": (section.get("rows") or [{}])[0].get("deleteQuantity", ""),
|
||||||
|
"processStatus": (section.get("rows") or [{}])[0].get("processStatus", ""),
|
||||||
|
}
|
||||||
|
for section in sections
|
||||||
|
],
|
||||||
|
"cartRatios": ratios,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"country_sections": sections,
|
||||||
|
"cart_ratios": ratios,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
log("queue payload", payload)
|
||||||
|
return payload
|
||||||
|
|
||||||
|
|
||||||
|
def make_monitor_without_startup_kill():
|
||||||
|
monitor = object.__new__(TaskMonitor)
|
||||||
|
monitor.running = True
|
||||||
|
monitor.user_info = {
|
||||||
|
"company": ZN_COMPANY,
|
||||||
|
"username": ZN_USERNAME,
|
||||||
|
"password": ZN_PASSWORD,
|
||||||
|
}
|
||||||
|
monitor.chunk_index = 1
|
||||||
|
monitor.max_workers = 1
|
||||||
|
monitor.executor = None
|
||||||
|
return monitor
|
||||||
|
|
||||||
|
|
||||||
|
def poll_java_task(task_id):
|
||||||
|
for _ in range(60):
|
||||||
|
try:
|
||||||
|
data = unwrap(
|
||||||
|
requests.post(
|
||||||
|
f"{JAVA_API_BASE}/api/patrol-delete/tasks/progress/batch",
|
||||||
|
json={"taskIds": [task_id]},
|
||||||
|
timeout=40,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
log("java progress", data)
|
||||||
|
items = data.get("items") or []
|
||||||
|
if items and items[0].get("taskStatus") in {"SUCCESS", "FAILED", "COMPLETED"}:
|
||||||
|
return items[0]
|
||||||
|
except Exception as exc:
|
||||||
|
log(f"java progress poll failed: {exc}")
|
||||||
|
time.sleep(5)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def drain_queue():
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
JSON_TASK_QUEUE.get_nowait()
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def make_user_info(company_name=None):
|
||||||
|
return {
|
||||||
|
"company": company_name or ZN_COMPANY,
|
||||||
|
"username": ZN_USERNAME,
|
||||||
|
"password": ZN_PASSWORD,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def complete_draft_payload_rows(tags):
|
||||||
|
rows = []
|
||||||
|
for item in tags:
|
||||||
|
rows.append(
|
||||||
|
{
|
||||||
|
"status": "补全草稿",
|
||||||
|
"tag": item.get("tag", ""),
|
||||||
|
"type": "completeDraft",
|
||||||
|
"quantity": str(item.get("quantity") if item.get("quantity") is not None else ""),
|
||||||
|
"deleteQuantity": str(item.get("quantity") if item.get("quantity") is not None else ""),
|
||||||
|
"processStatus": "已完成",
|
||||||
|
"raw_text": item.get("raw_text", ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def run_complete_draft_real_browser():
|
||||||
|
log("starting real complete-draft read test")
|
||||||
|
log("scope", {"shop": SHOP_NAME, "countries": COUNTRIES, "user_id": USER_ID})
|
||||||
|
match_item = get_match_item()
|
||||||
|
driver = InventoryManage(make_user_info(match_item.get("companyName")))
|
||||||
|
try:
|
||||||
|
browser = driver.open_shop(match_item.get("shopName") or SHOP_NAME)
|
||||||
|
if not browser or browser == "店铺不存在":
|
||||||
|
raise RuntimeError(f"open shop failed: {browser}")
|
||||||
|
if driver.need_login():
|
||||||
|
raise RuntimeError("shop requires login; complete-draft read test cannot continue safely")
|
||||||
|
|
||||||
|
normalized_sections = []
|
||||||
|
for country in COUNTRIES:
|
||||||
|
log(f"switching country for complete-draft read: {country}")
|
||||||
|
if not driver.switch_to_country(country):
|
||||||
|
raise RuntimeError(f"switch country failed: {country}")
|
||||||
|
tags = driver.get_complete_draft_quick_view_tags(match_item.get("shopName") or SHOP_NAME, country)
|
||||||
|
payload_rows = complete_draft_payload_rows(tags)
|
||||||
|
normalized = PatrolDeleteTask._normalize_country_sections_for_result(
|
||||||
|
[{"country": country, "rows": payload_rows}]
|
||||||
|
)[0]
|
||||||
|
normalized_sections.append(normalized)
|
||||||
|
log(
|
||||||
|
"complete draft country result",
|
||||||
|
{
|
||||||
|
"country": country,
|
||||||
|
"rawTags": tags,
|
||||||
|
"payloadRowsBeforeNormalize": payload_rows,
|
||||||
|
"normalizedForSubmit": normalized,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
log("complete draft normalized sections", normalized_sections)
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
driver.close_store()
|
||||||
|
except Exception as exc:
|
||||||
|
log(f"close store failed: {exc}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if TS_MODE == "complete-draft":
|
||||||
|
run_complete_draft_real_browser()
|
||||||
|
return
|
||||||
|
|
||||||
|
log("starting real patrol-delete automation")
|
||||||
|
log("scope", {"shop": SHOP_NAME, "countries": COUNTRIES, "user_id": USER_ID})
|
||||||
|
log("java api base", {"JAVA_API_BASE": JAVA_API_BASE, "DELETE_BRAND_API_BASE": DELETE_BRAND_API_BASE})
|
||||||
|
log("ziniao env", {"company": bool(ZN_COMPANY), "username": bool(ZN_USERNAME), "password": bool(ZN_PASSWORD)})
|
||||||
|
|
||||||
|
drain_queue()
|
||||||
|
match_item = get_match_item()
|
||||||
|
created_task = create_java_task(match_item)
|
||||||
|
task_id = created_task["taskId"]
|
||||||
|
payload = build_queue_payload(created_task)
|
||||||
|
|
||||||
|
monitor = make_monitor_without_startup_kill()
|
||||||
|
monitor_thread = threading.Thread(target=monitor.start, daemon=True)
|
||||||
|
monitor_thread.start()
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
enqueue_result = WindowAPI(DummyWindow()).enqueue_json(payload)
|
||||||
|
log("enqueue result", enqueue_result)
|
||||||
|
if not enqueue_result.get("success"):
|
||||||
|
raise RuntimeError(f"enqueue failed: {enqueue_result}")
|
||||||
|
|
||||||
|
deadline = time.time() + 60 * 45
|
||||||
|
last_status = None
|
||||||
|
while time.time() < deadline:
|
||||||
|
state = runing_task.get(task_id)
|
||||||
|
if state and state != last_status:
|
||||||
|
log("python task state", state)
|
||||||
|
last_status = dict(state)
|
||||||
|
if state and state.get("status") in {"completed", "failed", "stopped"}:
|
||||||
|
break
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
monitor.running = False
|
||||||
|
JSON_TASK_QUEUE.put({"type": "__stop__"})
|
||||||
|
monitor_thread.join(timeout=10)
|
||||||
|
|
||||||
|
log("python final state", runing_task.get(task_id))
|
||||||
|
final_java = poll_java_task(task_id)
|
||||||
|
log("java final", final_java)
|
||||||
|
log("finished", {"taskId": task_id})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user