feat(#48): add SYB sync orchestration, import endpoint and page entry

Stage 2. Completes the path from the SYB API to the archive.

sybimport.Sync pages a date range day by day and folds each detail line
through the existing idempotent ApplyDetail. The paging loop is driven by
listTotal, never by the list response's own total, which live data
confirmed is the page's row count rather than the filtered total. A day
whose completeness cannot be proven — a short page, a total that drifted
while paging, a detail response missing an order — stops the run instead
of reporting a partial import as a whole one. Rows already written stay:
they are idempotent on (order_code, detail_id), so a re-run overwrites.

sybimport.Connect reuses the cached session and only discards it when SYB
explicitly says it is invalid. Caching the numeric user id alongside the
cookies is required, not incidental: session validation calls
/am/user/get?id=, and a wrong id comes back as a business error rather
than a logout, so cookies alone can never be revalidated.

The import endpoint is single-flight and detached from the request
context, so closing the tab cannot abandon a half-finished range. It
reads only; no SYB write endpoint is reachable from GoAuto.

The page swaps its "no import entry" warning for a date-range dialog that
warns when the span is wide — a single week held over 7000 orders — and
reports partial progress when a run fails midway.

Verified: go build, go vet, go test ./... all pass. The drift check was
mutation-tested. Not verified: the MySQL migration for syb_session, and
any browser walkthrough.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
QiuSW
2026-08-19 16:56:00 +08:00
co-authored by Claude Opus 5
parent 4886e0d0a4
commit 7edb4e7b9f
11 changed files with 952 additions and 51 deletions
+6
View File
@@ -19,3 +19,9 @@ export function reparseSybProductsBatch(data) {
export function correctSybProduct(productId, data) {
return request({ url: `/api/admin/v1/syb-products/${productId}/correction`, method: 'patch', data })
}
// 从 SYB 拉取指定日期范围的货运单并入库。耗时可能很长(一周可达数千张),
// 所以单独放大超时,不用 request 的默认值。
export function importSybProducts(data) {
return request({ url: '/api/admin/v1/syb-products/import', method: 'post', data, timeout: 30 * 60 * 1000 })
}