feat: bmi
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { WHO_BMI_STANDARDS } from "@/data/whoBmiStandards";
|
||||
import {
|
||||
BODY_COMPOSITION_COLORS,
|
||||
getBmiTone,
|
||||
} from "@/utils/body-composition-status";
|
||||
|
||||
const props = defineProps<{
|
||||
weightKg: number;
|
||||
bmi: number;
|
||||
bmiStatus: string;
|
||||
}>();
|
||||
|
||||
const statusColor = computed(
|
||||
() => BODY_COMPOSITION_COLORS[getBmiTone(props.bmi)],
|
||||
);
|
||||
|
||||
const recommendation = computed(() => {
|
||||
if (props.bmi < 18.5) {
|
||||
return "體重低於正常範圍,建議留意營養攝取與健康狀況。";
|
||||
}
|
||||
|
||||
if (props.bmi < 25) {
|
||||
return "體重位於正常範圍,請持續維持均衡飲食與規律運動。";
|
||||
}
|
||||
|
||||
if (props.bmi < 30) {
|
||||
return "體重已超過正常範圍,建議適度調整體重。";
|
||||
}
|
||||
|
||||
return "您的 BMI 已進入肥胖範圍,建議諮詢專業人員並逐步調整生活習慣。";
|
||||
});
|
||||
|
||||
function formatMeasurement(value: number): string {
|
||||
return Number.isFinite(value) ? value.toFixed(1) : "--";
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card class="analysis-card rounded-xl" elevation="1">
|
||||
<v-card-title class="text-h5 font-weight-black text-center pt-6">
|
||||
體重與 BMI 分析
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text class="pa-4 pa-sm-6">
|
||||
<div class="metrics-grid mb-5">
|
||||
<div class="metric-cell text-center">
|
||||
<div class="text-body-large text-grey-darken-2 mb-2">體重</div>
|
||||
<div class="metric-value text-grey-darken-4">
|
||||
{{ formatMeasurement(weightKg) }}
|
||||
<span class="metric-unit">公斤</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metric-cell text-center">
|
||||
<div class="text-body-large text-grey-darken-2 mb-2">BMI</div>
|
||||
<div class="metric-value" :style="{ color: statusColor }">
|
||||
{{ formatMeasurement(bmi) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap justify-center align-center ga-2 mb-5">
|
||||
<span class="text-title-medium">您的 BMI 屬於</span>
|
||||
<v-chip
|
||||
class="semantic-chip font-weight-black"
|
||||
:color="statusColor"
|
||||
label
|
||||
size="large"
|
||||
variant="flat"
|
||||
>
|
||||
{{ bmiStatus }}
|
||||
</v-chip>
|
||||
</div>
|
||||
|
||||
<v-alert
|
||||
class="recommendation-alert mb-6"
|
||||
:color="statusColor"
|
||||
icon="mdi-bullhorn-outline"
|
||||
variant="tonal"
|
||||
>
|
||||
{{ recommendation }}
|
||||
</v-alert>
|
||||
|
||||
<v-sheet class="who-panel rounded-xl pa-4" color="grey-lighten-4">
|
||||
<div class="who-title text-center mb-1">世界衛生組織 WHO 定義</div>
|
||||
<div class="who-formula text-grey-darken-2 text-center mb-5">
|
||||
(BMI = 體重 ÷ 身高²)
|
||||
</div>
|
||||
|
||||
<div class="who-standards">
|
||||
<div
|
||||
v-for="standard in WHO_BMI_STANDARDS"
|
||||
:key="standard.label"
|
||||
class="who-standard rounded-lg text-center"
|
||||
:style="{
|
||||
backgroundColor: BODY_COMPOSITION_COLORS[standard.tone],
|
||||
}"
|
||||
>
|
||||
<div class="who-standard-label">{{ standard.label }}</div>
|
||||
<div class="who-standard-range">{{ standard.range }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="who-note text-grey-darken-2 text-center mb-0 mt-5">
|
||||
BMI 只是初步判斷,需搭配體脂率<br
|
||||
class="d-none d-sm-inline"
|
||||
/>與肌肉量進一步分析。
|
||||
</p>
|
||||
</v-sheet>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.analysis-card {
|
||||
border: 1px solid rgba(var(--v-theme-primary), 0.24);
|
||||
}
|
||||
|
||||
.metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.metric-cell {
|
||||
min-width: 0;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.metric-cell + .metric-cell {
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.14);
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: clamp(2.25rem, 10vw, 3.125rem);
|
||||
font-weight: 900;
|
||||
line-height: 1.1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.metric-unit {
|
||||
font-size: clamp(0.875rem, 3.5vw, 1.25rem);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.recommendation-alert {
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.semantic-chip {
|
||||
color: #252525 !important;
|
||||
}
|
||||
|
||||
.who-title {
|
||||
font-size: clamp(1.25rem, 5vw, 1.65rem);
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.who-formula,
|
||||
.who-note {
|
||||
font-size: clamp(1rem, 4vw, 1.25rem);
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.who-standards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.who-standard {
|
||||
min-width: 0;
|
||||
padding: 18px 6px 16px;
|
||||
color: #2b2b2b;
|
||||
}
|
||||
|
||||
.who-standard-label {
|
||||
margin-bottom: 4px;
|
||||
font-size: clamp(1.2rem, 5vw, 1.55rem);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.who-standard-range {
|
||||
font-size: clamp(0.92rem, 3.8vw, 1.12rem);
|
||||
font-weight: 800;
|
||||
line-height: 1.25;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.metric-cell {
|
||||
padding-inline: 6px;
|
||||
}
|
||||
|
||||
.who-panel {
|
||||
padding-inline: 12px !important;
|
||||
}
|
||||
|
||||
.who-standards {
|
||||
gap: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user