Initial commit: HealthManager full-stack health management platform

Backend: .NET 10 + PostgreSQL + EF Core + JWT + SignalR
Frontend patient: React 19 + TypeScript + Vite (mobile H5)
Frontend doctor: React 19 + TypeScript + Vite (desktop web)
This commit is contained in:
MingNian
2026-05-20 16:18:56 +08:00
commit 435af55c4a
215 changed files with 18595 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { PageHeader } from '@/components/layout/PageHeader';
import { Card } from '@/components/common/Card';
import { Empty } from '@/components/common/Empty';
import * as followupService from '@/services/followup.service';
import type { FollowUp } from '@/types';
import { formatDate } from '@/utils/format';
import styles from './FollowUpListPage.module.css';
export function FollowUpListPage() {
const navigate = useNavigate();
const [followups, setFollowups] = useState<FollowUp[]>([]);
const [tab, setTab] = useState<'upcoming' | 'completed'>('upcoming');
useEffect(() => {
followupService.getFollowUps().then(setFollowups);
}, []);
const filtered = followups.filter((f) => tab === 'upcoming' ? f.status === 'upcoming' : f.status === 'completed');
const statusColor = (s: FollowUp['status']) => {
if (s === 'upcoming') return '#3B82F6';
if (s === 'completed') return '#10B981';
return '#EF4444';
};
return (
<div className="page--no-tab">
<PageHeader title="复查管理" />
<div className={styles.tabs}>
<button className={`${styles.tab} ${tab === 'upcoming' ? styles.tabActive : ''}`} onClick={() => setTab('upcoming')}></button>
<button className={`${styles.tab} ${tab === 'completed' ? styles.tabActive : ''}`} onClick={() => setTab('completed')}></button>
</div>
{filtered.length === 0 ? (
<Empty icon="🏥" message="暂无复查计划" />
) : (
filtered.map((f) => (
<Card key={f.id} className={styles.card} onClick={() => navigate(`/health/medications`)}>
<div className={styles.cardHeader}>
<span className={styles.title}>{f.title}</span>
<span className={styles.status} style={{ color: statusColor(f.status) }}>
{f.status === 'upcoming' ? '待复查' : '已完成'}
</span>
</div>
<div className={styles.meta}>
<span>{f.doctorName || '未分配'} · {f.patientName || ''}</span>
</div>
<div className={styles.meta}>
<span>{formatDate(f.scheduledAt, 'YYYY-MM-DD HH:mm')}</span>
</div>
</Card>
))
)}
<button className={styles.fab} onClick={() => navigate('/services/follow-ups/add')}>+ </button>
</div>
);
}