25 KiB
25 KiB
前台弹窗统一加载与业务流程升级
Problem Statement
前台多个用户操作弹窗在点击后需要等待较长时间才出现可用内容。受影响的场景包括会员中心的续费/购买、订单中心的订单详情、官方认证以及我的徽章;同类问题还可能存在于其他前台弹窗。
当前体验的问题不是单一的视觉延迟,而是弹窗入口、数据请求、业务操作和结果刷新之间缺少统一的快速反馈与状态协议:
- 点击后可能出现空白等待,用户无法判断弹窗是否已经打开、请求是否正在进行或操作是否失败。
- 同一用户短时间内重复打开弹窗时,可能重复请求相同数据,且关闭弹窗后仍可能留下未完成的请求或重复初始化。
- 会员购买、订单操作、认证提交和徽章查看各自拥有不同的加载、成功、失败和刷新反馈,用户难以形成稳定预期。
- 业务状态变更后,弹窗和背后的用户中心/订单列表可能继续显示旧数据。
- 移动端弹窗的可用空间、按钮触达和错误反馈需要与桌面端保持一致。
- 站点已有支付、商城订单、认证、徽章和原生后台操作能力,但缺少围绕弹窗体验的统一性能预算、缓存失效和前后台状态闭环。
本需求将前台弹窗性能优化升级为一套统一的弹窗运行时和四类业务流程改造:会员购买链路、订单处理链路、官方认证链路、徽章获取链路。流程可以重排、合并和改善状态反馈,但会员价格/权益、订单账务、认证资格与审核规则、徽章授予条件等核心业务规则继续由现有配置和领域服务决定。
Current State
- 前台资源采用模块化 JavaScript 与 CSS;用户中心、商城、支付和其他前台功能存在多个独立交互入口。具体资源拆分、重复初始化和浏览器主线程耗时仍需在实现前用基线测量确认。
- 用户中心只对当前活动面板做服务端渲染,但用户中心外壳、顶部信息和仪表盘仍会计算统计、用户元数据和公开身份信号;打开一个弹窗前可能已经承担与当前操作无关的页面级计算。
- 会员弹窗当前由服务端生成完整 HTML;前端每次打开都会重新请求该 modal,服务端渲染目录后又重复读取会员等级。目录和弹窗没有持久缓存,设置只有请求内记忆。无 VIP 元数据时,会员等级还会回退查询有效会员订单;外部支付完成后前端每 3 秒轮询一次,最多轮询 40 次。
- 订单中心列表目前会执行列表查询、总数查询和多项统计查询,首屏通常包含多次 COUNT;订单行装饰可能按行读取标题、缩略图和链接,资源订单存在 N+1 风险。订单表现有索引没有覆盖用户、状态和创建时间的复合查询。待处理的外部订单详情会触发网关远程对账,虽然有短暂节流,但没有详情视图缓存。
- 订单前端有硬编码 REST 基础地址而没有统一使用已注入的地址回退;这会增加环境配置和部署差异带来的失败面。
- 官方认证用户中心面板会服务端读取验证状态、最新申请和申请数据;这些 facade 调用会重复查询申请记录。认证 REST 的所有者权限检查与处理器也会重复按 UUID 查询。待审核页面初始化即轮询,页面重新可见时立即刷新;刷新可能调用外部云服务,HTTP 超时可达 20 秒,当前没有轮询或对象缓存。
- 徽章入口每次打开都会请求用户徽章列表,没有客户端缓存;佩戴成功后又通过旧 AJAX 打开单个徽章 modal,形成 REST 与 AJAX 混流。旧 AJAX 仍包含公开入口和 HTML modal 路径,部分路径没有 nonce;徽章服务的初始化也存在重复调用。
- 商城、订单、支付、认证和徽章已有领域服务与原生后台操作能力;本需求优先复用这些能力,而不是在弹窗中复制业务规则。商城、订单/售后和认证审核等运营工作继续属于原生 WordPress 后台,配置内容继续属于管理端 SPA。
- 当前仓库没有统一的前台弹窗性能预算或通用的“开壳 → 数据加载 → 内容就绪 → 业务操作 → 刷新”协议;四类功能除请求内设置 memo 和支付对账的短暂节流外,没有统一的持久/对象/视图缓存。
- WordPress REST 端点必须位于现有
aksrt/v1命名空间并具备权限回调;AJAX 操作必须继续使用 nonce 校验。仓库没有已提交的 PHPUnit、JavaScript 单元测试或 phpcs 测试套件;验证依赖静态契约审计、构建检查、WordPress 运行环境和浏览器场景验收。
Solution
统一弹窗体验
所有前台弹窗统一采用以下交互时序:
- 用户点击入口后立即创建弹窗壳,先显示标题、关闭控件和与最终布局一致的骨架屏;不得在数据返回前显示长时间空白。
- 只加载当前打开弹窗所需的数据,不因打开一个弹窗而请求其他弹窗的数据。弹窗壳和最小运行时可在页面初始化阶段准备,但不强制预取全部业务数据。
- 数据返回后以稳定布局替换骨架,减少内容跳动;数据为空、无权限、请求失败和超时都使用明确的状态面板,不使用误导性的空白。
- 关闭弹窗时取消仍未需要的请求和监听器;再次打开时复用短时间内成功取得的数据,并使用单请求去重避免并发重复请求。
- 业务操作显示处理中状态,防止重复点击;操作成功后只刷新受影响的领域数据和背后的页面摘要,不进行整页刷新。
- 操作失败时保留用户已填写或已选择的内容,在不泄露敏感数据的前提下提供可重试反馈;需要重新认证、无权限或状态过期时给出明确下一步。
- 统一桌面端和移动端的标题栏、关闭方式、焦点管理、键盘操作、触摸区域、按钮反馈、骨架和错误状态;保留每类业务自身的信息层级,不进行无必要的完整视觉重做。
四类业务流程
会员购买与续费
- 在一个连续流程中展示可购买/续费/升级的套餐、既有会员状态、权益和价格信息。
- 提交前明确订单金额、优惠/权益适用状态和支付承接方式;不在前端重新计算或修改服务端价格。
- 支付创建、跳转、取消、失败和异步完成均有明确状态;成功后刷新会员状态、订单摘要和相关入口,失败后允许安全重试。
- 复用现有支付网关和订单原语,不在弹窗中保存或暴露支付密钥,不改变支付回调和账务规则。
- 用最小化 JSON 视图模型替代每次打开都生成完整 HTML;目录、会员状态和支付结果按阶段加载,支付轮询改为有上限、有退避、可见性敏感且可被最终状态终止的同步机制。
订单详情与处理
- 订单详情先显示订单状态和摘要骨架,再加载商品/服务明细、金额、时间线和允许的操作。
- 允许的取消、支付、退款/售后等操作由服务端返回,前端不得根据本地状态臆造操作权限。
- 操作提交后立即进入处理中状态;服务端状态变化后刷新订单详情和订单列表摘要,避免继续显示旧状态。
- 将列表统计和订单行装饰改为可批量取得或按需取得,消除首屏无关 COUNT 与资源订单 N+1;详情对账只在必要时触发,避免打开普通详情就同步等待外部网关。
- 支持支付异步完成、请求超时、订单已被其他页面处理以及重复点击等边界状态。
官方认证
- 弹窗根据当前用户返回未申请、待审核、已通过、已拒绝或需要补充资料等状态,并只显示当前状态允许的操作。
- 认证资料展示、提交、补交和结果反馈使用统一校验与错误提示;提交期间防止重复提交,失败时保留可安全恢复的输入。
- 后台审核人员可以查看必要资料、更新审核结果并填写可对用户展示的原因;用户端在审核状态变化后可主动刷新或在下次打开时得到新状态。
- 将状态、最新申请和申请表单数据合并为一次最小读取;所有者检查与处理器复用同一份已加载申请,避免重复 UUID 查询。待审核刷新采用节流、退避和页面可见性控制,外部云服务调用不得阻塞弹窗壳。
- 认证资料属于敏感用户数据,响应只返回当前用户可见字段;后台能力继续执行现有角色和权限校验。
我的徽章
- 以分组或分类方式展示已获得、未获得和进行中的徽章状态;详情中说明现有授予条件或进度。
- 徽章列表和低频变化的说明数据可使用短缓存;领取、达成或后台调整后立即失效并刷新相关列表。
- 统一 REST 与旧 AJAX 的读取/详情路径,最终以一个带权限和 nonce 边界的规范化数据链路为唯一实现;移除旧 HTML modal 混流,避免佩戴后再次重复请求。
- 空列表、未满足条件、数据加载失败和徽章详情不存在均有明确状态,不把“未获得”误显示为请求失败。
- 复用现有徽章定义和授予规则,不在前端复制条件判断或直接授予徽章。
前后台闭环与分阶段灰度
- 前台弹窗、REST/AJAX 数据源、领域服务和原生后台操作共同组成一条状态闭环。
- 首先交付公共弹窗运行时和徽章/认证流程,其次交付订单流程,最后切换会员支付流程;每阶段以性能、错误率和业务回归指标达标后再放量。
- 灰度使用按领域启用的临时发布控制,不创建两套长期业务数据或双读兼容层。每个领域切换到新流程后,以新流程作为唯一前台实现。
- 运营工作仍在原生 WordPress 后台处理;SPA 只承载配置类内容。若认证审核、订单售后或徽章管理缺少前台所需的后台承接,应补齐对应原生操作能力,而不是把操作台塞入配置 SPA。
User Stories
- 作为已登录用户,我点击任一前台弹窗入口后,可以在约定的时间预算内先看到弹窗标题、关闭控件和骨架,而不是面对空白页面。
- 作为用户,我打开同一弹窗时只触发当前业务所需的数据请求;短时间内再次打开可以复用最近成功数据,不必重复等待。
- 作为用户,我关闭弹窗或快速切换弹窗时,旧请求不会覆盖新弹窗内容,也不会造成重复监听、重复请求或页面卡顿。
- 作为会员用户,我可以在一个连续流程中完成续费或升级选择、价格确认、支付承接和结果确认;取消、失败和异步支付完成都有可理解的反馈。
- 作为普通用户,我可以查看可购买的会员套餐和权益,但价格与购买资格以服务端返回为准,前端不会显示可执行但实际无权完成的操作。
- 作为用户,我打开订单详情时可以先看到订单状态摘要,再查看明细和时间线;订单状态变化后详情与订单列表会同步更新。
- 作为用户,我可以在订单允许时执行支付、取消或售后操作;重复点击、状态已改变、请求超时和服务端拒绝均不会产生重复订单操作。
- 作为用户,我可以在认证弹窗看到当前状态、可执行的下一步和审核反馈;提交或补交资料时不会因重复点击创建重复申请。
- 作为认证审核人员,我可以在原生后台查看必要资料、处理认证结果并填写用户可见原因;前台重新打开或刷新后能看到最新状态。
- 作为用户,我可以快速查看已获得、未获得和进行中的徽章,并理解现有条件或进度;徽章数据为空与请求失败不会混淆。
- 作为用户,我完成购买、订单操作、认证提交或徽章状态变化后,相关弹窗和背后的用户中心/订单列表不会继续展示明显过期的数据。
- 作为移动端用户,我可以在窄屏中打开、关闭、滚动和提交弹窗,主要按钮有足够触摸区域,加载、错误和成功反馈不被遮挡。
- 作为未登录或无权限用户,我不会通过弹窗获得私有订单、认证资料、会员状态或其他用户徽章数据;系统会给出登录或权限提示。
- 作为站点管理员,我可以按阶段查看弹窗性能、失败率和业务操作错误,并在某个领域异常时暂停该阶段放量,而不影响其他领域。
Implementation Decisions
New Modules
- 统一弹窗运行时:提供
open(kind, context)、close(handle)、refresh(handle)三个主要入口;负责弹窗壳、骨架、焦点、生命周期、移动端行为和请求取消,不承载具体业务规则。 - 弹窗注册与加载器:提供
register(kind, loader)和load(kind, context, signal);按弹窗类型懒加载对应模块和最小数据,拒绝页面级的全量预取。 - 短缓存与请求去重层:提供
read(key)、write(key, value, ttl)、invalidate(tags);按用户和业务上下文隔离缓存,合并相同的进行中请求,登出/切换用户时清空私有缓存。 - 统一状态模型:定义
idle、loading、ready、empty、submitting、success、error、unauthorized和stale等可观察状态,供所有弹窗复用骨架、反馈和重试行为。 - 会员流程协调器:提供套餐/状态加载、购买或续费提交、支付结果同步和领域失效;只调用现有会员、订单和支付服务。
- 订单流程协调器:提供订单详情加载、允许操作读取、支付/取消/售后提交和状态刷新;以服务端返回的允许操作为唯一依据。
- 认证流程协调器:提供认证状态加载、资料校验/提交、补交和刷新,以及后台审核结果同步;负责敏感字段的最小化传输。
- 徽章流程协调器:提供徽章列表/详情加载、分类与进度视图模型和状态失效;不复制徽章授予条件。
- 后台流程承接模块:在原生 WordPress 后台提供订单处理、认证审核和徽章管理所需的操作界面或补齐现有操作能力;配置型开关仍遵守 SPA 配置边界。
- 弹窗性能观测器:提供
mark(event, context)和measure(openId);记录点击、弹窗壳可见、请求开始、首个内容可见、内容就绪、操作开始、操作完成和错误,不记录支付凭证或认证敏感资料。
Architectural Decisions
- 单一弹窗协议:所有前台弹窗通过统一运行时打开,业务模块只提供视图模型和操作结果;不得继续为每个弹窗复制一套壳、加载动画、错误处理和缓存逻辑。
- 主动打开优先,按需加载数据:点击时先显示壳和骨架,再加载当前弹窗数据;不以页面加载时全量请求或强制预取换取表面速度。经过基线验证后,低成本的浏览器空闲预取可以作为后续优化,但不能阻塞首屏。
- 缓存只解决重复等待,不覆盖业务事实:动态数据使用短 TTL 的内存缓存,订单、支付、认证和会员状态在任何成功写操作后立即按标签失效并重新读取;徽章说明等低频数据可以采用较长但仍有限的 TTL。
- 响应以最小视图模型为边界:每个弹窗只接收首屏需要的字段和服务端计算出的允许操作;明细、历史或低优先级内容分段加载,避免一个大 payload 拖慢首屏。
- 服务端状态为唯一事实源:价格、会员资格、订单状态、退款/售后权限、认证状态和徽章授予结果均由服务端领域服务决定;前端只负责展示和发起操作。
- 操作必须可重入且可去重:支付创建、订单操作、认证提交和任何领取动作应沿用现有 nonce/权限边界,并使用请求锁或幂等标识避免重复提交;异步支付结果继续由现有回调/状态机制确认。
- 服务端查询按首屏需要收敛:会员目录/会员状态、认证状态/最新申请/表单、订单统计与行装饰、徽章拥有关系与佩戴状态应在同一领域读取上下文中复用,优先批量查询,避免重复 COUNT、N+1 和同请求重复按 UUID 查找。
- 外部服务不阻塞开壳:支付对账、认证云服务刷新等远端调用必须在弹窗壳之后执行,并有超时、退避、可见性控制和最终状态终止条件;普通订单详情不应无条件同步等待远程对账。
- 服务端地址与数据链路统一:前端请求统一使用主题注入的 API 地址与 nonce 配置,不在功能脚本中硬编码 REST 根地址;同一业务不得继续混用 REST 和无 nonce 的旧 HTML AJAX modal。
- 用户数据隔离:缓存键至少区分当前用户、业务对象、站点上下文和必要的版本信息;登出、切换账户和权限变化时不能复用前一个用户的数据。
- 前后台职责不变:前台负责用户流程,原生后台负责运营和审核,SPA 负责配置;新增或调整 REST 控制器必须有
permission_callback,所有输出遵守现有清理和转义规则。 - 渐进发布但不保留兼容双路:灰度按领域启用同一套新运行时和流程;领域完成切换后移除旧的弹窗调用路径,不添加旧 option 双读、旧 API 别名、双模板或数据迁移兼容层。
- 性能以真实测量为准:记录基线、缓存命中与冷加载的 p75/p95,不以“感觉更快”替代测量;后端同时观察请求耗时、SQL 数量、响应体大小和错误率。
Schema Changes
- 不新增会员、订单、认证或徽章的核心数据表;继续使用现有领域数据、配置和状态机。
- 为支持流程状态同步,可以在现有响应模型中补充最小化的
allowed_actions、updated_at、状态版本或失效标签等元数据,但不得复制领域状态或在前端保存业务事实。 - 如灰度控制尚无合适的现有发布配置,可新增按领域的临时发布开关,并明确移除时点;该开关只控制新流程放量,不承担旧数据兼容或业务规则切换。
- 性能观测默认不新增认证资料、支付凭证或订单内容的持久化表;只记录脱敏的计时、结果类别和错误类型,具体存储方式在实现阶段依据现有观测能力确定。
API Contracts
- 弹窗读取合约:各领域提供按当前用户和上下文读取首屏视图模型的 GET 能力;响应包含数据、状态版本、更新时间、允许操作和可选的失效标签。不得返回当前用户无权查看的订单、认证资料或其他用户徽章信息。
- 会员合约:读取会员状态、可用套餐和服务端计算的购买/续费信息;写操作返回订单/支付承接结果和可追踪的状态标识,不返回支付密钥。支付异步完成后通过现有状态查询或回调链路确认。
- 订单合约:读取订单摘要、明细、时间线和服务端允许的操作;支付、取消、退款/售后等操作返回最新状态或明确的处理中状态,并支持重复请求安全失败或幂等返回。列表统计和资源商品展示必须避免把无关的多次 COUNT 或逐行查询带入弹窗首屏。
- 认证合约:读取当前用户认证状态和最小必要资料;提交/补交接口返回审核状态和用户可见反馈,后台审核接口只对具备相应能力的人员开放,并区分内部备注与用户可见原因。待审核刷新不能因外部云服务暂时不可用而使弹窗壳无法打开。
- 徽章合约:读取分类、获得状态、进度和详情;任何领取或状态变化操作返回最新徽章状态并触发相关缓存失效。授予条件由服务端执行;旧无 nonce 的 HTML modal 路径在切换后不再作为公共入口。
- 公共约束:新旧调整后的 REST 路由统一使用
aksrt/v1命名空间、明确的permission_callback、参数验证、输出转义和结构化错误;AJAX 路径继续验证 nonce。接口不得为兼容旧弹窗而长期保留两套响应形状。 - 并发与失效合约:读取请求可以携带客户端上下文和取消信号;写操作成功后响应必须足以让前端失效相关缓存并重新读取,避免只能整页刷新才能得到最新状态。
Navigation
- 前台保留现有用户中心、会员中心、订单中心、认证入口和徽章入口;入口的深链和返回行为继续可用,但打开方式统一进入新的弹窗运行时。
- 会员入口进入会员购买/续费流程;订单入口进入订单详情并根据服务端状态展示可用操作;认证入口进入当前认证状态对应的下一步;徽章入口进入徽章列表或详情。
- 弹窗关闭后返回原页面滚动位置和上下文;成功操作后更新背后页面的摘要、余额、会员状态或订单列表,不强制整页跳转。
- 原生后台继续承载订单/售后、认证审核、徽章运营等日常操作;管理端 SPA 只承载对应的配置内容和必要的发布开关。
- 灰度顺序为:公共弹窗运行时与徽章/认证 → 订单 → 会员支付。每一阶段独立观察并确认后再启用下一阶段。
Testing Decisions
采用“静态契约审计 + 后端性能基线 + 浏览器交互与网络条件验收 + 分阶段灰度观测”的组合,不依赖仓库中不存在的单元测试工具。
性能与加载
- 在桌面和移动视口分别记录点击到弹窗壳可见、点击到首个内容可见、点击到内容就绪、写操作完成的时间。
- 先记录旧实现基线,再以初始预算验收:弹窗壳 p75 约 100ms 内可见;缓存命中内容 p75 约 200ms 内可见;冷加载内容 p75 ≤ 800ms、p95 ≤ 1.5s。预算需在真实 WordPress 环境和网络条件下校准,不以本地开发机单点结果代替。
- 检查冷缓存、热缓存、慢网络、请求超时、接口 5xx、浏览器返回页面、快速重复点击和关闭后重新打开;确认没有重复请求、过大的首屏响应或旧请求覆盖新内容。
- 对每个阶段观察首屏可见时间、内容就绪时间、请求/SQL 数量、响应体大小、失败率、重复提交率和业务状态不一致率。
- 重点回归已确认的瓶颈:会员完整 HTML 和重复会员等级读取、支付高频轮询;订单多次 COUNT、资源订单 N+1、详情远程对账;认证重复申请查询和外部刷新超时;徽章 REST/AJAX 混流、重复读取和旧 modal 请求。
业务流程
- 会员:未开通、有效会员、过期会员、续费、升级、支付取消、支付失败、异步支付成功、重复点击和回到订单详情。
- 订单:待支付、处理中、已完成、已取消、退款/售后中、操作权限变化、订单已被其他页面更新、重复提交和超时重试。
- 认证:未申请、待审核、通过、拒绝、补交资料、字段校验失败、重复提交、无权限、后台审核后前台刷新和敏感字段隔离。
- 徽章:有/无徽章、已获得、未获得、进行中、详情缺失、后台规则变化后的刷新、领取或状态变化(若现有能力支持)以及请求失败。
- 验证所有成功写操作都会刷新相关弹窗和背后页面,且核心价格、账务、权限、审核资格和授予规则仍由服务端决定。
安全、兼容与可访问性
- 验证未登录用户、普通用户、目标对象所有者、无权用户和后台不同角色的读取与写入边界;确认 REST 权限回调、AJAX nonce、参数清理和输出转义完整。徽章旧公开入口的权限和 nonce 边界必须在统一链路切换时重新验收。
- 验证订单、认证资料、支付状态和徽章数据不会因缓存键、并发请求或浏览器后退而跨用户泄露。
- 验证弹窗键盘可达、焦点不会丢失、关闭方式明确、错误不只依赖颜色、骨架不会造成明显布局跳动;移动端无横向溢出。
- 如变更后台 SPA schema、路由或 REST 合约,运行管理员契约审计并完成一次生产构建;按仓库要求以完整构建产物原子部署。
- 每个灰度阶段完成 WordPress 运行环境人工验收和性能/错误指标检查后,才进入下一阶段;异常时暂停后续放量,不通过兼容分支掩盖错误。
Out of Scope
- 修改会员价格、会员权益、支付网关规则、订单账务、退款核算、认证资格/审核政策或徽章授予条件;这些规则只允许被新的流程正确调用和展示。
- 新增支付渠道、替换支付供应商、在浏览器保存支付凭证,或改变支付回调/异步结算机制。
- 新增公开认证资料库、向其他用户暴露认证文档、跨用户查看订单或徽章数据。
- 把订单、售后、认证审核或徽章运营工作台迁移进配置型 SPA;日常运营仍属于原生 WordPress 后台。
- 全站页面导航、用户中心信息架构、品牌设计系统或所有非弹窗页面的全面重做;本期只统一弹窗运行时和四类流程所需的轻量体验。
- 强制页面加载时预取所有弹窗数据、长期持久化敏感弹窗数据、建立订单/认证/徽章的第二套事实存储或长期保留旧新双路实现。
- 以新增兼容别名、旧 option 双读、静默降级或数据迁移层解决旧实现问题;流程切换后以新的规范化链路为唯一实现。
- 建立独立的数据仓库、复杂转化漏斗或第三方用户行为追踪系统;本期观测只服务于弹窗性能、错误和业务状态闭环。