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:
+405
-96
@@ -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; }
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 () {} // 弹窗卡片内点击拦截冒泡用
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user