feat: 增加各个模块
This commit is contained in:
@@ -1,42 +1,198 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<image class="logo" src="/static/logo.png" />
|
||||
<view class="text-area">
|
||||
<text class="title">{{ title }}</text>
|
||||
<view class="min-h-screen flex flex-col gap-3 bg-[#f2f4f3]">
|
||||
<view class="border-b border-gray-100 bg-white px-4 pb-3">
|
||||
<view class="mt-2 flex items-center justify-between">
|
||||
<view class="flex flex-col">
|
||||
<text class="text-lg text-gray-800 font-semibold">
|
||||
{{ greeting }}
|
||||
</text>
|
||||
<text class="mt-0.5 text-xs text-gray-400">
|
||||
{{ today }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<wd-button type="success">成功按钮</wd-button>
|
||||
|
||||
<wd-card title="📊 今日概览" custom-class="!mx-2 !mb-0">
|
||||
<view class="grid grid-cols-2 gap-3">
|
||||
<view
|
||||
v-for="item in overviewItems"
|
||||
:key="item.label"
|
||||
class="rounded-xl bg-[#f2f4f3] p-3 shadow-sm"
|
||||
>
|
||||
<view class="flex items-center gap-2">
|
||||
<view class="h-8 w-8 flex items-center justify-center rounded-full" :class="item.bg">
|
||||
<text class="text-sm">
|
||||
{{ item.icon }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="text-xs text-gray-400">
|
||||
{{ item.label }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="mt-2 block text-xl text-gray-800 font-bold">
|
||||
{{ item.value }}
|
||||
</text>
|
||||
<text class="mt-1 text-xs text-gray-400">
|
||||
{{ item.sub }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<!-- 今日计划 -->
|
||||
<wd-card title="🎯 今日计划" custom-class="!mx-2 !mb-0">
|
||||
<view v-for="(plan, idx) in plans" :key="idx">
|
||||
<view class="flex items-center justify-between py-2.5">
|
||||
<view class="flex items-center gap-2.5">
|
||||
<text class="text-lg">{{ plan.icon }}</text>
|
||||
<text class="text-sm">{{ plan.label }}</text>
|
||||
</view>
|
||||
|
||||
<wd-tag v-if="plan.done" type="success" round>
|
||||
已完成
|
||||
</wd-tag>
|
||||
<wd-tag v-else type="danger" round>
|
||||
未完成
|
||||
</wd-tag>
|
||||
</view>
|
||||
<view v-if="idx < plans.length - 1" class="h-1px w-full bg-[#f2f4f3]" />
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<record-popup />
|
||||
|
||||
<weight-popup />
|
||||
<sleep-popup />
|
||||
<sport-popup />
|
||||
<bp-popup />
|
||||
<glucose-popup />
|
||||
<temp-popup />
|
||||
|
||||
<wd-fab v-if="recordStore.showFab" type="primary" :expandable="false" @click="handelFabClick" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
const title = ref('Hello')
|
||||
<script lang="ts" setup>
|
||||
import RecordPopup from "@/components/Home/RecordPopup.vue";
|
||||
import WeightPopup from "@/components/Home/WeightPopup.vue";
|
||||
import SleepPopup from "@/components/Home/SleepPopup.vue";
|
||||
import SportPopup from "@/components/Home/SportPopup.vue";
|
||||
import BpPopup from "@/components/Home/BpPopup.vue";
|
||||
import GlucosePopup from "@/components/Home/GlucosePopup.vue";
|
||||
import TempPopup from "@/components/Home/TempPopup.vue";
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { useRecordStore } from '@/store/record'
|
||||
import type { IHealthRecord } from '@/utils/record'
|
||||
import { getDateStr, getDayRecords } from '@/utils/record'
|
||||
|
||||
defineOptions({
|
||||
name: 'Home',
|
||||
})
|
||||
|
||||
const recordStore = useRecordStore()
|
||||
|
||||
const todayRecords = ref<IHealthRecord[]>([])
|
||||
|
||||
const now = new Date()
|
||||
const hour = now.getHours()
|
||||
|
||||
const greeting = computed(() => {
|
||||
if (hour < 6)
|
||||
return '夜深了 🌙'
|
||||
if (hour < 12)
|
||||
return '早上好 ☀️'
|
||||
if (hour < 18)
|
||||
return '下午好 👋'
|
||||
return '晚上好 🌆'
|
||||
})
|
||||
|
||||
const today = computed(() => {
|
||||
const m = now.getMonth() + 1
|
||||
const d = now.getDate()
|
||||
const w = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()]
|
||||
return `${m}月${d}日 周${w}`
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
todayRecords.value = getDayRecords(getDateStr(Date.now()))
|
||||
})
|
||||
|
||||
watch(() => recordStore.isRecord, () => {
|
||||
todayRecords.value = getDayRecords(getDateStr(Date.now()))
|
||||
})
|
||||
|
||||
// 今日概览
|
||||
const overviewItems = computed(() => {
|
||||
const list = todayRecords.value
|
||||
|
||||
// 体重:取最新一条
|
||||
const weight = list.filter(r => r.type === 'weight').pop()
|
||||
// 血压:取最新一条
|
||||
const bp = list.filter(r => r.type === 'bloodPressure').pop()
|
||||
// 睡眠:取最新一条
|
||||
const sleep = list.filter(r => r.type === 'sleep').pop()
|
||||
// 运动:全部累加
|
||||
const sports = list.filter(r => r.type === 'sport')
|
||||
const sportTotal = sports.reduce((sum, r) => sum + (r.duration || 0), 0)
|
||||
|
||||
return [
|
||||
{
|
||||
icon: '⚖️',
|
||||
label: '体重',
|
||||
value: weight ? `${weight.value} kg` : '未记录',
|
||||
sub: '',
|
||||
bg: 'bg-[#E89E3A]',
|
||||
},
|
||||
{
|
||||
icon: '😴',
|
||||
label: '睡眠',
|
||||
value: sleep ? `${sleep.duration}h` : '未记录',
|
||||
sub: '',
|
||||
bg: 'bg-[#2E5B8C]',
|
||||
},
|
||||
{
|
||||
icon: '🏃',
|
||||
label: '运动',
|
||||
value: sportTotal > 0 ? `${sportTotal}min` : '0min',
|
||||
sub: sportTotal >= 30 ? '已达标' : '目标 30min',
|
||||
bg: 'bg-[#3A7C5B]',
|
||||
},
|
||||
{
|
||||
icon: '❤️',
|
||||
label: '血压',
|
||||
value: bp ? `${bp.systolic}/${bp.diastolic}` : '未记录',
|
||||
sub: '',
|
||||
bg: 'bg-[#C04A3C]',
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
// 今日计划
|
||||
const plans = computed(() => {
|
||||
const list = todayRecords.value
|
||||
const hasWeight = list.some(r => r.type === 'weight')
|
||||
const sportTotal = list
|
||||
.filter(r => r.type === 'sport')
|
||||
.reduce((sum, r) => sum + (r.duration || 0), 0)
|
||||
const sleepOnTime = list
|
||||
.filter(r => r.type === 'sleep')
|
||||
.some((r) => {
|
||||
const hour = new Date(r.startTime).getHours()
|
||||
return hour <= 23
|
||||
})
|
||||
const hasBp = list.some(r => r.type === 'bloodPressure')
|
||||
|
||||
return [
|
||||
{ icon: '⚖️', label: '记录体重', done: hasWeight },
|
||||
{ icon: '❤️', label: '测量血压', done: hasBp },
|
||||
{ icon: '🏃', label: '运动30分钟', done: sportTotal >= 30 },
|
||||
{ icon: '🛏️', label: '23:00 前入睡', done: sleepOnTime },
|
||||
]
|
||||
})
|
||||
|
||||
function handelFabClick() {
|
||||
recordStore.showRecordPopup = true
|
||||
recordStore.showFab = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 200rpx;
|
||||
width: 200rpx;
|
||||
margin-top: 200rpx;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.text-area {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
color: #8f8f94;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user