feat: radar

This commit is contained in:
skytek_xinliang
2026-09-21 15:13:46 +08:00
parent be1cf7d978
commit 261c5516ef
9 changed files with 426 additions and 178 deletions
+48 -41
View File
@@ -51,37 +51,19 @@
</v-btn>
</v-card-subtitle>
<!-- 四項核心能力數值簡覽 -->
<v-row v-if="RADAR_ENABLED" class="mt-4" no-gutters>
<v-col class="text-center border pa-2" cols="3">
<div class="">肌力</div>
<v-row v-if="RADAR_ENABLED && physicalFitnessRadarData" class="mt-4" no-gutters>
<v-col
v-for="summary in radarSummaries"
:key="summary.label"
class="text-center border pa-2"
cols="12"
sm="6"
md="4"
>
<div>{{ summary.label }}</div>
<div class="font-weight-black">
{{ store.radarData.strength }}
</div>
</v-col>
<v-col class="text-center border pa-2" cols="3">
<div class="">平衡</div>
<div class="font-weight-black">
{{ store.radarData.balance }}
</div>
</v-col>
<v-col class="text-center border pa-2" cols="3">
<div class="">敏捷</div>
<div class="font-weight-black">
{{ store.radarData.agility }}
</div>
</v-col>
<v-col class="text-center border pa-2" cols="3">
<div class="">心肺</div>
<div class="font-weight-black">
{{ store.radarData.cardio }}
{{ summary.score }}
</div>
</v-col>
</v-row>
@@ -121,10 +103,19 @@
<v-card-title> 個人五維健康力指標 </v-card-title>
<v-card-subtitle>
綜合 11 項現場普測數值計算得出,<br />藍色為同齡正常參考值區間。
綜合 11 項現場普測數值計算得出,<br />藍色為目前樣本平均基準。
</v-card-subtitle>
<HealthRadarChart :radar-data="store.radarData" />
<v-alert
v-if="!physicalFitnessRadarData"
class="ma-4"
density="compact"
type="info"
variant="tonal"
>
體適能資料不足,完成 11 項測驗後即可計算五維健康力指標。
</v-alert>
<HealthRadarChart v-else :radar-data="physicalFitnessRadarData" />
</v-card>
<ModuleRouterCard
v-if="BODY_COMPOSITION_ENABLED"
@@ -142,15 +133,6 @@
@refresh="loadPhysicalFitness"
/>
<ModuleRouterCard
v-if="SELF_ASSESSMENT_ENABLED"
description="完成線上自評,取得初步風險分級。"
icon="mdi-clipboard-text-search"
icon-color="accent"
title="自評"
to="/self-assessment"
/>
<ModuleRouterCard
v-if="CHECKIN_ENABLED"
description="完成數值紀錄,建立個人功能基線。"
@@ -244,7 +226,6 @@
</div>
</div>
</v-card>
</template>
<IntroductionCarousel v-if="!store.isLoggedIn" />
@@ -382,6 +363,7 @@ import {
import { useAppStore } from '@/stores/app'
import { useCourseStore } from '@/stores/course'
import { getApiErrorMessage } from '@/utils/api-error'
import { calculatePhysicalFitnessRadar } from '@/utils/physical-fitness-radar'
const store = useAppStore()
const courseStore = useCourseStore()
@@ -397,6 +379,31 @@ const physicalFitnessLoading = ref(false)
const physicalFitnessError = ref('')
const displayUserName = useDisplayUserName(store.userProfile)
const physicalFitnessRadarData = computed(() =>
calculatePhysicalFitnessRadar(physicalFitnessItems.value)
)
const radarSummaries = computed(() => {
if (!physicalFitnessRadarData.value) {
return []
}
return [
{
label: '上肢肌力',
score: physicalFitnessRadarData.value.upperBodyStrength,
},
{
label: '下肢肌耐力',
score: physicalFitnessRadarData.value.lowerBodyStrengthAndEndurance,
},
{ label: '心肺耐力', score: physicalFitnessRadarData.value.cardio },
{
label: '平衡、敏捷與行動',
score: physicalFitnessRadarData.value.balanceAgilityAndMobility,
},
{ label: '柔軟度', score: physicalFitnessRadarData.value.flexibility },
]
})
const MISSING_GROUP_DIALOG_KEY = 'missing-fitness-group-dialog-shown'