- fix(booking): 修复未认领画像阻断约课问题,支持约课事务内自动认领绑定 - fix(app): 修复 Pinia 状态解构导致响应式失效,补齐 PortraitRadar 组件实例传参 - fix(admin): 修复经营助手复测待办点击 404,优化体验课后线索回访文案 - fix(server): 线下评估日期间隔按中国时区校验,复测按期次单项核销,优化单次评估分享卡与限流清理 - test: 补齐 body-portrait-offline 与 booking 来源画像单元测试 Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
3.6 KiB
Vue
76 lines
3.6 KiB
Vue
<template>
|
||
<view class="page" :style="{ paddingTop: navBarHeight }">
|
||
<CustomNavBar title="你的身体画像" show-back />
|
||
<view v-if="teaser" class="card">
|
||
<text class="kicker">你的身体画像</text>
|
||
<text class="title">{{ teaser.headline }}</text>
|
||
<text class="summary">{{ claimed && report ? report.summary : '登录后查看完整个性化报告。问卷画像只能反映生活习惯和主观感受。' }}</text>
|
||
<text class="match">问卷依据:{{ teaser.matchQuality === 'full' ? '充分' : '一般' }}。这表示回答是否足够形成解释,不是诊断准确率。</text>
|
||
</view>
|
||
<SafetyNotice v-if="report?.safety.flagged" :message="report.safety.message || ''" />
|
||
<PortraitRadar v-if="claimed && report" :scores="report.scores" />
|
||
<view v-if="claimed && report" class="block">
|
||
<view v-for="(item, index) in report.evidence" :key="item.title" class="evidence">
|
||
<text class="etitle">{{ index + 1 }} {{ item.title }}</text>
|
||
<text class="eans">根据你的答案:{{ item.answers.join('、') }}</text>
|
||
<text class="ebody">{{ item.explanation }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="claimed && report" class="block">
|
||
<text class="etitle">这些问题是有关联的</text>
|
||
<text v-for="stepItem in report.chain.steps" :key="stepItem" class="chain">{{ stepItem }}</text>
|
||
<text class="ebody">{{ report.chain.takeaway }}</text>
|
||
</view>
|
||
<text class="disclaimer">非医疗诊断,仅用于运动训练参考。</text>
|
||
<view class="cta" @tap="continueFlow">{{ claimed ? '查看建议' : '登录查看完整报告' }}</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import { storeToRefs } from 'pinia'
|
||
import { onShow } from '@dcloudio/uni-app'
|
||
import CustomNavBar from '../../components/CustomNavBar.vue'
|
||
import PortraitRadar from '../../components/PortraitRadar.vue'
|
||
import SafetyNotice from '../../components/SafetyNotice.vue'
|
||
import { getSystemLayout } from '../../utils/system'
|
||
import { getErrorMessage } from '../../utils/auth'
|
||
import { useBodyPortraitStore } from '../../stores/body-portrait'
|
||
import { useUserStore } from '../../stores/user'
|
||
|
||
const navBarHeight = ref(`${getSystemLayout().navBarHeight}px`)
|
||
const portrait = useBodyPortraitStore()
|
||
const userStore = useUserStore()
|
||
const { teaser, report, claimed } = storeToRefs(portrait)
|
||
|
||
onShow(async () => {
|
||
if (!teaser.value && !portrait.session) {
|
||
await portrait.loadMine().catch(() => {})
|
||
}
|
||
if (teaser.value) await portrait.track('report_viewed')
|
||
})
|
||
|
||
async function continueFlow() {
|
||
try {
|
||
if (!claimed.value) {
|
||
if (!userStore.loggedIn) await userStore.login()
|
||
await portrait.claim()
|
||
}
|
||
uni.navigateTo({ url: '/pages/portrait/advice' })
|
||
} catch (err) {
|
||
uni.showToast({ title: getErrorMessage(err, '请先登录后查看完整报告'), icon: 'none' })
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.page { min-height: 100vh; background: #fbf9f6; padding: 0 40rpx 120rpx; }
|
||
.card, .block, .evidence { background: #fff; border-radius: 24rpx; padding: 32rpx; margin-bottom: 24rpx; }
|
||
.kicker { color: #8a7b6e; font-size: 22rpx; }
|
||
.title { display: block; margin-top: 12rpx; font-size: 40rpx; color: #4a4035; line-height: 1.4; }
|
||
.summary, .match, .ebody, .eans, .chain { display: block; margin-top: 16rpx; color: #7a6a5a; font-size: 26rpx; line-height: 1.7; }
|
||
.etitle { display: block; font-size: 30rpx; color: #4a4035; }
|
||
.disclaimer { display: block; color: #a09080; font-size: 22rpx; margin: 12rpx 0 24rpx; }
|
||
.cta { height: 92rpx; border-radius: 999rpx; background: #6b8276; color: #fff; display: flex; align-items: center; justify-content: center; }
|
||
</style>
|