106 lines
20 KiB
Markdown
106 lines
20 KiB
Markdown
# 原生 App 真机验收清单
|
||
|
||
此清单用于 Android/iOS 自定义基座或签名包验收。`verify:app-assets` 校验源码侧原生配置和静态资源,`verify:android-apk` 校验实际 APK 元数据、签名与哈希;两者都不能替代本清单。
|
||
|
||
## 预条件
|
||
|
||
1. 已执行 `npm --prefix mobile-uni run build:app`,并使用 HBuilderX 的**自定义运行基座**运行当前资源。
|
||
2. Android 首次上机前,核对版本化 `mobile-uni/.env` 中法务确认的 `VITE_APP_TERMS_URL`、`VITE_APP_PRIVACY_URL`,执行 `npm --prefix mobile-uni run configure:app-legal`、`build:app` 和 `verify:app-release`;不得手工放入占位地址。启动原生提示必须关闭,登录页是唯一法务同意入口。
|
||
3. 使用有效的移动端测试账号;不得把管理员 Web 登录态当作 App 登录验证。
|
||
4. 每台设备保留系统版本、App `versionName/versionCode`、基座/包哈希、录屏或截图和失败日志。
|
||
5. HBuilderX/CLI 编译链必须与手机调试基座兼容;启动时出现版本不匹配弹窗即视为未通过。当前版本组合和排障命令见 `MOBILE_APP_PACKAGING.md`。
|
||
|
||
Android 每个人工步骤完成后,可在不改变设备状态的前提下保存统一证据。下列脚本只读取当前版本、前台 Activity、四项敏感权限、UI 层级、截图和应用退出记录;不会启动/停止应用、安装/卸载、清数据、授权/撤权或代替用户点击。`screen.png` 和 `window.xml` 可能包含屏幕可见信息,只会写入 Git 已忽略的 `output/`,不得转存手机号、验证码或业务原文到仓库:
|
||
|
||
```powershell
|
||
.\scripts\capture-android-acceptance.ps1 `
|
||
-Serial emulator-5554 `
|
||
-Stage fresh-install-no-native-privacy
|
||
```
|
||
|
||
每次手动操作后换一个简短的 `-Stage`。当前版本首次启动应记录为 `fresh-install-no-native-privacy`;登录页默认未勾选、两个法务链接可打开、未勾选发送验证码和登录均被阻止,可分别使用 `login-consent-default`、`login-legal-links`、`login-consent-required`。麦克风拒绝可使用 `microphone-denied`。脚本仍兼容识别旧包的 `first-choice`、`exit-confirmation` 和 `not-visible`,仅用于历史取证,不再是当前验收流程。脚本不把“拍到页面”自动判成业务通过;验收人仍须结合预期、截图和 `acceptance-evidence.json` 签认。
|
||
|
||
### 自动化前置检查
|
||
|
||
先运行 `npm --prefix mobile-uni run audit:ui-tokens` 记录源码 token 收敛度,再完成 `npm --prefix mobile-uni run build:h5` 并运行 `npm --prefix mobile-uni run audit:ui-rendered`。后者默认以 390×844 打开六个未登录/空态路由,检查横向溢出、控制台错误和实际生效样式,并把报告与截图写入 Git 已忽略的 `output/ui-ux/`。审计发现的 palette 外颜色、孤立字号或非 token 圆角应作为视觉债务显式保留或修正;命令退出 0 只代表采集完成,不能替代下方 Android/iOS 系统权限、认证业务、前后台、弱网和真实媒体验收。
|
||
|
||
## 当前证据边界
|
||
|
||
2026-07-26 已在 vivo V2443A(Android 15)的 HBuilderX 5.22 标准基座完成手机号登录,并通过生产 `dashscope/qwen3-asr-flash` 跑通“按住说话 → ASR → 提交”链路。2026-07-28 同一机型再次由 HBuilderX CLI `5.22.2026072503-alpha` 完成标准基座编译、同步和启动;未配置正式法务地址时,登录页协议默认未勾选并明确阻止验证码与登录,点击协议入口不会打开占位地址。
|
||
|
||
同日已通过 DCloud 云端证书生成并安装首个自定义基座,包名 `com.yincheng.wygj`、版本 `0.1.5 (105)`,云打包、签名、USB 安装、资源同步和启动链路成立。系统读取发现首版因未显式配置而使用默认 `targetSdkVersion=28`,随后已在 manifest 固定为 35,并将设备信息与外部存储设为启动时不申请。最终 API 35 自定义基座大小为 `21,158,193` 字节,SHA-256 为 `82D3352FF96A86F5DB4AC0C71DCB0ED6CEC98F2A785F6EAED2FE8D4FC0C5F704`,实际 APK 的包名、版本、API 35、单签名和 v2 签名均已由脚本复核。
|
||
|
||
新基座已在 vivo V2443A 完成保留数据的覆盖安装和系统 Launcher 冷启动。系统读取为 `minSdk=21`、`targetSdk=35`;启动后设备信息、外部存储、相机和麦克风均保持未授权,未出现启动权限弹窗。员工端首屏、状态栏和底部手势区正常渲染,未发现白屏、崩溃或 `FATAL EXCEPTION`;登录页法务门禁继续生效。
|
||
|
||
23:12 又生成可独立安装的非自定义基座 DCloud 云证书内测 APK `bangdao-0.1.5-dcloud-test.apk`,大小 `33,920,950` 字节,SHA-256 为 `AB634EB9A9F0939804151ED14815484FBD75DFE36CC24DF00EC23BDD762D8FD1`。APK 反编译门禁已确认包内 `androidPrivacy.json` 使用线上《服务协议》和《隐私政策》地址;同签名覆盖安装成功。只清除 `com.yincheng.wygj` 测试数据后,以系统 Launcher Activity 冷启动,原生 template 弹窗真实显示“同意并继续/暂不同意”,两个链接均在 vivo 系统浏览器打开对应 HTTPS 页面,且未发现 `FATAL EXCEPTION`。验收过程没有代替用户点击同意或拒绝;拒绝退出、同意后登录、主动录音权限、弱网、方言、iOS 和下列全项仍未通过。
|
||
|
||
2026-07-29 当时候选包升级为 `0.1.6 (106)`,大小 `33,921,279` 字节,SHA-256 为 `A5F026B70F11327355597B9FEA3625C4168700297E6D7847F10B079CEB860914`。191 项移动端单元测试和类型检查通过;APK 已通过 API 35、法务链接、签名、包内 `app-service.js` 与当前 App-Plus 编译产物一致性以及手机号、固定测试验证码、私钥和常见令牌扫描。该包在同一 vivo V2443A 完成保留数据的覆盖安装和 Launcher 冷启动,系统读取为 `minSdk=21`、`targetSdk=35`,相机、录音和媒体权限保持未授权,未发现 `FATAL EXCEPTION`。因为覆盖安装保留了前一版本的隐私状态,本次未重新触发首次隐私弹窗;该记录仅作历史追溯。
|
||
|
||
同日,本机 Android Studio `Medium_Phone` 虚拟机完成 Android 15/API 35 启动,物理分辨率 `1080×2400`、密度 `420`。在虚拟机此前未安装本应用的前提下,`0.1.6 (106)` 首次安装成功并从系统 Launcher 冷启动,`am start -W` 记录总耗时约 `6.4s`;最新包真实显示原生《服务协议和隐私政策》弹窗,四项相机、录音、图片和视频权限均为 `granted=false`,crash 缓冲区为空。截图和 UI 层级保存在忽略目录 `output/aug1-rc/android-emulator/`;验收未代替用户点击同意或拒绝。虚拟机证据用于补充干净安装和 API 35 权限基线,不能替代真实设备的媒体、WebRTC、弱网和系统浏览器交互。
|
||
|
||
同日,候选包继续升级为 `0.1.8 (108)`,大小 `33,921,705` 字节,SHA-256 为 `E252140645F3AAD14B3594FD78E76BDF1A2122F7DC70EBD21CC5DF53223C7878`。新增的项目根原生清单与 `network_security_config.xml` 已进入实际云打包输入,193 项移动端测试、类型检查、App 构建及联网法务预检通过;APK 反编译确认包内资源与当前编译产物一致、`usesCleartextTraffic=false`、`networkSecurityConfig` 引用、系统证书信任配置、签名和敏感值扫描均通过。虚拟机卸载旧实例后全新安装,Launcher 冷启动总耗时 `2.904s`,最新原生隐私弹窗真实显示,四项敏感权限均为 `granted=false`,crash 缓冲区为空。仍未代替用户点击拒绝或同意。
|
||
|
||
同一 `0.1.8` APK 又在虚拟机完成保留数据的同版本覆盖安装。覆盖后冷启动 `3.092s`、标准 Launcher Intent 暖启动 `0.538s`、从系统桌面恢复热启动 `0.120s`;原生隐私弹窗和四项未授权状态始终保持,未发现 FATAL 或 ANR。该结果证明当前 APK 的安装升级、入口解析和首次弹窗前生命周期基线,不证明登录后前后台、弱网、录音或业务闭环。
|
||
|
||
随后针对 Android 系统文件选择器“用户取消”被误判成上传或转写失败的问题,将五个文件选择服务统一为结构化取消信号,并在九个页面恢复空闲态、清理残留“转写中”提示;真实平台异常仍显示稳定中文错误。新增回归覆盖五个选择器的取消/失败分流以及九个消费页面。直通车页同时补齐首次弱网导致五个直达对象加载失败后的原位重试,失败时清空旧通道并禁止提交,恢复后自动选择有效通道;再增加 package、lockfile 与 manifest 版本一致性门禁。移动端测试增至 `198/198`,类型检查通过。自动化证明状态机已修复,但真实系统文件选择器取消与断网恢复仍须人工点击确认。
|
||
|
||
当时候选包继续升级为 `0.1.10 (110)`,大小 `33,922,134` 字节,SHA-256 为 `20CB16B4E9D024DBF5EEEF577BFBA3B4DF5E5E78B597BABB99CB7450C7AE5034`。DCloud 云打包成功后,APK 元数据、测试签名、包内资源、法务链接、网络安全配置和敏感值门禁全部通过;同一虚拟机从 `0.1.9` 保留数据覆盖安装成功,Launcher 冷启动约 `1.271s`,显示原生隐私弹窗,四项敏感权限仍为 `granted=false`,未发现 FATAL 或 ANR。该记录仅作历史追溯。
|
||
|
||
2026-07-29 又以新增的只读统一取证脚本复核同一虚拟机的当前状态:前台 Activity 为 `io.dcloud.PandoraEntryActivity`,原生隐私标题、“暂不同意”和“同意并继续”三个控件均可见,手机号登录尚不可见;相机、录音、图片和视频权限仍为 `false`,应用退出记录中未出现 Crash/ANR。截图、UI、权限、Activity、退出记录和 JSON 均落在忽略目录 `output/aug1-rc/android-acceptance/20260728-192056-privacy-before-choice/`。该次只记录选择前基线,仍未代替用户做隐私选择。
|
||
|
||
2026-07-29 当前非自定义基座内测 APK 已升级为 `0.1.13 (113)`,大小 `33,921,543` 字节,SHA-256 为 `FA2D2A6DC84AE759714E6D16D146C1E1552A0F3F53C046069422012361D1D0C0`。DCloud 云端证书打包成功,APK 深检通过包名、API 35、v2 测试签名、登录页法务门禁、身份失败关闭、包内资源一致性、敏感值和禁止明文 HTTP。干净提交 `af8af2f6` 的统一 RC 已达到 `releaseEligible=true`。生产固定码的首次获取/登录、退出、旧令牌失效、等待防刷窗口后的再次获取和重新登录已在非真机认证脚本中通过,两次验证码请求均确认未真实发送短信;固定码认证不再列为功能缺口,这不替代本文件下列 Android 真机权限、系统选择器、前后台、弱网、附件和媒体链路验收。
|
||
|
||
同日,`0.1.13 (113)` 已在 vivo V2443A(Android 15/API 35)完成从 `0.1.6` 保留数据覆盖安装、同版本再次覆盖安装和 Launcher 冷启动;两次安装均成功,冷启动约 `1.1s`/`1.2s`,相机、录音、图片和视频权限保持未授权,未发现 Crash/ANR。真机登录页确认协议默认未勾选,“获取验证码”和“登录”都会先显示协议门禁;勾选后继续进入验证码必填校验。《服务协议》和《隐私政策》分别由 vivo 系统浏览器打开线上 `/legal/terms.html` 与 `/legal/privacy.html`,隐私正文显示 2026-07-28 版本。按 Home 后进程保持,重新唤起为 `HOT`、约 `0.2s`,页面恢复且无 Crash/ANR。脱敏截图和统一取证保存在 `output/aug1-rc/android-acceptance/20260729-140453-upgrade-0.1.13-cold-launch/`;登录页只截取不含手机号的下半屏,未保存手机号、验证码或令牌。该证据完成登录法务门禁和前后台基础恢复,不替代真实账号登录、麦克风、WebRTC、系统选择器、真实断网、附件和 ASR/TTS 验收。
|
||
|
||
同一真机随后使用生产现有在职 APP 主体和固定码完成页面登录;账号、固定码和令牌未进入日志、截图或仓库。`0.1.13` 允许麦克风后,原生按住录音、上传和生产 ASR 已跑通,识别结果进入真实“问”主路径。拒绝麦克风后的文件降级同时暴露两个 App-Plus 缺陷:`uni.chooseFile` 在 App 不受支持,且 Native.js 无法可靠构造并传递 Java `byte[]`。调查包 `0.1.14/0.1.15` 仅用于定位,生成的 APK 已删除,不得分发。
|
||
|
||
`0.1.16 (116)` 源码阶段完成了 Android 系统 `ACTION_OPEN_DOCUMENT`、`ParcelFileDescriptor + FileChannel.transferFrom`、应用专属外部缓存、App 媒体选择器和权限 Activity/页面生命周期修复,并在 HBuilderX 5.22 标准调试基座完成取消、重复打开和真实 WAV 上传/ASR。成果投稿阶段先后定位并修复了追问反复调用模型和 `45,000ms` 超时问题,确认卡已经能出现。上述调查只保留为历史过程。
|
||
|
||
2026-07-30,同一 vivo 真机的已登录线上会话进入“学习”中心时曾显示“发生未知异常”。生产只读日志确认 `GET /api/aihr/mobile/practice/mistakes` 的 JSON `LIKE` 百分号被 `String.formatted()` 误解析;提交 `edb8c825` 改为专用占位符并随后端 JAR `346687564b38adbba643fc7d94d2faedbb51449198b4eef6c3fa90fb99646c83` 定向发布。签名 `0.1.17` 真机复验已加载真实今日任务、岗位 SOP 和错题本,未再出现系统错误;证据位于 `output/aug1-rc/android-acceptance/20260730-123522-aug1-0.1.17-learning-center/`。
|
||
|
||
当前 DCloud 测试签名候选已升级为 `0.1.17 (117)`:大小 `33,922,976` 字节,APK SHA-256 `0A8581D70A5988E4BDCF4BB3F0C88B4608FA8C6785FDCF1569DD56CE88E27F60`。拆包门禁确认包内业务资源与当前 App-Plus 构建一致;同一 APK 已在 vivo Android 15 真机完成登录、麦克风允许/拒绝/恢复、权限 Activity 返回、系统文件/媒体选择器取消、`191,352` 字节合成中文 WAV 选择和生产 ASR、成果投稿确认保存。正式结论仍为 No-Go 的原因已转为业务内容/通道/负责人签认、受控分发与企业签名决策,以及真实断网、WebRTC、实际图片/视频/文档、受控下载和其余角色门禁。
|
||
|
||
随后根据企业内部应用的体验决策,`0.1.12 (112)` 取消 DCloud 启动原生确认,法务同意统一放到登录页。新 APK 大小 `33,921,458` 字节,SHA-256 为 `DD24E5F20BC7C064F5059E538A1FAB7518DF46CBAB502F59A3629F0B1B1F5EBB`;包体门禁确认 `prompt=none`、登录页两个 HTTPS 链接和未勾选拦截均已内置。在同一 Android 15/API 35 虚拟机卸载旧包后全新安装,取证结果为原生隐私层 `not-visible`、四项敏感权限未授权、进程与前台 Activity 正常且无 Crash/ANR,证据位于 `output/aug1-rc/android-acceptance/20260729-021418-no-native-privacy-fresh-install-retry/`。当前 AVD 是 `x86_64`,而 APK 只含 `arm64-v8a/armeabi-v7a`;DCloud Weex 跨架构转译实际报 `spinWaitPeer timeout`、`sender is null` 和 IPC timeout,所以原生外壳可见但页面主体空白。该现象不证明产品页面失败,也不能作为页面通过证据;不得为此修改正式 ABI、回退 H5 壳或增加业务兜底。
|
||
|
||
同一 `mobile-uni` 源码的 H5 构建另在 390×844 Playwright 真浏览器补验:登录页核心表单、登录按钮和协议行均在首屏;协议默认未勾选,点击“获取验证码”或“登录”都显示“请先阅读并勾选同意”,且网络列表无业务请求;勾选后进入手机号必填校验;《服务协议》《隐私政策》分别打开 `https://peilian.njzhmj.top/legal/terms.html` 与 `https://peilian.njzhmj.top/legal/privacy.html`,页面标题和正文可读,控制台 0 错误。截图位于 `output/playwright/aug1-login-consent/`。该证据仅覆盖 Web 页面布局、链接与请求前门禁,不替代 App 运行、认证账号业务、系统录音/媒体权限或弱网验收。
|
||
|
||
## 已完成的 Android 基座证据
|
||
|
||
- [x] 自定义基座包名、版本、API 35、单签名、v2 签名和 SHA-256 可重复校验。
|
||
- [x] 同签名同版本覆盖安装成功,未卸载或清除 App 数据。
|
||
- [x] 系统 Launcher 冷启动进入员工首页,无启动权限弹窗、白屏或崩溃。
|
||
- [x] 启动后设备信息、外部存储、相机和麦克风权限均保持未授权。
|
||
- [x] 独立 DCloud 云证书内测 APK 的包内法务配置、API 35、单签名、v2 签名和 SHA-256 可重复校验。
|
||
- [x] 清除本 App 测试数据后首次启动先显示原生隐私弹窗,服务协议与隐私政策链接均可在系统浏览器打开。
|
||
- [x] `0.1.6 (106)` 历史候选包完成同签名覆盖安装、冷启动和启动权限复核,包内资源与当时 App-Plus 编译产物一致。
|
||
- [x] `0.1.8 (108)` 在本机 Android 15/API 35 虚拟机完成卸载重装和冷启动,最新包原生隐私弹窗真实显示,四项敏感权限保持未授权、网络安全配置已进入 APK 且未见崩溃。
|
||
- [x] `0.1.8 (108)` 在同一虚拟机完成保留数据覆盖安装、标准 Launcher 启动和首次隐私弹窗前的后台/前台恢复,未见 FATAL 或 ANR。
|
||
- [x] `0.1.10 (110)` 从 `0.1.9` 保留数据覆盖安装并冷启动成功,最新原生隐私弹窗、未授权权限基线和无 FATAL/ANR 状态保持。
|
||
- [x] 只读统一取证脚本已通过状态变更命令回归并在虚拟机实跑,可重复保存当前版本、Activity、隐私控件、权限、UI、截图和退出记录。
|
||
- [x] 媒体选择取消/真实失败、Android 系统选择器生命周期、直通车首次弱网恢复和登录法务门禁状态机已由当前 209/209 个移动端测试覆盖;真实断网恢复仍列为下方人工门禁。
|
||
- [x] `0.1.12 (112)` 全新安装后不显示原生隐私确认,四项敏感权限保持未授权且无 Crash/ANR;包内登录协议门禁与统一 RC 自动校验通过。
|
||
- [x] `0.1.13 (113)` 在 vivo Android 15 真机完成保留数据升级、同版本覆盖安装、冷启动、登录法务门禁、两个线上法务正文和前后台热恢复;四项敏感权限保持未授权且未见 Crash/ANR。
|
||
- [x] 同一真机在签名 `0.1.17` 完成真实页面登录、麦克风允许/拒绝/恢复、原生录音取消、系统文件/媒体选择器取消、真实 WAV 选择/生产 ASR 和成果投稿确认保存。
|
||
|
||
## Android(最低 Android 10 + 一台当前主流机型)
|
||
|
||
- [x] 登录页协议默认未勾选;两个法务链接能打开正确正文;未勾选时验证码和登录均不发请求,勾选后才允许继续。
|
||
- [x] 在 Android 设备选择数据库现有有效手机号,点击获取验证码后使用生产固定码登录;未开启真实短信,且未保存手机号、固定码或令牌。
|
||
- [x] 首次录音允许麦克风后可完成转写;拒绝麦克风后系统“禁止”生效、不循环申请,并能进入本地音频选择继续 ASR。签名 `0.1.17` 已完成允许、拒绝、选择器取消、WAV 选择、生产 ASR和权限恢复。
|
||
- [ ] 原生实时对练可完成麦克风授权、实时转写与远端语音播放;WebRTC/WebView 不可用或断线时明确提示并保留录音对练。
|
||
- [ ] 图片、视频、文档和音频可选择并上传;受控附件下载后可打开,不泄露 OSS 地址。签名 `0.1.17` 已完成音频选择/上传/ASR及图片/视频选择器取消;实际图片、视频、文档和受控下载仍待验收。
|
||
- [ ] 前后台切换、网络断开/恢复、窄屏和底部手势区无白屏、遮挡或重复提交。
|
||
- [ ] 再次安装同版本后,桌面图标、启动图和 Android 导航栏不闪白。
|
||
|
||
## iPhone(iOS 15 + 一台当前刘海或灵动岛机型)
|
||
|
||
- [ ] 初次访问录音时,系统麦克风说明与功能一致;拒绝后可选择音频且不崩溃。
|
||
- [ ] 选择图片/视频/文件时,系统照片/文件访问说明与功能一致;取消选择不会残留上传状态。
|
||
- [ ] 登录、录音转写、TTS 播放、上传、受控下载、前后台切换均通过。
|
||
- [ ] 启动图全屏,无黑边;状态栏、刘海、底部安全区和键盘不遮挡主要操作。
|
||
- [ ] App Store 图标无透明通道、未预制圆角;真机图标更新后重启设备复核 iOS 缓存。
|
||
|
||
## 通过口径
|
||
|
||
每个平台的必测项全部通过,且录音拒绝、媒体取消、登录失效和离线恢复四种反例均留有证据,才可进入签名包或 TestFlight/企业 APK 测试。任何 App 壳、权限、原生插件或证书变更都必须重新云打包并重跑本清单。
|