Files
wordpress-theme-aksrt/.specs/plans/frontend-modal-runtime.md
T
2026-08-05 02:04:55 +08:00

7.6 KiB

Plan: Frontend Modal Runtime

Architectural Decisions

  • Canonical runtime: assets/js/core/modal-runtime.js is the single AksrtModalRuntime seam for shell creation, lifecycle, focus, loading, error, cancellation, and refresh. assets/js/core/modal-triggers.js only binds the new declarative trigger contract; no legacy modal alias or compatibility bridge exists.
  • Loader contract: A loader receives a domain context and abort signal and returns a minimal view model plus render/update callbacks. AksrtModalRuntime.openRemote({responseType: 'json', renderData}) owns the request, cache, cancellation, and lifecycle while the domain renderer owns only view-model markup. It may read only the active modal's data.
  • Cache contract: Use in-memory, user-scoped cache entries with short TTLs, in-flight request deduplication, explicit invalidation tags, and complete clearing on logout/account switch. Do not persist private modal payloads in localStorage.
  • State contract: All domains use the same idle, loading, ready, empty, submitting, success, error, unauthorized, and stale states. Skeletons match the final layout and never represent business truth.
  • API boundary: Existing aksrt/v1 domain routes remain the service boundary; HTML modal responses are replaced domain by domain with minimal JSON view models. Every changed REST route keeps a permission_callback; AJAX is not a new data path.
  • Request adapter: Add one thin AksrtRequest adapter for the injected REST root, nonce headers, JSON/error envelopes, 401 handling, and abort signals. Domain files stop maintaining their own REST-root and response-parsing variants.
  • Rehydrate and feedback: Every runtime-rendered HTML response calls AksrtFrontend.rehydrate(body, 'modal'); shared feedback calls the existing callable AksrtToast API directly. There is one binding path and no compatibility fallback.
  • Rollout: Add a temporary per-domain rollout section under the existing Tools configuration surface, read through AKSRT_Settings. One canonical new implementation is enabled per domain; the switch is for staged release, not a compatibility data layer.
  • Telemetry: Use browser performance.mark/measure and server Server-Timing/existing deployment observability by default. Do not add a private payload or payment/identity-content event store in this foundation plan.
  • Build boundary: Frontend assets are plain theme JavaScript, not the Admin SPA bundle. Run node --check for changed JS and run the admin contract audit only when the rollout schema/controller changes.

Phase 1 — Modal latency is measurable and rollout is controllable

User stories: US1, US2, US3, US14.

What to build

Create the typed rollout reader and configuration contract, then add a small telemetry module that marks the existing VIP, order, identity, and badge open flows without changing their business behavior. Establish cold-cache and warm-cache baselines for click-to-shell, click-to-first-content, click-to-ready, request count, SQL count, response size, and error outcome. The rollout reader must be consumed through AKSRT_Settings and the existing Tools schema/controller path, not a raw option read.

Primary integration points:

  • AKSRT_Settings and the Tools schema/controller for frontend_modal_rollout.
  • assets/js/core/modal-telemetry.js (new) and the existing feature enqueue/config injection in src/Core/ScriptsPart1c.php and the surface script enqueue modules.
  • Existing flows in assets/js/pay-vip.js, assets/js/order-center.js, assets/js/routes/user-center-auth.js, and assets/js/user-badges.js for baseline marks only.

Done when

  • The Tools schema, REST response, and AKSRT_Settings reader expose independent VIP, order, identity, and badge rollout values; php tools/audit-admin-contracts.php exits 0.
  • assets/js/core/modal-telemetry.js emits click, shell, first-content, ready, action-start, action-end, and error marks without including payment credentials, order contents, or identity evidence.
  • Browser scenario modal-baseline records cold and warm measurements for all four current entry points, and the baseline artifact names the request/SQL counts used for later comparison.
  • node --check assets/js/core/modal-telemetry.js assets/js/pay-vip.js assets/js/order-center.js assets/js/routes/user-center-auth.js assets/js/user-badges.js passes.

Phase 2 — Any modal opens with a cancellable shell and reusable cache

User stories: US1, US2, US3, US12, US13.

What to build

Build the canonical AksrtModalRuntime in assets/js/core/modal-runtime.js with focused request, cache, state, and trigger modules. The runtime must show a skeleton before data, use the single new modal trigger contract, abort requests on close/replacement, deduplicate reads, invalidate explicit tags, restore focus, support keyboard/overlay close, mobile bottom-sheet behavior, retryable errors, and call AksrtFrontend.rehydrate after every HTML render. All domain callers use the canonical request/runtime/Toast APIs directly; no legacy alias, second host, or migration compatibility path is retained.

Done when

  • assets/js/core/modal-runtime.js exposes one canonical AksrtModalRuntime.open/close/refresh lifecycle, AksrtRequest owns REST root/nonce/envelope handling, and no domain script creates a second global modal host.
  • node --check assets/js/core/modal-triggers.js assets/js/core/request.js assets/js/core/modal-runtime.js assets/js/core/modal-cache.js assets/js/core/modal-state.js assets/js/pay-vip.js passes.
  • Browser scenario modal-shell-lifecycle verifies shell visibility within the 100ms initial budget, skeleton/error/retry states, ESC and overlay close, focus return, request cancellation, mobile bottom-sheet behavior, callable Toast, and AksrtFrontend.rehydrate(body, 'modal') after runtime HTML.
  • Browser scenario modal-cache-dedupe verifies one read for concurrent/repeated opens, invalidation after a successful write, no reuse after logout/account switch, and one pay-vip binding; git grep -n "AksrtRemoteModal\|RefreshModal\|data-aksrt-remote-modal" -- '*.js' '*.php' '*.css' returns no matches.

Out of Scope

  • 修改会员价格、会员权益、支付网关规则、订单账务、退款核算、认证资格/审核政策或徽章授予条件;这些规则只允许被新的流程正确调用和展示。
  • 新增支付渠道、替换支付供应商、在浏览器保存支付凭证,或改变支付回调/异步结算机制。
  • 新增公开认证资料库、向其他用户暴露认证文档、跨用户查看订单或徽章数据。
  • 把订单、售后、认证审核或徽章运营工作台迁移进配置型 SPA;日常运营仍属于原生 WordPress 后台。
  • 全站页面导航、用户中心信息架构、品牌设计系统或所有非弹窗页面的全面重做;本期只统一弹窗运行时和四类流程所需的轻量体验。
  • 强制页面加载时预取所有弹窗数据、长期持久化敏感弹窗数据、建立订单/认证/徽章的第二套事实存储或长期保留旧新双路实现。
  • 以新增兼容别名、旧 option 双读、静默降级或数据迁移层解决旧实现问题;流程切换后以新的规范化链路为唯一实现。
  • 建立独立的数据仓库、复杂转化漏斗或第三方用户行为追踪系统;本期观测只服务于弹窗性能、错误和业务状态闭环。

Open Questions

  • 部署环境是否已有 RUM/Server-Timing 收集端?默认先交付浏览器 marks 与响应头,不在主题内新增持久化指标表。
  • frontend_modal_rollout 的临时开关在所有领域切换完成后的删除版本,需要在发布记录中确定。