feat(miniapp): align UI with H5 and harden device debugging

五个页面按 h5/css 的 style.css → ui-20261009 → ui-20261012 覆盖顺序逐条重排,
换算规则固定为 calc(N * var(--u)) → 2N rpx,固定 px 的字号保持 px。

- app.acss:换回 H5 设计 token(方角小倒角按钮 10rpx、卡片 14rpx、.chev 折线箭头)
- splash/profile/history:底图与按钮文字图改用 H5 资源,隐私/政策弹窗按 H5 重排
- report:环形分用 conic-gradient、人脸裁切窗口叠加 face_maps、标记点百分比盒、
  侧脸皱纹 pending/unavailable 文案;用 Playwright 抓 H5 94 个选择器几何比对,
  整页高 2438.7 vs 2438.67
- camera:淘宝 <camera> 组件在真机整页崩溃(嵌了微信专有的 <cover-view>),
  改为默认系统相机 + `config.nativeCamera` 开关 + pages/camtest 冒烟页验证组件
- permissions:淘宝用带前缀的 scope.camera(裸名返回 5022 Scope:camera信息不存在),
  先试带前缀再退回裸名,拒绝后不再重复弹窗
- voice:非 HTTPS 资源导致的异常不再冒泡成整页崩溃;app.js 加开发版错误 toast
- 开发版入口:权限诊断(启动页/相机页)、相机组件测试
- 测试 20/20(新增权限与相机能力用例)
This commit is contained in:
xsl
2026-11-01 23:30:38 +08:00
parent f5c416dd9d
commit fed52930cc
33 changed files with 3061 additions and 876 deletions
+68 -65
View File
@@ -1,77 +1,80 @@
<!-- ═════ 05-07 拍照页 ═════
覆盖在 camera 原生组件上的一切必须用 cover-view / cover-image -->
两种形态,由 config.nativeCamera 决定:
① cameraEnabled=true → 真机取景:<camera> 铺满 + 椭圆镂空蒙版 + 快门直接 takePhoto(对齐 H5 #s-cam)
② cameraEnabled=false → 系统相机:静态版面 + 快门调 my.chooseImage
关键:<camera> 不能嵌 <cover-view>(微信专有组件,淘宝上会导致整页崩溃),
所以相机是兄弟节点,覆盖层用普通 view + box-shadow 镂空。 -->
<view class="cam">
<view a:if="{{debugMode && !cameraEnabled}}" class="debug-banner">相机验收 · 免登录 · 照片只在本页处理,不上传</view>
<view a:if="{{debugComplete}}" class="debug-results">
<view class="debug-title">三步拍摄与 JPEG 压缩已完成</view>
<view>请核对实际照片方向是否为正脸、右脸、左脸;本页不判断姿态是否合格。</view>
<view class="debug-result" a:for="{{debugPhotos}}" a:key="key">
<image src="{{item.photo}}" mode="aspectFit" />
<view>{{item.title}} · JPEG {{item.width}}×{{item.height}} · 约{{item.kilobytes}}KB</view>
</view>
<button class="btn-primary" onTap="onDebugRestart">重新验收</button>
<button onTap="onCancel">退出并清空本页照片</button>
<!-- ①真机取景:相机铺满,不加任何子节点 -->
<camera a:if="{{cameraEnabled}}" id="skin-camera" class="cam-device"
device-position="{{devicePosition}}" flash="off"
onError="onCameraError" onStop="onCameraStop" />
<!-- ②系统相机兜底:H5 相机静态态(白底 + 85% 黑蒙版 ≈ #262626) -->
<view class="cam-bg" a:if="{{!cameraEnabled}}" />
<!-- 取景蒙版:H5 用 SVG 镂空;这里用带巨大 box-shadow 的椭圆开窗,视觉等效 -->
<view class="cam-mask">
<view class="cam-hole mask-{{maskStep}}" />
</view>
<view a:if="{{!cameraEnabled && !debugComplete}}" class="camera-permission">
<view>{{stepText}} · {{stepTip}}</view>
<view>{{permissionMessage}}</view>
<button class="btn-primary" onTap="onEnableCamera">开启相机</button>
<button onTap="onOpenSettings">授权设置</button>
<button onTap="onSystemCamera">使用系统相机</button>
<button onTap="onAlbum">从相册选择</button>
<view a:if="{{previewUrl}}">
<image src="{{previewUrl}}" mode="aspectFit" style="width:100%;height:400rpx;" />
<button onTap="onRetake">重新选择</button><button class="btn-primary" onTap="onConfirm">使用照片</button>
</view>
<view a:if="{{analyzing}}">{{debugMode ? '正在验证本地图片压缩…' : '正在生成您的肌肤报告…'}}</view>
<view class="cam-step">
<view class="cam-step-no">{{stepText}}</view>
<view class="cam-step-tip">{{stepTip}}</view>
</view>
<camera a:if="{{cameraEnabled}}" id="skin-camera" class="cam-device" device-position="{{devicePosition}}"
flash="off" onError="onCameraError" onStop="onCameraStop">
<!-- 顶部步骤文案 -->
<cover-view class="cam-step">
<cover-view a:if="{{debugMode}}">开发调试 · 不上传照片</cover-view>
<cover-view class="cam-step-no">{{stepText}}</cover-view>
<cover-view class="cam-step-tip">{{stepTip}}</cover-view>
</cover-view>
<!-- 取景蒙版:人脸轮廓(骨架版用椭圆线框,朝向提示随步切换;精确轮廓 TODO:换 cover-image 轮廓图) -->
<cover-view class="cam-mask">
<cover-view class="cam-oval mask-{{maskStep}}"></cover-view>
</cover-view>
<view class="cam-guide">
<block a:for="{{guides}}" a:key="*this">
<view a:if="{{index > 0}}" class="cam-guide-sep" />
<text class="cam-guide-item">{{item}}</text>
</block>
</view>
<!-- 底部引导要点 -->
<cover-view class="cam-guide">
<cover-view class="cam-guide-item" a:for="{{guides}}" a:key="*this">{{item}}</cover-view>
</cover-view>
<!-- 拍后预览:确认使用 / 重拍 -->
<view class="cam-preview" a:if="{{previewUrl}}" catchTap="noop">
<image class="cam-preview-img" src="{{previewUrl}}" mode="aspectFit" />
<view class="cam-preview-btns">
<view class="cam-preview-btn" onTap="onRetake">重拍</view>
<view class="cam-preview-btn ok" onTap="onConfirm">使用照片</view>
</view>
</view>
<!-- 控制条:相册 / 快门 / 翻转 -->
<cover-view class="cam-controls">
<cover-view class="cam-side" onTap="onAlbum">相册</cover-view>
<cover-view class="cam-shutter" onTap="onShutter">
<cover-view class="cam-shutter-dot"></cover-view>
</cover-view>
<cover-view class="cam-side" onTap="onFlip">翻转</cover-view>
</cover-view>
<!-- 分析中 -->
<view class="cam-analyzing" a:if="{{analyzing}}">
<view class="cam-analyzing-text">{{debugMode ? '正在验证本地图片压缩…' : '正在生成您的肌肤报告…'}}</view>
<view class="cam-cancel" onTap="onCancel">{{debugMode ? '退出验收' : '返回,稍后查看历史报告'}}</view>
</view>
<!-- 本步完成停顿卡 -->
<cover-view class="cam-done" a:if="{{doneTip}}">{{doneTip}}</cover-view>
<!-- 底部控制条:相册 / 快门 / 翻转 -->
<view class="cam-controls" a:if="{{!previewUrl && !analyzing}}">
<view class="cam-side" onTap="onAlbum">相册</view>
<view class="cam-shutter" onTap="onShutter">
<view class="cam-shutter-dot" />
</view>
<view class="cam-side" onTap="{{cameraEnabled ? 'onFlip' : 'onOpenSettings'}}">{{cameraEnabled ? '翻转' : '授权设置'}}</view>
</view>
<!-- 拍后预览:确认使用 / 重拍 -->
<cover-view class="cam-preview" a:if="{{previewUrl}}" catchTap="noop">
<cover-image class="cam-preview-img" src="{{previewUrl}}"></cover-image>
<cover-view class="cam-preview-btns">
<cover-view class="cam-preview-btn" onTap="onRetake">重拍</cover-view>
<cover-view class="cam-preview-btn ok" onTap="onConfirm">使用照片</cover-view>
</cover-view>
</cover-view>
<!-- 提示/错误文案 -->
<view class="cam-hint" a:if="{{permissionMessage && !previewUrl && !analyzing}}">{{permissionMessage}}</view>
<!-- 分析中 -->
<cover-view class="cam-analyzing" a:if="{{analyzing}}">
<cover-view class="cam-analyzing-text">{{debugMode ? '正在验证本地图片压缩…' : '正在生成您的肌肤报告…'}}</cover-view>
<cover-view class="cam-cancel" onTap="onCancel">{{debugMode ? '退出验收' : '返回,稍后查看历史报告'}}</cover-view>
</cover-view>
</camera>
<!-- 开发版:权限诊断 -->
<view class="cam-diag-entry" a:if="{{showDiagnose}}" onTap="onDiagnose">权限诊断</view>
<view class="cam-diag" a:if="{{diagText}}" catchTap="noop">
<scroll-view class="cam-diag-scroll" scroll-y>
<text class="cam-diag-text">{{diagText}}</text>
</scroll-view>
<view class="cam-diag-close" onTap="onCloseDiagnose">关闭</view>
</view>
<!-- 压缩降级用的隐藏画布(canvas 重绘压缩,不可见) -->
<canvas id="compress-canvas" class="compress-canvas" width="{{compressWidth}}" height="{{compressHeight}}" style="width:{{compressWidth}}px;height:{{compressHeight}}px;" />
<!-- 调试模式结果页 -->
<view class="cam-debug" a:if="{{debugComplete}}">
<view class="cam-debug-title">三步拍摄与 JPEG 压缩已完成</view>
<view class="cam-debug-note">请核对实际照片方向是否为正脸、右脸、左脸;本页不判断姿态是否合格。</view>
<view class="cam-debug-item" a:for="{{debugPhotos}}" a:key="key">
<image class="cam-debug-img" src="{{item.photo}}" mode="aspectFit" />
<view class="cam-debug-meta">{{item.title}} · JPEG {{item.width}}×{{item.height}} · 约{{item.kilobytes}}KB</view>
</view>
<button class="btn-primary cam-debug-btn" onTap="onDebugRestart">重新验收</button>
<view class="cam-debug-exit" onTap="onCancel">退出并清空本页照片</view>
</view>
</view>