feat: medication reminders, follow-up/visit separation, health record page
Backend: - MedicationService: today-summary with missed detection (local time) - FollowUpService: doctor-initiated follow-ups filter, AddAsync supports Notes - FollowUpController: type query param (followup/recheck) - MedicationController: today-summary endpoint - Auth: UpdateProfileRequest→class, StentDate/StentType, soft-delete fix Patient frontend: - HomePage: date display, medication reminder cards with missed status - MedicationListPage: beautified with delete button, slot preview - MedicationDetailPage: redesigned with progress bars, new CSS - ProfilePage: beautified menu icons, health record link - HealthRecordPage: new page with indicators, history, meds, reports - ServicesHub: added doctor-visit card - VisitListPage: doctor-initiated follow-ups view - EditProfilePage: removed height/weight, added stent fields - Fixed getProfile field mappings (nickname, height, weight, stent) Doctor frontend: - Layout: added 随访管理 sidebar item with SVG icon - FollowUpListPage: recheck-only filter, complete/delete buttons, collapsed completed - VisitListPage/EditPage: doctor follow-up management - PatientListPage: added stentType column - Dashboard: fixed pending reports endpoint - ReportListPage/DetailPage: fixed uploadedAt field - ChatPage: SignalR real-time, dynamic hostname
This commit is contained in:
@@ -30,77 +30,67 @@ export function ProfilePage() {
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card className={styles.statsCard}>
|
||||
<div className={styles.stat}>
|
||||
<span className={styles.statValue}>{user?.height || '-'}cm</span>
|
||||
<span className={styles.statLabel}>身高</span>
|
||||
</div>
|
||||
<div className={styles.statDivider} />
|
||||
<div className={styles.stat}>
|
||||
<span className={styles.statValue}>{user?.weight || '-'}kg</span>
|
||||
<span className={styles.statLabel}>体重</span>
|
||||
</div>
|
||||
<div className={styles.statDivider} />
|
||||
<div className={styles.stat}>
|
||||
<span className={styles.statValue}>{user?.medicalHistory?.join('、') || '-'}</span>
|
||||
<span className={styles.statLabel}>病史</span>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<div className={styles.menuList}>
|
||||
<button className={styles.menuItem} onClick={() => navigate('/health/medications')}>
|
||||
<span>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#D67E0B" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ verticalAlign: 'middle', marginRight: 10 }}>
|
||||
<rect x="4" y="5" width="16" height="14" rx="4" />
|
||||
<path d="M10 9v6M14 9v6M8 12h8" />
|
||||
</svg>
|
||||
我的用药
|
||||
<button className={styles.menuItem} onClick={() => navigate('/profile/health-record')}>
|
||||
<span className={styles.menuItemLeft}>
|
||||
<span className={styles.menuIcon} style={{ background: 'var(--color-primary-bg)' }}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--color-primary)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<line x1="16" y1="13" x2="8" y2="13" />
|
||||
<line x1="16" y1="17" x2="8" y2="17" />
|
||||
</svg>
|
||||
</span>
|
||||
健康档案
|
||||
</span>
|
||||
<span>→</span>
|
||||
</button>
|
||||
<button className={styles.menuItem} onClick={() => navigate('/notifications')}>
|
||||
<span>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#4F6EF7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ verticalAlign: 'middle', marginRight: 10 }}>
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
|
||||
</svg>
|
||||
<span className={styles.menuItemLeft}>
|
||||
<span className={styles.menuIcon} style={{ background: '#EFF6FF' }}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#339AF0" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
|
||||
</svg>
|
||||
</span>
|
||||
消息通知
|
||||
</span>
|
||||
<div className={styles.menuRight}>
|
||||
<span className={styles.menuArrow}>
|
||||
{unreadCount > 0 && <Badge count={unreadCount} />}
|
||||
<span>→</span>
|
||||
</div>
|
||||
</span>
|
||||
</button>
|
||||
<button className={styles.menuItem} onClick={() => navigate('/home/device-binding')}>
|
||||
<span>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#6366F1" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ verticalAlign: 'middle', marginRight: 10 }}>
|
||||
<rect x="5" y="2" width="14" height="20" rx="2" ry="2" />
|
||||
<line x1="12" y1="18" x2="12.01" y2="18" />
|
||||
</svg>
|
||||
<span className={styles.menuItemLeft}>
|
||||
<span className={styles.menuIcon} style={{ background: '#F3E8FF' }}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#845EF7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect x="5" y="2" width="14" height="20" rx="2" ry="2" />
|
||||
<line x1="12" y1="18" x2="12.01" y2="18" />
|
||||
</svg>
|
||||
</span>
|
||||
设备管理
|
||||
</span>
|
||||
<span>→</span>
|
||||
</button>
|
||||
<button className={styles.menuItem} onClick={() => navigate('/profile/settings')}>
|
||||
<span>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#845EF7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ verticalAlign: 'middle', marginRight: 10 }}>
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
||||
</svg>
|
||||
<span className={styles.menuItemLeft}>
|
||||
<span className={styles.menuIcon} style={{ background: '#EDF0FD' }}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#4F6EF7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
||||
</svg>
|
||||
</span>
|
||||
设置
|
||||
</span>
|
||||
<span>→</span>
|
||||
</button>
|
||||
<button className={styles.menuItem} onClick={() => navigate('/profile/settings/about')}>
|
||||
<span>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#20C997" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ verticalAlign: 'middle', marginRight: 10 }}>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="12" y1="16" x2="12" y2="12" />
|
||||
<line x1="12" y1="8" x2="12.01" y2="8" />
|
||||
</svg>
|
||||
<span className={styles.menuItemLeft}>
|
||||
<span className={styles.menuIcon} style={{ background: '#E6F9F2' }}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#20C997" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="12" y1="16" x2="12" y2="12" />
|
||||
<line x1="12" y1="8" x2="12.01" y2="8" />
|
||||
</svg>
|
||||
</span>
|
||||
关于
|
||||
</span>
|
||||
<span>→</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user