feat: init fitness-coach (backend + miniprogram)

- backend: NestJS service with exercise/plan data
- miniprogram: WeChat mini program client
- exclude node_modules, dist, runtime data-store, local env
This commit is contained in:
2026-07-22 00:35:40 +08:00
commit b3b58e66fb
103 changed files with 154759 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
<view class="home" style="padding-top: {{statusBarHeight}}px;">
<!-- Hero -->
<view class="hero">
<view class="hero__eyebrow">FITCOACH · 智能健身教练</view>
<view class="hero__title">今天,练点什么?</view>
<view class="hero__sub">精准匹配你的目标肌群,让每一次训练都更高效</view>
<view class="search-pill" bindtap="onSearch">
<text class="search-pill__icon">🔍</text>
<text class="search-pill__ph">搜索动作 / 器械 / 部位</text>
</view>
<view class="cta" bindtap="goRecommend">
<text class="cta__icon">✨</text>
<text class="cta__txt">智能推荐</text>
<text class="cta__arrow"></text>
</view>
</view>
<!-- 快捷入口 2x3 -->
<view class="section quick">
<view class="quick__grid">
<view
wx:for="{{quickEntries}}"
wx:key="key"
class="quick__tile"
data-url="{{item.url}}"
bindtap="onQuick">
<text class="quick__emoji">{{item.emoji}}</text>
<text class="quick__label">{{item.label}}</text>
</view>
</view>
</view>
<!-- 精选动作 横向滑动 -->
<view class="section">
<section-header eyebrow="FEATURED" title="精选动作" subtitle="编辑精选 · 高效入门" action="全部" bind:action="goRecommend" />
<scroll-view wx:if="{{featured.length}}" scroll-x class="hscroll">
<view class="hscroll__item" wx:for="{{featured}}" wx:key="id">
<exercise-card exercise="{{item}}" compact bind:tap="onExercise" />
</view>
</scroll-view>
<view wx:else class="empty">暂无数据</view>
</view>
<!-- 训练组合 横向 -->
<view class="section" wx:if="{{collections.length}}">
<section-header eyebrow="PROGRAMS" title="训练组合" subtitle="一键开启主题训练" />
<scroll-view scroll-x class="chip-scroll">
<view
wx:for="{{collections}}"
wx:key="slug"
class="prog"
style="background: {{item.color}}22; border-color: {{item.color}}55;"
data-slug="{{item.slug}}"
bindtap="onCollection">
<text class="prog__emoji">{{item.emoji}}</text>
<text class="prog__name" style="color: {{item.color}};">{{item.name}}</text>
</view>
</scroll-view>
</view>
<!-- 按部位浏览 -->
<view class="section">
<section-header eyebrow="BY BODY PART" title="按部位浏览" subtitle="选择你的目标区域" />
<view class="bp-grid">
<view
wx:for="{{bodyParts}}"
wx:key="value"
class="bp"
data-value="{{item.value}}"
data-label="{{item.label}}"
bindtap="onScanBodyPart">
<text class="bp__label">{{item.label}}</text>
<text class="bp__count">{{item.count}} 个动作</text>
</view>
</view>
</view>
<!-- 热门器械 -->
<view class="section" wx:if="{{equipment.length}}">
<section-header eyebrow="EQUIPMENT" title="热门器械" subtitle="按器械筛选动作" />
<scroll-view scroll-x class="chip-scroll">
<view
wx:for="{{equipment}}"
wx:key="value"
class="eq"
data-value="{{item.value}}"
data-label="{{item.label}}"
bindtap="onScanEquipment">
<text class="eq__name">{{item.label}}</text>
<text class="eq__count">{{item.count}}</text>
</view>
</scroll-view>
</view>
<view style="height: 160rpx;"></view>
<bottom-nav active="home" />
</view>