Files
mp-pilates/packages/app/src/pages/home/teaching-case.vue
2026-09-18 18:26:47 +08:00

51 lines
4.5 KiB
Vue
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.
<template>
<view class="page" :style="{ paddingTop: navBarHeight + 'px' }">
<CustomNavBar title="练习的改变" show-back />
<view class="content">
<view v-if="loading" class="state">正在读取案例…</view>
<view v-else-if="error" class="state">{{ error }}<button @tap="reload">重新加载</button></view>
<template v-else-if="item">
<text class="eyebrow">{{ item.displayName }} · 真实练习记录</text><text class="title">{{ item.title }}</text>
<view class="stat"><text class="number">{{ item.lessonCount }}</text><text>节课,记录这一段改变</text></view>
<TeachingCaseGallery :frames="item.frames" :lesson-count="item.lessonCount" @refresh="reload" />
<view v-if="item.background" class="story"><text class="label">练习的起点</text><text class="body">{{ item.background }}</text></view>
<view class="story"><text class="label">看得见,也感受得到</text><text class="body">{{ item.achievement }}</text></view>
<text class="notice">经学员单独授权公开分享。每个人的基础、练习频率与感受不同,案例不代表相同课时下的效果承诺。</text>
<view class="invite"><text class="invite-title">你的练习,从了解自己开始。</text><text class="notice">找到适合自己的节奏,和老师一起开始。</text><button class="primary" @tap="explore">了解课程与体验</button></view>
<button class="share" open-type="share">分享这段改变</button>
</template>
</view>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad, onShow, onShareAppMessage } from '@dcloudio/uni-app'
import type { TeachingCasePublic } from '@mp-pilates/shared'
import CustomNavBar from '../../components/CustomNavBar.vue'
import TeachingCaseGallery from '../../components/TeachingCaseGallery.vue'
import { getSystemLayout } from '../../utils/system'
import { get, HttpRequestError } from '../../utils/request'
const navBarHeight = getSystemLayout().navBarHeight
const id = ref(''), item = ref<TeachingCasePublic | null>(null), loading = ref(true), error = ref('')
let sequence = 0
async function reload() {
const seq = ++sequence; loading.value = true; error.value = ''; item.value = null
try { if (!id.value) throw new Error('案例链接不完整'); const result = await get<TeachingCasePublic>(`/teaching-cases/${encodeURIComponent(id.value)}`); if (seq === sequence) item.value = result }
catch (e) { if (seq === sequence) error.value = e instanceof HttpRequestError && e.statusCode === 404 ? '案例已下架或暂未公开。' : '案例暂时无法读取,请重试。' }
finally { if (seq === sequence) loading.value = false }
}
function explore() {
// A shared detail link can be the launch page, before home has registered events.
uni.setStorageSync('home:card-shop-requested', true)
uni.switchTab({ url: '/pages/home/index', fail: () => {
uni.removeStorageSync('home:card-shop-requested')
uni.showToast({ title: '打开课程失败,请重试', icon: 'none' })
} })
}
onLoad(query => { id.value = String(query?.id || '') }); onShow(reload)
onShareAppMessage(() => ({ title: item.value?.title || '教学案例', path: item.value ? `/pages/home/teaching-case?id=${item.value.id}` : '/pages/home/teaching-cases' }))
</script>
<style scoped>
.page{min-height:100vh;background:#fbf9f6;box-sizing:border-box;}.content{padding:42rpx 32rpx 80rpx;}.eyebrow{font-size:23rpx;color:#7b866e;letter-spacing:2rpx;}.title{display:block;font-family:'Songti SC','STSong',serif;font-size:46rpx;line-height:1.5;color:#454c3f;margin:22rpx 0;}.stat{display:flex;align-items:baseline;gap:18rpx;color:#7a806a;font-size:25rpx;margin:26rpx 0 34rpx;}.number{font-family:'Baskerville',serif;font-size:80rpx;line-height:1;color:#5c7151;}.story{padding:34rpx 0;border-bottom:1rpx solid #e5e0d5;}.label{display:block;font-size:24rpx;color:#8b806d;margin-bottom:18rpx;}.body{display:block;font-size:29rpx;color:#555448;line-height:1.9;white-space:pre-wrap;overflow-wrap:anywhere;}.notice{display:block;font-size:22rpx;line-height:1.9;color:#918775;margin-top:25rpx;}.invite{margin-top:40rpx;padding:28rpx;background:#eef0e6;border-radius:18rpx;}.invite-title{font-family:'Songti SC','STSong',serif;font-size:32rpx;color:#55634b;}.primary{background:#586c50;color:#fff;font-size:28rpx;line-height:88rpx;margin-top:26rpx;}.share{margin-top:22rpx;background:transparent;font-size:25rpx;color:#6f7a62;line-height:88rpx;}.share::after{border:0;}.state{text-align:center;padding:80rpx 0;font-size:28rpx;color:#857b6a;}
</style>