style: index page

This commit is contained in:
skytek_xinliang
2026-06-22 17:26:48 +08:00
parent f52f1a40f7
commit 11f309c54c
20 changed files with 870 additions and 1090 deletions
+156 -123
View File
@@ -7,11 +7,13 @@
</div>
<!-- 進度指示器 -->
<v-row class="mb-6 justify-center" dense>
<v-row class="mb-6 justify-center">
<v-col v-for="(stepName, idx) in stepNames" :key="idx" class="text-center" cols="3">
<v-avatar
class="text-white font-weight-bold mb-1 elevation-1"
:color="currentStep > idx ? 'primary' : currentStep === idx ? 'secondary' : 'grey-lighten-2'"
:color="
currentStep > idx ? 'primary' : currentStep === idx ? 'secondary' : 'grey-lighten-2'
"
size="28"
>
<v-icon v-if="currentStep > idx" icon="mdi-check" size="14" />
@@ -20,7 +22,13 @@
<div
class="text-caption font-weight-bold"
:class="currentStep === idx ? 'text-secondary' : currentStep > idx ? 'text-primary' : 'text-grey'"
:class="
currentStep === idx
? 'text-secondary'
: currentStep > idx
? 'text-primary'
: 'text-grey'
"
>
{{ stepName }}
</div>
@@ -37,7 +45,7 @@
基本資料確認
</h2>
<v-row dense>
<v-row>
<v-col cols="12" sm="6">
<v-text-field
v-model="profileForm.name"
@@ -120,7 +128,9 @@
活動習慣與想要改善的能力
</h2>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">1. 最近 7 您每週進行大運動幾次</p>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">
1. 最近 7 您每週進行大運動幾次
</p>
<v-radio-group v-model="assessmentForm.exerciseFrequency" class="mb-4" color="primary">
<v-card
@@ -151,18 +161,26 @@
</v-card>
</v-radio-group>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">2. 您目前最想改善的身體功能 (可複選)</p>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">
2. 您目前最想改善的身體功能 (可複選)
</p>
<v-row dense>
<v-row>
<v-col v-for="imp in improvementsOptions" :key="imp" cols="6">
<v-card
class="rounded-lg py-2 px-1 text-center cursor-pointer transition-card"
:class="{ 'bg-teal-lighten-5': assessmentForm.wantedImprovements.includes(imp) }"
:color="assessmentForm.wantedImprovements.includes(imp) ? 'primary' : 'grey-lighten-1'"
:color="
assessmentForm.wantedImprovements.includes(imp) ? 'primary' : 'grey-lighten-1'
"
variant="outlined"
@click="toggleImprovement(imp)"
>
<v-icon class="mb-1" :color="assessmentForm.wantedImprovements.includes(imp) ? 'primary' : 'grey'" :icon="getImprovementIcon(imp)" />
<v-icon
class="mb-1"
:color="assessmentForm.wantedImprovements.includes(imp) ? 'primary' : 'grey'"
:icon="getImprovementIcon(imp)"
/>
<div class="text-caption font-weight-bold">{{ imp }}</div>
</v-card>
</v-col>
@@ -176,14 +194,18 @@
身體限制與慢性病史
</h2>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">1. 過去一年是否有過跌倒史</p>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">
1. 過去一年是否有過跌倒史
</p>
<v-radio-group v-model="assessmentForm.hasFalls" class="mb-4" color="primary" inline>
<v-radio label="無跌倒" :value="false" />
<v-radio label="有跌倒過" :value="true" />
</v-radio-group>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">2. 目前身體關節疼痛狀況</p>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">
2. 目前身體關節疼痛狀況
</p>
<v-select
v-model="assessmentForm.painLevel"
@@ -194,9 +216,11 @@
variant="outlined"
/>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">3. 您有哪些慢性疾病 (可複選)</p>
<p class="text-body-2 font-weight-bold text-grey-darken-2 mb-2">
3. 您有哪些慢性疾病 (可複選)
</p>
<v-row class="mb-4" dense>
<v-row class="mb-4">
<v-col v-for="disease in diseaseOptions" :key="disease" cols="6">
<v-checkbox
v-model="assessmentForm.chronicDiseases"
@@ -221,7 +245,10 @@
@keyup.enter="addMedication"
/>
<div v-if="assessmentForm.medicationReminders.length > 0" class="d-flex flex-wrap gap-2 mt-2">
<div
v-if="assessmentForm.medicationReminders.length > 0"
class="d-flex flex-wrap gap-2 mt-2"
>
<v-chip
v-for="(med, idx) in assessmentForm.medicationReminders"
:key="idx"
@@ -241,7 +268,10 @@
<v-icon color="white" :icon="getResultIcon(resultLevel)" size="40" />
</v-avatar>
<h2 class="text-h5 font-weight-bold mb-1" :class="`text-${getResultColor(resultLevel)}`">
<h2
class="text-h5 font-weight-bold mb-1"
:class="`text-${getResultColor(resultLevel)}`"
>
自評分級{{ resultLevel }}
</h2>
@@ -254,7 +284,8 @@
</div>
<p v-if="resultLevel === '低風險'" class="text-body-2 text-grey-darken-3 mb-2">
您的身體功能與日常活動習慣良好建議您每週繼續保持 3 次以上的運動並可以預約普測活動以獲得精準的五維健康指標與運動處方
您的身體功能與日常活動習慣良好建議您每週繼續保持 3
次以上的運動並可以預約普測活動以獲得精準的五維健康指標與運動處方
</p>
<p v-else-if="resultLevel === '需追蹤'" class="text-body-2 text-grey-darken-3 mb-2">
@@ -266,7 +297,8 @@
</p>
<div class="font-weight-bold text-caption text-secondary mt-3">
* 禁忌提醒若收縮壓 > 160mmHg有關節強烈疼痛或暈眩時請立即暫停所有體能檢測與訓練
* 禁忌提醒若收縮壓 >
160mmHg有關節強烈疼痛或暈眩時請立即暫停所有體能檢測與訓練
</div>
</v-card>
</div>
@@ -310,13 +342,7 @@
</v-btn>
<div v-else class="w-100 d-flex gap-2">
<v-btn
block
class="rounded-lg py-2"
color="primary"
to="/appointment"
variant="flat"
>
<v-btn block class="rounded-lg py-2" color="primary" to="/appointment" variant="flat">
立即預約普測
</v-btn>
</div>
@@ -339,113 +365,120 @@
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import Layout from '@/components/layout/DefaultLayout.vue'
import { useAppStore } from '@/stores/app'
import { reactive, ref } from 'vue'
import Layout from '@/components/layout/DefaultLayout.vue'
import { useAppStore } from '@/stores/app'
const store = useAppStore()
const currentStep = ref(0)
const stepNames = ['基本資料', '功能狀態', '健康限制', '自評結果']
const store = useAppStore()
const currentStep = ref(0)
const stepNames = ['基本資料', '功能狀態', '健康限制', '自評結果']
const profileForm = reactive({
name: store.userProfile.name,
birthday: store.userProfile.birthday,
gender: store.userProfile.gender,
height: store.userProfile.height,
weight: store.userProfile.weight,
consent: store.userProfile.consent,
const profileForm = reactive({
name: store.userProfile.name,
birthday: store.userProfile.birthday,
gender: store.userProfile.gender,
height: store.userProfile.height,
weight: store.userProfile.weight,
consent: store.userProfile.consent,
})
const assessmentForm = reactive({
exerciseFrequency: store.selfAssessment.exerciseFrequency,
wantedImprovements: [...store.selfAssessment.wantedImprovements],
hasFalls: store.selfAssessment.hasFalls,
painLevel: store.selfAssessment.painLevel,
chronicDiseases: [...store.selfAssessment.chronicDiseases],
medicationReminders: [...store.selfAssessment.medicationReminders],
})
const medicationInput = ref('')
const resultLevel = ref(store.selfAssessment.scoreLevel)
const improvementsOptions = ['肌力', '平衡', '心肺', '柔軟度', '敏捷', '體脂/BMI']
const diseaseOptions = ['高血壓', '糖尿病', '高血脂', '心臟病', '關節退化', '骨質疏鬆']
function getImprovementIcon(imp: string) {
switch (imp) {
case '肌力': {
return 'mdi-arm-flex'
}
case '平衡': {
return 'mdi-scale-balance'
}
case '心肺': {
return 'mdi-heart-pulse'
}
case '柔軟度': {
return 'mdi-human-stretching'
}
case '敏捷': {
return 'mdi-run-fast'
}
case '體脂/BMI': {
return 'mdi-calculator'
}
default: {
return 'mdi-help-circle'
}
}
}
function toggleImprovement(imp: string) {
const index = assessmentForm.wantedImprovements.indexOf(imp)
if (index === -1) {
assessmentForm.wantedImprovements.push(imp)
} else {
assessmentForm.wantedImprovements.splice(index, 1)
}
}
function addMedication() {
if (medicationInput.value.trim()) {
assessmentForm.medicationReminders.push(medicationInput.value.trim())
medicationInput.value = ''
}
}
function removeMedication(index: number) {
assessmentForm.medicationReminders.splice(index, 1)
}
function handleSubmit() {
// 儲存至 store
store.updateProfile({
name: profileForm.name,
birthday: profileForm.birthday,
gender: profileForm.gender,
height: profileForm.height,
weight: profileForm.weight,
consent: profileForm.consent,
})
const assessmentForm = reactive({
exerciseFrequency: store.selfAssessment.exerciseFrequency,
wantedImprovements: [...store.selfAssessment.wantedImprovements],
hasFalls: store.selfAssessment.hasFalls,
painLevel: store.selfAssessment.painLevel,
chronicDiseases: [...store.selfAssessment.chronicDiseases],
medicationReminders: [...store.selfAssessment.medicationReminders],
store.submitSelfAssessment({
exerciseFrequency: assessmentForm.exerciseFrequency,
wantedImprovements: assessmentForm.wantedImprovements,
hasFalls: assessmentForm.hasFalls,
painLevel: assessmentForm.painLevel,
chronicDiseases: assessmentForm.chronicDiseases,
medicationReminders: assessmentForm.medicationReminders,
})
const medicationInput = ref('')
const resultLevel = ref(store.selfAssessment.scoreLevel)
// 取得計算後的結果
resultLevel.value = store.selfAssessment.scoreLevel
currentStep.value = 3
}
const improvementsOptions = ['肌力', '平衡', '心肺', '柔軟度', '敏捷', '體脂/BMI']
const diseaseOptions = ['高血壓', '糖尿病', '高血脂', '心臟病', '關節退化', '骨質疏鬆']
function getResultColor(lvl: string) {
if (lvl === '低風險') return 'success'
if (lvl === '需追蹤') return 'warning'
return 'error'
}
function getImprovementIcon (imp: string) {
switch (imp) {
case '肌力': { return 'mdi-arm-flex'
}
case '平衡': { return 'mdi-scale-balance'
}
case '心肺': { return 'mdi-heart-pulse'
}
case '柔軟度': { return 'mdi-human-stretching'
}
case '敏捷': { return 'mdi-run-fast'
}
case '體脂/BMI': { return 'mdi-calculator'
}
default: { return 'mdi-help-circle'
}
}
}
function toggleImprovement (imp: string) {
const index = assessmentForm.wantedImprovements.indexOf(imp)
if (index === -1) {
assessmentForm.wantedImprovements.push(imp)
} else {
assessmentForm.wantedImprovements.splice(index, 1)
}
}
function addMedication () {
if (medicationInput.value.trim()) {
assessmentForm.medicationReminders.push(medicationInput.value.trim())
medicationInput.value = ''
}
}
function removeMedication (index: number) {
assessmentForm.medicationReminders.splice(index, 1)
}
function handleSubmit () {
// 儲存至 store
store.updateProfile({
name: profileForm.name,
birthday: profileForm.birthday,
gender: profileForm.gender,
height: profileForm.height,
weight: profileForm.weight,
consent: profileForm.consent,
})
store.submitSelfAssessment({
exerciseFrequency: assessmentForm.exerciseFrequency,
wantedImprovements: assessmentForm.wantedImprovements,
hasFalls: assessmentForm.hasFalls,
painLevel: assessmentForm.painLevel,
chronicDiseases: assessmentForm.chronicDiseases,
medicationReminders: assessmentForm.medicationReminders,
})
// 取得計算後的結果
resultLevel.value = store.selfAssessment.scoreLevel
currentStep.value = 3
}
function getResultColor (lvl: string) {
if (lvl === '低風險') return 'success'
if (lvl === '需追蹤') return 'warning'
return 'error'
}
function getResultIcon (lvl: string) {
if (lvl === '低風險') return 'mdi-check-decagram'
if (lvl === '需追蹤') return 'mdi-alert-decagram'
return 'mdi-alert-octagon'
}
function getResultIcon(lvl: string) {
if (lvl === '低風險') return 'mdi-check-decagram'
if (lvl === '需追蹤') return 'mdi-alert-decagram'
return 'mdi-alert-octagon'
}
</script>
<style scoped>