From 722ee76d93ebcbbe090106f2ed0ce86a135abdc8 Mon Sep 17 00:00:00 2001 From: MingNian <1281442923@qq.com> Date: Fri, 22 May 2026 17:48:18 +0800 Subject: [PATCH] refactor: patient frontend UI overhaul - Reworked design system (variables, global styles, component CSS) - Updated TabBar with icon-based navigation - Redesigned HomePage, HealthHub, ServicesHub layouts - Improved Exercise/Diet, Medication, Profile pages styling - Simplified constants (removed emoji icons, streamlined data) - Fixed launch.json cwd paths for frontend projects --- .claude/launch.json | 12 +- frontend-patient/src/assets/styles/global.css | 44 +++++ .../src/assets/styles/variables.css | 63 +++--- .../src/components/common/Badge.module.css | 12 +- .../src/components/common/Button.module.css | 28 +-- .../src/components/common/Card.module.css | 8 +- .../src/components/common/Empty.module.css | 17 +- .../src/components/common/Empty.tsx | 15 +- .../src/components/common/Input.module.css | 7 +- .../src/components/common/Toast.module.css | 1 + .../components/layout/AppLayout.module.css | 1 + .../components/layout/PageHeader.module.css | 6 +- .../src/components/layout/TabBar.module.css | 54 +++-- .../src/components/layout/TabBar.tsx | 45 ++++- frontend-patient/src/pages/auth/LoginPage.tsx | 6 +- .../exercise-diet/ExerciseDietPage.module.css | 10 +- .../pages/exercise-diet/ExerciseDietPage.tsx | 6 +- .../src/pages/health/HealthHubPage.module.css | 32 ++- .../src/pages/health/HealthHubPage.tsx | 187 ++++++++++++------ .../health/HealthRecordListPage.module.css | 8 +- .../src/pages/health/HealthRecordListPage.tsx | 4 +- .../src/pages/home/DeviceBindingPage.tsx | 6 +- .../src/pages/home/HomePage.module.css | 163 +++++++++------ frontend-patient/src/pages/home/HomePage.tsx | 154 ++++++++++++--- .../MedicationDetailPage.module.css | 6 +- .../pages/medication/MedicationDetailPage.tsx | 2 +- .../medication/MedicationEditPage.module.css | 2 +- .../pages/medication/MedicationEditPage.tsx | 2 +- .../medication/MedicationListPage.module.css | 5 +- .../pages/medication/MedicationListPage.tsx | 78 +++----- .../notifications/NotificationListPage.tsx | 2 +- .../src/pages/profile/ProfilePage.module.css | 47 +++-- .../src/pages/profile/ProfilePage.tsx | 41 +++- .../src/pages/profile/staticPages.tsx | 6 +- .../pages/services/DoctorListPage.module.css | 15 +- .../src/pages/services/DoctorListPage.tsx | 2 +- .../services/FollowUpListPage.module.css | 4 +- .../src/pages/services/FollowUpListPage.tsx | 2 +- .../pages/services/ReportListPage.module.css | 4 +- .../src/pages/services/ReportListPage.tsx | 2 +- .../src/pages/services/ReportUploadPage.tsx | 8 +- .../pages/services/ServicesHubPage.module.css | 27 ++- .../src/pages/services/ServicesHubPage.tsx | 49 ++++- frontend-patient/src/utils/constants.ts | 54 ++--- 44 files changed, 854 insertions(+), 393 deletions(-) diff --git a/.claude/launch.json b/.claude/launch.json index 1a64841..7e61951 100644 --- a/.claude/launch.json +++ b/.claude/launch.json @@ -2,10 +2,18 @@ "version": "0.0.1", "configurations": [ { - "name": "健康管家 Web Demo", + "name": "健康管家-患者端", "runtimeExecutable": "cmd.exe", "runtimeArgs": ["/c", "D:\\nodejs\\npm.cmd", "run", "dev"], - "port": 5175 + "cwd": "D:\\APP\\frontend-patient", + "port": 5173 + }, + { + "name": "健康管家-医生端", + "runtimeExecutable": "cmd.exe", + "runtimeArgs": ["/c", "D:\\nodejs\\npm.cmd", "run", "dev"], + "cwd": "D:\\APP\\frontend-doctor", + "port": 5174 } ] } diff --git a/frontend-patient/src/assets/styles/global.css b/frontend-patient/src/assets/styles/global.css index 53930b6..f311521 100644 --- a/frontend-patient/src/assets/styles/global.css +++ b/frontend-patient/src/assets/styles/global.css @@ -36,7 +36,51 @@ white-space: nowrap; } +/* Section Title */ +.section-title { + font-size: var(--font-size-md); + font-weight: 700; + color: var(--color-text-primary); + margin-bottom: 12px; + display: flex; + align-items: center; + gap: 8px; +} + +.section-title::before { + content: ''; + width: 4px; + height: 18px; + border-radius: 2px; + background: var(--color-primary); +} + +/* Tag */ +.tag { + display: inline-flex; + align-items: center; + padding: 3px 10px; + border-radius: 20px; + font-size: 11px; + font-weight: 600; +} +.tag-success { background: var(--color-success-bg); color: #0D8A5E; } +.tag-warning { background: var(--color-warning-bg); color: #D67E0B; } +.tag-danger { background: var(--color-danger-bg); color: #D53131; } +.tag-info { background: var(--color-primary-bg); color: var(--color-primary); } +.tag-primary { background: var(--color-primary-bg); color: var(--color-primary); } + /* Transitions */ +@keyframes fadeInUp { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes pulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.06); } +} + .page-enter { animation: slideInRight 0.3s ease-out; } diff --git a/frontend-patient/src/assets/styles/variables.css b/frontend-patient/src/assets/styles/variables.css index 6bf59dc..c3c245c 100644 --- a/frontend-patient/src/assets/styles/variables.css +++ b/frontend-patient/src/assets/styles/variables.css @@ -1,30 +1,39 @@ :root { - /* Primary - Rich Medical Blue */ - --color-primary: #2563EB; - --color-primary-light: #3B82F6; - --color-primary-dark: #1D4ED8; - --color-primary-bg: #EFF6FF; - --color-primary-gradient: linear-gradient(135deg, #2563EB, #4F8AF8); + /* Primary - Modern Indigo Blue */ + --color-primary: #4F6EF7; + --color-primary-light: #6C8CFF; + --color-primary-dark: #3D56D4; + --color-primary-bg: #EEF1FE; + --color-primary-gradient: linear-gradient(135deg, #4F6EF7, #6C8CFF); + + /* Accent */ + --color-accent-red: #FF6B6B; + --color-accent-orange: #FFA94D; + --color-accent-green: #20C997; + --color-accent-purple: #845EF7; + --color-accent-sky: #339AF0; + --color-accent-pink: #F06595; /* Status */ - --color-success: #10B981; - --color-success-bg: #ECFDF5; + --color-success: #20C997; + --color-success-bg: #E6F9F2; --color-warning: #F59E0B; - --color-warning-bg: #FFFBEB; - --color-danger: #EF4444; - --color-danger-bg: #FEF2F2; + --color-warning-bg: #FFF4E5; + --color-danger: #FF6B6B; + --color-danger-bg: #FEE9E9; /* Neutral */ --color-white: #FFFFFF; - --color-bg: #F4F6FA; - --color-bg-secondary: #EBEEF3; - --color-border: #E4E7EC; - --color-border-light: #F0F1F4; + --color-bg: #F0F4F8; + --color-bg-secondary: #E8ECF2; + --color-border: #E4E8EE; + --color-border-light: #EEF1F6; + --color-divider: #EDF0F5; /* Text */ - --color-text-primary: #1A1E2B; - --color-text-secondary: #6B7280; - --color-text-tertiary: #9CA3AF; + --color-text-primary: #1A1D28; + --color-text-secondary: #5A5F72; + --color-text-tertiary: #9BA0B4; --color-text-inverse: #FFFFFF; /* Spacing */ @@ -37,21 +46,21 @@ --spacing-3xl: 32px; /* Border radius */ - --radius-sm: 8px; - --radius-md: 12px; + --radius-sm: 10px; + --radius-md: 14px; --radius-lg: 16px; --radius-xl: 20px; --radius-2xl: 24px; --radius-full: 9999px; /* Shadows */ - --shadow-xs: 0 1px 2px rgba(0,0,0,0.04); - --shadow-sm: 0 2px 8px rgba(0,0,0,0.05); - --shadow-md: 0 4px 16px rgba(0,0,0,0.07); - --shadow-lg: 0 8px 32px rgba(0,0,0,0.09); + --shadow-xs: 0 1px 3px rgba(0,0,0,0.03); + --shadow-sm: 0 2px 12px rgba(0,0,0,0.04); + --shadow-md: 0 4px 20px rgba(0,0,0,0.06); + --shadow-lg: 0 8px 30px rgba(0,0,0,0.08); /* Font */ - --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + --font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; --font-size-xs: 11px; --font-size-sm: 12px; --font-size-base: 14px; @@ -62,8 +71,8 @@ --font-size-3xl: 32px; /* Layout */ - --tab-bar-height: 56px; - --header-height: 48px; + --tab-bar-height: 64px; + --header-height: 50px; --max-content-width: 414px; /* Z-index */ diff --git a/frontend-patient/src/components/common/Badge.module.css b/frontend-patient/src/components/common/Badge.module.css index b1389f1..0f1ff32 100644 --- a/frontend-patient/src/components/common/Badge.module.css +++ b/frontend-patient/src/components/common/Badge.module.css @@ -2,14 +2,14 @@ display: inline-flex; align-items: center; justify-content: center; - min-width: 18px; - height: 18px; - padding: 0 5px; + min-width: 20px; + height: 20px; + padding: 0 6px; border-radius: 10px; - background: var(--color-danger); + background: var(--color-accent-red); color: white; font-size: 10px; - font-weight: 600; + font-weight: 700; line-height: 1; } @@ -18,5 +18,5 @@ width: 8px; height: 8px; border-radius: 50%; - background: var(--color-danger); + background: var(--color-accent-red); } diff --git a/frontend-patient/src/components/common/Button.module.css b/frontend-patient/src/components/common/Button.module.css index 4e2a20b..65408f2 100644 --- a/frontend-patient/src/components/common/Button.module.css +++ b/frontend-patient/src/components/common/Button.module.css @@ -4,7 +4,7 @@ justify-content: center; gap: var(--spacing-sm); border-radius: var(--radius-md); - font-weight: 500; + font-weight: 600; transition: all 0.2s; cursor: pointer; -webkit-tap-highlight-color: transparent; @@ -21,11 +21,13 @@ .lg { padding: 12px 24px; font-size: var(--font-size-md); } .primary { - background: var(--color-primary); + background: var(--color-primary-gradient); color: var(--color-text-inverse); + box-shadow: 0 4px 14px rgba(79,110,247,0.3); } .primary:hover:not(:disabled) { - background: var(--color-primary-dark); + box-shadow: 0 6px 20px rgba(79,110,247,0.35); + transform: translateY(-1px); } .secondary { @@ -48,24 +50,4 @@ .text { background: transparent; color: var(--color-primary); - padding-left: 4px; - padding-right: 4px; -} -.text:hover:not(:disabled) { - opacity: 0.8; -} - -.fullWidth { width: 100%; } - -.spinner { - width: 16px; - height: 16px; - border: 2px solid currentColor; - border-top-color: transparent; - border-radius: 50%; - animation: spin 0.6s linear infinite; -} - -@keyframes spin { - to { transform: rotate(360deg); } } diff --git a/frontend-patient/src/components/common/Card.module.css b/frontend-patient/src/components/common/Card.module.css index 37e4675..aa11722 100644 --- a/frontend-patient/src/components/common/Card.module.css +++ b/frontend-patient/src/components/common/Card.module.css @@ -1,17 +1,17 @@ .card { background: var(--color-white); - border-radius: var(--radius-lg); - padding: var(--spacing-lg); + border-radius: var(--radius-xl); + padding: 18px; box-shadow: var(--shadow-sm); + transition: transform 0.2s, box-shadow 0.2s; } .clickable { cursor: pointer; -webkit-tap-highlight-color: transparent; - transition: transform 0.15s, box-shadow 0.15s; } .clickable:active { - transform: scale(0.98); + transform: scale(0.985); box-shadow: var(--shadow-md); } diff --git a/frontend-patient/src/components/common/Empty.module.css b/frontend-patient/src/components/common/Empty.module.css index 4d2e8bd..42f21d3 100644 --- a/frontend-patient/src/components/common/Empty.module.css +++ b/frontend-patient/src/components/common/Empty.module.css @@ -7,11 +7,24 @@ } .icon { - font-size: 48px; - margin-bottom: 12px; + width: 64px; + height: 64px; + border-radius: 20px; + background: var(--color-bg-secondary); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 14px; +} + +.icon svg { + width: 32px; + height: 32px; + stroke: var(--color-text-tertiary); } .message { font-size: var(--font-size-sm); color: var(--color-text-tertiary); + font-weight: 500; } diff --git a/frontend-patient/src/components/common/Empty.tsx b/frontend-patient/src/components/common/Empty.tsx index 9d32335..5464a73 100644 --- a/frontend-patient/src/components/common/Empty.tsx +++ b/frontend-patient/src/components/common/Empty.tsx @@ -1,14 +1,23 @@ import styles from './Empty.module.css'; interface EmptyProps { - icon?: string; + icon?: React.ReactNode; message?: string; } -export function Empty({ icon = '📭', message = '暂无数据' }: EmptyProps) { +const DEFAULT_ICON = ( + +); + +export function Empty({ icon = DEFAULT_ICON, message = '暂无数据' }: EmptyProps) { return (
{message}
心脏健康管理平台
{d.description}