识别页面之前先补上人工确认这一步
我最初设计通行证入口时脑子里只有一个直线流程选择卡种进入识别页页面给出结果。写到一半我发现这条线里少了一个不能由程序替人作答的问题当前样本是否经过授权、当前选择的卡种是否和样本用途一致、即便将来有回调结果是否应该被用于当前操作。所以我把人工确认放在调用之前。它不是为了让按钮多一道手续也不是为了制造“已合规”的页面印象。页面只保存“样本已获授权可用于本次验证”这一次确认并在系统能力不具备时继续阻断。当前工程没有展示识别成功、没有返回字段也没有给出任何合规成功的结论入口只负责让不具备条件的请求停在前面。这篇讲的是人工确认与最小结果处理原则。它不会重复讨论怎样选择正确卡种也不会虚构 OCR 内容或声称任何合规检查已经通过。我为什么不让页面直接跳进识别当时我想过把“进入系统识别页”做成永远可点击的按钮再在运行时页面提示用户确认。这个方案看起来省事问题是调用意图已经发生入口却没有留下清晰的准入状态。后来我改成先让操作者勾选样本授权再结合设备能力决定按钮能否可用。入口中的复选框没有自动勾选初始authorizationConfirmed是 false。这个默认值很重要它避免页面一加载就暗示样本已经可以使用。用户不确认时门禁消息明确写着“无授权样本识别未启动”。State authorizationConfirmed: boolean false; State gateMessage: string 无授权样本识别未启动; Toggle({ type: ToggleType.Checkbox, isOn: this.authorizationConfirmed }) .onChange((isOn: boolean) { this.updateAuthorization(isOn); });我也没有把确认框的文字写成“本人已完成所有审核”。页面能确定的事实更小操作者确认当前样本可用于本次验证。它不替代业务人员对卡种、用途和现场条件的判断更不会因为勾上就自动产出一个可展示的身份信息。否是否是操作者选择当前卡种人工确认样本授权确认状态为 true停止在入口识别未启动当前设备支持系统能力停止在入口能力不支持保存已选类型并进入后续页后续运行时结果仍需独立处理这张图里人工确认不直接连到“识别完成”。它只是一道前置条件。这样的绘制看起来少了一个漂亮的终点却更符合当前页面拥有的信息。确认状态如何影响门禁提示updateAuthorization的逻辑故意把“取消确认”和“确认成功”拆开。取消时根据系统能力回到“无授权样本”或“设备未声明能力”确认时如果能力支持才提示“可以进入系统识别页”。如果设备不支持提示仍然保留阻断含义。private updateAuthorization(isOn: boolean): void { this.authorizationConfirmed isOn; if (!isOn) { this.gateMessage this.systemCapabilitySupported ? 无授权样本识别未启动 : 当前设备未声明 CardRecognition 系统能力识别未启动; return; } this.gateMessage this.systemCapabilitySupported ? 授权已确认可以进入系统识别页 : 授权已确认但当前设备不支持该系统能力; }我喜欢这段代码的原因是它没有把authorizationConfirmed当成通行凭证。它只是一个输入最终按钮仍由两个条件共同控制。确认与能力分别回答不同问题前者是当前使用是否得到人工确认后者是当前设备是否具备运行前提。少任何一个页面都不该继续。这也让我避免了另一种误导性 UI复选框勾上后把整体状态染成绿色并写“已完成”。现在绿色只在按钮可用的条件下出现而摘要区仍然写“识别未启动”。用户能知道入口已放行不会误以为运行结果已经回来。最小结果处理不给页面塞演示数据入口右侧的摘要给出四类信息当前状态、回调码、返回卡种、字段数量。当前状态固定为“识别未启动”另外三项分别为“未返回”“未返回”“0”。我没有用假的姓名、证件号码或卡种填充它们因为那会使人工确认和实际运行结果混在一起。Text(识别未启动) this.buildMetric(回调码, 未返回); this.buildMetric(返回卡种, 未返回); this.buildMetric(字段数量, 0);最小处理原则的意思不是“以后永远不处理结果”。它是指当前没有真实回调时只显示对流程有帮助、且确实存在的状态。若将来运行时页面获得返回也应避免把原始字段铺满界面、写入日志或放进截图。现有页面已经写明边界不在界面显示cardInfo字段值不写文件、不写日志、不进入截图归档只保留 code、cardType、字段数量和回调时间。后续运行时页门禁入口页面操作者后续运行时页门禁入口页面操作者入口页没有字段结果可展示alt[条件不足][条件齐备]确认样本可用于本次验证组合确认状态与设备能力保持未启动并说明原因仅携带已选卡种进入下一步这份克制不仅是隐私上的考虑也让调试更简单。入口页的职责限定后任何人看到“字段数量 0”都知道原因是尚未启动或尚未收到返回而不是去猜页面隐藏了多少数据。相反如果我在这里提前制造示例字段测试人员就无法判断那些内容来自哪里。调用前的确认如何保留在代码里真正执行跳转的startRecognition()先做早返回。它没有在条件不足时显示一个假的失败码也没有试图加载原生模块只有人工确认和能力状态同时为真才保存当前类型并进入后续页面。private startRecognition(): void { if (!this.authorizationConfirmed || !this.systemCapabilitySupported) { return; } AppStorage.setOrCreatestring(permitTypeKey, this.selectedType); router.pushUrl({ url: pages/article10/PermitRecognitionRuntimePage }); }这里有一个我特意不省略的细节保存的是permitTypeKey不是某段识别信息。入口向后传递的是用户已选择的类型让后续页在适当条件下使用它不在路由参数里夹带敏感样本也不把复选框状态伪装成服务回调。人工确认要落在真正的调用前因此测试不能只看勾选框是否能切换。我会依次验证未勾选时按钮禁用勾选但能力不支持时仍禁用满足两项条件后按钮可用取消勾选后按钮立刻回到禁用。这个过程可以证明入口对人和设备的两个前置判断都生效但不能证明之后的识别运行成功。我如何描述当前测试结论当前工程可确认的是页面能选择类型能保留操作者的样本授权确认能读取运行环境支持状态并在条件不满足时不启动后续动作。它还明确声明不打开相机、相册或识别组件。到这里为止描述都可以从代码和页面状态核对。当前工程不能确认的是是否对某张真实通行证取得了识别回调、是否有字段、字段是否正确、这些字段是否符合某项业务规范。没有真实样本和运行回调时任何“识别完成”或“确认合规”的说法都超出了页面事实。我宁愿让报告保留空白也不想用一段模拟结果填满它。这次调整改变了我对入口页的期待。它不需要表现得像一个已经完成任务的页面更重要的是它要在任务还不该开始时明确地停住并让操作者知道停住的原因。人工确认不是按钮前的一句免责声明而是流程里可观察、可撤销、可复测的状态。人工确认为什么要允许撤销我曾经考虑过一旦勾选授权确认就把它视作本页的固定事实不允许用户轻易取消。这样做表面上能减少误点实际却会让状态变得不可信。操作者可能发现自己选错了样本、拿错了卡种或只是想退出当前验证。确认如果不能撤销页面就会继续带着过期意图放行。现有逻辑把取消确认视为一次有效状态变化authorizationConfirmed回到 false按钮立刻恢复禁用门禁提示也回到“无授权样本识别未启动”或能力不支持的对应说明。它不追问取消原因也不保存额外描述因为当前入口并不需要扩大收集范围它只需要确保后续动作不再基于已经撤回的确认。这一点让我在测试里加入了“来回切换”用例。先确认授权看按钮是否满足其他条件后可用再取消看按钮是否立即禁用然后重新确认检查消息是否依据当前能力重新计算。这个用例比只测试一次勾选更能说明状态不是视觉装饰。不把确认当成业务结论人工确认很容易被写成“已审核”或“已合规”但这两个词比当前状态强得多。页面没有保存审核人、审核规则、业务流程结果也没有连接任何外部审批。它能表达的仅是当前操作者对“样本可用于本次验证”的确认。我在文案中保留“本次”两个字是为了让确认有明确范围。用户切换卡种、换了样本、关闭页面再回来都不应从这一个布尔状态推导出更广泛的许可。入口页负责将这次操作是否允许继续显式化而不是替其他环节作判断。同样即使两个门禁都满足页面也不显示“确认成功”。它显示的是“可以进入系统识别页”。这是一种有意的措辞差异它描述下一步资格不描述识别结果更不描述业务判断。最小摘要如何帮助排错我保留的摘要字段很少当前状态、回调码、返回卡种、字段数量、能力声明、系统版本和门禁结论。字段少并不代表信息不足因为它们都回答入口阶段真正需要的问题。当前状态回答是否已经启动能力声明回答环境能否继续门禁结论回答阻断原因类型和字段数量保持未返回或 0避免假装拥有内容。如果把摘要扩成一个完整的证件详情面板即使里面放的是演示数据也会让读者自然以为页面已经经过真实处理。更糟的是页面后续一旦接入真实回调展示、日志、截图和文件保存会同时变成需要审视的面。当前阶段采用最小摘要是为了让入口能被独立验证而不是预先把未知数据带进页面。页面里的结果处理边界也写得具体不显示cardInfo的字段值不写文件、不写日志、不进入截图归档只保留 code、cardType、字段数量和回调时间。即便将来出现回调这也是一个处理方向而非当前已经发生的事件。此刻我只能说明代码为最小处理留出了位置不能声称它已在某张卡片上执行。我如何安排一次不越界的页面测试第一次测试是在系统能力不支持或未知的环境中进行。打开页面后我确认摘要仍为识别未启动字段数量为 0勾选确认后若能力不支持按钮仍不可用。这个场景只验证阻断没有任何样本输入。第二次测试放在能力支持的环境中仍然不提供真实样本。未确认前按钮禁用确认后按钮可用取消确认后再次禁用。这里能验证确认状态参与了调用前判断也能验证它可撤销。即使按钮在某个状态可用我也不把这次测试称作识别测试因为没有进入实际服务运行也没有可记录的字段。第三次才是未来需要独立安排的运行时测试。它需要合适设备、经过授权的样本、明确用途和独立的结果处理方案。那会是另一项工作不能被入口页的勾选操作提前完成。本篇记录的是入口行为因此到人工确认和最小摘要为止就停止。否是否是页面加载读取系统能力状态未启动人工确认当前样本用途确认是否仍有效按钮禁用保留最小摘要系统能力支持按钮禁用说明环境限制只将类型交给后续页面这张补充图强调了撤销的路径。确认不是一次性盖章而是随当前操作存在的状态。只要用户撤销入口就应该恢复到未启动。这样既减少意外调用也让每次页面行为都能从当前字段解释。入口页的克制也是一种可维护性有了清楚的人工确认和最小处理后续维护时能区分两个问题入口是否错误放行和后续能力是否返回预期。若二者混在同一页任何异常都会变成模糊的“识别出问题”。把人、设备、调用和结果分段后每段都可以有自己的测试与记录不需要依赖一段敏感或虚构内容来证明流程存在。我认为这比把页面做得“像已经完成”更重要。用户看到空的字段和 0不会被误导开发者看到未启动也知道应该回到确认状态或设备能力测试人员能复现按钮何时可用、何时禁用。当前没有结果就让当前没有结果成为清楚的结果。防回归检查默认和取消确认时都保持“识别未启动”并且入口按钮不可用。人工确认仅表达当前样本用途仍须与系统能力共同决定是否进入后续页面。入口和测试记录只保留状态、类型和最小计数不展示、不写入、不归档任何假设或原始字段结果。