diff --git a/app/static/portal/common/api-client.js b/app/static/portal/common/api-client.js index 48d1bd3..ea8b9c6 100644 --- a/app/static/portal/common/api-client.js +++ b/app/static/portal/common/api-client.js @@ -27,7 +27,7 @@ const ENDPOINTS = Object.freeze({ RK003: { method: 'GET', path: '/api/v1/risk/alerts/{alertNo}' }, RK004: { method: 'GET', path: '/api/v1/risk/evidence/{source}' }, RK005: { method: 'GET', path: '/api/v1/risk/notifications' }, - RK006: { method: 'POST', path: '/api/v1/risk/alerts/scan', idempotent: true }, + RK006: { method: 'POST', path: '/api/v1/risk/alerts/scan', idempotent: true, timeout: 60000 }, RK007: { method: 'POST', path: '/api/v1/risk/alerts/{alertNo}/acknowledgements', idempotent: true }, RK008: { method: 'POST', path: '/api/v1/risk/alerts/{alertNo}/investigations', idempotent: true }, RK009: { method: 'POST', path: '/api/v1/risk/alerts/{alertNo}/exclusions', idempotent: true }, @@ -96,7 +96,10 @@ async function request(endpointId, options = {}) { const controller = new AbortController(); const abortListener = () => controller.abort(); options.signal?.addEventListener('abort', abortListener, { once: true }); - const timeoutId = window.setTimeout(() => controller.abort(), options.timeout || 8000); + const timeoutId = window.setTimeout( + () => controller.abort(), + options.timeout || endpoint.timeout || 8000, + ); try { const response = await fetch(`${pathFor(endpoint, options.pathParams)}${queryString}`, { method: endpoint.method, diff --git a/app/static/portal/employee-risk/dashboard/dashboard.js b/app/static/portal/employee-risk/dashboard/dashboard.js index 53c460f..2be8a17 100644 --- a/app/static/portal/employee-risk/dashboard/dashboard.js +++ b/app/static/portal/employee-risk/dashboard/dashboard.js @@ -1,4 +1,4 @@ -import { apiClient } from '/static/portal/common/api-client.js?v=20260913'; +import { apiClient } from '/static/portal/common/api-client.js?v=20260913-2'; import { getAuthContext, getPermissions, requireRiskStaff, updateAuthPermissions } from '/static/portal/common/auth.js'; import { escapeHtml, formatDateTime } from '/static/portal/common/formatters.js'; import { mountShell } from '/static/portal/common/layout/app-shell.js'; diff --git a/app/static/portal/employee-risk/dashboard/index.html b/app/static/portal/employee-risk/dashboard/index.html index 289bf91..b82d592 100644 --- a/app/static/portal/employee-risk/dashboard/index.html +++ b/app/static/portal/employee-risk/dashboard/index.html @@ -109,6 +109,6 @@ - + diff --git a/docs/风控业务演示文档/23-风控模块接口文档.md b/docs/风控业务演示文档/23-风控模块接口文档.md index 193e644..ad54690 100644 --- a/docs/风控业务演示文档/23-风控模块接口文档.md +++ b/docs/风控业务演示文档/23-风控模块接口文档.md @@ -307,6 +307,7 @@ Idempotency-Key: <必填> - 邮件发送失败不回滚预警。 - `notification_failure` 只代表通知记录创建失败。 - 邮件真实状态通过通知记录查询。 +- 手动扫描会等待高风险邮件发送结果,前端建议将该接口超时设置为不少于 60 秒。 ## 8. 人工处置接口 diff --git a/tests/unit/api/test_portal_frontend.py b/tests/unit/api/test_portal_frontend.py index 4041aed..eb51a6e 100644 --- a/tests/unit/api/test_portal_frontend.py +++ b/tests/unit/api/test_portal_frontend.py @@ -86,6 +86,15 @@ def test_api_client_registers_onboarding_risk_and_admin_endpoints() -> None: assert f"{endpoint_id}:" in source +def test_risk_scan_endpoint_uses_extended_timeout() -> None: + source = (PORTAL / "common" / "api-client.js").read_text(encoding="utf-8") + assert ( + "RK006: { method: 'POST', path: '/api/v1/risk/alerts/scan', " + "idempotent: true, timeout: 60000 }" in source + ) + assert "options.timeout || endpoint.timeout || 8000" in source + + def test_customer_questionnaire_uses_server_contract() -> None: source = (PORTAL / "customer" / "risk-questionnaire" / "risk-questionnaire.js").read_text( encoding="utf-8"