瀏覽代碼

feat: 完善数智健调系统前端功能与样式

- 更新全局样式变量,增强主题色彩和阴影效果
- 重构登录组件,增加用户名和密码输入框,优化按钮样式
- 添加用户中心、饮食、运动等模块的路由
- 更新仪表盘和饮食模块的样式,增加进度条和图表展示
- 删除首次使用页面,简化用户体验
- 引入 ECharts 依赖,支持数据可视化功能
17846405080 1 周之前
父節點
當前提交
33c621911a
共有 28 個文件被更改,包括 2091 次插入367 次删除
  1. 29 1
      campus_health_app/frontend/campus-health-app/src/app/app.routes.server.ts
  2. 0 4
      campus_health_app/frontend/campus-health-app/src/app/app.routes.ts
  3. 38 3
      campus_health_app/frontend/campus-health-app/src/app/modules/auth/login/login.component.html
  4. 223 34
      campus_health_app/frontend/campus-health-app/src/app/modules/auth/login/login.component.scss
  5. 21 4
      campus_health_app/frontend/campus-health-app/src/app/modules/auth/login/login.component.ts
  6. 6 0
      campus_health_app/frontend/campus-health-app/src/app/modules/dashboard/dashboard.component.html
  7. 232 67
      campus_health_app/frontend/campus-health-app/src/app/modules/dashboard/dashboard.component.scss
  8. 7 0
      campus_health_app/frontend/campus-health-app/src/app/modules/dashboard/dashboard.component.ts
  9. 34 0
      campus_health_app/frontend/campus-health-app/src/app/modules/diet/diet.component.html
  10. 232 61
      campus_health_app/frontend/campus-health-app/src/app/modules/diet/diet.component.scss
  11. 50 0
      campus_health_app/frontend/campus-health-app/src/app/modules/exercise/exercise.component.html
  12. 187 32
      campus_health_app/frontend/campus-health-app/src/app/modules/exercise/exercise.component.scss
  13. 0 20
      campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.component.html
  14. 0 79
      campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.component.scss
  15. 0 25
      campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.component.ts
  16. 0 10
      campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.routes.ts
  17. 22 15
      campus_health_app/frontend/campus-health-app/src/app/modules/monitoring/monitoring.component.scss
  18. 115 7
      campus_health_app/frontend/campus-health-app/src/styles.scss
  19. 46 0
      test-app/package-lock.json
  20. 2 0
      test-app/package.json
  21. 9 1
      test-app/src/app/app-routing.module.ts
  22. 2 1
      test-app/src/app/app.component.ts
  23. 4 3
      test-app/src/app/app.module.ts
  24. 19 0
      test-app/src/app/health-dashboard/health-dashboard-routing.module.ts
  25. 109 0
      test-app/src/app/health-dashboard/health-dashboard.component.html
  26. 379 0
      test-app/src/app/health-dashboard/health-dashboard.component.scss
  27. 310 0
      test-app/src/app/health-dashboard/health-dashboard.component.ts
  28. 15 0
      test-app/src/app/health-dashboard/health-dashboard.module.ts

+ 29 - 1
campus_health_app/frontend/campus-health-app/src/app/app.routes.server.ts

@@ -7,7 +7,35 @@ export const serverRoutes: Routes = [
   {
     path: 'login',
     component: LoginComponent,
-    title: '登录 - 校园运动健康APP'
+    title: '登录 - 数智健调系统'
+  },
+  {
+    path: 'dashboard',
+    loadChildren: () => import('./modules/dashboard/dashboard.routes').then(m => m.dashboardRoutes)
+  },
+  {
+    path: 'user-center',
+    loadChildren: () => import('./modules/user-center/user-center.routes').then(m => m.userCenterRoutes)
+  },
+  {
+    path: 'diet',
+    loadChildren: () => import('./modules/diet/diet.routes').then(m => m.dietRoutes)
+  },
+  {
+    path: 'exercise',
+    loadChildren: () => import('./modules/exercise/exercise.routes').then(m => m.exerciseRoutes)
+  },
+  {
+    path: 'monitoring',
+    loadChildren: () => import('./modules/monitoring/monitoring.routes').then(m => m.monitoringRoutes)
+  },
+  {
+    path: 'knowledge',
+    loadChildren: () => import('./modules/knowledge/knowledge.routes').then(m => m.knowledgeRoutes)
+  },
+  {
+    path: 'school-services',
+    loadChildren: () => import('./modules/school-services/school-services.routes').then(m => m.schoolServicesRoutes)
   },
   {
     path: '',

+ 0 - 4
campus_health_app/frontend/campus-health-app/src/app/app.routes.ts

@@ -7,10 +7,6 @@ export const routes: Routes = [
     component: LoginComponent,
     title: '登录 - 数智健调系统'
   },
-  {
-    path: 'first-use',
-    loadChildren: () => import('./modules/first-use/first-use.routes').then(m => m.firstUseRoutes)
-  },
   {
     path: 'dashboard',
     loadChildren: () => import('./modules/dashboard/dashboard.routes').then(m => m.dashboardRoutes)

+ 38 - 3
campus_health_app/frontend/campus-health-app/src/app/modules/auth/login/login.component.html

@@ -8,22 +8,57 @@
         </svg>
       </div>
       <h1>数智健调系统</h1>
+      <p class="subtitle">让健康管理更智能</p>
     </div>
 
     <div class="login-form">
+      <div class="form-group">
+        <label for="username">用户名</label>
+        <input 
+          type="text" 
+          id="username" 
+          class="form-control" 
+          placeholder="请输入用户名"
+          [(ngModel)]="username"
+        >
+      </div>
+      
+      <div class="form-group">
+        <label for="password">密码</label>
+        <input 
+          type="password" 
+          id="password" 
+          class="form-control" 
+          placeholder="请输入密码"
+          [(ngModel)]="password"
+        >
+      </div>
+
       <button
         type="button"
         [disabled]="isLoading"
         class="btn-login"
         (click)="onSubmit()"
       >
-        <span *ngIf="!isLoading">进入系统</span>
-        <span *ngIf="isLoading">加载中...</span>
+        <span *ngIf="!isLoading" class="btn-text">
+          <span class="btn-icon">🚀</span>
+          进入系统
+        </span>
+        <span *ngIf="isLoading" class="loading-content">
+          <span class="spinner"></span>
+          加载中...
+        </span>
       </button>
+
+      <div class="links-container">
+        <button class="link-btn" (click)="showForgotPassword()">忘记密码?</button>
+        <span class="separator">|</span>
+        <button class="link-btn" (click)="showRegister()">注册账号</button>
+      </div>
     </div>
 
     <div class="footer-text">
-      <p>© 2025 数智健调系统</p>
+      <p>© 2025 数智健调系统 - 让健康管理更智能</p>
     </div>
   </div>
 </div>

+ 223 - 34
campus_health_app/frontend/campus-health-app/src/app/modules/auth/login/login.component.scss

@@ -6,70 +6,149 @@
   min-height: 100vh;
   background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
   padding: 20px;
+  position: relative;
+  overflow: hidden;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: -50%;
+    left: -50%;
+    width: 200%;
+    height: 200%;
+    background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
+    animation: float 20s ease-in-out infinite;
+  }
+}
+
+@keyframes float {
+  0%, 100% { transform: translate(0, 0) rotate(0deg); }
+  33% { transform: translate(30px, -30px) rotate(120deg); }
+  66% { transform: translate(-20px, 20px) rotate(240deg); }
 }
 
 .login-box {
-  background: white;
-  border-radius: 20px;
-  padding: 40px;
-  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
-  max-width: 400px;
+  background: rgba(255, 255, 255, 0.95);
+  backdrop-filter: blur(10px);
+  border-radius: 24px;
+  padding: 48px 40px;
+  box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
+  max-width: 420px;
   width: 100%;
+  position: relative;
+  z-index: 1;
+  animation: slideUp 0.8s ease-out;
+}
+
+@keyframes slideUp {
+  from {
+    opacity: 0;
+    transform: translateY(30px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
 }
 
 .logo-container {
   text-align: center;
-  margin-bottom: 30px;
+  margin-bottom: 40px;
 }
 
 .logo {
-  margin: 0 auto 20px;
+  margin: 0 auto 24px;
+  animation: pulse 2s ease-in-out infinite;
+}
+
+@keyframes pulse {
+  0%, 100% { transform: scale(1); }
+  50% { transform: scale(1.05); }
 }
 
 .logo-container h1 {
   color: #1f2937;
-  font-size: 24px;
+  font-size: 28px;
   font-weight: 700;
+  margin: 0 0 8px 0;
+  background: linear-gradient(135deg, #1f2937 0%, #4f46e5 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+}
+
+.subtitle {
+  color: #6b7280;
+  font-size: 14px;
   margin: 0;
+  font-weight: 400;
 }
 
 .login-form {
   display: flex;
   flex-direction: column;
-  gap: 20px;
+  gap: 24px;
 }
 
 .form-group {
   display: flex;
   flex-direction: column;
   gap: 8px;
+  animation: fadeInUp 0.6s ease-out;
+  animation-fill-mode: both;
+  
+  &:nth-child(1) { animation-delay: 0.1s; }
+  &:nth-child(2) { animation-delay: 0.2s; }
+}
+
+@keyframes fadeInUp {
+  from {
+    opacity: 0;
+    transform: translateY(20px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
 }
 
 .form-group label {
-  color: #4b5563;
+  color: #374151;
   font-size: 14px;
-  font-weight: 500;
+  font-weight: 600;
+  margin-bottom: 4px;
 }
 
 .form-control {
-  padding: 12px 16px;
+  padding: 16px 20px;
   border: 2px solid #e5e7eb;
-  border-radius: 12px;
+  border-radius: 16px;
   font-size: 16px;
-  transition: all 0.3s ease;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
   background-color: #f9fafb;
+  color: #1f2937;
 
   &:focus {
     outline: none;
-    border-color: #34d399;
+    border-color: #4f46e5;
     background-color: white;
-    box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.1);
+    box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.1);
+    transform: translateY(-1px);
+  }
+
+  &:hover:not(:focus) {
+    border-color: #d1d5db;
+    background-color: #f3f4f6;
   }
 
   &:disabled {
     opacity: 0.6;
     cursor: not-allowed;
   }
+
+  &::placeholder {
+    color: #9ca3af;
+  }
 }
 
 .error-message {
@@ -82,19 +161,41 @@
 }
 
 .btn-login {
-  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
+  background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
   color: white;
   border: none;
-  padding: 14px 24px;
-  border-radius: 12px;
+  padding: 18px 32px;
+  border-radius: 16px;
   font-size: 16px;
   font-weight: 600;
   cursor: pointer;
-  transition: all 0.3s ease;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  position: relative;
+  overflow: hidden;
+  animation: fadeInUp 0.6s ease-out 0.3s both;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
+    transition: left 0.5s;
+  }
 
   &:hover:not(:disabled) {
-    transform: translateY(-2px);
-    box-shadow: 0 10px 25px -5px rgba(16, 185, 129, 0.5);
+    transform: translateY(-3px);
+    box-shadow: 0 15px 35px -5px rgba(79, 70, 229, 0.4);
+    
+    &::before {
+      left: 100%;
+    }
+  }
+
+  &:active:not(:disabled) {
+    transform: translateY(-1px);
   }
 
   &:disabled {
@@ -105,65 +206,153 @@
   }
 }
 
+.btn-text {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+}
+
+.btn-icon {
+  font-size: 18px;
+  animation: bounce 2s infinite;
+}
+
+@keyframes bounce {
+  0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
+  40% { transform: translateY(-3px); }
+  60% { transform: translateY(-2px); }
+}
+
+.loading-content {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 12px;
+}
+
+.spinner {
+  width: 20px;
+  height: 20px;
+  border: 2px solid rgba(255, 255, 255, 0.3);
+  border-top: 2px solid white;
+  border-radius: 50%;
+  animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
 .links-container {
   display: flex;
   justify-content: center;
   align-items: center;
   gap: 16px;
-  margin-top: 10px;
+  margin-top: 16px;
+  animation: fadeInUp 0.6s ease-out 0.4s both;
 }
 
 .link-btn {
   background: none;
   border: none;
-  color: #059669;
+  color: #4f46e5;
   cursor: pointer;
   font-size: 14px;
   font-weight: 500;
-  transition: color 0.3s ease;
+  transition: all 0.3s ease;
+  padding: 8px 12px;
+  border-radius: 8px;
 
   &:hover {
-    color: #047857;
+    color: #7c3aed;
+    background-color: rgba(79, 70, 229, 0.1);
+    transform: translateY(-1px);
+  }
+
+  &:active {
+    transform: translateY(0);
   }
 }
 
 .separator {
   color: #d1d5db;
+  font-weight: 300;
 }
 
 .footer-text {
   text-align: center;
-  margin-top: 30px;
+  margin-top: 32px;
   font-size: 12px;
   color: #6b7280;
+  animation: fadeInUp 0.6s ease-out 0.5s both;
 }
 
 .text-link {
-  color: #059669;
+  color: #4f46e5;
   text-decoration: none;
+  transition: color 0.3s ease;
 
   &:hover {
+    color: #7c3aed;
     text-decoration: underline;
   }
 }
 
 // 响应式设计
 @media (max-width: 480px) {
+  .login-container {
+    padding: 16px;
+  }
+
+  .login-box {
+    padding: 32px 24px;
+    border-radius: 20px;
+  }
+
+  .logo-container h1 {
+    font-size: 24px;
+  }
+
+  .subtitle {
+    font-size: 13px;
+  }
+
+  .form-control {
+    padding: 14px 16px;
+    font-size: 16px;
+  }
+
+  .btn-login {
+    padding: 16px 24px;
+    font-size: 16px;
+  }
+
+  .links-container {
+    flex-direction: column;
+    gap: 12px;
+  }
+
+  .separator {
+    display: none;
+  }
+}
+
+@media (max-width: 360px) {
   .login-box {
-    padding: 30px 20px;
+    padding: 24px 20px;
   }
 
   .logo-container h1 {
-    font-size: 20px;
+    font-size: 22px;
   }
 
   .form-control {
-    padding: 10px 14px;
-    font-size: 14px;
+    padding: 12px 14px;
   }
 
   .btn-login {
-    padding: 12px 20px;
-    font-size: 14px;
+    padding: 14px 20px;
   }
 }

+ 21 - 4
campus_health_app/frontend/campus-health-app/src/app/modules/auth/login/login.component.ts

@@ -1,29 +1,46 @@
 import { Component } from '@angular/core';
 import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
 import { Router } from '@angular/router';
 
 @Component({
   selector: 'app-login',
   standalone: true,
-  imports: [CommonModule],
+  imports: [CommonModule, FormsModule],
   templateUrl: './login.component.html',
   styleUrl: './login.component.scss'
 })
 export class LoginComponent {
   isLoading = false;
+  username = '';
+  password = '';
 
   constructor(
     private router: Router
   ) {}
 
   onSubmit(): void {
+    // 简单的表单验证
+    if (!this.username.trim() || !this.password.trim()) {
+      alert('请输入用户名和密码');
+      return;
+    }
+
     this.isLoading = true;
     
     // 模拟加载延迟
     setTimeout(() => {
       this.isLoading = false;
-      // 直接跳转到首页
-      this.router.navigate(['/first-use']);
-    }, 1000);
+      // 直接跳转到工作台
+      this.router.navigate(['/dashboard']);
+    }, 1500);
+  }
+
+  showForgotPassword(): void {
+    alert('忘记密码功能开发中...');
+  }
+
+  showRegister(): void {
+    alert('注册功能开发中...');
   }
 }

+ 6 - 0
campus_health_app/frontend/campus-health-app/src/app/modules/dashboard/dashboard.component.html

@@ -3,9 +3,15 @@
   <header class="dashboard-header">
     <div class="header-left">
       <h1>数智健调系统</h1>
+      <span class="header-subtitle">健康管理平台</span>
     </div>
     <div class="header-right">
+      <div class="user-info">
+        <span class="welcome-text">欢迎回来!</span>
+        <div class="user-avatar">👤</div>
+      </div>
       <button class="nav-button" (click)="navigateTo('user-center')">个人中心</button>
+      <button class="logout-button" (click)="logout()">退出登录</button>
     </div>
   </header>
 

+ 232 - 67
campus_health_app/frontend/campus-health-app/src/app/modules/dashboard/dashboard.component.scss

@@ -13,30 +13,99 @@
   display: flex;
   justify-content: space-between;
   align-items: center;
-  padding: 1rem 2rem;
-  background-color: #fff;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  padding: 1.5rem 2rem;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  color: white;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
   position: relative;
   z-index: 10;
 }
 
+.header-left {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+}
+
 .header-left h1 {
   margin: 0;
-  font-size: 1.5rem;
-  color: #1a73e8;
+  font-size: 1.8rem;
+  font-weight: 700;
+  color: white;
 }
 
-.nav-button {
+.header-subtitle {
+  font-size: 0.9rem;
+  color: rgba(255, 255, 255, 0.8);
+  font-weight: 400;
+}
+
+.header-right {
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+}
+
+.user-info {
+  display: flex;
+  align-items: center;
+  gap: 0.8rem;
   padding: 0.5rem 1rem;
-  background-color: #f5f7fa;
-  border: 1px solid #ddd;
-  border-radius: 4px;
+  background: rgba(255, 255, 255, 0.1);
+  border-radius: 12px;
+  backdrop-filter: blur(10px);
+}
+
+.welcome-text {
+  font-size: 0.9rem;
+  color: rgba(255, 255, 255, 0.9);
+}
+
+.user-avatar {
+  width: 32px;
+  height: 32px;
+  background: rgba(255, 255, 255, 0.2);
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 1.2rem;
+}
+
+.nav-button {
+  padding: 0.75rem 1.5rem;
+  background: rgba(255, 255, 255, 0.1);
+  border: 1px solid rgba(255, 255, 255, 0.2);
+  border-radius: 12px;
+  color: white;
   cursor: pointer;
   transition: all 0.3s ease;
+  font-weight: 500;
+  backdrop-filter: blur(10px);
+
+  &:hover {
+    background: rgba(255, 255, 255, 0.2);
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  }
 }
 
-.nav-button:hover {
-  background-color: #e8eaed;
+.logout-button {
+  padding: 0.75rem 1.5rem;
+  background: rgba(239, 68, 68, 0.8);
+  border: 1px solid rgba(239, 68, 68, 0.3);
+  border-radius: 12px;
+  color: white;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  font-weight: 500;
+  backdrop-filter: blur(10px);
+
+  &:hover {
+    background: rgba(239, 68, 68, 1);
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
+  }
 }
 
 // 主体内容布局
@@ -48,10 +117,11 @@
 
 // 侧边栏样式
 .dashboard-sidebar {
-  width: 200px;
-  background-color: #fff;
-  box-shadow: 2px 0 4px rgba(0, 0, 0, 0.05);
-  padding: 1rem 0;
+  width: 220px;
+  background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
+  box-shadow: 4px 0 12px rgba(0, 0, 0, 0.05);
+  padding: 1.5rem 0;
+  border-right: 1px solid #e2e8f0;
 }
 
 .nav-list {
@@ -63,29 +133,58 @@
 .nav-item {
   display: flex;
   align-items: center;
-  padding: 0.8rem 1.5rem;
+  padding: 1rem 1.5rem;
   cursor: pointer;
-  transition: all 0.3s ease;
-  border-left: 3px solid transparent;
-}
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  border-left: 4px solid transparent;
+  margin: 0.25rem 0;
+  position: relative;
 
-.nav-item:hover {
-  background-color: #f8f9fa;
+  &::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    width: 0;
+    background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
+    transition: width 0.3s ease;
+  }
+
+  &:hover {
+    background: linear-gradient(90deg, rgba(79, 70, 229, 0.05) 0%, transparent 100%);
+    transform: translateX(4px);
+    
+    &::before {
+      width: 4px;
+    }
+  }
+
+  &.active {
+    background: linear-gradient(90deg, rgba(79, 70, 229, 0.1) 0%, transparent 100%);
+    border-left-color: #4f46e5;
+    color: #4f46e5;
+    font-weight: 600;
+    
+    &::before {
+      width: 4px;
+    }
+  }
 }
 
-.nav-item.active {
-  background-color: #e8f0fe;
-  border-left-color: #1a73e8;
-  color: #1a73e8;
+.nav-icon {
+  margin-right: 1rem;
+  font-size: 1.3rem;
+  transition: transform 0.3s ease;
 }
 
-.nav-icon {
-  margin-right: 0.8rem;
-  font-size: 1.2rem;
+.nav-item:hover .nav-icon {
+  transform: scale(1.1);
 }
 
 .nav-text {
-  font-size: 0.95rem;
+  font-size: 1rem;
+  font-weight: 500;
 }
 
 // 主内容区域样式
@@ -115,39 +214,75 @@
 // 仪表盘卡片样式
 .dashboard-cards {
   display: grid;
-  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
-  gap: 1.5rem;
+  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+  gap: 2rem;
   margin-bottom: 2rem;
 }
 
 .dashboard-card {
-  background-color: #fff;
-  border-radius: 8px;
-  padding: 1.5rem;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-  transition: transform 0.2s ease, box-shadow 0.2s ease;
-}
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+  border-radius: 16px;
+  padding: 2rem;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  border: 1px solid rgba(226, 232, 240, 0.5);
+  position: relative;
+  overflow: hidden;
 
-.dashboard-card:hover {
-  transform: translateY(-2px);
-  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 4px;
+    background: linear-gradient(90deg, #4f46e5 0%, #7c3aed 100%);
+    transform: scaleX(0);
+    transition: transform 0.3s ease;
+  }
+
+  &:hover {
+    transform: translateY(-8px);
+    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+    
+    &::before {
+      transform: scaleX(1);
+    }
+  }
 }
 
 .card-icon {
-  font-size: 2rem;
-  margin-bottom: 1rem;
+  font-size: 2.5rem;
+  margin-bottom: 1.5rem;
+  display: block;
+  animation: float 3s ease-in-out infinite;
+}
+
+@keyframes float {
+  0%, 100% { transform: translateY(0px); }
+  50% { transform: translateY(-5px); }
 }
 
 .card-content h3 {
-  margin: 0 0 0.5rem 0;
-  font-size: 1.1rem;
-  color: #202124;
+  margin: 0 0 0.8rem 0;
+  font-size: 1.2rem;
+  color: #1e293b;
+  font-weight: 600;
 }
 
 .card-content p {
   margin: 0;
-  color: #5f6368;
-  font-size: 0.9rem;
+  color: #64748b;
+  font-size: 1rem;
+  line-height: 1.5;
+}
+
+.click-hint {
+  font-size: 0.85rem;
+  color: #4f46e5;
+  margin-top: 0.8rem;
+  font-weight: 500;
+  opacity: 0.8;
 }
 
 // 健康建议区域样式
@@ -185,55 +320,85 @@
   left: 0;
   right: 0;
   bottom: 0;
-  background-color: rgba(0, 0, 0, 0.5);
+  background: rgba(0, 0, 0, 0.6);
+  backdrop-filter: blur(8px);
   display: flex;
   justify-content: center;
   align-items: center;
   z-index: 1000;
+  animation: fadeIn 0.3s ease-out;
+}
+
+@keyframes fadeIn {
+  from { opacity: 0; }
+  to { opacity: 1; }
 }
 
 .modal-content {
-  background-color: white;
-  border-radius: 12px;
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+  border-radius: 20px;
   width: 90%;
-  max-width: 700px;
-  max-height: 80vh;
+  max-width: 800px;
+  max-height: 85vh;
   overflow-y: auto;
-  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
+  box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
+  animation: slideUp 0.4s cubic-bezier(0.4, 0, 0.2, 1);
+  border: 1px solid rgba(226, 232, 240, 0.5);
+}
+
+@keyframes slideUp {
+  from {
+    opacity: 0;
+    transform: translateY(30px) scale(0.95);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0) scale(1);
+  }
 }
 
 .modal-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
-  padding: 1.5rem 2rem;
-  border-bottom: 1px solid #e8eaed;
+  padding: 2rem 2.5rem;
+  border-bottom: 1px solid rgba(226, 232, 240, 0.5);
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
+  border-radius: 20px 20px 0 0;
 }
 
 .modal-header h3 {
   margin: 0;
-  font-size: 1.3rem;
-  color: #202124;
+  font-size: 1.5rem;
+  color: #1e293b;
+  font-weight: 700;
+  background: linear-gradient(135deg, #1e293b 0%, #4f46e5 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
 }
 
 .close-button {
-  background: none;
-  border: none;
-  font-size: 1.5rem;
+  background: rgba(239, 68, 68, 0.1);
+  border: 1px solid rgba(239, 68, 68, 0.2);
+  font-size: 1.2rem;
   cursor: pointer;
-  color: #5f6368;
+  color: #ef4444;
   padding: 0;
-  width: 30px;
-  height: 30px;
+  width: 36px;
+  height: 36px;
   display: flex;
   align-items: center;
   justify-content: center;
   border-radius: 50%;
-  transition: background-color 0.2s ease;
-}
+  transition: all 0.3s ease;
+  font-weight: 600;
 
-.close-button:hover {
-  background-color: #f5f7fa;
+  &:hover {
+    background: rgba(239, 68, 68, 0.2);
+    transform: scale(1.1);
+    box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
+  }
 }
 
 .modal-body {

+ 7 - 0
campus_health_app/frontend/campus-health-app/src/app/modules/dashboard/dashboard.component.ts

@@ -154,6 +154,13 @@ export class DashboardComponent {
 
   constructor(private router: Router) {}
 
+  // 退出登录
+  logout(): void {
+    if (confirm('确定要退出登录吗?')) {
+      this.router.navigate(['/login']);
+    }
+  }
+
   // 导航到不同模块
   navigateTo(module: string): void {
     this.router.navigate([`/${module}`]);

+ 34 - 0
campus_health_app/frontend/campus-health-app/src/app/modules/diet/diet.component.html

@@ -12,10 +12,44 @@
         <div class="calories-total">
           <span class="summary-label">今日总热量</span>
           <span class="summary-value">1,600 千卡</span>
+          <div class="progress-bar">
+            <div class="progress-fill" style="width: 80%;"></div>
+          </div>
         </div>
         <div class="calories-remaining">
           <span class="summary-label">剩余预算</span>
           <span class="summary-value">400 千卡</span>
+          <div class="progress-bar">
+            <div class="progress-fill remaining" style="width: 20%;"></div>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 营养摄入进度 -->
+      <div class="nutrition-progress">
+        <h3>营养摄入进度</h3>
+        <div class="nutrition-bars">
+          <div class="nutrition-item">
+            <span class="nutrition-label">蛋白质</span>
+            <div class="nutrition-bar">
+              <div class="nutrition-fill protein" style="width: 75%;"></div>
+            </div>
+            <span class="nutrition-value">60g / 80g</span>
+          </div>
+          <div class="nutrition-item">
+            <span class="nutrition-label">碳水化合物</span>
+            <div class="nutrition-bar">
+              <div class="nutrition-fill carbs" style="width: 85%;"></div>
+            </div>
+            <span class="nutrition-value">170g / 200g</span>
+          </div>
+          <div class="nutrition-item">
+            <span class="nutrition-label">脂肪</span>
+            <div class="nutrition-bar">
+              <div class="nutrition-fill fat" style="width: 60%;"></div>
+            </div>
+            <span class="nutrition-value">40g / 67g</span>
+          </div>
         </div>
       </div>
     </div>

+ 232 - 61
campus_health_app/frontend/campus-health-app/src/app/modules/diet/diet.component.scss

@@ -4,7 +4,7 @@
   display: flex;
   flex-direction: column;
   height: 100vh;
-  background-color: #f5f7fa;
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
   color: #333;
 }
 
@@ -12,29 +12,36 @@
 .diet-header {
   display: flex;
   align-items: center;
-  padding: 1rem 2rem;
-  background-color: #fff;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  padding: 1.5rem 2rem;
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  color: white;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
 }
 
 .back-button {
-  background: none;
-  border: none;
-  font-size: 1.2rem;
+  background: rgba(255, 255, 255, 0.1);
+  border: 1px solid rgba(255, 255, 255, 0.2);
+  border-radius: 12px;
+  padding: 0.75rem 1rem;
+  font-size: 1rem;
   cursor: pointer;
-  margin-right: 1rem;
-  color: #5f6368;
-  transition: color 0.2s ease;
-}
+  margin-right: 1.5rem;
+  color: white;
+  transition: all 0.3s ease;
+  backdrop-filter: blur(10px);
 
-.back-button:hover {
-  color: #202124;
+  &:hover {
+    background: rgba(255, 255, 255, 0.2);
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  }
 }
 
 .diet-header h1 {
   margin: 0;
-  font-size: 1.5rem;
-  color: #202124;
+  font-size: 1.8rem;
+  color: white;
+  font-weight: 700;
 }
 
 // 主内容区域
@@ -46,44 +53,143 @@
 
 // 饮食概览区域
 .diet-overview {
-  background-color: #fff;
-  border-radius: 8px;
-  padding: 1.5rem;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+  border-radius: 20px;
+  padding: 2rem;
+  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
   margin-bottom: 2rem;
+  border: 1px solid rgba(226, 232, 240, 0.5);
 }
 
 .diet-overview h2,
 .meals-list h2 {
-  margin: 0 0 1rem 0;
-  font-size: 1.3rem;
-  color: #202124;
+  margin: 0 0 1.5rem 0;
+  font-size: 1.5rem;
+  color: #1e293b;
+  font-weight: 700;
+  background: linear-gradient(135deg, #1e293b 0%, #4f46e5 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
 }
 
 .calories-summary {
-  display: flex;
-  justify-content: space-around;
-  padding-top: 1rem;
-  border-top: 1px solid #e8eaed;
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 2rem;
+  padding: 1.5rem 0;
+  border-top: 1px solid rgba(226, 232, 240, 0.5);
 }
 
 .calories-total,
 .calories-remaining {
   text-align: center;
+  padding: 1.5rem;
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
+  border-radius: 16px;
+  border: 1px solid rgba(226, 232, 240, 0.5);
 }
 
 .summary-label {
   display: block;
-  color: #5f6368;
-  font-size: 0.9rem;
-  margin-bottom: 0.5rem;
+  color: #64748b;
+  font-size: 1rem;
+  margin-bottom: 0.8rem;
+  font-weight: 500;
 }
 
 .summary-value {
   display: block;
-  font-size: 1.5rem;
-  font-weight: bold;
-  color: #1a73e8;
+  font-size: 2rem;
+  font-weight: 700;
+  color: #4f46e5;
+  margin-bottom: 1rem;
+}
+
+.progress-bar {
+  width: 100%;
+  height: 8px;
+  background: rgba(226, 232, 240, 0.5);
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+.progress-fill {
+  height: 100%;
+  background: linear-gradient(90deg, #4f46e5 0%, #7c3aed 100%);
+  border-radius: 4px;
+  transition: width 0.8s ease;
+
+  &.remaining {
+    background: linear-gradient(90deg, #10b981 0%, #059669 100%);
+  }
+}
+
+// 营养摄入进度
+.nutrition-progress {
+  margin-top: 2rem;
+  padding-top: 2rem;
+  border-top: 1px solid rgba(226, 232, 240, 0.5);
+}
+
+.nutrition-progress h3 {
+  margin: 0 0 1.5rem 0;
+  font-size: 1.2rem;
+  color: #1e293b;
+  font-weight: 600;
+}
+
+.nutrition-bars {
+  display: flex;
+  flex-direction: column;
+  gap: 1.5rem;
+}
+
+.nutrition-item {
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+}
+
+.nutrition-label {
+  min-width: 100px;
+  color: #64748b;
+  font-size: 0.95rem;
+  font-weight: 500;
+}
+
+.nutrition-bar {
+  flex: 1;
+  height: 12px;
+  background: rgba(226, 232, 240, 0.5);
+  border-radius: 6px;
+  overflow: hidden;
+}
+
+.nutrition-fill {
+  height: 100%;
+  border-radius: 6px;
+  transition: width 0.8s ease;
+
+  &.protein {
+    background: linear-gradient(90deg, #ef4444 0%, #dc2626 100%);
+  }
+
+  &.carbs {
+    background: linear-gradient(90deg, #f59e0b 0%, #d97706 100%);
+  }
+
+  &.fat {
+    background: linear-gradient(90deg, #8b5cf6 0%, #7c3aed 100%);
+  }
+}
+
+.nutrition-value {
+  min-width: 80px;
+  text-align: right;
+  color: #64748b;
+  font-size: 0.9rem;
+  font-weight: 500;
 }
 
 // 饮食记录列表
@@ -94,20 +200,39 @@
 .meals-container {
   display: flex;
   flex-direction: column;
-  gap: 1rem;
+  gap: 1.5rem;
 }
 
 .meal-card {
-  background-color: #fff;
-  border-radius: 8px;
-  padding: 1.5rem;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-  transition: transform 0.2s ease, box-shadow 0.2s ease;
-}
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+  border-radius: 16px;
+  padding: 2rem;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  border: 1px solid rgba(226, 232, 240, 0.5);
+  position: relative;
+  overflow: hidden;
 
-.meal-card:hover {
-  transform: translateY(-2px);
-  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 4px;
+    background: linear-gradient(90deg, #4f46e5 0%, #7c3aed 100%);
+    transform: scaleX(0);
+    transition: transform 0.3s ease;
+  }
+
+  &:hover {
+    transform: translateY(-4px);
+    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
+    
+    &::before {
+      transform: scaleX(1);
+    }
+  }
 }
 
 .meal-header {
@@ -169,37 +294,83 @@
 }
 
 .add-meal-button {
-  padding: 0.8rem 2rem;
-  background-color: #1a73e8;
-  color: #fff;
+  padding: 1rem 2.5rem;
+  background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
+  color: white;
   border: none;
-  border-radius: 4px;
-  font-size: 1rem;
+  border-radius: 16px;
+  font-size: 1.1rem;
+  font-weight: 600;
   cursor: pointer;
-  transition: background-color 0.2s ease;
-}
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  position: relative;
+  overflow: hidden;
+  box-shadow: 0 4px 20px rgba(79, 70, 229, 0.3);
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
+    transition: left 0.5s;
+  }
+
+  &:hover {
+    transform: translateY(-3px);
+    box-shadow: 0 8px 30px rgba(79, 70, 229, 0.4);
+    
+    &::before {
+      left: 100%;
+    }
+  }
 
-.add-meal-button:hover {
-  background-color: #1557b0;
+  &:active {
+    transform: translateY(-1px);
+  }
 }
 
 // 营养建议区域
 .nutrition-tips {
-  background-color: #fff;
-  border-radius: 8px;
-  padding: 1.5rem;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+  border-radius: 20px;
+  padding: 2rem;
+  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+  border: 1px solid rgba(226, 232, 240, 0.5);
+  position: relative;
+  overflow: hidden;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 4px;
+    background: linear-gradient(90deg, #10b981 0%, #059669 100%);
+  }
 }
 
 .nutrition-tips h3 {
-  margin: 0 0 1rem 0;
-  font-size: 1.1rem;
-  color: #202124;
+  margin: 0 0 1.5rem 0;
+  font-size: 1.3rem;
+  color: #1e293b;
+  font-weight: 700;
+  background: linear-gradient(135deg, #1e293b 0%, #10b981 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
 }
 
 .nutrition-tips p {
   margin: 0;
-  color: #5f6368;
-  font-size: 0.95rem;
-  line-height: 1.5;
+  color: #64748b;
+  font-size: 1rem;
+  line-height: 1.6;
+  padding: 1rem;
+  background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 100%);
+  border-radius: 12px;
+  border-left: 4px solid #10b981;
 }

+ 50 - 0
campus_health_app/frontend/campus-health-app/src/app/modules/exercise/exercise.component.html

@@ -12,14 +12,64 @@
         <div class="summary-item">
           <span class="summary-label">总时长</span>
           <span class="summary-value">75分钟</span>
+          <div class="progress-ring">
+            <svg class="progress-ring-svg" width="60" height="60">
+              <circle class="progress-ring-circle-bg" cx="30" cy="30" r="25"></circle>
+              <circle class="progress-ring-circle" cx="30" cy="30" r="25" style="stroke-dasharray: 157; stroke-dashoffset: 39;"></circle>
+            </svg>
+            <span class="progress-text">75%</span>
+          </div>
         </div>
         <div class="summary-item">
           <span class="summary-label">消耗热量</span>
           <span class="summary-value">550 千卡</span>
+          <div class="progress-ring">
+            <svg class="progress-ring-svg" width="60" height="60">
+              <circle class="progress-ring-circle-bg" cx="30" cy="30" r="25"></circle>
+              <circle class="progress-ring-circle calories" cx="30" cy="30" r="25" style="stroke-dasharray: 157; stroke-dashoffset: 55;"></circle>
+            </svg>
+            <span class="progress-text">65%</span>
+          </div>
         </div>
         <div class="summary-item">
           <span class="summary-label">总距离</span>
           <span class="summary-value">3.5公里</span>
+          <div class="progress-ring">
+            <svg class="progress-ring-svg" width="60" height="60">
+              <circle class="progress-ring-circle-bg" cx="30" cy="30" r="25"></circle>
+              <circle class="progress-ring-circle distance" cx="30" cy="30" r="25" style="stroke-dasharray: 157; stroke-dashoffset: 47;"></circle>
+            </svg>
+            <span class="progress-text">70%</span>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 运动类型分布 -->
+      <div class="exercise-chart">
+        <h3>运动类型分布</h3>
+        <div class="chart-container">
+          <div class="chart-legend">
+            <div class="legend-item">
+              <span class="legend-color cardio"></span>
+              <span class="legend-label">有氧运动</span>
+              <span class="legend-value">45分钟</span>
+            </div>
+            <div class="legend-item">
+              <span class="legend-color strength"></span>
+              <span class="legend-label">力量训练</span>
+              <span class="legend-value">20分钟</span>
+            </div>
+            <div class="legend-item">
+              <span class="legend-color flexibility"></span>
+              <span class="legend-label">柔韧性</span>
+              <span class="legend-value">10分钟</span>
+            </div>
+          </div>
+          <div class="chart-visual">
+            <div class="chart-segment cardio" style="--percentage: 60%;"></div>
+            <div class="chart-segment strength" style="--percentage: 27%;"></div>
+            <div class="chart-segment flexibility" style="--percentage: 13%;"></div>
+          </div>
         </div>
       </div>
     </div>

+ 187 - 32
campus_health_app/frontend/campus-health-app/src/app/modules/exercise/exercise.component.scss

@@ -4,7 +4,7 @@
   display: flex;
   flex-direction: column;
   height: 100vh;
-  background-color: #f5f7fa;
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
   color: #333;
 }
 
@@ -12,29 +12,36 @@
 .exercise-header {
   display: flex;
   align-items: center;
-  padding: 1rem 2rem;
-  background-color: #fff;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  padding: 1.5rem 2rem;
+  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
+  color: white;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
 }
 
 .back-button {
-  background: none;
-  border: none;
-  font-size: 1.2rem;
+  background: rgba(255, 255, 255, 0.1);
+  border: 1px solid rgba(255, 255, 255, 0.2);
+  border-radius: 12px;
+  padding: 0.75rem 1rem;
+  font-size: 1rem;
   cursor: pointer;
-  margin-right: 1rem;
-  color: #5f6368;
-  transition: color 0.2s ease;
-}
+  margin-right: 1.5rem;
+  color: white;
+  transition: all 0.3s ease;
+  backdrop-filter: blur(10px);
 
-.back-button:hover {
-  color: #202124;
+  &:hover {
+    background: rgba(255, 255, 255, 0.2);
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  }
 }
 
 .exercise-header h1 {
   margin: 0;
-  font-size: 1.5rem;
-  color: #202124;
+  font-size: 1.8rem;
+  color: white;
+  font-weight: 700;
 }
 
 // 主内容区域
@@ -46,43 +53,191 @@
 
 // 运动概览区域
 .exercise-overview {
-  background-color: #fff;
-  border-radius: 8px;
-  padding: 1.5rem;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
+  border-radius: 20px;
+  padding: 2rem;
+  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
   margin-bottom: 2rem;
+  border: 1px solid rgba(226, 232, 240, 0.5);
 }
 
 .exercise-overview h2,
 .exercises-list h2 {
-  margin: 0 0 1rem 0;
-  font-size: 1.3rem;
-  color: #202124;
+  margin: 0 0 1.5rem 0;
+  font-size: 1.5rem;
+  color: #1e293b;
+  font-weight: 700;
+  background: linear-gradient(135deg, #1e293b 0%, #10b981 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
 }
 
 .exercise-summary {
-  display: flex;
-  justify-content: space-around;
-  padding-top: 1rem;
-  border-top: 1px solid #e8eaed;
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 2rem;
+  padding: 1.5rem 0;
+  border-top: 1px solid rgba(226, 232, 240, 0.5);
 }
 
 .summary-item {
   text-align: center;
+  padding: 1.5rem;
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
+  border-radius: 16px;
+  border: 1px solid rgba(226, 232, 240, 0.5);
+  position: relative;
 }
 
 .summary-label {
   display: block;
-  color: #5f6368;
-  font-size: 0.9rem;
-  margin-bottom: 0.5rem;
+  color: #64748b;
+  font-size: 1rem;
+  margin-bottom: 0.8rem;
+  font-weight: 500;
 }
 
 .summary-value {
   display: block;
-  font-size: 1.3rem;
-  font-weight: bold;
-  color: #34a853;
+  font-size: 1.8rem;
+  font-weight: 700;
+  color: #10b981;
+  margin-bottom: 1rem;
+}
+
+// 进度环样式
+.progress-ring {
+  position: relative;
+  display: inline-block;
+}
+
+.progress-ring-svg {
+  transform: rotate(-90deg);
+}
+
+.progress-ring-circle-bg {
+  fill: none;
+  stroke: rgba(226, 232, 240, 0.5);
+  stroke-width: 4;
+}
+
+.progress-ring-circle {
+  fill: none;
+  stroke: #10b981;
+  stroke-width: 4;
+  stroke-linecap: round;
+  transition: stroke-dashoffset 0.8s ease;
+
+  &.calories {
+    stroke: #f59e0b;
+  }
+
+  &.distance {
+    stroke: #8b5cf6;
+  }
+}
+
+.progress-text {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  font-size: 0.8rem;
+  font-weight: 600;
+  color: #64748b;
+}
+
+// 运动类型分布图表
+.exercise-chart {
+  margin-top: 2rem;
+  padding-top: 2rem;
+  border-top: 1px solid rgba(226, 232, 240, 0.5);
+}
+
+.exercise-chart h3 {
+  margin: 0 0 1.5rem 0;
+  font-size: 1.2rem;
+  color: #1e293b;
+  font-weight: 600;
+}
+
+.chart-container {
+  display: flex;
+  align-items: center;
+  gap: 2rem;
+}
+
+.chart-legend {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 0.8rem;
+  padding: 0.8rem;
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
+  border-radius: 12px;
+  border: 1px solid rgba(226, 232, 240, 0.5);
+}
+
+.legend-color {
+  width: 16px;
+  height: 16px;
+  border-radius: 50%;
+  
+  &.cardio {
+    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
+  }
+  
+  &.strength {
+    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
+  }
+  
+  &.flexibility {
+    background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
+  }
+}
+
+.legend-label {
+  flex: 1;
+  color: #64748b;
+  font-size: 0.95rem;
+  font-weight: 500;
+}
+
+.legend-value {
+  color: #1e293b;
+  font-size: 0.9rem;
+  font-weight: 600;
+}
+
+.chart-visual {
+  width: 120px;
+  height: 120px;
+  border-radius: 50%;
+  background: conic-gradient(
+    #ef4444 0deg 216deg,
+    #f59e0b 216deg 284deg,
+    #8b5cf6 284deg 360deg
+  );
+  position: relative;
+  
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 60px;
+    height: 60px;
+    background: white;
+    border-radius: 50%;
+    transform: translate(-50%, -50%);
+  }
 }
 
 // 运动记录列表

+ 0 - 20
campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.component.html

@@ -1,20 +0,0 @@
-<div class="welcome-container">
-  <div class="welcome-header">
-    <h1>欢迎使用数智健调系统</h1>
-  </div>
-  
-  <div class="welcome-content">
-    <div class="welcome-message">
-      <p>感谢您登录系统!</p>
-      <p>这是您的个人健康管理中心,我们致力于帮助您建立健康的生活方式。</p>
-    </div>
-    
-    <div class="welcome-actions">
-      <button class="primary-button" (click)="onStartUsing()">开始使用</button>
-    </div>
-  </div>
-  
-  <div class="welcome-footer">
-    <p>© 2025 数智健调系统 - 让健康管理更智能</p>
-  </div>
-</div>

+ 0 - 79
campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.component.scss

@@ -1,79 +0,0 @@
-// 欢迎页面的基本样式
-.welcome-container {
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-  background-color: #f5f7fa;
-  padding: 20px;
-}
-
-.welcome-header {
-  text-align: center;
-  margin-bottom: 30px;
-}
-
-.welcome-header h1 {
-  font-size: 2.5rem;
-  color: #333;
-  margin: 0;
-  font-weight: 600;
-}
-
-.welcome-content {
-  background-color: white;
-  border-radius: 12px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-  padding: 40px;
-  max-width: 600px;
-  width: 100%;
-  text-align: center;
-}
-
-.welcome-message {
-  margin-bottom: 40px;
-}
-
-.welcome-message p {
-  font-size: 1.1rem;
-  color: #666;
-  margin-bottom: 15px;
-  line-height: 1.6;
-}
-
-.welcome-message p:first-child {
-  font-size: 1.3rem;
-  color: #333;
-  font-weight: 500;
-}
-
-.welcome-actions {
-  margin-bottom: 30px;
-}
-
-.primary-button {
-  background-color: #4d7cf3;
-  color: white;
-  border: none;
-  padding: 12px 30px;
-  font-size: 1rem;
-  font-weight: 500;
-  border-radius: 8px;
-  cursor: pointer;
-  transition: background-color 0.3s ease;
-}
-
-.primary-button:hover {
-  background-color: #3a6ce8;
-}
-
-.welcome-footer {
-  text-align: center;
-  color: #999;
-  font-size: 0.9rem;
-}
-
-.welcome-footer p {
-  margin: 0;
-}

+ 0 - 25
campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.component.ts

@@ -1,25 +0,0 @@
-import { Component } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { Router } from '@angular/router';
-
-@Component({
-  selector: 'app-first-use',
-  standalone: true,
-  imports: [CommonModule],
-  templateUrl: './first-use.component.html',
-  styleUrl: './first-use.component.scss'
-})
-export class FirstUseComponent {
-
-  constructor(private router: Router) {}
-
-  // 可以在这里添加一些初始化逻辑
-  ngOnInit(): void {
-    // 例如:加载用户信息、检查用户设置等
-  }
-
-  // 开始使用按钮点击事件
-  onStartUsing(): void {
-    this.router.navigate(['/dashboard']);
-  }
-}

+ 0 - 10
campus_health_app/frontend/campus-health-app/src/app/modules/first-use/first-use.routes.ts

@@ -1,10 +0,0 @@
-import { Routes } from '@angular/router';
-import { FirstUseComponent } from './first-use.component';
-
-export const firstUseRoutes: Routes = [
-  {
-    path: '',
-    component: FirstUseComponent,
-    title: '欢迎使用 - 数智健调系统'
-  }
-];

+ 22 - 15
campus_health_app/frontend/campus-health-app/src/app/modules/monitoring/monitoring.component.scss

@@ -4,7 +4,7 @@
   display: flex;
   flex-direction: column;
   height: 100vh;
-  background-color: #f5f7fa;
+  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
   color: #333;
 }
 
@@ -12,29 +12,36 @@
 .monitoring-header {
   display: flex;
   align-items: center;
-  padding: 1rem 2rem;
-  background-color: #fff;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  padding: 1.5rem 2rem;
+  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
+  color: white;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
 }
 
 .back-button {
-  background: none;
-  border: none;
-  font-size: 1.2rem;
+  background: rgba(255, 255, 255, 0.1);
+  border: 1px solid rgba(255, 255, 255, 0.2);
+  border-radius: 12px;
+  padding: 0.75rem 1rem;
+  font-size: 1rem;
   cursor: pointer;
-  margin-right: 1rem;
-  color: #5f6368;
-  transition: color 0.2s ease;
-}
+  margin-right: 1.5rem;
+  color: white;
+  transition: all 0.3s ease;
+  backdrop-filter: blur(10px);
 
-.back-button:hover {
-  color: #202124;
+  &:hover {
+    background: rgba(255, 255, 255, 0.2);
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  }
 }
 
 .monitoring-header h1 {
   margin: 0;
-  font-size: 1.5rem;
-  color: #202124;
+  font-size: 1.8rem;
+  color: white;
+  font-weight: 700;
 }
 
 // 主内容区域

+ 115 - 7
campus_health_app/frontend/campus-health-app/src/styles.scss

@@ -2,12 +2,44 @@
 
 /* 全局变量定义 */
 :root {
-  --bg-primary: #f5f7fa;
-  --bg-secondary: #fff;
-  --text-primary: #333;
-  --text-secondary: #5f6368;
-  --border-color: #e8eaed;
+  // 主色调
+  --primary-color: #4f46e5;
+  --primary-light: #7c3aed;
+  --secondary-color: #10b981;
+  --accent-color: #f59e0b;
+  --danger-color: #ef4444;
+  
+  // 背景色
+  --bg-primary: #f8fafc;
+  --bg-secondary: #ffffff;
+  --bg-tertiary: #f1f5f9;
+  
+  // 文字颜色
+  --text-primary: #1e293b;
+  --text-secondary: #64748b;
+  --text-muted: #94a3b8;
+  
+  // 边框和阴影
+  --border-color: #e2e8f0;
+  --border-light: rgba(226, 232, 240, 0.5);
   --shadow-color: rgba(0, 0, 0, 0.1);
+  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
+  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
+  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
+  --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.1);
+  
+  // 圆角
+  --radius-sm: 8px;
+  --radius-md: 12px;
+  --radius-lg: 16px;
+  --radius-xl: 20px;
+  
+  // 间距
+  --spacing-xs: 0.5rem;
+  --spacing-sm: 1rem;
+  --spacing-md: 1.5rem;
+  --spacing-lg: 2rem;
+  --spacing-xl: 3rem;
 }
 
 /* 夜间模式变量 */
@@ -21,13 +53,89 @@
 }
 
 /* 全局样式应用 */
+* {
+  box-sizing: border-box;
+}
+
 body {
-  background-color: var(--bg-primary);
+  background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-tertiary) 100%);
   color: var(--text-primary);
   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
   margin: 0;
   padding: 0;
-  transition: background-color 0.3s ease, color 0.3s ease;
+  line-height: 1.6;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+/* 全局工具类 */
+.gradient-text {
+  background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+}
+
+.card {
+  background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
+  border-radius: var(--radius-lg);
+  box-shadow: var(--shadow-md);
+  border: 1px solid var(--border-light);
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  
+  &:hover {
+    transform: translateY(-2px);
+    box-shadow: var(--shadow-xl);
+  }
+}
+
+.btn {
+  padding: 0.75rem 1.5rem;
+  border: none;
+  border-radius: var(--radius-md);
+  font-weight: 600;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  position: relative;
+  overflow: hidden;
+  
+  &.btn-primary {
+    background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
+    color: white;
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 8px 25px rgba(79, 70, 229, 0.3);
+    }
+  }
+  
+  &.btn-secondary {
+    background: linear-gradient(135deg, var(--secondary-color) 0%, #059669 100%);
+    color: white;
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 8px 25px rgba(16, 185, 129, 0.3);
+    }
+  }
+}
+
+/* 响应式断点 */
+@media (max-width: 768px) {
+  :root {
+    --spacing-sm: 0.75rem;
+    --spacing-md: 1rem;
+    --spacing-lg: 1.5rem;
+    --spacing-xl: 2rem;
+  }
+}
+
+@media (max-width: 480px) {
+  :root {
+    --spacing-sm: 0.5rem;
+    --spacing-md: 0.75rem;
+    --spacing-lg: 1rem;
+    --spacing-xl: 1.5rem;
+  }
 }
 
 /* 确保所有容器都使用主题变量 */

+ 46 - 0
test-app/package-lock.json

@@ -15,6 +15,8 @@
         "@angular/platform-browser": "^20.3.0",
         "@angular/platform-browser-dynamic": "^20.3.2",
         "@angular/router": "^20.3.0",
+        "echarts": "^6.0.0",
+        "ngx-echarts": "^20.0.2",
         "rxjs": "~7.8.0",
         "tslib": "^2.3.0",
         "zone.js": "^0.15.1"
@@ -7672,6 +7674,22 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/echarts": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz",
+      "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "2.3.0",
+        "zrender": "6.0.0"
+      }
+    },
+    "node_modules/echarts/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "license": "0BSD"
+    },
     "node_modules/ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -11027,6 +11045,19 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/ngx-echarts": {
+      "version": "20.0.2",
+      "resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-20.0.2.tgz",
+      "integrity": "sha512-kDoIFp7SrWCPWG9nX9IX9ARnIh4f5p8VYtRWvhXwlf5gW+GxUbeDKYpvIvBVjaftudLZIMwZ/N4GADQSIus57Q==",
+      "license": "MIT",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "peerDependencies": {
+        "@angular/core": ">=20.0.0",
+        "echarts": ">=5.0.0"
+      }
+    },
     "node_modules/node-addon-api": {
       "version": "6.1.0",
       "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
@@ -15440,6 +15471,21 @@
       "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz",
       "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==",
       "license": "MIT"
+    },
+    "node_modules/zrender": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz",
+      "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "tslib": "2.3.0"
+      }
+    },
+    "node_modules/zrender/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "license": "0BSD"
     }
   }
 }

+ 2 - 0
test-app/package.json

@@ -29,6 +29,8 @@
     "@angular/platform-browser": "^20.3.0",
     "@angular/platform-browser-dynamic": "^20.3.2",
     "@angular/router": "^20.3.0",
+    "echarts": "^6.0.0",
+    "ngx-echarts": "^20.0.2",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",
     "zone.js": "^0.15.1"

+ 9 - 1
test-app/src/app/app-routing.module.ts

@@ -3,7 +3,15 @@ import { RouterModule, Routes } from '@angular/router';
 
 // 定义路由配置
 const routes: Routes = [
-  // 主页面路由将在后续开发中添加
+  {
+    path: '',
+    redirectTo: 'dashboard',
+    pathMatch: 'full'
+  },
+  {
+    path: 'dashboard',
+    loadChildren: () => import('./health-dashboard/health-dashboard.module').then(m => m.HealthDashboardModule)
+  }
 ];
 
 @NgModule({

+ 2 - 1
test-app/src/app/app.component.ts

@@ -3,7 +3,8 @@ import { Component } from '@angular/core';
 @Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
-  styleUrls: ['./app.component.scss']
+  styleUrls: ['./app.component.scss'],
+  standalone: true
 })
 export class AppComponent {
   title = '数智健调系统';

+ 4 - 3
test-app/src/app/app.module.ts

@@ -1,15 +1,16 @@
 import { NgModule } from '@angular/core';
 import { BrowserModule } from '@angular/platform-browser';
-import { CommonModule } from '@angular/common';
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';
+import { NgxEchartsModule } from 'ngx-echarts';
 
 @NgModule({
   declarations: [],
   imports: [
     BrowserModule,
-    CommonModule,
-    AppRoutingModule
+    AppRoutingModule,
+    NgxEchartsModule.forRoot({ echarts: () => import('echarts') }),
+    AppComponent
   ],
   providers: [],
   bootstrap: [AppComponent]

+ 19 - 0
test-app/src/app/health-dashboard/health-dashboard-routing.module.ts

@@ -0,0 +1,19 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { HealthDashboardComponent } from './health-dashboard.component';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: HealthDashboardComponent,
+    data: {
+      title: '健康数据仪表盘'
+    }
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule]
+})
+export class HealthDashboardRoutingModule { }

+ 109 - 0
test-app/src/app/health-dashboard/health-dashboard.component.html

@@ -0,0 +1,109 @@
+<div class="health-dashboard">
+  <!-- 页面头部 -->
+  <div class="dashboard-header">
+    <h1>健康数据仪表盘</h1>
+    <div class="header-actions">
+      <div class="time-range-selector">
+        <button @if (currentRange === 'week') { class="active" } (click)="changeTimeRange('day')">今日</button>
+        <button @if (currentRange === 'week') { class="active" } (click)="changeTimeRange('week')">本周</button>
+        <button @if (currentRange === 'month') { class="active" } (click)="changeTimeRange('month')">本月</button>
+      </div>
+      <button class="export-btn" (click)="exportData()">
+        <i class="icon-export"></i> 导出数据
+      </button>
+    </div>
+  </div>
+
+  <!-- 健康指标汇总卡片 -->
+  <div class="summary-cards">
+    <div class="summary-card">
+      <div class="card-icon exercise-icon"></div>
+      <div class="card-content">
+        <div class="card-title">总运动时长</div>
+        <div class="card-value">{{ healthSummary.totalExercise }}</div>
+        <div class="card-unit">分钟</div>
+      </div>
+    </div>
+    <div class="summary-card">
+      <div class="card-icon calorie-icon"></div>
+      <div class="card-content">
+        <div class="card-title">总消耗卡路里</div>
+        <div class="card-value">{{ healthSummary.totalCalories }}</div>
+        <div class="card-unit">千卡</div>
+      </div>
+    </div>
+    <div class="summary-card">
+      <div class="card-icon heart-icon"></div>
+      <div class="card-content">
+        <div class="card-title">平均心率</div>
+        <div class="card-value">{{ healthSummary.avgHeartRate }}</div>
+        <div class="card-unit">bpm</div>
+      </div>
+    </div>
+    <div class="summary-card">
+      <div class="card-icon sleep-icon"></div>
+      <div class="card-content">
+        <div class="card-title">平均睡眠</div>
+        <div class="card-value">{{ healthSummary.avgSleep }}</div>
+        <div class="card-unit">小时</div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 图表区域 -->
+  <div class="charts-grid">
+    <!-- 健身活动图表 -->
+    <div class="chart-card">
+      <div class="chart-header">
+        <h3>健身活动分析</h3>
+      </div>
+      <div class="chart-container">
+        <div echarts [options]="fitnessActivityOption" class="chart"></div>
+      </div>
+    </div>
+
+    <!-- 卡路里消耗图表 -->
+    <div class="chart-card">
+      <div class="chart-header">
+        <h3>卡路里消耗趋势</h3>
+      </div>
+      <div class="chart-container">
+        <div echarts [options]="calorieOption" class="chart"></div>
+      </div>
+    </div>
+
+    <!-- 心率变化图表 -->
+    <div class="chart-card">
+      <div class="chart-header">
+        <h3>心率变化监测</h3>
+      </div>
+      <div class="chart-container">
+        <div echarts [options]="heartRateOption" class="chart"></div>
+      </div>
+    </div>
+
+    <!-- 睡眠分布图表 -->
+    <div class="chart-card">
+      <div class="chart-header">
+        <h3>睡眠质量分析</h3>
+      </div>
+      <div class="chart-container">
+        <div echarts [options]="sleepOption" class="chart"></div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 健康建议部分 -->
+  <div class="health-advice">
+    <h3>健康建议</h3>
+    <div class="advice-content">
+      <p>基于您的健康数据,我们为您提供以下建议:</p>
+      <ul>
+        <li>您的运动频率良好,但可以适当增加力量训练的比例。</li>
+        <li>保持充足的水分摄入,尤其是在运动前后。</li>
+        <li>建议优化睡眠环境,提高深度睡眠比例。</li>
+        <li>继续保持规律的运动习惯,这对您的整体健康非常有益。</li>
+      </ul>
+    </div>
+  </div>
+</div>

+ 379 - 0
test-app/src/app/health-dashboard/health-dashboard.component.scss

@@ -0,0 +1,379 @@
+// 健康数据仪表盘样式
+
+// 变量定义
+$primary-color: #5470c6;
+$secondary-color: #ee6666;
+$success-color: #91cc75;
+$warning-color: #fac858;
+$info-color: #73c0de;
+$light-bg: #f5f7fa;
+$card-bg: #ffffff;
+$text-primary: #333333;
+$text-secondary: #666666;
+$text-light: #999999;
+$border-color: #e8e8e8;
+$shadow-light: 0 2px 8px rgba(0, 0, 0, 0.06);
+$shadow-medium: 0 4px 16px rgba(0, 0, 0, 0.1);
+$border-radius: 12px;
+$transition-speed: 0.3s;
+
+// 主容器
+.health-dashboard {
+  padding: 24px;
+  min-height: 100vh;
+  background-color: $light-bg;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+}
+
+// 页面头部
+.dashboard-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 32px;
+  padding-bottom: 16px;
+  border-bottom: 1px solid $border-color;
+
+  h1 {
+    color: $text-primary;
+    font-size: 28px;
+    font-weight: 600;
+    margin: 0;
+  }
+
+  .header-actions {
+    display: flex;
+    align-items: center;
+    gap: 20px;
+
+    .time-range-selector {
+      display: flex;
+      background-color: $card-bg;
+      border-radius: 24px;
+      padding: 4px;
+      box-shadow: $shadow-light;
+
+      button {
+        padding: 8px 20px;
+        border: none;
+        background: transparent;
+        border-radius: 20px;
+        color: $text-secondary;
+        cursor: pointer;
+        transition: all $transition-speed ease;
+        font-size: 14px;
+        font-weight: 500;
+
+        &.active {
+          background-color: $primary-color;
+          color: white;
+          box-shadow: 0 2px 8px rgba(84, 112, 198, 0.3);
+        }
+
+        &:hover:not(.active) {
+          color: $primary-color;
+        }
+      }
+    }
+
+    .export-btn {
+      display: flex;
+      align-items: center;
+      gap: 6px;
+      padding: 10px 20px;
+      background-color: $success-color;
+      color: white;
+      border: none;
+      border-radius: 8px;
+      cursor: pointer;
+      font-size: 14px;
+      font-weight: 500;
+      transition: all $transition-speed ease;
+      box-shadow: 0 2px 8px rgba(145, 204, 117, 0.3);
+
+      &:hover {
+        background-color: #85b76a;
+        transform: translateY(-1px);
+        box-shadow: 0 4px 12px rgba(145, 204, 117, 0.4);
+      }
+
+      &:active {
+        transform: translateY(0);
+      }
+    }
+  }
+}
+
+// 健康指标汇总卡片
+.summary-cards {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
+  gap: 20px;
+  margin-bottom: 32px;
+}
+
+.summary-card {
+  display: flex;
+  align-items: center;
+  gap: 16px;
+  padding: 20px;
+  background-color: $card-bg;
+  border-radius: $border-radius;
+  box-shadow: $shadow-light;
+  transition: all $transition-speed ease;
+  position: relative;
+  overflow: hidden;
+
+  &:hover {
+    transform: translateY(-2px);
+    box-shadow: $shadow-medium;
+  }
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 4px;
+    height: 100%;
+  }
+
+  &:nth-child(1)::before {
+    background-color: $primary-color;
+  }
+
+  &:nth-child(2)::before {
+    background-color: $secondary-color;
+  }
+
+  &:nth-child(3)::before {
+    background-color: $success-color;
+  }
+
+  &:nth-child(4)::before {
+    background-color: $warning-color;
+  }
+
+  .card-icon {
+    width: 48px;
+    height: 48px;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: rgba(84, 112, 198, 0.1);
+    position: relative;
+
+    &::after {
+        content: '';
+        position: absolute;
+        width: 24px;
+        height: 24px;
+      }
+
+      &.exercise-icon::after {
+        content: '🏃';
+        font-size: 24px;
+      }
+
+      &.calorie-icon::after {
+        content: '🔥';
+        font-size: 24px;
+      }
+
+      &.heart-icon::after {
+        content: '❤️';
+        font-size: 24px;
+      }
+
+      &.sleep-icon::after {
+        content: '😴';
+        font-size: 24px;
+      }
+  }
+
+  .card-content {
+    flex: 1;
+
+    .card-title {
+      color: $text-light;
+      font-size: 12px;
+      font-weight: 500;
+      text-transform: uppercase;
+      letter-spacing: 0.5px;
+      margin-bottom: 4px;
+    }
+
+    .card-value {
+      color: $text-primary;
+      font-size: 24px;
+      font-weight: 600;
+      margin-bottom: 2px;
+    }
+
+    .card-unit {
+      color: $text-secondary;
+      font-size: 12px;
+    }
+  }
+}
+
+// 图表网格
+.charts-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
+  gap: 24px;
+  margin-bottom: 32px;
+}
+
+// 图表卡片
+.chart-card {
+  background-color: $card-bg;
+  border-radius: $border-radius;
+  box-shadow: $shadow-light;
+  transition: all $transition-speed ease;
+  overflow: hidden;
+
+  &:hover {
+    box-shadow: $shadow-medium;
+  }
+
+  .chart-header {
+    padding: 20px 24px 16px;
+    border-bottom: 1px solid $border-color;
+
+    h3 {
+      color: $text-primary;
+      font-size: 16px;
+      font-weight: 600;
+      margin: 0;
+    }
+  }
+
+  .chart-container {
+    padding: 20px;
+
+    .chart {
+      width: 100%;
+      height: 300px;
+    }
+  }
+}
+
+// 健康建议部分
+.health-advice {
+  background-color: $card-bg;
+  border-radius: $border-radius;
+  box-shadow: $shadow-light;
+  padding: 24px;
+  transition: all $transition-speed ease;
+
+  &:hover {
+    box-shadow: $shadow-medium;
+  }
+
+  h3 {
+    color: $text-primary;
+    font-size: 18px;
+    font-weight: 600;
+    margin: 0 0 16px 0;
+    padding-bottom: 12px;
+    border-bottom: 1px solid $border-color;
+  }
+
+  .advice-content {
+    color: $text-secondary;
+    font-size: 14px;
+    line-height: 1.6;
+
+    p {
+      margin: 0 0 12px 0;
+    }
+
+    ul {
+      margin: 0;
+      padding-left: 20px;
+
+      li {
+        margin-bottom: 8px;
+        position: relative;
+
+        &::before {
+          content: '✓';
+          position: absolute;
+          left: -20px;
+          color: $success-color;
+          font-weight: bold;
+        }
+      }
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 1200px) {
+  .charts-grid {
+    grid-template-columns: 1fr;
+  }
+}
+
+@media (max-width: 768px) {
+  .health-dashboard {
+    padding: 16px;
+  }
+
+  .dashboard-header {
+    flex-direction: column;
+    gap: 16px;
+    text-align: center;
+
+    .header-actions {
+      flex-direction: column;
+      gap: 16px;
+      width: 100%;
+
+      .export-btn {
+        width: 100%;
+        justify-content: center;
+      }
+    }
+  }
+
+  .summary-cards {
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 16px;
+  }
+
+  .summary-card {
+    padding: 16px;
+
+    .card-icon {
+      width: 40px;
+      height: 40px;
+    }
+
+    .card-value {
+      font-size: 20px;
+    }
+  }
+
+  .chart-card {
+    .chart-container {
+      padding: 16px;
+
+      .chart {
+        height: 250px;
+      }
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .summary-cards {
+    grid-template-columns: 1fr;
+  }
+
+  .dashboard-header h1 {
+    font-size: 24px;
+  }
+}

+ 310 - 0
test-app/src/app/health-dashboard/health-dashboard.component.ts

@@ -0,0 +1,310 @@
+import { Component, OnInit } from '@angular/core';
+import * as echarts from 'echarts';
+import { NgxEchartsModule } from 'ngx-echarts';
+
+@Component({
+  selector: 'app-health-dashboard',
+  templateUrl: './health-dashboard.component.html',
+  styleUrls: ['./health-dashboard.component.scss'],
+  standalone: true,
+  imports: [NgxEchartsModule]
+})
+export class HealthDashboardComponent implements OnInit {
+  // 当前时间段选择
+  currentRange = 'week';
+
+  // 健身活动数据
+  fitnessActivityData = [
+    { name: '周一', 跑步: 45, 游泳: 0, 骑行: 0, 健身: 30 },
+    { name: '周二', 跑步: 0, 游泳: 60, 骑行: 0, 健身: 0 },
+    { name: '周三', 跑步: 30, 游泳: 0, 骑行: 45, 健身: 0 },
+    { name: '周四', 跑步: 0, 游泳: 0, 骑行: 0, 健身: 60 },
+    { name: '周五', 跑步: 60, 游泳: 0, 骑行: 0, 健身: 0 },
+    { name: '周六', 跑步: 0, 游泳: 45, 骑行: 30, 健身: 30 },
+    { name: '周日', 跑步: 0, 游泳: 0, 骑行: 60, 健身: 0 }
+  ];
+
+  // 卡路里消耗数据
+  calorieData = [
+    { name: '周一', value: 420 },
+    { name: '周二', value: 380 },
+    { name: '周三', value: 450 },
+    { name: '周四', value: 520 },
+    { name: '周五', value: 600 },
+    { name: '周六', value: 580 },
+    { name: '周日', value: 480 }
+  ];
+
+  // 心率数据
+  heartRateData = [
+    { time: '07:00', value: 65 },
+    { time: '09:00', value: 105 },
+    { time: '11:00', value: 72 },
+    { time: '13:00', value: 85 },
+    { time: '15:00', value: 75 },
+    { time: '17:00', value: 120 },
+    { time: '19:00', value: 90 },
+    { time: '21:00', value: 70 }
+  ];
+
+  // 睡眠数据
+  sleepData = [
+    { name: '深睡', value: 2.5 },
+    { name: '浅睡', value: 4.2 },
+    { name: '清醒', value: 1.3 }
+  ];
+
+  // 图表配置
+  fitnessActivityOption: echarts.EChartsOption = {};
+  calorieOption: echarts.EChartsOption = {};
+  heartRateOption: echarts.EChartsOption = {};
+  sleepOption: echarts.EChartsOption = {};
+
+  // 健康指标汇总
+  healthSummary = {
+    totalExercise: 295,
+    totalCalories: 3430,
+    avgHeartRate: 85,
+    avgSleep: 8
+  };
+
+  constructor() { }
+
+  ngOnInit(): void {
+    this.initCharts();
+  }
+
+  private initCharts(): void {
+    // 初始化健身活动图表
+    this.fitnessActivityOption = {
+      title: {
+        text: '本周健身活动',
+        left: 'center'
+      },
+      tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+          type: 'shadow'
+        }
+      },
+      legend: {
+        data: ['跑步', '游泳', '骑行', '健身'],
+        bottom: 10
+      },
+      grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '15%',
+        top: '15%',
+        containLabel: true
+      },
+      xAxis: {
+        type: 'category',
+        data: this.fitnessActivityData.map(item => item.name)
+      },
+      yAxis: {
+        type: 'value',
+        name: '时长(分钟)',
+        axisLabel: {
+          formatter: '{value} 分钟'
+        }
+      },
+      series: [
+        {
+          name: '跑步',
+          type: 'bar',
+          data: this.fitnessActivityData.map(item => item.跑步),
+          itemStyle: {
+            color: '#5470c6'
+          }
+        },
+        {
+          name: '游泳',
+          type: 'bar',
+          data: this.fitnessActivityData.map(item => item.游泳),
+          itemStyle: {
+            color: '#91cc75'
+          }
+        },
+        {
+          name: '骑行',
+          type: 'bar',
+          data: this.fitnessActivityData.map(item => item.骑行),
+          itemStyle: {
+            color: '#fac858'
+          }
+        },
+        {
+          name: '健身',
+          type: 'bar',
+          data: this.fitnessActivityData.map(item => item.健身),
+          itemStyle: {
+            color: '#ee6666'
+          }
+        }
+      ]
+    };
+
+    // 初始化卡路里消耗图表
+    this.calorieOption = {
+      title: {
+        text: '每日卡路里消耗',
+        left: 'center'
+      },
+      tooltip: {
+        trigger: 'axis'
+      },
+      grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '15%',
+        top: '15%',
+        containLabel: true
+      },
+      xAxis: {
+        type: 'category',
+        data: this.calorieData.map(item => item.name)
+      },
+      yAxis: {
+        type: 'value',
+        name: '卡路里(kcal)'
+      },
+      series: [
+        {
+          name: '卡路里',
+          type: 'line',
+          data: this.calorieData.map(item => item.value),
+          smooth: true,
+          areaStyle: {
+            color: {
+              type: 'linear',
+              x: 0,
+              y: 0,
+              x2: 0,
+              y2: 1,
+              colorStops: [
+                { offset: 0, color: 'rgba(238, 102, 102, 0.6)' },
+                { offset: 1, color: 'rgba(238, 102, 102, 0.1)' }
+              ]
+            }
+          },
+          lineStyle: {
+            color: '#ee6666'
+          },
+          itemStyle: {
+            color: '#ee6666'
+          }
+        }
+      ]
+    };
+
+    // 初始化心率图表
+    this.heartRateOption = {
+      title: {
+        text: '今日心率变化',
+        left: 'center'
+      },
+      tooltip: {
+        trigger: 'axis'
+      },
+      grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '15%',
+        top: '15%',
+        containLabel: true
+      },
+      xAxis: {
+        type: 'category',
+        data: this.heartRateData.map(item => item.time)
+      },
+      yAxis: {
+        type: 'value',
+        name: '心率(bpm)',
+        min: 40,
+        max: 140
+      },
+      series: [
+        {
+          name: '心率',
+          type: 'line',
+          data: this.heartRateData.map(item => item.value),
+          smooth: true,
+          lineStyle: {
+            color: '#5470c6'
+          },
+          itemStyle: {
+            color: '#5470c6'
+          }
+        }
+      ]
+    };
+
+    // 初始化睡眠图表
+    this.sleepOption = {
+      title: {
+        text: '睡眠分布',
+        left: 'center'
+      },
+      tooltip: {
+        trigger: 'item',
+        formatter: '{b}: {c}小时 ({d}%)'
+      },
+      series: [
+        {
+          type: 'pie',
+          radius: ['40%', '70%'],
+          avoidLabelOverlap: false,
+          itemStyle: {
+            borderRadius: 10,
+            borderColor: '#fff',
+            borderWidth: 2
+          },
+          label: {
+            show: false,
+            position: 'center'
+          },
+          emphasis: {
+            label: {
+              show: true,
+              fontSize: 20,
+              fontWeight: 'bold'
+            }
+          },
+          labelLine: {
+            show: false
+          },
+          data: [
+            {
+              value: this.sleepData[0].value,
+              name: this.sleepData[0].name,
+              itemStyle: { color: '#5470c6' }
+            },
+            {
+              value: this.sleepData[1].value,
+              name: this.sleepData[1].name,
+              itemStyle: { color: '#91cc75' }
+            },
+            {
+              value: this.sleepData[2].value,
+              name: this.sleepData[2].name,
+              itemStyle: { color: '#fac858' }
+            }
+          ]
+        }
+      ]
+    };
+  }
+
+  // 切换时间段数据
+  changeTimeRange(range: string): void {
+    this.currentRange = range;
+    // 这里可以实现不同时间段数据的切换逻辑
+    console.log(`切换到${range}时间段`);
+  }
+
+  // 导出数据
+  exportData(): void {
+    alert('数据导出功能将在后续版本中实现');
+  }
+}

+ 15 - 0
test-app/src/app/health-dashboard/health-dashboard.module.ts

@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { NgxEchartsModule } from 'ngx-echarts';
+import { HealthDashboardRoutingModule } from './health-dashboard-routing.module';
+
+@NgModule({
+  declarations: [],
+  imports: [
+    CommonModule,
+    NgxEchartsModule.forChild(),
+    HealthDashboardRoutingModule
+  ],
+  exports: []
+})
+export class HealthDashboardModule { }