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
+405 -96
View File
@@ -1,145 +1,454 @@
/* ═════ 启动页样式 ═════ */
/* ═════ 01 启动页 —— 逐条对照 H5:
style.css #s-splash(L83-102) .splash-bg .splash-slogan .splash-bottom .brand-row .btn-primary
ui-20261009.css L8,L20-30,L88,L100-105
ui-20261012.css L4,L9-30 .splash-slogan / .splash-slogan-copy / .splash-bottom / .brand-lockup
换算:calc(N * var(--u)) → 2N rpx;固定 px 的字号/行高/圆角保持不变。 ═════ */
page { background: #101823; }
/* H5 .screen(#s-splash: position:absolute; inset:0; overflow-y:auto) */
.splash {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
background: #101823;
}
/* ─── H5 .splash-bg ─── */
.splash-bg {
position: absolute;
left: 0; top: 0;
inset: 0;
width: 100%;
height: 100%;
}
.splash-slogan {
position: absolute;
top: 200rpx;
left: 0;
right: 0;
text-align: center;
color: #FFFFFF;
}
.splash-slogan text {
display: block;
font-size: 44rpx;
font-weight: 600;
line-height: 1.6;
}
.splash-bottom {
position: absolute;
left: 0; right: 0; bottom: 0;
padding: 0 64rpx 96rpx;
/* ─── H5 .account-status(.account-status-home) ─── */
.account-status {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 14px;
border-radius: 8px;
font-size: 12px;
box-sizing: border-box;
}
.account-status-home {
position: absolute;
top: max(10px, env(safe-area-inset-top));
right: 12px;
z-index: 2;
background: rgba(0, 0, 0, .533);
color: #fff;
}
/* H5 .account-status span::before */
.account-label { display: flex; align-items: center; }
.account-dot {
display: inline-block;
width: 7px;
height: 7px;
margin-right: 7px;
border-radius: 50%;
background: #b7bac0;
}
.account-status-on .account-dot { background: #34ca7b; }
.account-text { white-space: nowrap; }
/* H5 .account-logout(ui-20261012 L4) */
.account-logout {
font-size: 11px;
opacity: .8;
white-space: nowrap;
}
/* ─── H5 .splash-slogan.splash-slogan-updated(ui-20261012 L9-20) ─── */
.splash-slogan {
position: absolute;
left: calc(50% - 1.041667px);
top: max(6.838833%, calc(env(safe-area-inset-top) + 48px));
width: 249.305556px;
height: 75.347222px;
transform: translateX(-50%);
text-align: center;
color: #fff;
font-size: 23px;
font-weight: 400;
line-height: 1.16;
letter-spacing: 0;
text-shadow: none;
}
/* H5 .splash-slogan-updated .splash-slogan-copy{width:100%;height:100%;clip-path:inset(68% 0 0)}
→ 等价实现:只露出底部 32%(24.111111px),image 整体上移 68%(51.236111px) */
.splash-slogan-copy-clip {
position: absolute;
left: 0;
right: 0;
top: 51.236111px;
height: 24.111111px;
overflow: hidden;
}
.splash-slogan-copy {
position: absolute;
left: 0;
top: -51.236111px;
width: 100%;
height: 75.347222px;
}
.splash-slogan-brand,
.splash-slogan-english {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-family: Arial, sans-serif;
font-size: 23px;
font-weight: 400;
line-height: 1;
white-space: nowrap;
color: #fff;
}
.splash-slogan-brand { top: -4px; font-size: 28px; }
.splash-slogan-english { top: 26.736111px; }
/* ─── H5 .splash-bottom(ui-20261012 L25) ─── */
.splash-bottom {
position: absolute;
left: 0;
right: 0;
bottom: max(5.882353%, env(safe-area-inset-bottom));
display: flex;
flex-direction: column;
align-items: center;
gap: 14.583334rpx; /* calc(7.291667 * var(--u)) */
padding-bottom: 0;
}
/* H5 .brand-row(ui-20261012 L26) */
.brand-row {
display: flex;
align-items: center;
margin-bottom: 32rpx;
gap: 0;
margin-bottom: 20.833334rpx; /* calc(10.416667 * var(--u)) */
}
.brand-logo {
height: 48rpx;
margin-right: 16rpx;
}
.brand-text {
color: #FFFFFF;
font-size: 32rpx;
font-weight: 600;
.brand-lockup {
width: 179.513889px;
height: 20.486111px;
}
/* ─── 隐私授权弹窗 ─── */
.privacy-row {
/* ─── H5 #s-splash .btn-primary(ui-20261012 L28) ─── */
.splash .btn-primary {
display: flex;
align-items: center;
margin-bottom: 32rpx;
}
.checkbox {
width: 36rpx;
height: 36rpx;
border: 2rpx solid #E5E5E5;
border-radius: 50%;
margin-right: 16rpx;
box-sizing: border-box;
position: relative;
}
.checkbox.checked {
justify-content: center;
width: 362.5rpx; /* calc(181.25 * var(--u)) */
height: 77.777778rpx; /* calc(38.888889 * var(--u)) */
line-height: 77.777778rpx;
border-radius: 13.888888rpx; /* calc(6.944444 * var(--u)) */
background: #F5F078;
border-color: #F5F078;
}
.checkbox.checked::after {
content: '';
position: absolute;
left: 10rpx;
top: 6rpx;
width: 8rpx;
height: 14rpx;
border-right: 4rpx solid #282828;
border-bottom: 4rpx solid #282828;
transform: rotate(45deg);
}
.privacy-text {
font-size: 26rpx;
color: #4A4A4A;
}
.privacy-link {
color: #282828;
font-size: 14.5px;
font-weight: 500;
letter-spacing: 1rpx;
padding: 0;
border: none;
box-sizing: border-box;
transition: transform .12s ease;
}
.splash .btn-primary::after { border: none; }
.btn-press { transform: scale(.96); }
/* H5 .btn-history{background:#fff} */
.splash .btn-history { background: #fff; }
/* H5 .splash-button-label(ui-20261012 L29-30) */
.splash-button-label {
width: 55.902778px;
height: 13.888889px;
}
.splash .btn-history .splash-button-label,
.splash-button-label.btn-history-label {
width: 56.597222px;
height: 13.541667px;
}
.btn-busy { opacity: .6; }
/* ─── 弹层基类(H5 .overlay) ─── */
.splash .overlay {
position: fixed;
inset: 0;
z-index: 50;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, .5);
}
/* ═══ 隐私授权弹窗 H5 #p-privacy ═══ */
/* H5 #p-privacy{background:linear-gradient(#0008,#0008),url(bg-splash-h5) center/cover} */
.overlay-bg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.overlay-dim {
position: absolute;
inset: 0;
z-index: 1;
background: rgba(0, 0, 0, .533);
}
/* H5 #p-privacy .popup(ui-20261012 L34-38) */
.splash .popup {
position: relative;
z-index: 2;
width: 307.986111px;
height: 313.194444px;
min-height: 313.194444px;
top: -42.881944px;
padding: 0;
background: #fff;
border-radius: 8.680556px;
display: flex;
flex-direction: column;
text-align: left;
box-sizing: border-box;
text-rendering: geometricPrecision;
}
/* H5 .popup-close / #p-privacy .popup-close(L65-66) */
.splash .popup-close {
position: absolute;
top: 10.055556px;
right: 10.055556px;
width: 32px;
height: 32px;
margin: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
box-sizing: border-box;
}
.splash .popup-close::after { border: none; }
.popup-close-img {
width: 17.708333px;
height: 17.361111px;
}
/* H5 .popup-title(L39-44) */
.splash .popup-title {
position: absolute;
left: 31.944444px;
top: 35px;
margin: 0;
font-size: 23.148148px;
line-height: 28.935185px;
font-weight: 700;
letter-spacing: 0;
color: #282828;
white-space: nowrap;
text-align: left; /* 覆盖 app.acss .popup-title{text-align:center} */
}
/* H5 .popup-body(L45-49) */
.splash .popup-body {
position: absolute;
left: 31.944444px;
top: 109.027778px;
width: 243.75px;
margin: 0;
font-size: 11.574074px;
line-height: 17.361111px;
font-weight: 400;
letter-spacing: 0;
color: #282828;
}
/* H5 .privacy-row / .checkbox / .privacy-text / .privacy-link(L53-56) */
.splash .privacy-row {
position: absolute;
left: 29.861111px;
top: 184.375px;
display: flex;
align-items: center;
gap: 10.069444px;
}
.splash .checkbox {
width: 11.805556px;
height: 12.152778px;
border-radius: 50%;
border: 1px solid #282828;
background: #fff;
flex-shrink: 0;
position: relative;
box-sizing: border-box;
}
.splash .checkbox.checked::after {
content: "";
position: absolute;
inset: 2px;
border-radius: 50%;
background: #2C2C2C;
}
.splash .privacy-text {
font-size: 10.127315px;
line-height: 18.807870px;
color: #757575;
white-space: nowrap;
}
.splash .privacy-link {
color: #282828;
font-weight: 700;
text-decoration: underline;
}
.popup-btn { width: 100%; }
/* H5 #p-privacy .popup-btn(L57-63) —— 必须排在 .btn-primary 之后才能覆盖宽高 */
.splash .popup-btn {
position: absolute;
left: 63.194444px;
top: 239.930556px;
margin: 0;
width: 181.25px;
height: 38.888889px;
line-height: 38.888889px;
font-size: 14.467593px;
font-weight: 700;
letter-spacing: 0;
border-radius: 6.944444px;
}
@media (max-height: 440px) {
.splash .popup { top: 0; }
}
/* ─── 隐私协议全文弹层 ─── */
.overlay-policy { padding: 0; }
/* ═══ 隐私政策全文 H5 #p-policy ═══ */
.splash .overlay-policy { background: #F5F5F5; z-index: 60; }
.policy-page {
position: relative;
width: 100%;
height: 100%;
background: #FFFFFF;
display: flex;
flex-direction: column;
background: #fff;
}
.policy-back {
/* H5 .policy-float-back + .nav-back */
.splash .policy-float-back {
position: absolute;
top: 24rpx;
left: 24rpx;
top: 12px;
left: 12px;
z-index: 2;
width: 64rpx;
height: 64rpx;
line-height: 56rpx;
font-size: 56rpx;
color: #282828;
background: none;
width: 27px;
height: 27px;
margin: 0;
padding: 0;
}
.policy-back::after { border: none; }
.policy-scroll {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border: 1px solid #E5E5E5;
border-radius: 50%;
box-shadow: 0 1px 6px rgba(0, 0, 0, .12);
box-sizing: border-box;
padding: 96rpx 40rpx 64rpx;
}
.splash .policy-float-back::after { border: none; }
/* H5 .policy-body + #p-policy .policy-body{padding-top:52px} */
.policy-body {
flex: 1;
min-height: 0;
box-sizing: border-box;
padding: 52px 20px 48px;
background: #fff;
}
.policy-title {
font-size: 36rpx;
font-size: 19px;
font-weight: 700;
margin-bottom: 40rpx;
color: #282828;
line-height: 1.4;
margin-bottom: 16px;
}
.policy-h2 {
font-size: 30rpx;
font-size: 15px;
font-weight: 600;
margin: 40rpx 0 16rpx;
color: #282828;
margin: 26px 0 10px;
padding-left: 9px;
border-left: 4px solid #F5F078;
line-height: 1.3;
}
.policy-p {
font-size: 26rpx;
font-size: 12.5px;
color: #4A4A4A;
line-height: 1.8;
margin-bottom: 16rpx;
line-height: 1.9;
margin-bottom: 10px;
text-align: justify;
}
.policy-end {
text-align: center;
font-size: 12.5px;
color: #868686;
font-size: 24rpx;
margin: 48rpx 0;
line-height: 1.9;
text-align: center;
margin: 28px 0 10px;
}
/* ─── H5 .toast ─── */
.toast {
position: fixed;
left: 50%;
bottom: 15%;
transform: translateX(-50%) translateY(8px);
max-width: 86%;
background: rgba(20, 20, 20, .85);
color: #fff;
font-size: 13px;
line-height: 1.5;
text-align: center;
padding: 9px 18px;
border-radius: 18px;
opacity: 0;
pointer-events: none;
transition: all .25s ease;
z-index: 99;
box-sizing: border-box;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* ═══ 开发版入口(H5 无;保持低调) ═══ */
.dev-entries {
position: absolute;
z-index: 3;
top: max(10px, env(safe-area-inset-top));
left: 12px;
display: flex;
flex-direction: column;
gap: 6px;
}
.dev-entry {
font-size: 10px;
line-height: 1.5;
color: rgba(255, 255, 255, .42);
}
.diag-panel {
position: absolute;
z-index: 20;
left: 32rpx;
right: 32rpx;
top: 240rpx;
bottom: 160rpx;
background: rgba(6, 16, 26, .96);
border: 1rpx solid rgba(120, 200, 255, .35);
border-radius: 20rpx;
padding: 20rpx;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.diag-scroll { flex: 1; min-height: 0; }
.diag-text {
color: #9fd0ff;
font-size: 22rpx;
line-height: 1.7;
white-space: pre-wrap;
word-break: break-all;
}
.diag-close {
margin-top: 16rpx;
text-align: center;
color: #0b1622;
background: #ffd94d;
border-radius: 12rpx;
padding: 16rpx 0;
font-size: 26rpx;
}
.account-links { display: flex; justify-content: center; gap: 40rpx; color: #fff; margin-top: 24rpx; font-size: 24rpx; }
.splash-slogan { top: 10.7%; }
.splash-slogan text { font-size: 44rpx; line-height: 1.4; }
.brand-row { justify-content: center; }
.brand-logo { width: 450rpx; height: 52rpx; margin: 0; }
.camera-debug-entry { position: absolute; z-index: 2; top: 24rpx; right: 24rpx; padding: 16rpx 24rpx; border-radius: 16rpx; color: #fff; background: rgba(0,0,0,.65); font-size: 24rpx; }
.mvp-debug-entry { top: 100rpx; }
+66 -28
View File
@@ -1,49 +1,84 @@
<!-- ═════ 01 启动页 ═════ -->
<!-- ═════ 01 启动页 —— 对照 H5 index.html #s-splash(L43-58) + #p-privacy(L294-307) + #p-policy(L335-466) ═════ -->
<view class="splash">
<view class="camera-debug-entry" a:if="{{showCameraDebug}}" onTap="onCameraDebug">开发调试 · 相机验收</view>
<view class="camera-debug-entry mvp-debug-entry" a:if="{{showMvpDebug}}" onTap="onMvpDebug">SAE MVP 连通性</view>
<image class="splash-bg" src="{{bgUrl}}" mode="aspectFill" />
<view class="splash-slogan">
<text>1'me,</text>
<text>FROM THE INSIDE OUT</text>
<text>以我为始 自有表现</text>
<!-- 开发版入口(H5 无此入口,保持现有实现,样式低调) -->
<view class="dev-entries" a:if="{{showCameraDebug || showMvpDebug || showDiagnose}}">
<view class="dev-entry" a:if="{{showCameraDebug}}" onTap="onCameraDebug">开发调试 · 相机验收</view>
<view class="dev-entry" a:if="{{showMvpDebug}}" onTap="onMvpDebug">SAE MVP 连通性</view>
<view class="dev-entry" a:if="{{showDiagnose}}" onTap="onDiagnose">权限诊断</view>
<view class="dev-entry" a:if="{{showDiagnose}}" onTap="onCamTest">相机组件测试</view>
</view>
<!-- 诊断结果浮层:真机上唯一能看到相机能力/授权返回值的地方 -->
<view class="diag-panel" a:if="{{diagText}}">
<scroll-view class="diag-scroll" scroll-y>
<text class="diag-text">{{diagText}}</text>
</scroll-view>
<view class="diag-close" onTap="onCloseDiagnose">关闭</view>
</view>
<!-- H5 .splash-bg -->
<image class="splash-bg" src="{{bgUrl}}" mode="aspectFill" />
<!-- H5 .account-status.account-status-home -->
<view class="account-status account-status-home {{signedIn ? 'account-status-on' : ''}}">
<view class="account-label">
<view class="account-dot"></view>
<text class="account-text">{{accountLabel}}</text>
</view>
<view class="account-logout" a:if="{{signedIn}}" onTap="onLogout">退出登录</view>
</view>
<!-- H5 .splash-slogan.splash-slogan-updated
.splash-slogan-copy 原为 object-fit + clip-path:inset(68% 0 0) 只露底部 32%(中文那行),
acss 里改成等价的 overflow 裁切容器 + 上移 68% 的 image,像素结果一致 -->
<view class="splash-slogan">
<view class="splash-slogan-copy-clip">
<image class="splash-slogan-copy" src="{{sloganUrl}}" mode="scaleToFill" />
</view>
<view class="splash-slogan-brand">1'me,</view>
<view class="splash-slogan-english">FROM THE INSIDE OUT</view>
</view>
<!-- H5 .splash-bottom:brand-lockup + 开始检测 + 我的报告 -->
<view class="splash-bottom">
<view class="brand-row">
<image src="{{logoUrl}}" class="brand-logo" mode="heightFix" />
</view>
<button class="btn-primary splash-btn" onTap="onOpenPrivacy">开始检测</button>
<view a:if="{{signedIn}}" class="account-links">
<text onTap="onHistory">历史报告</text><text onTap="onLogout">退出登录</text>
<image class="brand-lockup" src="{{logoUrl}}" mode="aspectFit" />
</view>
<button class="btn-primary" hover-class="btn-press" onTap="onOpenPrivacy">
<image class="splash-button-label" src="{{startLabelUrl}}" mode="aspectFit" />
</button>
<button class="btn-primary btn-history" hover-class="btn-press" onTap="onHistory">
<image class="splash-button-label btn-history-label" src="{{historyLabelUrl}}" mode="aspectFit" />
</button>
</view>
<!-- ═══ 弹窗:隐私授权 ═══ -->
<view class="overlay" a:if="{{showPrivacy}}" onTap="onClosePrivacy">
<view class="popup" catchTap="noop">
<button class="popup-close" onTap="onClosePrivacy">✕</button>
<!-- ═══ 弹窗:隐私授权(H5 #p-privacy) ═══ -->
<view class="overlay overlay-privacy" a:if="{{showPrivacy}}" onTap="onClosePrivacy">
<image class="overlay-bg" src="{{bgUrl}}" mode="aspectFill" />
<view class="overlay-dim"></view>
<view class="popup privacy-popup" catchTap="noop">
<button class="popup-close" onTap="onClosePrivacy">
<image class="popup-close-img" src="{{closeIconUrl}}" mode="aspectFit" />
</button>
<view class="popup-title">
<text>欢迎体验1'me</text>
<text>肌肤状态评估服务!</text>
<view>欢迎体验1'me</view>
<view>肌肤状态评估服务!</view>
</view>
<view class="popup-body">授权淘宝账号后,我们将采集您的面部影像和基础档案,用于生成肌肤分析报告,并在服务器保存检测记录及照片,供您查看最近5份报告。照片将交由 Face⁺⁺ 提供检测分析。</view>
<view class="popup-body">我们将采集您的面部影像,为您生成专属肌肤分析与状态管理方案。所有数据严格保密,仅用于本次检测分析。</view>
<view class="privacy-row" onTap="onToggleAgree">
<view class="checkbox {{agreed ? 'checked' : ''}}"></view>
<view class="privacy-text">
我已阅读并同意
<text class="privacy-link" catchTap="onOpenPolicy">相关隐私协议</text>
</view>
<view class="privacy-text">我已阅读并同意相关<text class="privacy-link" catchTap="onOpenPolicy">隐私协议</text></view>
</view>
<button class="btn-primary popup-btn" loading="{{busy}}" disabled="{{busy}}" onTap="onAgreeContinue">授权登录并继续</button>
<button class="btn-primary popup-btn {{busy ? 'btn-busy' : ''}}" hover-class="btn-press" onTap="onAgreeContinue">继续</button>
</view>
</view>
<!-- ═══ 弹层:隐私政策全文(Face++ 个人信息与隐私保护政策,与 H5 同文) ═══ -->
<!-- ═══ 弹层:隐私政策全文(H5 #p-policy) ═══ -->
<view class="overlay overlay-policy" a:if="{{showPolicy}}">
<view class="policy-page">
<button class="policy-back" onTap="onClosePolicy">‹</button>
<scroll-view scroll-y class="policy-scroll">
<button class="nav-back policy-float-back" onTap="onClosePolicy">
<view class="chev left"></view>
</button>
<scroll-view scroll-y class="policy-body">
<view class="policy-title">Face⁺⁺个人信息与隐私保护政策</view>
<view class="policy-h2">前言</view>
@@ -80,4 +115,7 @@
</scroll-view>
</view>
</view>
<!-- H5 .toast -->
<view class="toast {{toastOn ? 'show' : ''}}">{{toastText}}</view>
</view>
+57 -14
View File
@@ -1,23 +1,51 @@
/* ═════ 启动页:品牌底图 + Slogan + 隐私授权弹窗(对齐 H5 #s-splash + #p-privacy) ═════ */
/* ═════ 启动页:品牌底图 + Slogan + 开始检测/我的报告 + 隐私授权弹窗
对照 H5 index.html #s-splash(L43-58)、#p-privacy(L294-307)、#p-policy(L335-466)
交互保持:登录(必须勾选协议)、restore、历史入口、退出登录、政策全文、开发版入口。 ═════ */
var api = require('../../utils/api.js');
var development = require('../../utils/development');
var config = require('../../config');
Page({
data: {
bgUrl: api.assetUrl('img/bg-splash.jpg'), // 底图远程加载
// 图片全部走 api.assetUrl(与 H5 h5/assets/ 同相对路径)
bgUrl: api.assetUrl('img/ui-20261009/bg-splash-h5.jpg'),
logoUrl: api.assetUrl('img/ui-20261012/brand-lockup.png'),
sloganUrl: api.assetUrl('img/ui-20261012/splash-slogan.png'),
startLabelUrl: api.assetUrl('img/ui-20261012/button-start-label.png'),
historyLabelUrl: api.assetUrl('img/ui-20261012/button-history-label.png'),
closeIconUrl: api.assetUrl('img/ui-20261009/icon-close.png'),
showPrivacy: false, // 隐私授权弹窗
agreed: false, // 隐私协议勾选
showPolicy: false, busy: false, signedIn: false, showCameraDebug: development.cameraDebugEnabled(),
showMvpDebug: config.mvpLocal === true
showPolicy: false,
busy: false,
signedIn: false,
accountLabel: '尚未登录', // H5 renderAccountStatus()
toastText: '', toastOn: false,
showCameraDebug: development.cameraDebugEnabled(),
showMvpDebug: config.mvpLocal === true || (config.transport === 'cloud' && config.environment !== 'production'),
showDiagnose: config.environment !== 'production',
diagText: ''
},
onShow: function () {
var that = this;
api.restore().then(function (user) { that.setData({ signedIn: !!user }); }).catch(function () {});
api.restore().then(function (user) { that.setData({ signedIn: !!user, accountLabel: user ? '淘宝已登录' : '尚未登录' }); })
.catch(function () {});
},
// 「开始检测」→ 隐私授权弹窗
// H5 .toast(自定义轻提示,替代系统 toast 以获得一致的视觉)
toast: function (msg) {
var that = this;
this.setData({ toastText: msg, toastOn: true });
clearTimeout(this.toastTimer);
this.toastTimer = setTimeout(function () {
that.setData({ toastOn: false });
}, Math.max(1800, String(msg).length * 130));
},
// 「开始检测」→ 隐私授权弹窗(H5 data-action="open-privacy")
onOpenPrivacy: function () {
if (api.user()) { my.navigateTo({ url: '/pages/profile/profile' }); return; }
this.setData({ showPrivacy: true });
@@ -26,7 +54,7 @@ Page({
this.setData({ showPrivacy: false });
},
// 勾选/取消隐私协议(点链接不触发,由 catchtap 分隔)
// 勾选/取消隐私协议(点链接不触发,由 catchTap 分隔)
onToggleAgree: function () {
this.setData({ agreed: !this.data.agreed });
},
@@ -40,37 +68,52 @@ Page({
// 「继续」:必须已勾选协议
onAgreeContinue: function () {
var that = this;
if (this.data.busy) return;
if (!this.data.agreed) {
my.showToast({ content: '请先阅读并同意隐私协议', type: 'none' });
this.toast('请先阅读并同意隐私协议');
return;
}
var that = this;
this.setData({ busy: true });
api.login(true).then(function () {
that.setData({ showPrivacy: false, signedIn: true });
that.setData({ showPrivacy: false, signedIn: true, accountLabel: '淘宝已登录' });
my.navigateTo({ url: '/pages/profile/profile' });
}).catch(function (err) {
my.showToast({ content: err.message, type: 'none' });
that.toast(err.message);
}).then(function () { that.setData({ busy: false }); });
},
// H5 data-action="history" / 「我的报告」
onHistory: function () {
if (!api.user()) { this.onOpenPrivacy(); return; }
my.navigateTo({ url: '/pages/history/history' });
},
onLogout: function () {
var that = this;
api.logout().then(function () { that.setData({ signedIn: false, agreed: false }); })
.catch(function (err) { my.showToast({ content: err.message, type: 'none' }); });
api.logout().then(function () {
that.setData({ signedIn: false, agreed: false, accountLabel: '尚未登录' });
}).catch(function (err) { that.toast(err.message); });
},
onCameraDebug: function () {
if (!development.cameraDebugEnabled()) return;
my.navigateTo({ url: '/pages/camera/camera?debug=camera' });
},
onMvpDebug: function () {
if (!config.mvpLocal) return;
if (!config.mvpLocal && !(config.transport === 'cloud' && config.environment !== 'production')) return;
my.navigateTo({ url: '/pages/mvp/mvp' });
},
// 相机/相册权限诊断:相机页可能整页崩掉,所以在启动页也能点
onDiagnose: function () {
var that = this;
this.setData({ diagText: '检测中…' });
require('../../utils/permissions').diagnose().then(function (info) {
that.setData({ diagText: info.join('\n') });
}).catch(function (err) {
that.setData({ diagText: 'diagnose error: ' + (err && err.message ? err.message : String(err)) });
});
},
onCloseDiagnose: function () { this.setData({ diagText: '' }); },
// 相机组件冒烟测试:单独一页只放 <camera>,用来判断淘宝真机是否支持该组件
onCamTest: function () { my.navigateTo({ url: '/pages/camtest/camtest' }); },
noop: function () {} // 弹窗卡片内点击拦截冒泡用
});