Initial commit of akmon project
This commit is contained in:
209
pages/ec/elder/health-details.uvue
Normal file
209
pages/ec/elder/health-details.uvue
Normal file
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<view class="health-details">
|
||||
<view class="header">
|
||||
<text class="title">健康详情</text>
|
||||
</view>
|
||||
<view class="summary-section">
|
||||
<view class="summary-item">
|
||||
<text class="label">姓名:</text>
|
||||
<text class="value">{{ elderInfo.name }}</text>
|
||||
</view>
|
||||
<view class="summary-item">
|
||||
<text class="label">性别:</text>
|
||||
<text class="value">{{ elderInfo.gender }}</text>
|
||||
</view>
|
||||
<view class="summary-item">
|
||||
<text class="label">年龄:</text>
|
||||
<text class="value">{{ getAge(elderInfo.birthday) }}</text>
|
||||
</view>
|
||||
<view class="summary-item">
|
||||
<text class="label">房间号:</text>
|
||||
<text class="value">{{ elderInfo.room_number }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="vital-history-section">
|
||||
<text class="section-title">生命体征历史</text>
|
||||
<view v-if="vitalHistory.length > 0">
|
||||
<view class="vital-row" v-for="vital in vitalHistory" :key="vital.id">
|
||||
<text class="vital-date">{{ formatDateTime(vital.measured_at) }}</text>
|
||||
<text class="vital-type">{{ getVitalLabel(vital.vital_type) }}</text>
|
||||
<text class="vital-value">{{ getVitalValue(vital) }}</text>
|
||||
<text class="vital-status" :class="vital.is_abnormal ? 'abnormal' : 'normal'">
|
||||
{{ vital.is_abnormal ? '异常' : '正常' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="empty-state">
|
||||
<text>暂无生命体征记录</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="health-record-section">
|
||||
<text class="section-title">健康档案</text>
|
||||
<view v-if="healthRecords.length > 0">
|
||||
<view class="record-row" v-for="record in healthRecords" :key="record.id">
|
||||
<text class="record-date">{{ formatDate(record.record_date) }}</text>
|
||||
<text class="record-type">{{ getRecordTypeText(record.record_type) }}</text>
|
||||
<text class="record-summary">身高: {{ record.height_cm }}cm 体重: {{ record.weight_kg }}kg</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="empty-state">
|
||||
<text>暂无健康档案</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="alert-section">
|
||||
<text class="section-title">健康预警</text>
|
||||
<view v-if="alerts.length > 0">
|
||||
<view class="alert-row" v-for="alert in alerts" :key="alert.id">
|
||||
<text class="alert-title">{{ alert.title }}</text>
|
||||
<text class="alert-severity" :class="getSeverityClass(alert.severity)">{{ getSeverityText(alert.severity) }}</text>
|
||||
<text class="alert-time">{{ formatDateTime(alert.created_at) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="empty-state">
|
||||
<text>暂无健康预警</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import { formatDate, formatDateTime, getAge, getRecordTypeText, getSeverityText, getSeverityClass } from '../types.uts'
|
||||
import type { Elder, VitalSign, HealthAlert } from '../types.uts'
|
||||
|
||||
const elderInfo = ref<Elder>({
|
||||
id: '',
|
||||
name: '',
|
||||
gender: '',
|
||||
birthday: '',
|
||||
room_number: '',
|
||||
// ...可补充其它字段
|
||||
})
|
||||
const vitalHistory = ref<VitalSign[]>([])
|
||||
const healthRecords = ref<any[]>([])
|
||||
const alerts = ref<HealthAlert[]>([])
|
||||
|
||||
function getVitalLabel(type: string): string {
|
||||
const labels = {
|
||||
'heart_rate': '心率',
|
||||
'blood_pressure': '血压',
|
||||
'temperature': '体温',
|
||||
'blood_sugar': '血糖',
|
||||
'oxygen_saturation': '血氧'
|
||||
}
|
||||
return labels[type] || type
|
||||
}
|
||||
function getVitalValue(vital: VitalSign): string {
|
||||
switch (vital.vital_type) {
|
||||
case 'heart_rate': return vital.heart_rate ? vital.heart_rate + ' bpm' : '-'
|
||||
case 'blood_pressure': return vital.systolic_pressure && vital.diastolic_pressure ? `${vital.systolic_pressure}/${vital.diastolic_pressure} mmHg` : '-'
|
||||
case 'temperature': return vital.temperature ? vital.temperature + '°C' : '-'
|
||||
case 'blood_sugar': return vital.glucose_level ? vital.glucose_level + ' mmol/L' : '-'
|
||||
case 'oxygen_saturation': return vital.oxygen_saturation ? vital.oxygen_saturation + '%' : '-'
|
||||
default: return '-'
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async(options: OnLoadOptions) => {
|
||||
const elderId = options['id']
|
||||
if (!elderId) return
|
||||
// 获取老人基本信息
|
||||
const elderRes = await supa.rpc('get_elder_info', { elder_id: elderId }).execute()
|
||||
if (elderRes && elderRes.length > 0) elderInfo.value = elderRes[0]
|
||||
// 获取生命体征历史
|
||||
const vitalsRes = await supa.rpc('get_vital_history', { elder_id: elderId, limit: 20 }).execute()
|
||||
if (vitalsRes) vitalHistory.value = vitalsRes
|
||||
// 获取健康档案
|
||||
const healthRes = await supa.rpc('get_health_records', { elder_id: elderId }).execute()
|
||||
if (healthRes) healthRecords.value = healthRes
|
||||
// 获取健康预警
|
||||
const alertRes = await supa.rpc('get_health_alerts', { elder_id: elderId }).execute()
|
||||
if (alertRes) alerts.value = alertRes
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.health-details {
|
||||
padding: 40rpx;
|
||||
background: #f8f9fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.summary-section {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.summary-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.label {
|
||||
color: #666;
|
||||
width: 120rpx;
|
||||
}
|
||||
.value {
|
||||
color: #222;
|
||||
font-weight: 500;
|
||||
}
|
||||
.vital-history-section, .health-record-section, .alert-section {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #007AFF;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.vital-row, .record-row, .alert-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.vital-date, .record-date, .alert-time {
|
||||
width: 180rpx;
|
||||
color: #888;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.vital-type, .record-type, .alert-title {
|
||||
width: 120rpx;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.vital-value, .record-summary {
|
||||
flex: 1;
|
||||
color: #222;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.vital-status.normal {
|
||||
color: #4caf50;
|
||||
}
|
||||
.vital-status.abnormal {
|
||||
color: #f44336;
|
||||
}
|
||||
.alert-severity {
|
||||
margin-left: 16rpx;
|
||||
font-size: 26rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
.empty-state {
|
||||
color: #aaa;
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user