# 全项目第二轮体验与代码优化设计 ## 目标 在不推翻已通过国风视觉、不改变现有业务枚举、不接入未经授权的远程服务的前提下,修复 Android 原生路由、共享弹窗高度预算、关键交互语义和密码策略的一致性问题,并为世系树补充可恢复定位能力。 ## 已确认基线 - G01~G10 保持已人工验收结果;只有明确的共享回归或 Android 运行时缺陷才允许触及。 - G11 之后全部活动页面已完成 MuMu 逐页与主要状态审核。 - 127/127 个 PowerShell 契约通过;66/66 个 Vue 文件与响应式覆盖清单一致。 - Vue 中 `100% 100% no-repeat` 为 0;页面/组件直接声明 `border-image-slice` 为 0。 - 当前 MuMu 为 `emulator-5554`,物理 900×1600、320 dpi;不得由代理启动或关闭。 ## 全局约束 - 视觉验证只使用 MuMu Android,不使用浏览器。 - 内容高度由内容决定;弹窗只使用视口最大高度和内部滚动。 - 不通过缩小字号、固定正文高度或强制单行掩盖布局问题。 - 九宫格切片继续只由 `styles/adaptive-frame-profiles.scss` 持有。 - 固定比例图标、缩略图和印章的例外继续只由响应式 allowlist 持有。 - 页面示例提示只使用“某某某”;现有 fixture 数据不纳入文案替换。 - 不执行 Git add、commit、push、restore、checkout。 - 每个生产改动先有失败契约,改后跑聚焦契约、四项基线并在 MuMu 验证。 ## 专家交叉评审结论 视觉交互专家认为现有国风体系健康,不应重做;功能代码专家认为最高价值缺陷集中在 Android 路由所有权。双方一致接受分批修复,并共同否决全量视觉重做、全量原生按钮迁移、状态库引入、虚拟列表和无后端契约的假持久化。 ## 批次一:活动页原生路由参数 ### 问题 G01、G03、G06 在 Android WebView 中仍优先读取 `location.hash`。R01 已实证该路径会忽略 UniApp 原生查询参数。 ### 五个方案 1. 保持现状:已被 MuMu 反证,淘汰。 2. 调整双读取优先级:仍保留两个运行时合同,淘汰。 3. 用 H5 条件编译保留 hash:可行但生产页面仍承担测试入口,非最简。 4. 新建全局 route-query 工具:对三个简单枚举参数过度抽象。 5. 页面 `onLoad(query)` 成为唯一入口,页面内白名单归一化:最小且符合 UniApp。 ### 选择 采用方案 5。G01 保存 `state/genealogyId`,G03 保存 `step/genealogyId`,G06 保存 `mode/state`;删除活动页的 hash、URLSearchParams 和 hashchange 监听。`ModulePage`、`TreeMemberForm` 与封存 A06 没有活动消费者,本批不延长其生命周期。 ### 验收 从 G05 进入 G03 首代人物步骤、从 G01 进入 G06 邀请码模式,返回再进入不串状态;活动路由静态扫描不得再出现 H5 查询读取。 ## 批次二:AppDialog 唯一高度预算 ### 问题 长弹窗的遮罩 padding、九宫格边框、视口高度和安全区分别计算,所有权分散;极短屏或非零安全区存在侵入系统栏或底部操作空间不足的风险。 ### 五个方案 1. 增大固定 padding:不适配设备差异。 2. 只在内容区减安全区:父子仍重复猜测空间。 3. 外层 safe-area padding,保留内容公式:预算仍分裂。 4. 改成标题/正文/操作 sticky 三段:改变已验收结构,范围过大。 5. `.app-dialog-layer` 持有安全区与外边距,`.app-dialog` 持有唯一 max-height,正文只在剩余空间内部滚动。 ### 选择 采用方案 5,不改变视觉层级、按钮顺序或九宫格资产。短弹窗继续内容驱动,长弹窗滚动到操作区。 ### 验收 G10 通过/拒绝、R04 删除、R08 长内容、M10 协议/退出在当前 MuMu 均完整;长内容顶部不进入状态栏,底部按钮可达,短弹窗不产生大空白。 ## 批次三:共享点击表面语义与按压反馈 ### 问题 AppTabbar 与 GenealogyCard 是活动共享表面,但目前主要依赖普通 `view @click`,缺少当前项播报和统一按压反馈。 ### 五个方案 1. 不处理:TalkBack 与即时反馈缺陷继续存在。 2. 所有页面就地补属性:重复且易漏。 3. 全量替换为原生 button:Android 默认样式回归面大。 4. 新建 AppPressable 并迁移全部点击表面:本轮过度设计。 5. 保留现有 DOM 与皮肤,只给两个活动共享组件补 role、动态 aria、选中/禁用语义和无位移 hover-class。 ### 选择 采用方案 5。Tabbar 使用 `tablist/tab/aria-selected`;GenealogyCard 使用单一 button 语义与包含家谱名、角色、当前状态的可访问名称。按压态只改变透明度,不改变尺寸。 ### 验收 F01/M01 底栏与 G01 家谱卡在 MuMu 中点击热区不变、无布局位移、选中态仍清楚;静态契约验证可访问属性和 pressed class。 ## 批次四:G10 拒绝错误可达性 ### 问题 拒绝原因的可见错误没有与 textarea 程序化关联,提交失败后也没有稳定焦点返回路径。 ### 五个方案 1. 仅保留红色文字:不可访问。 2. 只加 `role=alert`:能播报但未关联字段。 3. 新增页顶错误摘要:改变已验收视觉。 4. 全项目一次性迁移所有表单:回归面过大。 5. G10 先建立稳定 id、aria-invalid、aria-describedby、alert,并在失败后 nextTick 聚焦字段。 ### 选择 采用方案 5,作为后续表单迁移样板,不改变弹窗现有外观。 ### 验收 拒绝原因为空时错误出现并与字段关联,焦点回到 textarea;输入后错误与 invalid 状态同步清除;键盘弹出时操作按钮仍能滚动到达。 ## 批次五:统一密码策略 ### 问题 A04、A05 只判断非空,M04 要求 8~32 位且含字母和数字,同一账户合同互相矛盾。 ### 五个方案 1. 保持三套规则:错误。 2. 将 M04 正则复制到 A04/A05:产生三份所有者。 3. 仅依赖服务端:当前 mock 模式无法及时反馈。 4. 动态拉取服务端策略:尚无接口合同。 5. `utils/validation.js` 持有唯一密码规则与错误文案,三页共同消费。 ### 选择 采用方案 5。规则为 8~32 位、同时含字母与数字;M04 额外拒绝新旧密码相同。旧页面正则和分裂文案必须删除。 ### 验收 三页对空值、7 位、纯字母、纯数字、合法 8 位和 33 位输入给出一致结果;MuMu 中错误换行与内容高度正常。 ## 批次六:T01 回到当前成员 ### 问题 世系树横向平移后没有恢复到当前成员的动作,大谱系中容易失去上下文。 ### 五个方案 1. 不处理:保留迷失风险。 2. 每次选择自动居中:干扰自由浏览。 3. 始终显示固定按钮:增加默认页面密度。 4. 新增小地图和缩放:属于重设计。 5. 仅在用户明显平移后显示“回到当前成员”,通过稳定节点 id 和 `scroll-into-view` 主动恢复。 ### 选择 采用方案 5。动作复用现有工具栏风格,不改变节点、连线、画布尺寸和底部详情卡。 ### 验收 左右平移后动作出现;点击后当前节点重新可见、选中成员和详情不变,动作消失;空/加载/错误状态不显示。 ## 明确暂缓 - 返回页栈:问题真实,但必须先把“恢复来源上下文”和“深链 fallback”分类,并与保存后的数据刷新一起设计,禁止机械替换所有 `redirectTo/reLaunch`。 - 短信验证码:记录为认证合同债务;真实接口、过期、重发和 token 所有权确定前,不制造本地假验证。 - 跨页保存/删除:当前 mock fixture 分散,不能继续把视图切换声称为持久成功;领域 repository 作为独立后续迁移,不在本批扩大范围。 - 全局文字 token:只在本批新增的错误/辅助文案保持可读,不对所有 19~21rpx 文本一刀切。 ## 完成定义 六个批次各自通过先失败后通过的聚焦契约和 MuMu 验证;随后全部 PowerShell 契约、四项指定基线、66/66 覆盖与两个禁用扫描再次通过。共享改动必须回归至少一个已人工验收页面。