- 8 个页面 exercise-card 由 bind:tap 改为 catch:tap,拦截原生 tap 冒泡 避免一次点击被『自定义事件 + 原生冒泡』触发两次, 第二次 e.detail 无 id → navigateTo detail?id=undefined → 404 - 所有 onExercise 顶部加 id 守卫,无 id 直接 return - exercise-card 点击前校验 exercise.id,缺失不触发 - detail onLoad 的 id 为空时直接显示空态,不再发起错误请求
79 lines
3.0 KiB
Plaintext
79 lines
3.0 KiB
Plaintext
<view class="page" wx:if="{{exercise}}">
|
||
<navbar title="{{exercise.displayName || exercise.name}}" show-back />
|
||
|
||
<view class="favbtn" style="top: {{statusBarHeight + 12}}px;" bindtap="onToggleFav">
|
||
<text>{{favorited ? '♥' : '♡'}}</text>
|
||
</view>
|
||
|
||
<view class="hero">
|
||
<image
|
||
wx:if="{{heroSrc && !heroError}}"
|
||
class="hero__img"
|
||
src="{{heroSrc}}"
|
||
mode="aspectFill"
|
||
lazy-load="true"
|
||
binderror="onHeroError" />
|
||
<view wx:else class="hero__ph">🏋️</view>
|
||
</view>
|
||
|
||
<view class="body section">
|
||
<view class="name">{{exercise.displayName || exercise.name}}</view>
|
||
|
||
<view class="metas">
|
||
<view class="meta"><view class="meta__k">部位</view><view class="meta__v">{{exercise.bodyPartLabel}}</view></view>
|
||
<view class="meta"><view class="meta__k">器械</view><view class="meta__v">{{exercise.equipmentLabel}}</view></view>
|
||
<view class="meta"><view class="meta__k">目标</view><view class="meta__v gold-text">{{exercise.targetLabel}}</view></view>
|
||
<view class="meta"><view class="meta__k">类型</view><view class="meta__v">{{exercise.typeLabel}}</view></view>
|
||
</view>
|
||
|
||
<view class="block" wx:if="{{exercise.muscleGroupLabel}}">
|
||
<view class="block__h eyebrow">主要肌群</view>
|
||
<view class="chips">
|
||
<text class="tag tag--gold">{{exercise.muscleGroupLabel}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="block" wx:if="{{exercise.secondaryMusclesLabels.length}}">
|
||
<view class="block__h eyebrow">协同肌群</view>
|
||
<view class="chips">
|
||
<text wx:for="{{exercise.secondaryMusclesLabels}}" wx:key="*this" class="tag">{{item}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="block" wx:if="{{exercise.instructionSteps.zh.length}}">
|
||
<view class="block__h eyebrow">动作步骤</view>
|
||
<view class="steps">
|
||
<view class="step" wx:for="{{exercise.instructionSteps.zh}}" wx:key="index">
|
||
<view class="step__n">{{index + 1}}</view>
|
||
<view class="step__t">{{item}}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="block" wx:if="{{exercise.instructions.zh}}">
|
||
<view class="block__h eyebrow">要点提示</view>
|
||
<view class="tips">{{exercise.instructions.zh}}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section" wx:if="{{related.length}}">
|
||
<view class="block__h eyebrow">相关推荐</view>
|
||
<scroll-view scroll-x class="hscroll">
|
||
<view class="hscroll__item" wx:for="{{related}}" wx:key="id">
|
||
<exercise-card exercise="{{item}}" compact catch:tap="onExercise" />
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<view class="addbar">
|
||
<view class="cta" bindtap="onAdd">{{ planId ? '加入该计划' : '加入计划' }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view wx:else class="empty-page">
|
||
<view class="topbar" style="padding-top: {{statusBarHeight}}px;">
|
||
<view class="topbar__back" bindtap="onBack">‹</view>
|
||
</view>
|
||
<view class="empty">{{ loading ? '加载中…' : '未找到该动作' }}</view>
|
||
</view>
|