189 lines
12 KiB
XML
189 lines
12 KiB
XML
<import src="../../components/brand-header.axml" />
|
||
<template is="brand-header" data="{{brandHeader: brandHeader}}" />
|
||
<!-- ═════ 08 报告页 —— 对照 H5 index.html #s-report L174-291 ═════
|
||
结构逐块对应:.report-title → .card.card-summary(环形评分 + 生物可视年龄 + 三维度)
|
||
→ 三组 .dimension-title + .card.card-detail(紧塑力 2 视图 / 透亮感 3 视图 / 稳韧力 2 视图)
|
||
→ .prod-title → .card.report-care-products(日常护理 + 推荐产品)→ .report-disclaimer。
|
||
样式见 report.acss;数据仍由 utils/report-model.js 的 model()/layers()/marks() 产出。 -->
|
||
<view class="report" style="padding-top:{{brandHeader.height}}px;">
|
||
<view class="session-guard" a:if="{{identityChecking || identityError}}">
|
||
<view>{{identityChecking ? '正在确认当前淘宝账号…' : identityError}}</view>
|
||
<button a:if="{{identityError}}" class="btn-primary" onTap="onRetryIdentity">重新验证</button>
|
||
</view>
|
||
<!-- H5 #s-report: background:#efefef url(bg-report-h5.webp) center top/100% auto。
|
||
该 webp 为 1080×7512 的纯 #EFEFEF 单色图(全图仅一种颜色 239,239,239),
|
||
与 app.acss 里 page 的底色完全等价;acss 侧不再引 32MB 解码量的空图,
|
||
直接用 page 底色(否则 <image> 还会把页面滚动高度撑到 2608px)。 -->
|
||
|
||
<view class="report-body" hidden="{{identityChecking || identityError}}">
|
||
<!-- H5 h1.report-title -->
|
||
<view class="report-title">您的肌肤状态表现</view>
|
||
|
||
<!-- H5 .card.card-summary -->
|
||
<view class="card card-summary">
|
||
<view class="sum-score">
|
||
<view class="score-dial">
|
||
<!-- H5 <svg class="ring"><circle class="ring-bg">+<circle class="ring-fg">:
|
||
环轨道 + conic-gradient 进度弧 + 圆头补点(acss 无 svg,几何等价) -->
|
||
<view class="ring-track"></view>
|
||
<view class="ring-arc" style="background-image: conic-gradient(#F5F078 0deg {{ringDeg}}deg, rgba(0,0,0,0) {{ringDeg}}deg);"></view>
|
||
<view class="ring-cap" a:if="{{ringCap}}" style="left:108rpx;top:14.4rpx;"></view>
|
||
<view class="ring-cap" a:if="{{ringCap}}" style="{{ringCapEnd}}"></view>
|
||
<view class="ring-hole"></view>
|
||
<view class="ring-center">
|
||
<view class="stat-value"><text class="stat-b">{{total != null ? total : '--'}}</text><text class="stat-i">分</text></view>
|
||
<view class="stat-label">综合评分</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="sum-age">
|
||
<!-- H5 .sum-age > .stat-label -->
|
||
<view class="stat-label">生物可视年龄</view>
|
||
<view class="age-dial">
|
||
<view class="stat-value stat-age"><text class="stat-b">{{skinAge != null ? skinAge : '--'}}</text><text class="stat-i">岁</text></view>
|
||
</view>
|
||
<!-- H5 ui-20261009.css 把 .age-pill 置为 display:none !important(新版设计不再展示对比胶囊);
|
||
report-model 仍产出 ageNote,这里与 H5 一样保留数据但不展示 -->
|
||
<view class="age-pill" a:if="{{ageNote}}">{{ageNote}}</view>
|
||
</view>
|
||
|
||
<!-- H5 .card-dims:grid-column 1/-1,占满总分卡整行 -->
|
||
<view class="card-dims">
|
||
<view class="dims-row">
|
||
<view class="dim {{item.rank}}" a:for="{{dims}}" a:key="key">
|
||
<view class="dim-name">{{item.name}}</view>
|
||
<view class="dim-score {{item.rank === 'worst' ? 'dim-bad' : ''}}"><text class="dim-int">{{item.int}}</text><text class="dim-dec">.{{item.dec ? item.dec : '-'}}</text></view>
|
||
<view class="dim-bar"><view class="dim-fill" style="width:{{item.barWidth}}%;"></view></view>
|
||
<!-- H5 用 visibility 占位,非最低分维度也保留 12px 高度 -->
|
||
<view class="dim-flag">优先关注</view>
|
||
</view>
|
||
</view>
|
||
<!-- H5 #dims-note(ui-20261012 恢复了这块「近期优先关注」) -->
|
||
<view class="dims-note" a:if="{{focusName}}">
|
||
<view class="dims-note-l1">近期优先关注:<text class="dims-focus">{{focusName}}</text></view>
|
||
<view class="dims-note-l2">{{focusSlogan}}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- H5 三组 <h2 class="dimension-title"> + <div class="card card-detail"> -->
|
||
<block a:for="{{cards}}" a:for-item="card" a:for-index="ci" a:key="key">
|
||
<view class="dimension-title {{card.titleCls}}">{{card.title}}</view>
|
||
<view class="card card-detail {{card.cardCls}}">
|
||
<!-- H5 .detail-tabs > button.dtab > span.dtab-tx -->
|
||
<view class="detail-tabs">
|
||
<view class="dtab {{card.index === vi ? 'active' : ''}}" a:for="{{card.views}}" a:for-item="tab" a:for-index="vi" a:key="key"
|
||
data-card="{{card.key}}" data-index="{{vi}}" onTap="onTabTap">
|
||
<text class="dtab-tx">{{tab.name}}</text>
|
||
</view>
|
||
</view>
|
||
<view class="detail-viewport {{card.dragging ? 'dragging' : ''}}" style="{{card.height ? 'height:' + card.height + 'px;' : ''}}">
|
||
<view class="detail-panels {{card.dragging ? 'dragging' : ''}}" style="transform:translateX(-{{card.index * 100}}%) translateX({{card.dragOffset || 0}}px);">
|
||
<block a:for="{{card.views}}" a:for-item="view" a:for-index="vi" a:key="key">
|
||
<!-- Keep all panels mounted for the H5 finger-following track. -->
|
||
<view class="dpanel {{card.index === vi ? 'active' : ''}}" aria-hidden="{{card.index !== vi}}">
|
||
<view class="ditem">
|
||
<view class="viz-frame {{view.frameCls}}" data-card="{{card.key}}" data-view="{{view.key}}"
|
||
onTouchStart="onPanelTouchStart" onTouchMove="onPanelTouchMove" onTouchEnd="onPanelTouchEnd" onTouchCancel="onPanelTouchCancel" onTap="onZoomPhoto">
|
||
<!-- hasVisual=false 时整块画框只留占位文案(H5 renderViz 的降级:轮廓/肤色/平滑度/痘痘
|
||
必须有人脸照片,皱纹/水分/泛红可只挂 face_maps 图层) -->
|
||
<view class="viz-stage" a:if="{{view.hasVisual}}">
|
||
<!-- 照片与 face_maps 图层共用 view.photoStyle(人脸裁切窗口),保证叠加层位置一致 -->
|
||
<image class="viz-photo" a:if="{{frontPhoto}}" src="{{frontPhoto}}" mode="{{view.fit}}" style="{{view.photoStyle}}" onLoad="onPhotoLoad" />
|
||
<view class="viz-dim" a:if="{{view.dark}}"></view>
|
||
<image class="viz-layer {{view.blend ? 'viz-blend' : ''}}" a:for="{{view.layers}}" a:for-item="layer" a:key="*this"
|
||
src="{{layer}}" mode="scaleToFill" style="opacity:{{view.alpha}};{{view.photoStyle}}" />
|
||
<!-- H5 canvas 里按矩形坐标描边的痘/斑标记 -->
|
||
<view class="viz-mark" a:for="{{view.marks}}" a:for-item="mark" a:key="id"
|
||
style="left:{{mark.left}}%;top:{{mark.top}}%;width:{{mark.width}}%;height:{{mark.height}}%;border-color:{{mark.color}};"></view>
|
||
</view>
|
||
<view class="viz-missing" a:if="{{!view.hasVisual}}">本次未获取{{view.name}}检测图</view>
|
||
</view>
|
||
|
||
<!-- H5 .contour-sides(轮廓=原图;皱纹=原图压暗 + 侧脸皱纹图层 / 加载态) -->
|
||
<view class="contour-sides contour-sides-reversed {{view.dim ? 'wrinkle-sides' : ''}}" a:if="{{sidesShown && (view.dim || view.key === 'contour')}}">
|
||
<block a:for="{{sides}}" a:for-item="side" a:key="key">
|
||
<view class="contour-side {{side.key === 'right' ? 'right' : ''}}" a:if="{{side.photo}}"
|
||
data-card="{{card.key}}" data-view="{{view.key}}" data-side="{{side.key}}" onTap="onZoomPhoto">
|
||
<image class="side-img" src="{{side.photo}}" mode="{{side.photoStyle ? 'scaleToFill' : 'aspectFill'}}" style="{{side.photoStyle}}"
|
||
data-side="{{side.key}}" data-photo="{{side.photo}}" onLoad="onSidePhotoLoad" />
|
||
<block a:if="{{view.dim}}">
|
||
<view class="side-dim"></view>
|
||
<image class="side-img" a:if="{{side.layer}}" src="{{side.layer}}" mode="{{side.photoStyle ? 'scaleToFill' : 'aspectFill'}}" style="{{side.photoStyle}}" />
|
||
<view class="side-loading" a:if="{{side.loading}}"><view>皱纹标注</view><view>加载中…</view></view>
|
||
</block>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
<view class="wrinkle-layer-note" a:if="{{view.dim && wrinkleNote}}">{{wrinkleNote}}</view>
|
||
|
||
<!-- H5 .ditem-text > p.ditem-para -->
|
||
<view class="ditem-text">
|
||
<view class="ditem-para" a:if="{{view.text}}">{{view.text}}</view>
|
||
</view>
|
||
<!-- H5 #smooth-map-note(仅平滑度面板) -->
|
||
<view class="viz-caption" a:if="{{view.caption}}">{{view.caption}}</view>
|
||
</view>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</block>
|
||
|
||
<!-- H5 h2.prod-title(两行固定文案) -->
|
||
<view class="prod-title">
|
||
<view>感受高光时刻</view>
|
||
<view>从日常的好状态开始</view>
|
||
</view>
|
||
|
||
<!-- H5 .card.card-care.report-care-products -->
|
||
<view class="card report-care-products">
|
||
<view class="card-heading">日常护理</view>
|
||
<view class="care-list">
|
||
<view class="care-item {{ci === careAdvice.length - 1 ? 'last' : ''}}" a:for="{{careAdvice}}" a:for-item="care" a:for-index="ci" a:key="key">{{ci + 1}}、{{care.text}}</view>
|
||
<view class="care-item last" a:if="{{!careAdvice.length}}">本次有效数据不足,暂无个性化护理建议。</view>
|
||
</view>
|
||
|
||
<view class="product-section-heading">推荐产品</view>
|
||
<view class="care-item product-unavailable" a:if="{{!product}}">本次未获取有效肌龄,暂无法推荐产品,建议重新检测。</view>
|
||
<view class="card-product" a:if="{{product}}" onTap="onMore">
|
||
<view class="prod-card">
|
||
<view class="prod-info">
|
||
<view class="prod-card-title">{{product.title}}</view>
|
||
<view class="prod-name">{{product.name}}</view>
|
||
<image class="prod-badge" src="{{productBadgeUrl}}" mode="widthFix" />
|
||
</view>
|
||
<view class="prod-scroll"><image class="prod-img" src="{{product.image}}" mode="scaleToFill" /></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- H5 p.report-disclaimer(三行固定文案) -->
|
||
<view class="report-disclaimer">
|
||
<view class="report-disclaimer-line">*您的肌肤状态会随年龄、环境、作息和生活节奏动态变化。</view>
|
||
<view class="report-disclaimer-line">*本次检测仅代表当前肌肤状态参考。</view>
|
||
<view class="report-disclaimer-line">*仅根据您最近的测肤记录推荐。</view>
|
||
</view>
|
||
|
||
</view>
|
||
<!-- H5: tap an inspection image to enlarge; tap again to return. -->
|
||
<view class="report-zoom" a:if="{{zoom && !identityChecking && !identityError}}" onTap="onCloseZoom" catchTouchMove="noop">
|
||
<view class="report-zoom-enter">
|
||
<view class="report-zoom-frame" style="{{zoom.frameStyle}}">
|
||
<view class="viz-stage" a:if="{{!zoom.side}}">
|
||
<image class="viz-photo" a:if="{{zoom.photo}}" src="{{zoom.photo}}" mode="{{zoom.fit}}" style="{{zoom.photoStyle}}" />
|
||
<view class="viz-dim" a:if="{{zoom.dark}}"></view>
|
||
<image class="viz-layer {{zoom.blend ? 'viz-blend' : ''}}" a:for="{{zoom.layers}}" a:for-item="layer" a:key="*this" src="{{layer}}" mode="scaleToFill" style="opacity:{{zoom.alpha}};{{zoom.photoStyle}}" />
|
||
<view class="viz-mark" a:for="{{zoom.marks}}" a:for-item="mark" a:key="id" style="left:{{mark.left}}%;top:{{mark.top}}%;width:{{mark.width}}%;height:{{mark.height}}%;border-color:{{mark.color}};"></view>
|
||
</view>
|
||
<block a:else>
|
||
<image class="report-zoom-side report-zoom-bitmap" src="{{zoom.bakedPhoto || zoom.photo}}" mode="aspectFit"
|
||
data-photo="{{zoom.photo}}" data-generation="{{zoom.generation}}" onLoad="onZoomSideLoad" />
|
||
</block>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<canvas id="report-side-zoom-canvas" canvas-id="report-side-zoom-canvas" width="835" height="738" class="report-zoom-canvas" />
|
||
</view>
|