import { View, Text } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { safeNavigateTo } from '@/utils/navigate'; import { useAuthStore } from '../../stores/auth'; import { useElderClass } from '../../hooks/useElderClass'; import GuestGuard from '../../components/GuestGuard'; import Loading from '../../components/Loading'; import PageShell from '@/components/ui/PageShell'; import ContentCard from '@/components/ui/ContentCard'; import SegmentTabs from '../../components/SegmentTabs'; import { useHealthOverview, VITAL_TABS, type VitalType } from './useHealthOverview'; import { submitSuggestionFeedback } from '../../services/ai-analysis'; import './index.scss'; const QUICK_ENTRIES = [ { label: '录入体征', icon: '✏', color: 'input', path: '/pages/pkg-health/input/index' }, { label: '健康趋势', icon: '📈', color: 'trend', path: '/pages/pkg-health/trend/index' }, { label: '我的报告', icon: '📋', color: 'report', path: '/pages/pkg-profile/reports/index' }, { label: '健康档案', icon: '健', color: 'med', path: '/pages/pkg-profile/health-records/index' }, ] as const; function statusClass(status?: string): string { if (!status) return ''; if (status === 'high' || status === 'abnormal') return 'vital-warn'; if (status === 'low') return 'vital-warn'; return 'vital-ok'; } function formatDate(): string { const d = new Date(); const month = d.getMonth() + 1; const day = d.getDate(); const weekDays = ['日', '一', '二', '三', '四', '五', '六']; return `${month}月${day}日 周${weekDays[d.getDay()]}`; } export default function Health() { const user = useAuthStore((s) => s.user); const modeClass = useElderClass(); const { todaySummary, loading, error, activeTab, trendData, trendLoading, aiSuggestions, thresholds, alertCount, handleTabChange, fetchData, } = useHealthOverview(); if (!user) { return ; } if (error) { return ( 健康总览 ); } const maxTrendValue = trendData.reduce((max, d) => Math.max(max, d.value), 1); const dayLabels = ['日', '一', '二', '三', '四', '五', '六']; const summary = todaySummary || {}; const vitals = [ { label: '血压', value: summary.blood_pressure ? `${summary.blood_pressure.systolic}/${summary.blood_pressure.diastolic}` : '—', unit: 'mmHg', status: summary.blood_pressure?.status }, { label: '心率', value: summary.heart_rate ? `${summary.heart_rate.value}` : '—', unit: 'bpm', status: summary.heart_rate?.status }, { label: '血糖', value: summary.blood_sugar ? `${summary.blood_sugar.value}` : '—', unit: 'mmol/L', status: summary.blood_sugar?.status }, { label: '体重', value: summary.weight ? `${summary.weight.value}` : '—', unit: 'kg', status: summary.weight?.status }, ]; const recordedCount = vitals.filter((v) => v.value !== '—').length; const getThresholdValue = (type: VitalType): number | null => { if (!thresholds.length) return null; const th = thresholds; if (type === 'blood_pressure') { const v = th.find((t) => t.indicator === 'systolic_bp' && t.level === 'high'); return v?.threshold_value ?? 140; } if (type === 'heart_rate') { const v = th.find((t) => t.indicator === 'heart_rate' && t.level === 'high'); return v?.threshold_value ?? 100; } if (type === 'blood_sugar') { const v = th.find((t) => t.indicator === 'blood_sugar_fasting' && t.level === 'high'); return v?.threshold_value ?? 6.1; } return null; }; return ( 健康总览 {formatDate()} {/* 今日体征 hero 卡片 */} 今日体征 {recordedCount > 0 && ( 已记录 {recordedCount} 项 )} {loading ? : ( {vitals.map((v) => ( {v.value} {v.unit} {v.label} ))} )} {/* 快捷入口 — 横排 4 格图标 */} {QUICK_ENTRIES.map((e) => ( safeNavigateTo(e.path)} > {e.icon} {e.label} ))} {/* 告警横幅 */} {alertCount > 0 && ( safeNavigateTo('/pages/pkg-health/alerts/index')} > {alertCount} 条待处理告警 )} {/* AI 建议 */} {aiSuggestions.length > 0 && ( AI 健康建议 {aiSuggestions.length} 条 {aiSuggestions.map((s) => { const riskCls = s.risk_level === 'high' ? 'ai-risk-high' : s.risk_level === 'medium' ? 'ai-risk-medium' : 'ai-risk-low'; const params = s.params as Record | null; const reason = (params?.reason as string) || (params?.message as string) || '健康建议'; return ( { if (s.suggestion_type === 'appointment') safeNavigateTo('/pages/appointment/create/index'); else if (s.suggestion_type === 'followup') safeNavigateTo('/pages/pkg-profile/followups/index'); }}> {reason.slice(0, 50)} { try { await submitSuggestionFeedback(s.id, 'adopt'); Taro.showToast({ title: '已采纳', icon: 'success' }); fetchData(); } catch { Taro.showToast({ title: '操作失败', icon: 'none' }); } }}> 采纳 { try { await submitSuggestionFeedback(s.id, 'ignore'); Taro.showToast({ title: '已忽略', icon: 'success' }); fetchData(); } catch { Taro.showToast({ title: '操作失败', icon: 'none' }); } }}> 忽略 { try { await submitSuggestionFeedback(s.id, 'consult'); safeNavigateTo('/pages/consultation/index'); } catch { Taro.showToast({ title: '操作失败', icon: 'none' }); } }}> 咨询医生 ); })} )} {/* 7天趋势 */} 近 7 天趋势 {trendLoading ? : trendData.length === 0 ? ( 暂无趋势数据 ) : ( {(() => { const tv = getThresholdValue(activeTab); if (tv) { const pct = Math.min(95, (tv / maxTrendValue) * 100); return ( {tv} ); } return null; })()} {trendData.map((point, i) => { const heightPct = Math.max(8, (point.value / maxTrendValue) * 100); const tv = getThresholdValue(activeTab); const isAbnormal = tv ? point.value >= tv : false; const dayOfWeek = new Date(point.date).getDay(); return ( {dayLabels[dayOfWeek]} ); })} )} {/* 健康资讯入口 */} safeNavigateTo('/pages/article/index')}> 最新健康资讯 › ); }