Files
wx_pbzc/pages/index/index.wxml
T
lc 0464eeaba6 feat(timer): 训练页改版 hero 风格 + 进度环刻度 + 醒目姿态提示气泡
- progress-ring: canvas 新增秒刻度层(四分位加粗), 环内加 subText, 移除组件内 statusText
- timer.wxml: 环下方状态词 + 目标信息卡(今日目标·第N天›静态箭头) + 运行提示; 进度环传 ticks/subText
- timer.js: 派生 ringTicks/ringSubText/statusText/goalLine/runningTip/tipType/tipIcon, 各生命周期计算下发
- timer.wxss: 按钮贴底(flex-start+margin-top:auto), 新增 .timer-status/.goal-card/.timer-tip 气泡卡片(主色左边框+小三角+tipPulse 呼吸), 文字放大加粗
- 姿态提示分语义: posture/phase(主色) / done(成功色), 图标用 peopleFill/successFill
- 状态机/计时/循环FSM/呼吸环/彩带/弹窗/语音震动常亮全部保留
- 另含 index 进度地图右上角奖杯图标删除(quest-trophy 样式清理)
2026-08-11 15:38:37 +08:00

185 lines
6.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<view class="container page-enter" style="{{themeStyle}}">
<!-- 全宽渐变头图 hero -->
<view class="hero">
<view class="hero-top">
<!-- 圆形头像:无头像时白底 + peopleFill 占位(橙图标在白底清晰);
有头像时透明描边,远程(cloud://)头像靠外层 overflow:hidden 裁圆 -->
<view class="hero-avatar {{avatarUrl ? 'has-avatar' : ''}}">
<image
class="hero-avatar-img"
src="{{avatarUrl || icons.peopleFill}}"
mode="{{avatarUrl ? 'aspectFill' : 'aspectFit'}}"
></image>
</view>
<view class="hero-user">
<text class="hero-greet">{{greetText}}{{nickName || '运动达人'}}</text>
<text class="hero-social">{{streakText}}</text>
</view>
</view>
<view class="hero-challenge">
<text class="hero-time">「{{todayTargetText}}」</text>
<text class="hero-cta-text">敢不敢来挑战?</text>
</view>
</view>
<!-- 闯关进度地图(上浮叠在 hero 下) -->
<ui-card variant="in" index="0" class="quest-card {{justCompleted ? 'just-completed' : ''}}">
<view class="quest-head">
<text class="quest-title">{{planName}}<text class="quest-sub">第 {{planDay}} / {{planTotal}} 天</text></text>
</view>
<view class="quest-map">
<block wx:for="{{questNodes}}" wx:key="label">
<view class="q-node {{item.state}} {{item.final ? 'final' : ''}}">{{item.label}}</view>
<view wx:if="{{index < questNodes.length - 1}}" class="q-link {{item.state === 'done' ? 'done' : ''}}"></view>
</block>
</view>
<text class="quest-tip">{{questTip}}</text>
</ui-card>
<!-- 计时环 dial -->
<view class="timer-wrap">
<view class="dial">
<text class="dial-time" style="font-size: {{targetTimeFontSize}}rpx;">{{todayTargetText}}</text>
<text class="dial-label">今日目标时长</text>
</view>
<view class="benefit">⚡ 预计消耗 <text class="benefit-hl">{{estKcal}}</text> 千卡</view>
</view>
<!-- 操作按钮区 -->
<view class="action-buttons">
<ui-btn
variant="primary"
size="xl"
block
text="{{todayDone ? '再战一次 ' : '立即挑战 '}}{{todayTargetText}}"
icon-src="{{icons.playWhite}}"
bindtap="onStartTrain"
custom-style="border-radius:16rpx;box-shadow:0 8rpx 20rpx rgba(var(--primary-rgb),0.35);animation:ctaPulse 2s ease-in-out infinite;"
></ui-btn>
<view class="action-row">
<ui-btn
class="action-cell"
variant="ghost"
size="xl"
block
text="自由训练"
icon-src="{{icons.timeFill}}"
bindtap="onFreeTrain"
custom-style="border-radius:16rpx;"
></ui-btn>
<ui-btn
class="action-cell"
variant="ghost"
size="xl"
block
text="循环训练"
icon-src="{{icons.repeatFill}}"
bindtap="onCircuitTrain"
custom-style="border-radius:16rpx;"
></ui-btn>
</view>
</view>
<!-- 时间选择弹窗 -->
<ui-modal
visible="{{showPicker}}"
position="bottom"
bind:close="onClosePicker"
>
<text class="picker-title">选择训练时长</text>
<view class="preset-grid">
<view
class="preset-item {{customDuration === item ? 'selected' : ''}}"
wx:for="{{presets}}"
wx:key="*this"
data-value="{{item}}"
bindtap="onSelectPreset"
>
<text class="preset-num">{{item}}</text>
<text class="preset-unit">秒</text>
</view>
</view>
<view class="custom-input-row">
<text class="custom-label">自定义:</text>
<input
class="custom-input"
type="number"
placeholder="输入秒数"
value="{{customInput}}"
focus="{{pickerInputFocus}}"
bindinput="onCustomInput"
bindfocus="onPickerInputFocus"
/>
<text class="custom-label">秒</text>
</view>
<ui-btn
variant="primary"
size="lg"
block
text="开始自由训练"
bindtap="onConfirmFree"
custom-style="border-radius:16rpx;"
></ui-btn>
<text class="picker-cancel" bindtap="onClosePicker">取消</text>
</ui-modal>
<!-- 循环训练配置弹窗:每组时长 / 组数 / 休息 / 每周次数,保存后持久化 -->
<ui-modal
visible="{{showCircuitPicker}}"
position="bottom"
bind:close="onCloseCircuitPicker"
>
<text class="picker-title">循环训练设置</text>
<text class="picker-sub">自定义每组时长、组数与组间休息</text>
<view class="circuit-row">
<text class="circuit-row-label">每组时长</text>
<view class="stepper">
<view class="stepper-btn" data-field="hold" data-delta="-10" bindtap="onCircuitStep"></view>
<text class="stepper-val">{{cHold}}秒</text>
<view class="stepper-btn" data-field="hold" data-delta="10" bindtap="onCircuitStep">+</view>
</view>
</view>
<view class="circuit-row">
<text class="circuit-row-label">组数</text>
<view class="stepper">
<view class="stepper-btn" data-field="sets" data-delta="-1" bindtap="onCircuitStep"></view>
<text class="stepper-val">{{cSets}}组</text>
<view class="stepper-btn" data-field="sets" data-delta="1" bindtap="onCircuitStep">+</view>
</view>
</view>
<view class="circuit-row">
<text class="circuit-row-label">组间休息</text>
<view class="stepper">
<view class="stepper-btn" data-field="rest" data-delta="-10" bindtap="onCircuitStep"></view>
<text class="stepper-val">{{cRest}}秒</text>
<view class="stepper-btn" data-field="rest" data-delta="10" bindtap="onCircuitStep">+</view>
</view>
</view>
<view class="circuit-row">
<text class="circuit-row-label">每周目标</text>
<view class="stepper">
<view class="stepper-btn" data-field="sessions" data-delta="-1" bindtap="onCircuitStep"></view>
<text class="stepper-val">{{cSessions}}次/周</text>
<view class="stepper-btn" data-field="sessions" data-delta="1" bindtap="onCircuitStep">+</view>
</view>
</view>
<ui-btn
variant="primary"
size="lg"
block
text="保存并开始"
bindtap="onConfirmCircuit"
custom-style="border-radius:16rpx;"
></ui-btn>
<text class="picker-cancel" bindtap="onCloseCircuitPicker">取消</text>
</ui-modal>
</view>