@seasonkoh/webaz 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -49,7 +49,10 @@ export function transition(db, orderId, toStatus, actorId, evidenceIds = [], not
|
|
|
49
49
|
if (rule.requiresEvidence && evidenceIds.length === 0) {
|
|
50
50
|
return {
|
|
51
51
|
success: false,
|
|
52
|
-
error:
|
|
52
|
+
error: `此操作需要证据。可任选一种方式提供:\n` +
|
|
53
|
+
`(A) 传 evidence_description(文字描述,如 "物流单号: SF1234567 / 顺丰" / "已揽收 GPS:31.2,121.5") — agent 最方便\n` +
|
|
54
|
+
`(B) 上传文件作为证据 — 提示:${rule.evidenceHint ?? '相关证明文件'}\n` +
|
|
55
|
+
`两种都会写入 evidence 表,效力等同。`
|
|
53
56
|
};
|
|
54
57
|
}
|
|
55
58
|
// 5. 执行转移(数据库事务,保证原子性)
|
|
@@ -351,7 +354,7 @@ function getActiveDeadline(order, db) {
|
|
|
351
354
|
// QA 轮 7 P1:旧表 picked_up 状态没 deadline → agent 不知道下一步多久前要做完
|
|
352
355
|
// 修:picked_up 状态视为"已揽收,等运输/投递",下一个 deadline 是 delivery_deadline
|
|
353
356
|
// QA 轮 7 P1(另一条):disputed 状态下没读 dispute_cases 的 arbitrate_deadline → agent 不知道仲裁还有多久
|
|
354
|
-
const
|
|
357
|
+
const deadlineMapMarket = {
|
|
355
358
|
created: 'pay_deadline',
|
|
356
359
|
paid: 'accept_deadline',
|
|
357
360
|
accepted: 'ship_deadline',
|
|
@@ -360,6 +363,18 @@ function getActiveDeadline(order, db) {
|
|
|
360
363
|
in_transit: 'delivery_deadline',
|
|
361
364
|
delivered: 'confirm_deadline',
|
|
362
365
|
};
|
|
366
|
+
// 2026-05-31 修:self-fulfill(logistics_id 空)无三方揽收环节,shipped/picked_up/in_transit
|
|
367
|
+
// 全部直接走 delivery_deadline,跟 CURRENT_RESPONSIBLE_SELF_FULFILL 对齐(都归 seller)。
|
|
368
|
+
// 之前 deadlineMap 单表导致 self-fulfill shipped 显示 pickup_deadline + responsible=seller,
|
|
369
|
+
// agent 看到矛盾不知道下一步(pickup 是物流的事,seller 又没物流可揽收)。
|
|
370
|
+
const deadlineMapSelfFulfill = {
|
|
371
|
+
...deadlineMapMarket,
|
|
372
|
+
shipped: 'delivery_deadline',
|
|
373
|
+
picked_up: 'delivery_deadline',
|
|
374
|
+
in_transit: 'delivery_deadline',
|
|
375
|
+
};
|
|
376
|
+
const isSelfFulfill = !order.logistics_id;
|
|
377
|
+
const deadlineMap = isSelfFulfill ? deadlineMapSelfFulfill : deadlineMapMarket;
|
|
363
378
|
// disputed 状态:从 `disputes` 表(active dispute, not the `dispute_cases` archive)查 deadline
|
|
364
379
|
// 优先返 arbitrate_deadline(仲裁总截止);如果还在 respond 窗口(被诉方未回应)返 respond_deadline
|
|
365
380
|
if (order.status === 'disputed' && db) {
|
|
@@ -214,9 +214,15 @@ Roles:
|
|
|
214
214
|
name: 'webaz_search',
|
|
215
215
|
description: `Search WebAZ marketplace + cross-platform anchor lookup. No auth required.
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
⚠️ **STRICT MATCH ONLY** — query 永远是精准匹配(等于 title / 等于 external_title / 包含 ≥6 字符 alias)。
|
|
218
|
+
不做 fuzzy LIKE 模糊降级。短查询(如 "钱包" "iphone")很大概率 0 命中,这是设计如此,不是 bug。
|
|
219
|
+
0 命中时,**不要**自己拼短词 retry,也**不要**调别的工具假装搜索;应**引导用户访问 https://webaz.xyz/#discover**
|
|
220
|
+
在搜索框输入关键词浏览(那里有 fuzzy LIKE)。模糊搜索是用户主动行为,不是 agent 代办。
|
|
221
|
+
|
|
222
|
+
USE THIS when:
|
|
223
|
+
- 用户给出 **完整商品标题 / SKU / 精准描述**(典型 strict match,如 "AirPods Pro 2 USB-C 港行"), OR
|
|
224
|
+
- 用户给出 **筛选条件**(category / max_price / min_return_days / max_handling_hours / sort), OR
|
|
225
|
+
- 用户粘贴 ANY external product URL/share-text from Taobao / Tmall / JD / PDD / 1688 / Douyin / Xiaohongshu
|
|
220
226
|
→ WebAZ exact-matches against its anchor registry (canonical product fingerprints across
|
|
221
227
|
platforms). matched_by='none' means truly not indexed — do NOT silently fall back to keyword,
|
|
222
228
|
and do NOT guess similar products.
|
|
@@ -225,7 +231,8 @@ USE THIS when the user:
|
|
|
225
231
|
NOT a separate browser-fetch capability. Returns structured specs + logistics + after-sales +
|
|
226
232
|
agent_summary (one-line decision hint).
|
|
227
233
|
|
|
228
|
-
【Keyword search】Pass query / category / max_price / min_return_days / max_handling_hours.
|
|
234
|
+
【Keyword search — STRICT】Pass query / category / max_price / min_return_days / max_handling_hours.
|
|
235
|
+
query 命中 = (1) 完全等于 product.title OR (2) 完全等于任一 external_title OR (3) 用户文本包含任一卖家声明 alias_value (≥6 字符)。模糊关键词请引导用户去 PWA #discover。
|
|
229
236
|
|
|
230
237
|
【External-link paste search】When user pastes share text from Taobao/Tmall/JD/Pinduoduo/1688/Douyin/Xiaohongshu
|
|
231
238
|
(e.g. '【淘宝】「Product Name」 https://e.tb.cn/xxx ...'), do:
|
|
@@ -1789,7 +1796,12 @@ async function handleSearch(args) {
|
|
|
1789
1796
|
params.push(Math.min(limit * 3, 500)); // 取更多候选,便于 trending 排序
|
|
1790
1797
|
const products = db.prepare(sql).all(...params);
|
|
1791
1798
|
if (products.length === 0) {
|
|
1792
|
-
|
|
1799
|
+
// query 模式 0 命中 = strict 精准匹配未命中。**不做 fuzzy fallback**(协议精准承诺)。
|
|
1800
|
+
// 引导用户去 PWA 发现页做模糊搜索;agent 不应自己 LIKE 降级,那会污染精准 trust。
|
|
1801
|
+
const hint = query
|
|
1802
|
+
? `精准匹配 0 命中(query='${String(query).slice(0, 40)}')。webaz_search 是协议精准接口,不做模糊降级。要做模糊搜索请引导用户访问 https://webaz.xyz/#discover ,在搜索框输入关键词浏览 — 这是用户主动操作,不是 agent 代办。`
|
|
1803
|
+
: '没有找到匹配的商品';
|
|
1804
|
+
return { found: 0, message: hint, products: [], matched_by: 'strict_no_match' };
|
|
1793
1805
|
}
|
|
1794
1806
|
const enriched = products.map((p) => {
|
|
1795
1807
|
const boost = getSearchBoost(db, p.seller_id);
|
package/dist/pwa/public/app.js
CHANGED
|
@@ -420,6 +420,10 @@ async function apiWithStatus(method, path, body) {
|
|
|
420
420
|
const opts = {
|
|
421
421
|
method,
|
|
422
422
|
headers: { 'Content-Type': 'application/json', ...(state.apiKey ? { Authorization: `Bearer ${state.apiKey}` } : {}) },
|
|
423
|
+
// 2026-05-31 修:boot 阶段 fetch 必须有 timeout,否则服务挂时 render 永远 await,
|
|
424
|
+
// skeleton "正在恢复登录..." 永不替换 = PWA 刷新卡死。10s 后强制 abort → catch → status=0 →
|
|
425
|
+
// 命中已有的"无法连接+重试"兜底 UI(render 530-548)。
|
|
426
|
+
signal: AbortSignal.timeout(10000),
|
|
423
427
|
}
|
|
424
428
|
if (body) opts.body = JSON.stringify(body)
|
|
425
429
|
try {
|
|
@@ -427,7 +431,7 @@ async function apiWithStatus(method, path, body) {
|
|
|
427
431
|
const json = await res.json().catch(() => ({}))
|
|
428
432
|
return { status: res.status, body: json }
|
|
429
433
|
} catch {
|
|
430
|
-
return { status: 0, body: { error: 'network' } } // 0 =
|
|
434
|
+
return { status: 0, body: { error: 'network' } } // 0 = 网络不可达或超时,保留 key 等下次
|
|
431
435
|
}
|
|
432
436
|
}
|
|
433
437
|
|
|
@@ -10600,22 +10604,25 @@ async function initShareCtx() {
|
|
|
10600
10604
|
}
|
|
10601
10605
|
|
|
10602
10606
|
// Enrich:并发 fetch sponsor 公开卡 + target 预览(阻塞返回,确保 banner 渲染时数据齐)
|
|
10607
|
+
// 2026-05-31 修:每个 fetch 加 AbortSignal.timeout(5000),防 boot 阶段任一 fetch hang
|
|
10608
|
+
// 把 render 卡死在"正在恢复登录..."
|
|
10609
|
+
const sig = () => ({ signal: AbortSignal.timeout(5000) })
|
|
10603
10610
|
const fetches = []
|
|
10604
10611
|
if (ctx.sponsor_id && !ctx.sponsor_name) {
|
|
10605
|
-
fetches.push(fetch(`/api/users/${ctx.sponsor_id}/public-card
|
|
10612
|
+
fetches.push(fetch(`/api/users/${ctx.sponsor_id}/public-card`, sig()).then(r => r.json()).then(card => {
|
|
10606
10613
|
if (card?.name) writeShareCtx({ sponsor_name: card.name, sponsor_bio: card.bio, sponsor_joined_days_ago: card.joined_days_ago })
|
|
10607
10614
|
}).catch(() => {}))
|
|
10608
10615
|
}
|
|
10609
10616
|
if (ctx.target_hash && !ctx.target_preview) {
|
|
10610
10617
|
const m = ctx.target_hash.match(/^#order-product\/(.+)$/)
|
|
10611
10618
|
if (m) {
|
|
10612
|
-
fetches.push(fetch(`/api/products/${m[1]}/preview
|
|
10619
|
+
fetches.push(fetch(`/api/products/${m[1]}/preview`, sig()).then(r => r.json()).then(p => {
|
|
10613
10620
|
if (p?.id) writeShareCtx({ target_kind: 'product', target_preview: p })
|
|
10614
10621
|
}).catch(() => {}))
|
|
10615
10622
|
} else if (ctx.target_hash.startsWith('#u/')) {
|
|
10616
10623
|
const uid = ctx.target_hash.slice(3)
|
|
10617
10624
|
if (/^usr_[A-Za-z0-9_]+$/.test(uid)) {
|
|
10618
|
-
fetches.push(fetch(`/api/users/${uid}/public-card
|
|
10625
|
+
fetches.push(fetch(`/api/users/${uid}/public-card`, sig()).then(r => r.json()).then(p => {
|
|
10619
10626
|
if (p?.id) writeShareCtx({ target_kind: 'user', target_preview: p })
|
|
10620
10627
|
}).catch(() => {}))
|
|
10621
10628
|
}
|
package/dist/pwa/public/sw.js
CHANGED
package/dist/pwa/server.js
CHANGED
|
@@ -126,6 +126,8 @@ import { registerExternalAnchorsRoutes } from './routes/external-anchors.js';
|
|
|
126
126
|
import { registerAnchorsRoutes } from './routes/anchors.js';
|
|
127
127
|
// 仲裁员申请 (#1013 Phase 44) — 4 user + 3 admin endpoints
|
|
128
128
|
import { registerArbitratorRoutes } from './routes/arbitrator.js';
|
|
129
|
+
// 卖家配额 + 数据中心 (#1013 Phase 45) — 4 user + 3 admin
|
|
130
|
+
import { registerSellerQuotaRoutes } from './routes/seller-quota.js';
|
|
129
131
|
// 验证员用户侧 (#1013 Phase 46) — 5 endpoints
|
|
130
132
|
import { registerVerifierUserRoutes } from './routes/verifier-user.js';
|
|
131
133
|
// 公开用户主页 (#1013 Phase 47) — 6 endpoints
|
|
@@ -7257,6 +7259,13 @@ registerOrdersCreateRoutes(app, {
|
|
|
7257
7259
|
signPassport: (message) => privateKeyToAccount(derivePrivKey('platform-hot-wallet')).signMessage({ message }),
|
|
7258
7260
|
issuerAddress: () => privateKeyToAddress(derivePrivKey('platform-hot-wallet')),
|
|
7259
7261
|
});
|
|
7262
|
+
// #1013 Phase 45: 卖家配额 + 数据中心 7 endpoints — 2026-05-31 修补:之前 import 了但忘了 register,
|
|
7263
|
+
// 导致 /api/seller/quota-status + /api/seller/insights 落入 SPA fallback 返回 HTML,前端 JSON.parse 死循环
|
|
7264
|
+
registerSellerQuotaRoutes(app, {
|
|
7265
|
+
db, generateId, auth,
|
|
7266
|
+
requireUsersAdmin: (req, res) => requireAdminPermission(req, res, 'users'),
|
|
7267
|
+
safeRoles, checkSellerCanList, adminCanOperateOn, logAdminAction, QUOTA_TIERS,
|
|
7268
|
+
});
|
|
7260
7269
|
// #1013 Phase 86: 5 disputes 读端点已迁出
|
|
7261
7270
|
registerDisputesReadRoutes(app, {
|
|
7262
7271
|
db, auth, errorRes,
|
package/package.json
CHANGED