Files
gym-manage/gym-manage-uniapp/pages/memberInfo/bodyTestHistory.vue
T
2026-06-04 14:18:53 +08:00

211 lines
6.4 KiB
Vue

<template>
<view class="scroll-container theme-light">
<view class="bt-page">
<MemberInfoSubNav title="体测报告" @back="onBack" />
<view class="mi-mod-tabs">
<view
v-for="y in years"
:key="y"
class="bt-tab"
:class="{ 'bt-tab--active': activeYear === y }"
hover-class="mi-tap-tab--hover"
:hover-stay-time="150"
@tap="activeYear = y"
>
<text class="bt-tab__text">{{ y === 'all' ? '全部' : y + '年' }}</text>
</view>
</view>
<view class="bt-page__action-bar bt-page__action-bar--end">
<text
class="bt-page__action-link"
hover-class="mi-tap--hover"
:hover-stay-time="150"
@tap="goCompare"
>
历史对比
</text>
</view>
<view class="bt-page__body">
<view
v-for="(item, index) in records"
:key="item.id"
class="mi-timeline-card"
hover-class="mi-tap-row--hover"
@tap="viewReport(item)"
>
<view class="mi-timeline-card__line">
<view class="mi-timeline-card__dot"></view>
<view v-if="index < records.length - 1" class="mi-timeline-card__bar"></view>
</view>
<view class="mi-timeline-card__content">
<view class="mi-timeline-card__head">
<text class="mi-timeline-card__date">{{ item.date }} {{ item.time }}</text>
<text class="mi-timeline-card__score">{{ item.score }}</text>
</view>
<text class="mi-timeline-card__grade">{{ item.grade }} {{ item.gradeLabel }} · {{ item.status }}</text>
<text class="mi-timeline-card__metrics">
体脂 {{ item.metrics.bodyFat }}% · 肌肉 {{ item.metrics.muscleMass }}kg · BMI {{ item.metrics.bmi }}
</text>
<view v-if="item.changeBadge" class="mi-timeline-card__badge" :class="item.changeBadge.good ? 'mi-timeline-card__badge--good' : 'mi-timeline-card__badge--warn'">
<text>{{ item.changeBadge.text }}</text>
</view>
</view>
</view>
<view v-if="!records.length" class="bt-empty">
<text class="bt-empty__text">暂无体测报告</text>
</view>
</view>
</view>
</view>
</template>
<script>
import MemberInfoSubNav from '@/components/memberInfo/MemberInfoSubNav.vue'
import { PAGE, navigateToPage, goBackOrTab } from '@/common/constants/routes.js'
import { loadMemberStore } from '@/common/memberInfo/store.js'
import { getBodyTestHistory, getBodyTestYears, getBodyTestChangeBadge } from '@/common/memberInfo/bodyTestStore.js'
export default {
components: { MemberInfoSubNav },
data() {
return { activeYear: 'all', years: [], allRecords: [] }
},
computed: {
records() {
const list = this.activeYear === 'all'
? this.allRecords
: this.allRecords.filter((r) => r.date.startsWith(this.activeYear))
return list.map((item, index) => {
const previous = list[index + 1]
return {
...item,
changeBadge: getBodyTestChangeBadge(item, previous)
}
})
}
},
watch: {
activeYear() { this.loadList() }
},
onShow() { this.loadList() },
methods: {
loadList() {
const store = loadMemberStore()
this.years = getBodyTestYears(store)
this.allRecords = getBodyTestHistory(store)
},
onBack() { goBackOrTab(PAGE.MEMBER) },
viewReport(item) {
navigateToPage(`${PAGE.BODY_TEST_REPORT}?id=${item.id}`)
},
goCompare() {
navigateToPage(PAGE.BODY_TEST_COMPARE)
}
}
}
</script>
<style>
@import '@/common/style/base.css';
@import '@/common/style/memberInfo/pages/page-reset.css';
@import '@/common/style/memberInfo/pages/sub-page-base.css';
@import '@/common/style/memberInfo/member-info-component-reset.css';
@import '@/common/style/memberInfo/member-info-sub-nav.css';
@import '@/common/style/memberInfo/member-info-tap.css';
@import '@/common/style/memberInfo/pages/body-test-common.css';
.mi-timeline-card {
display: flex;
flex-direction: row;
gap: 12px;
margin-bottom: 4px;
}
.mi-timeline-card__line {
width: 16px;
display: flex;
flex-direction: column;
align-items: center;
}
.mi-timeline-card__dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--accent-orange, #FF6B35);
flex-shrink: 0;
}
.mi-timeline-card__bar {
flex: 1;
width: 2px;
background: var(--border-light, #E9EDF2);
margin: 4px 0;
}
.mi-timeline-card__content {
flex: 1;
padding: 12px 14px;
margin-bottom: 10px;
border-radius: 14px;
background: var(--bg-white, #fff);
box-shadow: var(--shadow-sm);
}
.mi-timeline-card__head {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.mi-timeline-card__date {
font-size: 13px;
font-weight: 600;
color: var(--text-dark, #1E2A3A);
}
.mi-timeline-card__score {
font-size: 18px;
font-weight: 800;
color: var(--primary-dark, #0B2B4B);
}
.mi-timeline-card__grade {
font-size: 12px;
color: var(--text-muted, #5E6F8D);
margin-top: 4px;
display: block;
}
.mi-timeline-card__metrics {
font-size: 11px;
color: var(--text-light, #8A99B4);
margin-top: 4px;
display: block;
}
.mi-timeline-card__badge {
display: inline-block;
margin-top: 8px;
padding: 2px 8px;
border-radius: 6px;
}
.mi-timeline-card__badge--good {
background: rgba(46, 204, 113, 0.12);
}
.mi-timeline-card__badge--good text {
font-size: 10px;
color: var(--success-green, #2ECC71);
font-weight: 600;
}
.mi-timeline-card__badge--warn text {
font-size: 10px;
color: var(--warning-amber, #F39C12);
font-weight: 600;
}
</style>