diff --git a/CLAUDE.md b/CLAUDE.md index 04196bf..6667401 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,9 +33,9 @@ playwright install chromium .venv/Scripts/python.exe -m inbound_verify.cli.server # 或:inbound-verify-server -# DB CLI:建库 / 初始化 / 灌数据 / 全流程 -.venv/Scripts/python.exe -m inbound_verify.store createdb # 或 init | ingest | all -# 或:inbound-verify-db createdb|init|ingest|all +# DB CLI:建库 / 初始化 / 灌数据 / 全流程 / 单站单类 +.venv/Scripts/python.exe -m inbound_verify.store createdb # 或 init | ingest | ingest-one | all +# 或:inbound-verify-db createdb|init|ingest|ingest-one|all # 单站点联调:在 config.yaml 设 debug.enabled=true + debug.target_site=顺心|百世|中通|韵达|安能 # 网页站:只挂载该站;安能:只启动 Electron 应用。 @@ -112,6 +112,18 @@ playwright install chromium `inbound_verify.compare`(菜单 [9])纯离线:读 `downloads/` 下各站应到/实到 xlsx, 比对生成 `output/应到未到数据.xlsx`(汇总 + 各站明细)。 +### 自动入库(下载成功后 → PostgreSQL) +`dispatch_task` 下载成功后,在 `_record_business_date` 旁挂一个**尽力而为**钩子 +`_persist_to_db(site, kind)`(`runtime`):懒导入 `store`,调 `store.ingest_task(site, kind)` +按 kind 幂等 UPSERT 进 PostgreSQL(expected/actual 各入其列;undelivered——百世入未到、 +4 站连入 expected+actual)。**绝不影响下载任务的成功判定**:所有写库/写状态都包 try/except, +失败只告警。 +- 开关 `postgres.auto_ingest`(默认开)+ `connect_timeout_seconds`(兜 cpolar 抖动)。 +- 可见性:结果写 `state_store.ingest_state`(每站每类 ok/count/ingested_at/error),经 + `GET /status` 的 `ingest` 字段暴露。 +- 手动:`store` CLI `ingest-one ` 用同套路由单测(脱离下载)。 +- 注意:跑在 Playwright 线程、同步阻塞;cpolar 慢/断靠超时 + try/except 降级,不重试不补入。 + ### 路径 `inbound_verify.paths` 把 `DOWNLOAD_DIR` / `CONFIG_PATH` / `BASE_DIR` 全部锚定到项目目录, **不依赖运行时 cwd**——别用相对路径或 `os.getcwd()`。 diff --git a/README.md b/README.md index 2a8c1eb..fe8849f 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ InboundVerify/ │ ├── state_store.py # SQLite 状态持久化(state/state.db) │ ├── domain.py # 站点 / 文件名 / 列映射共享配置(单一来源,leaf) │ ├── compare.py # 全站点应到未到离线比对,输出 output/应到未到数据.xlsx -│ ├── store.py # DB CLI 入口(createdb|init|ingest|all) +│ ├── store.py # DB CLI 入口(createdb|init|ingest|ingest-one|all) │ ├── sites/ # 各站点模块(流程 + 重置 + 重试,自洽) │ │ ├── shunxin.py # 顺心(含双账号) │ │ ├── baishi.py # 百世 diff --git a/config.example.yaml b/config.example.yaml index 25cbbba..45a05a8 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -46,7 +46,7 @@ zto: # 韵达快运 (https://ky-sso.yunda56.com) # ---------------------------------------------------------------------------- yunda: - # 自动登录的账号与密码(由 site_yunda.yunda_login 读取并填入登录表单)。 + # 自动登录的账号与密码(由 inbound_verify.sites.yunda.yunda_login 读取并填入登录表单)。 # 留空时自动登录会填入空串导致登录失败,届时可在浏览器中改为手动登录。 # 真实凭据仅写进被 .gitignore 忽略的 config.yaml,切勿提交示例值。 username: "YOUR_USERNAME_HERE" @@ -58,9 +58,9 @@ yunda: # ---------------------------------------------------------------------------- # 安能全网门户(Electron 桌面应用,非网页) # ---------------------------------------------------------------------------- -# 与其他站点不同:安能不由 main_router 用浏览器打开,而是以调试模式启动其 +# 与其他站点不同:安能不由浏览器打开,而是以调试模式启动其 # Electron 可执行文件(自动选取一个空闲端口作为 --remote-debugging-port,避免端口冲突), -# 启动后请在应用内手动登录,main_router 会自动轮询判断是否进入主页。 +# 启动后请在应用内手动登录,runtime 会自动轮询判断是否进入主页。 anneng: # 【已废弃】下载日期改由 Web 前端/API 按站点设偏移(0=今天,1=昨天…,存 state.db),此项不再生效。 query_days: 1 diff --git a/docs/安能门户CDP连接指南.md b/docs/安能门户CDP连接指南.md index 7e917cc..8857071 100644 --- a/docs/安能门户CDP连接指南.md +++ b/docs/安能门户CDP连接指南.md @@ -143,7 +143,7 @@ class CDP: """绑定到单个页面目标的同步 CDP 客户端。""" def __init__(self, ws_url): - self.ws = websocket.create_connection(ws_url) + self.ws = websocket.create_connection(ws_url, timeout=15) # 15s socket 超时:防 Electron 业务 tab 偶发不回包时 recv 无限阻塞 self._id = 0 def call(self, method, **params): diff --git a/docs/站点统计逻辑审查报告.md b/docs/站点统计逻辑审查报告.md index e852c89..43ce8cd 100644 --- a/docs/站点统计逻辑审查报告.md +++ b/docs/站点统计逻辑审查报告.md @@ -87,7 +87,7 @@ | 接口 | 返回内容 | 是否含应到/已到计数 | |---|---|---| -| `GET /status` | 各站 `login_state` + `expected/actual/undelivered_ready` + `business_date` + `worker_ready` | **不含**计数,只给就绪标志 | +| `GET /status` | 各站 `login_state` + `expected/actual/undelivered_ready` + `business_date` + `worker_ready` + `ingest`(每站每类入库 ok/count/时间) | **不含**应到/已到件数计数(`ingest` 是入库条数,非核销件数) | | `GET /report` | `FileResponse(output/应到未到数据.xlsx)` | 计数只在 xlsx 里 | | `GET /data/{filename}` | 下载 `downloads/` 下某源文件 | 原始数据,非统计值 | diff --git a/inbound_verify/cli/server.py b/inbound_verify/cli/server.py index fe0c85d..c928c28 100644 --- a/inbound_verify/cli/server.py +++ b/inbound_verify/cli/server.py @@ -10,7 +10,7 @@ # 独占所有 page 操作;与主线程仅经 Queue + SQLite 通信。 # 违反"路由不碰 Playwright"会崩(sync 对象跨线程访问)。 # -# 运行:python server.py (默认监听 0.0.0.0:8000) +# 运行:python -m inbound_verify.cli.server (或 inbound-verify-server;默认监听 0.0.0.0:8000) import os import queue