Files
health-mp/src/pages/record/index.vue

160 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="min-h-screen bg-[#f2f4f3]">
<view class="sticky top-0 z-10 flex flex-col gap-2 bg-white p-2">
<view class="flex items-center justify-evenly">
<wd-button icon="caret-left" type="primary" :round="true" size="small" @click="changeMonth(-1)" />
<view class="flex flex-col items-center" @click="openDatePicker">
<text class="text-base text-gray-800 font-semibold">{{ displayDate }}</text>
</view>
<wd-button icon="caret-right" type="primary" :round="true" size="small" @click="changeMonth(1)" />
<wd-button type="primary" size="small" @click="goToday">
回到今天
</wd-button>
</view>
<wd-segmented v-model:value="current" :options="list"/>
</view>
<!-- 时间轴区域 -->
<view class="px-5 py-2">
<wd-empty v-if="grouped.length === 0" icon="no-content" tip="暂无记录" />
<!-- 外层每个日期分组 -->
<view v-for="group in grouped" :key="group.date" class="mb-6">
<!-- 日期分类标题 -->
<view class="mb-2 flex items-center gap-2 pl-1">
<text class="text-sm text-gray-500 font-medium">{{ group.date }}</text>
<text class="text-xs text-gray-400">{{ group.weekday }}</text>
<view class="ml-2 h-[1px] flex-1 bg-gray-200" />
</view>
<!-- 该日期下的时间轴 -->
<view class="relative pl-6">
<view
class="absolute bottom-1 top-1 w-[2px] from-[#07c160] via-[#2E5B8C] to-[#dde3e0] bg-gradient-to-b"
style="left: 0;"
/>
<view
v-for="(item, idx) in group.items"
:key="item.id || idx"
class="relative mb-5 last:mb-0"
>
<view
class="absolute border-[2.5px] border-white rounded-full shadow-sm"
style="width: 14px; height: 14px; left: -30px; top: 0; z-index: 2;"
:class="getRecordMeta(item.type).color"
/>
<!-- 卡片 -->
<view class="rounded-xl bg-white p-3.5 shadow-sm">
<view class="flex items-center justify-between">
<text class="text-xs text-gray-400 font-mono">{{ item.time }}</text>
<wd-tag :type="getRecordStatus(item).type" round>
{{ getRecordStatus(item).label }}
</wd-tag>
</view>
<view class="mt-1.5 flex items-center gap-2">
<view
class="h-7 w-7 flex items-center justify-center rounded-lg text-sm"
:class="getRecordMeta(item.type).color"
>
<text>{{ getRecordMeta(item.type).icon }}</text>
</view>
<text class="text-sm text-gray-700 font-medium">{{ getRecordMeta(item.type).label }}</text>
</view>
<text class="mt-1.5 block text-xl text-gray-800 font-bold">{{ getRecordValue(item) }}</text>
<text v-if="item.note" class="mt-0.5 block text-xs text-gray-400 leading-relaxed">
{{ item.note }}
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 日期选择器 -->
<wd-datetime-picker
v-model="currentDate"
v-model:visible="showDatePicker"
type="year-month"
:max-date="Date.now()"
@confirm="onDateConfirm"
/>
</view>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import {
getMonthRecords,
getMonthStr,
getRecordMeta,
getRecordStatus,
getRecordValue,
groupByDate,
} from '@/utils/record'
import { onShow } from "@dcloudio/uni-app";
import type { IHealthRecord } from "@/type/record";
const currentDate = ref(Date.now())
const showDatePicker = ref(false)
const list = ref<string[]>(['所有', '体重', '睡眠', '运动', '血压', '血糖', '心率'])
const current = ref('所有')
const displayDate = computed(() => {
const d = new Date(currentDate.value)
return `${d.getFullYear()}${d.getMonth() + 1}`
})
const records = ref<IHealthRecord[]>([])
const grouped = ref<ReturnType<typeof groupByDate>>([])
function loadRecords() {
const all = getMonthRecords(getMonthStr(currentDate.value))
records.value = all
grouped.value = groupByDate(all)
}
onShow(() => {
loadRecords()
})
function changeMonth(offset: number) {
const d = new Date(currentDate.value)
d.setMonth(d.getMonth() + offset)
currentDate.value = d.getTime()
loadRecords()
}
function goToday() {
currentDate.value = Date.now()
loadRecords()
}
function openDatePicker() {
showDatePicker.value = true
}
function onDateConfirm() {
loadRecords()
}
</script>
<style scoped lang="scss">
:deep(.wd-segmented) {
overflow: auto;
}
:deep(.wd-segmented__item) {
min-width: 60px;
flex-shrink: 0;
justify-content: center;
}
</style>