徐福静0235668 3 giorni fa
parent
commit
4f7404bfeb
44 ha cambiato i file con 10757 aggiunte e 256 eliminazioni
  1. 2 2
      angular.json
  2. 31 1
      src/app/business/business-routing-module.ts
  3. 95 5
      src/app/business/dashboard/dashboard.html
  4. 406 0
      src/app/business/dashboard/dashboard.scss
  5. 260 4
      src/app/business/dashboard/dashboard.ts
  6. 34 8
      src/app/consumer/booking-recycle/booking-recycle.html
  7. 13 13
      src/app/consumer/booking-recycle/booking-recycle.ts
  8. 24 0
      src/app/consumer/consumer-routing-module.ts
  9. 22 11
      src/app/consumer/earnings/earnings.html
  10. 496 134
      src/app/consumer/earnings/earnings.scss
  11. 379 47
      src/app/consumer/earnings/earnings.ts
  12. 1 1
      src/app/consumer/home/ar-recognition/ar-recognition.scss
  13. 1 1
      src/app/consumer/home/collectors/collectors.scss
  14. 24 5
      src/app/consumer/points-mall/points-mall.html
  15. 10 10
      src/app/consumer/points-mall/points-mall.ts
  16. 250 0
      src/app/consumer/profile/about-us/about-us.html
  17. 530 0
      src/app/consumer/profile/about-us/about-us.scss
  18. 181 0
      src/app/consumer/profile/about-us/about-us.ts
  19. 167 0
      src/app/consumer/profile/addresses/addresses.html
  20. 473 0
      src/app/consumer/profile/addresses/addresses.scss
  21. 253 0
      src/app/consumer/profile/addresses/addresses.ts
  22. 225 0
      src/app/consumer/profile/customer-service/customer-service.html
  23. 740 0
      src/app/consumer/profile/customer-service/customer-service.scss
  24. 354 0
      src/app/consumer/profile/customer-service/customer-service.ts
  25. 174 0
      src/app/consumer/profile/favorites/favorites.html
  26. 508 0
      src/app/consumer/profile/favorites/favorites.scss
  27. 280 0
      src/app/consumer/profile/favorites/favorites.ts
  28. 198 0
      src/app/consumer/profile/invite-friends/invite-friends.html
  29. 575 0
      src/app/consumer/profile/invite-friends/invite-friends.scss
  30. 257 0
      src/app/consumer/profile/invite-friends/invite-friends.ts
  31. 159 0
      src/app/consumer/profile/orders/orders.html
  32. 454 0
      src/app/consumer/profile/orders/orders.scss
  33. 212 0
      src/app/consumer/profile/orders/orders.ts
  34. 247 0
      src/app/consumer/profile/privacy-policy/privacy-policy.html
  35. 409 0
      src/app/consumer/profile/privacy-policy/privacy-policy.scss
  36. 82 0
      src/app/consumer/profile/privacy-policy/privacy-policy.ts
  37. 17 12
      src/app/consumer/profile/profile.ts
  38. 389 0
      src/app/consumer/profile/settings/settings.html
  39. 799 0
      src/app/consumer/profile/settings/settings.scss
  40. 344 0
      src/app/consumer/profile/settings/settings.ts
  41. 202 0
      src/app/consumer/profile/user-agreement/user-agreement.html
  42. 378 0
      src/app/consumer/profile/user-agreement/user-agreement.scss
  43. 82 0
      src/app/consumer/profile/user-agreement/user-agreement.ts
  44. 20 2
      src/app/shared/components/svg-icons/svg-icons.component.ts

+ 2 - 2
angular.json

@@ -46,8 +46,8 @@
                 },
                 {
                   "type": "anyComponentStyle",
-                  "maximumWarning": "4kB",
-                  "maximumError": "8kB"
+                  "maximumWarning": "8kB",
+                  "maximumError": "25kB"
                 }
               ],
               "outputHashing": "all"

+ 31 - 1
src/app/business/business-routing-module.ts

@@ -10,11 +10,41 @@ import { EnterpriseCenter } from './enterprise-center/enterprise-center';
 const routes: Routes = [
   { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
   { path: 'dashboard', component: Dashboard },
+  
+  // 订单相关路由
+  { path: 'orders', component: OrderManagement },
+  { path: 'orders/create', component: OrderManagement },
+  { path: 'orders/assign', component: OrderManagement },
+  { path: 'orders/pending', component: OrderManagement },
+  { path: 'orders/statistics', component: OrderManagement },
   { path: 'order-management', component: OrderManagement },
+  
+  // 设备相关路由
+  { path: 'equipment', component: DeviceManagement },
+  { path: 'equipment/status', component: DeviceManagement },
+  { path: 'equipment/maintenance', component: DeviceManagement },
   { path: 'device-management', component: DeviceManagement },
+  
+  // 报表相关路由
+  { path: 'reports', component: DataReports },
   { path: 'data-reports', component: DataReports },
+  
+  // 业务数据详情路由
+  { path: 'recycling/details', component: DataReports },
+  { path: 'finance/revenue', component: DataReports },
+  
+  // AI助手相关路由
+  { path: 'ai-assistant', component: AiOperationsAssistant },
   { path: 'ai-operations-assistant', component: AiOperationsAssistant },
-  { path: 'enterprise-center', component: EnterpriseCenter }
+  
+  // 企业中心相关路由
+  { path: 'profile', component: EnterpriseCenter },
+  { path: 'enterprise-center', component: EnterpriseCenter },
+  
+  // 其他功能路由
+  { path: 'applications', component: OrderManagement },
+  { path: 'alerts', component: Dashboard },
+  { path: 'todos', component: Dashboard }
 ];
 
 @NgModule({

+ 95 - 5
src/app/business/dashboard/dashboard.html

@@ -1,6 +1,96 @@
-<div class="dashboard-container">
-  <div class="dashboard-header">
-    <h1>企业仪表盘</h1>
+<!-- 顶部导航 -->
+<header class="header">
+  <div class="container">
+    <div class="header-content">
+      <div class="logo">
+        <span class="logo-icon">♻️</span>
+        <span>智回回收</span>
+      </div>
+      <div class="user-info">
+        <span>企业管理员</span>
+        <div class="avatar">
+          <span>管</span>
+        </div>
+      </div>
+    </div>
   </div>
-  <!-- 页面内容已清理,保留基本结构 -->
-</div>
+</header>
+
+<!-- 主要内容 -->
+<main class="content">
+  <div class="container">
+    <!-- 工作台首页 -->
+    <section id="dashboard">
+      <h2 class="section-title">工作台首页 <span class="more-link">今日数据</span></h2>
+      
+      <!-- 核心数据看板 -->
+      <div class="data-dashboard">
+        <div class="data-card" *ngFor="let card of dataCards" (click)="onDataCardClick(card)">
+          <div class="data-label">{{card.label}}</div>
+          <div class="data-value">{{card.value}}</div>
+          <div class="data-trend">{{card.trend}}</div>
+        </div>
+      </div>
+      
+      <!-- 预警信息卡片 -->
+      <div class="card alert-card" *ngIf="alertInfo.content.length > 0">
+        <div class="alert-title">
+          <span class="alert-icon">{{alertInfo.icon}}</span>
+          <span>{{alertInfo.title}}</span>
+        </div>
+        <div class="alert-content">
+          <p *ngFor="let content of alertInfo.content">• {{content}}</p>
+        </div>
+      </div>
+      
+      <!-- AI运营助手 -->
+      <div class="ai-assistant" (click)="onAIAssistantClick()">
+        <div class="ai-header">
+          <div class="ai-icon">🤖</div>
+          <div class="ai-title">AI运营助手</div>
+        </div>
+        <div class="ai-suggestions">
+          <div class="ai-suggestion" *ngFor="let suggestion of aiSuggestions" (click)="onAISuggestionClick(suggestion)">
+            {{suggestion.text}}
+          </div>
+        </div>
+      </div>
+      
+      <!-- 快捷操作入口 -->
+      <div class="card">
+        <h3 class="section-title">快捷操作</h3>
+        <div class="quick-actions">
+          <div class="action-item" *ngFor="let action of quickActions" (click)="onQuickActionClick(action)">
+            <div class="action-icon">{{action.icon}}</div>
+            <div class="action-label">{{action.label}}</div>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 待办事项列表 -->
+      <div class="card">
+        <h3 class="section-title">待办事项 <span class="more-link" (click)="onViewMoreClick('todos')">查看全部</span></h3>
+        <div class="todo-list">
+          <div class="todo-item" *ngFor="let todo of todoItems" (click)="onTodoItemClick(todo)">
+            <div class="todo-info">
+              <div class="todo-icon">{{todo.icon}}</div>
+              <div>
+                <div class="todo-title">{{todo.title}}</div>
+                <div class="todo-desc">{{todo.description}}</div>
+              </div>
+            </div>
+            <div class="todo-count">{{todo.count}}</div>
+          </div>
+        </div>
+      </div>
+    </section>
+  </div>
+</main>
+
+<!-- 底部导航 -->
+<nav class="bottom-nav">
+  <div class="nav-item" *ngFor="let item of navItems" [class.active]="item.active" (click)="onNavItemClick(item)">
+    <div class="nav-icon">{{item.icon}}</div>
+    <div>{{item.label}}</div>
+  </div>
+</nav>

+ 406 - 0
src/app/business/dashboard/dashboard.scss

@@ -0,0 +1,406 @@
+:root {
+  --primary-color: #2ecc71;
+  --primary-dark: #27ae60;
+  --primary-light: #a9dfbf;
+  --secondary-color: #3498db;
+  --accent-color: #f39c12;
+  --warning-color: #e74c3c;
+  --light-bg: #f8f9fa;
+  --dark-text: #2c3e50;
+  --light-text: #7f8c8d;
+  --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  --border-radius: 12px;
+}
+
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+  font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
+}
+
+body {
+  background-color: #f5f7fa;
+  color: var(--dark-text);
+  line-height: 1.6;
+}
+
+.container {
+  max-width: 100%;
+  margin: 0 auto;
+  padding: 0 15px;
+}
+
+/* 顶部导航 */
+.header {
+  background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
+  color: white;
+  padding: 15px 0;
+  position: sticky;
+  top: 0;
+  z-index: 100;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+.header-content {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.logo {
+  display: flex;
+  align-items: center;
+  font-weight: bold;
+  font-size: 20px;
+}
+
+.logo-icon {
+  margin-right: 10px;
+  font-size: 24px;
+}
+
+.user-info {
+  display: flex;
+  align-items: center;
+}
+
+.avatar {
+  width: 36px;
+  height: 36px;
+  border-radius: 50%;
+  background-color: rgba(255, 255, 255, 0.3);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-left: 10px;
+}
+
+/* 底部导航 */
+.bottom-nav {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background-color: white;
+  display: flex;
+  justify-content: space-around;
+  padding: 10px 0;
+  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
+  z-index: 100;
+}
+
+.nav-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  font-size: 12px;
+  color: var(--light-text);
+  flex: 1;
+  cursor: pointer;
+  transition: all 0.3s ease;
+}
+
+.nav-item.active {
+  color: var(--primary-color);
+}
+
+.nav-icon {
+  font-size: 20px;
+  margin-bottom: 4px;
+}
+
+/* 内容区域 */
+.content {
+  padding: 20px 0 80px;
+}
+
+.section-title {
+  font-size: 18px;
+  font-weight: 600;
+  margin-bottom: 15px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.more-link {
+  font-size: 14px;
+  color: var(--primary-color);
+  font-weight: normal;
+  cursor: pointer;
+  transition: color 0.3s ease;
+
+  &:hover {
+    color: var(--primary-dark);
+  }
+}
+
+/* 卡片样式 */
+.card {
+  background-color: white;
+  border-radius: var(--border-radius);
+  box-shadow: var(--card-shadow);
+  padding: 16px;
+  margin-bottom: 16px;
+}
+
+/* 核心数据看板 */
+.data-dashboard {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 12px;
+  margin-bottom: 16px;
+}
+
+.data-card {
+  padding: 16px;
+  border-radius: var(--border-radius);
+  color: white;
+  display: flex;
+  flex-direction: column;
+  cursor: pointer;
+  transition: transform 0.3s ease;
+
+  &:hover {
+    transform: translateY(-2px);
+  }
+}
+
+.data-card:nth-child(1) {
+  background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
+}
+
+.data-card:nth-child(2) {
+  background: linear-gradient(135deg, var(--secondary-color), #2980b9);
+}
+
+.data-card:nth-child(3) {
+  background: linear-gradient(135deg, var(--accent-color), #e67e22);
+}
+
+.data-card:nth-child(4) {
+  background: linear-gradient(135deg, #9b59b6, #8e44ad);
+}
+
+.data-value {
+  font-size: 24px;
+  font-weight: bold;
+  margin: 8px 0 4px;
+}
+
+.data-label {
+  font-size: 14px;
+  opacity: 0.9;
+}
+
+.data-trend {
+  font-size: 12px;
+  opacity: 0.8;
+}
+
+/* 预警卡片 */
+.alert-card {
+  border-left: 4px solid var(--warning-color);
+  background-color: #fff9f9;
+}
+
+.alert-title {
+  display: flex;
+  align-items: center;
+  color: var(--warning-color);
+  font-weight: 600;
+  margin-bottom: 8px;
+}
+
+.alert-icon {
+  margin-right: 8px;
+}
+
+.alert-content p {
+  margin-bottom: 4px;
+  font-size: 14px;
+  color: var(--dark-text);
+}
+
+/* 快捷操作 */
+.quick-actions {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 16px;
+  text-align: center;
+}
+
+.action-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  cursor: pointer;
+  transition: transform 0.3s ease;
+
+  &:hover {
+    transform: translateY(-2px);
+  }
+}
+
+.action-icon {
+  width: 48px;
+  height: 48px;
+  background-color: var(--primary-light);
+  border-radius: 12px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 8px;
+  color: var(--primary-dark);
+  font-size: 20px;
+}
+
+.action-label {
+  font-size: 13px;
+  color: var(--dark-text);
+}
+
+/* 待办事项 */
+.todo-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 12px 0;
+  border-bottom: 1px solid #eee;
+  cursor: pointer;
+  transition: background-color 0.3s ease;
+
+  &:hover {
+    background-color: #f8f9fa;
+  }
+
+  &:last-child {
+    border-bottom: none;
+  }
+}
+
+.todo-info {
+  display: flex;
+  align-items: center;
+}
+
+.todo-icon {
+  width: 36px;
+  height: 36px;
+  border-radius: 8px;
+  background-color: #f0f7f4;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 12px;
+  color: var(--primary-color);
+}
+
+.todo-title {
+  font-weight: 600;
+  margin-bottom: 2px;
+}
+
+.todo-desc {
+  font-size: 12px;
+  color: var(--light-text);
+}
+
+.todo-count {
+  background-color: var(--warning-color);
+  color: white;
+  border-radius: 10px;
+  padding: 2px 8px;
+  font-size: 12px;
+}
+
+/* AI助手卡片 */
+.ai-assistant {
+  background: linear-gradient(135deg, #2c3e50, #34495e);
+  color: white;
+  border-radius: var(--border-radius);
+  padding: 20px;
+  margin-bottom: 16px;
+  cursor: pointer;
+  transition: transform 0.3s ease;
+
+  &:hover {
+    transform: translateY(-2px);
+  }
+}
+
+.ai-header {
+  display: flex;
+  align-items: center;
+  margin-bottom: 16px;
+}
+
+.ai-icon {
+  width: 40px;
+  height: 40px;
+  background-color: rgba(255, 255, 255, 0.2);
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 12px;
+  font-size: 20px;
+}
+
+.ai-title {
+  font-size: 18px;
+  font-weight: 600;
+}
+
+.ai-suggestions {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 10px;
+}
+
+.ai-suggestion {
+  background-color: rgba(255, 255, 255, 0.1);
+  border-radius: 8px;
+  padding: 10px;
+  font-size: 14px;
+  cursor: pointer;
+  transition: background-color 0.3s ease;
+
+  &:hover {
+    background-color: rgba(255, 255, 255, 0.2);
+  }
+}
+
+/* 响应式调整 */
+@media (min-width: 768px) {
+  .container {
+    max-width: 750px;
+  }
+  
+  .data-dashboard {
+    grid-template-columns: repeat(4, 1fr);
+  }
+
+  .quick-actions {
+    grid-template-columns: repeat(4, 1fr);
+  }
+
+  .ai-suggestions {
+    grid-template-columns: repeat(2, 1fr);
+  }
+}
+
+@media (max-width: 480px) {
+  .data-dashboard {
+    grid-template-columns: 1fr;
+  }
+
+  .quick-actions {
+    grid-template-columns: repeat(2, 1fr);
+  }
+
+  .ai-suggestions {
+    grid-template-columns: 1fr;
+  }
+}

+ 260 - 4
src/app/business/dashboard/dashboard.ts

@@ -1,6 +1,39 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { RouterModule } from '@angular/router';
+import { RouterModule, Router } from '@angular/router';
+
+interface DataCard {
+  value: string;
+  label: string;
+  trend: string;
+  icon: string;
+}
+
+interface AlertInfo {
+  title: string;
+  content: string[];
+  icon: string;
+}
+
+interface QuickAction {
+  label: string;
+  icon: string;
+  route?: string;
+  action?: string;
+}
+
+interface TodoItem {
+  title: string;
+  description: string;
+  count: number;
+  icon: string;
+  route?: string;
+}
+
+interface AISuggestion {
+  text: string;
+  action?: string;
+}
 
 @Component({
   selector: 'app-dashboard',
@@ -8,6 +41,229 @@ import { RouterModule } from '@angular/router';
   templateUrl: './dashboard.html',
   styleUrl: './dashboard.scss'
 })
-export class Dashboard {
-  constructor() {}
+export class Dashboard implements OnInit {
+  // 用户信息
+  userInfo = {
+    name: '张经理',
+    company: '绿色回收有限公司'
+  };
+
+  // 核心数据
+  dataCards: DataCard[] = [
+    {
+      value: '2,456',
+      label: '今日回收量(kg)',
+      trend: '↑ 12.5%',
+      icon: '♻️'
+    },
+    {
+      value: '¥18,920',
+      label: '产值',
+      trend: '↑ 8.3%',
+      icon: '💰'
+    },
+    {
+      value: '94.2%',
+      label: '订单完成率',
+      trend: '↑ 2.1%',
+      icon: '📊'
+    },
+    {
+      value: '98.5%',
+      label: '设备运行率',
+      trend: '→ 0%',
+      icon: '⚙️'
+    }
+  ];
+
+  // 预警信息
+  alertInfo: AlertInfo = {
+    title: '预警信息',
+    icon: '⚠️',
+    content: [
+      '设备A3需要维护保养',
+      '库存不足,建议及时补货',
+      '3个订单超时未处理'
+    ]
+  };
+
+  // 快捷操作
+  quickActions: QuickAction[] = [
+    {
+      label: '创建订单',
+      icon: '📝',
+      route: '/business/orders/create'
+    },
+    {
+      label: '分配订单',
+      icon: '📋',
+      route: '/business/orders/assign'
+    },
+    {
+      label: '查看报表',
+      icon: '📈',
+      route: '/business/reports'
+    },
+    {
+      label: 'AI助手',
+      icon: '🤖',
+      action: 'openAI'
+    }
+  ];
+
+  // 待办事项
+  todoItems: TodoItem[] = [
+    {
+      title: '待处理订单',
+      description: '需要及时处理的新订单',
+      count: 12,
+      icon: '📦',
+      route: '/business/orders/pending'
+    },
+    {
+      title: '待审核申请',
+      description: '用户提交的回收申请',
+      count: 8,
+      icon: '📋',
+      route: '/business/applications'
+    },
+    {
+      title: '设备维护计划',
+      description: '本周需要维护的设备',
+      count: 3,
+      icon: '🔧',
+      route: '/business/equipment/maintenance'
+    }
+  ];
+
+  // AI建议
+  aiSuggestions: AISuggestion[] = [
+    { text: '优化回收路线', action: 'optimizeRoute' },
+    { text: '库存预警提醒', action: 'inventoryAlert' },
+    { text: '设备维护建议', action: 'maintenanceAdvice' },
+    { text: '效率分析报告', action: 'efficiencyReport' }
+  ];
+
+  // 底部导航
+  navItems = [
+    { label: '工作台', icon: '🏠', route: '/business/dashboard', active: true },
+    { label: '订单', icon: '📋', route: '/business/orders', active: false },
+    { label: '设备', icon: '⚙️', route: '/business/equipment', active: false },
+    { label: '报表', icon: '📊', route: '/business/reports', active: false },
+    { label: '我的', icon: '👤', route: '/business/profile', active: false }
+  ];
+
+  constructor(private router: Router) {}
+
+  ngOnInit() {
+    // 初始化数据
+    this.loadDashboardData();
+  }
+
+  // 加载仪表板数据
+  loadDashboardData() {
+    // 这里可以调用API获取实时数据
+    console.log('Loading dashboard data...');
+  }
+
+  // 数据卡片点击事件
+  onDataCardClick(card: DataCard) {
+    console.log('Data card clicked:', card.label);
+    // 根据不同的卡片跳转到相应的详情页
+    switch (card.label) {
+      case '今日回收量(kg)':
+        this.router.navigate(['/business/recycling/details']);
+        break;
+      case '产值':
+        this.router.navigate(['/business/finance/revenue']);
+        break;
+      case '订单完成率':
+        this.router.navigate(['/business/orders/statistics']);
+        break;
+      case '设备运行率':
+        this.router.navigate(['/business/equipment/status']);
+        break;
+    }
+  }
+
+  // 快捷操作点击事件
+  onQuickActionClick(action: QuickAction) {
+    if (action.route) {
+      this.router.navigate([action.route]);
+    } else if (action.action) {
+      this.handleAction(action.action);
+    }
+  }
+
+  // 待办事项点击事件
+  onTodoItemClick(item: TodoItem) {
+    if (item.route) {
+      this.router.navigate([item.route]);
+    }
+  }
+
+  // AI助手点击事件
+  onAIAssistantClick() {
+    console.log('AI Assistant clicked');
+    this.router.navigate(['/business/ai-assistant']);
+  }
+
+  // AI建议点击事件
+  onAISuggestionClick(suggestion: AISuggestion) {
+    if (suggestion.action) {
+      this.handleAction(suggestion.action);
+    }
+  }
+
+  // 底部导航点击事件
+  onNavItemClick(item: any) {
+    // 更新活跃状态
+    this.navItems.forEach(nav => nav.active = false);
+    item.active = true;
+    
+    // 导航到对应页面
+    this.router.navigate([item.route]);
+  }
+
+  // 处理各种操作
+  private handleAction(action: string) {
+    switch (action) {
+      case 'openAI':
+        this.router.navigate(['/business/ai-assistant']);
+        break;
+      case 'optimizeRoute':
+        console.log('Optimizing route...');
+        // 实现路线优化逻辑
+        break;
+      case 'inventoryAlert':
+        console.log('Setting inventory alert...');
+        // 实现库存预警逻辑
+        break;
+      case 'maintenanceAdvice':
+        console.log('Getting maintenance advice...');
+        // 实现维护建议逻辑
+        break;
+      case 'efficiencyReport':
+        console.log('Generating efficiency report...');
+        // 实现效率报告逻辑
+        break;
+    }
+  }
+
+  // 用户头像点击事件
+  onUserAvatarClick() {
+    this.router.navigate(['/business/profile']);
+  }
+
+  // 查看更多点击事件
+  onViewMoreClick(section: string) {
+    switch (section) {
+      case 'alerts':
+        this.router.navigate(['/business/alerts']);
+        break;
+      case 'todos':
+        this.router.navigate(['/business/todos']);
+        break;
+    }
+  }
 }

+ 34 - 8
src/app/consumer/booking-recycle/booking-recycle.html

@@ -17,7 +17,13 @@
         class="category-item" 
         [class.active]="category.active"
         (click)="selectCategory(category)">
-        <div class="category-icon"><i [class]="category.icon"></i></div>
+        <div class="category-icon">
+          <app-svg-icon 
+            [name]="category.icon" 
+            size="lg" 
+            [color]="category.active ? 'primary' : 'secondary'">
+          </app-svg-icon>
+        </div>
         <div>{{category.name}}</div>
       </div>
     </div>
@@ -50,7 +56,7 @@
   <!-- 回收方式选择 -->
   <div class="form-section">
     <div class="section-title">
-      <i class="fas fa-truck"></i> 回收方式
+      <app-svg-icon name="recycle-method" size="md" color="#2e7d32"></app-svg-icon> 回收方式
     </div>
     
     <div class="recycle-method">
@@ -59,7 +65,13 @@
         class="method-card" 
         [class.active]="method.active"
         (click)="selectMethod(method)">
-        <div class="method-icon"><i [class]="method.icon"></i></div>
+        <div class="method-icon">
+          <app-svg-icon 
+            [name]="method.icon" 
+            size="xl" 
+            [color]="method.active ? 'primary' : 'secondary'">
+          </app-svg-icon>
+        </div>
         <div class="method-title">{{method.name}}</div>
         <div class="method-desc">{{method.description}}</div>
       </div>
@@ -89,7 +101,7 @@
   <!-- 时间选择 -->
   <div class="form-section">
     <div class="section-title">
-      <i class="far fa-clock"></i> 回收时间
+      <app-svg-icon name="clock" size="md" color="#2e7d32"></app-svg-icon> 回收时间
     </div>
     
     <div class="time-options">
@@ -98,7 +110,13 @@
         class="time-option" 
         [class.active]="option.active"
         (click)="selectTimeOption(option)">
-        <div class="method-icon"><i [class]="option.icon"></i></div>
+        <div class="method-icon">
+          <app-svg-icon 
+            [name]="option.icon" 
+            size="xl" 
+            [color]="option.active ? 'primary' : 'secondary'">
+          </app-svg-icon>
+        </div>
         <div class="method-title">{{option.name}}</div>
         <div class="method-desc">{{option.description}}</div>
       </div>
@@ -131,7 +149,7 @@
   <!-- 附加服务 -->
   <div class="form-section">
     <div class="section-title">
-      <i class="fas fa-concierge-bell"></i> 附加服务
+      <app-svg-icon name="service" size="md" color="#2e7d32"></app-svg-icon> 附加服务
     </div>
     
     <div class="additional-services">
@@ -139,7 +157,13 @@
         *ngFor="let service of additionalServices"
         class="service-item">
         <div class="service-info">
-          <div class="service-icon"><i [class]="service.icon"></i></div>
+          <div class="service-icon">
+            <app-svg-icon 
+              [name]="service.icon" 
+              size="lg" 
+              color="secondary">
+            </app-svg-icon>
+          </div>
           <div>
             <div class="service-name">{{service.name}}</div>
             <div class="service-desc">{{service.description}}</div>
@@ -157,7 +181,9 @@
       
       <div class="service-item" style="flex-direction: column; align-items: flex-start;">
         <div class="service-info" style="width: 100%; margin-bottom: 10px;">
-          <div class="service-icon"><i class="fas fa-note-sticky"></i></div>
+          <div class="service-icon">
+            <app-svg-icon name="edit" size="lg" color="secondary"></app-svg-icon>
+          </div>
           <div>
             <div class="service-name">备注</div>
             <div class="service-desc">特殊要求或说明</div>

+ 13 - 13
src/app/consumer/booking-recycle/booking-recycle.ts

@@ -60,24 +60,24 @@ export class BookingRecycle implements OnInit {
   
   // 废品分类
   wasteCategories: WasteCategory[] = [
-    { id: 'paper', name: '纸类', icon: 'fas fa-newspaper', active: true },
-    { id: 'plastic', name: '塑料', icon: 'fas fa-bottle-water', active: false },
-    { id: 'glass', name: '玻璃', icon: 'fas fa-wine-glass', active: false },
-    { id: 'electronic', name: '电子', icon: 'fas fa-microchip', active: false },
-    { id: 'textile', name: '衣物', icon: 'fas fa-shirt', active: false },
-    { id: 'other', name: '其他', icon: 'fas fa-box', active: false }
+    { id: 'paper', name: '纸类', icon: 'waste-info', active: true },
+    { id: 'plastic', name: '塑料', icon: 'waste-info', active: false },
+    { id: 'glass', name: '玻璃', icon: 'waste-info', active: false },
+    { id: 'electronic', name: '电子', icon: 'electronics', active: false },
+    { id: 'textile', name: '衣物', icon: 'waste-info', active: false },
+    { id: 'other', name: '其他', icon: 'waste-info', active: false }
   ];
 
   // 回收方式
   recycleMethods: RecycleMethod[] = [
-    { id: 'pickup', name: '上门回收', description: '回收员上门收取', icon: 'fas fa-home', active: true },
-    { id: 'dropoff', name: '自助投递', description: '送至自助点', icon: 'fas fa-location-dot', active: false }
+    { id: 'pickup', name: '上门回收', description: '回收员上门收取', icon: 'recycle-method', active: true },
+    { id: 'dropoff', name: '自助投递', description: '送至自助点', icon: 'address', active: false }
   ];
 
   // 时间选项
   timeOptions: TimeOption[] = [
-    { id: 'immediate', name: '立即上门', description: '最快30分钟', icon: 'fas fa-bolt', active: true },
-    { id: 'scheduled', name: '预约时间', description: '选择日期', icon: 'fas fa-calendar-days', active: false }
+    { id: 'immediate', name: '立即上门', description: '最快30分钟', icon: 'clock', active: true },
+    { id: 'scheduled', name: '预约时间', description: '选择日期', icon: 'clock', active: false }
   ];
 
   // 日期选项
@@ -100,9 +100,9 @@ export class BookingRecycle implements OnInit {
 
   // 附加服务
   additionalServices: AdditionalService[] = [
-    { id: 'carry', name: '搬运服务', description: '协助搬运重物', price: '免费', icon: 'fas fa-dolly', enabled: false },
-    { id: 'clean', name: '清洁服务', description: '清理回收区域', price: '+5元', icon: 'fas fa-broom', enabled: false },
-    { id: 'sort', name: '分类服务', description: '专业分类指导', price: '免费', icon: 'fas fa-sort', enabled: false }
+    { id: 'carry', name: '搬运服务', description: '协助搬运重物', price: '免费', icon: 'service', enabled: false },
+    { id: 'clean', name: '清洁服务', description: '清理回收区域', price: '+5元', icon: 'service', enabled: false },
+    { id: 'sort', name: '分类服务', description: '专业分类指导', price: '免费', icon: 'service', enabled: false }
   ];
 
   // 表单数据

+ 24 - 0
src/app/consumer/consumer-routing-module.ts

@@ -13,6 +13,17 @@ import { DropPointsComponent } from './home/drop-points/drop-points';
 import { CollectorsComponent } from './home/collectors/collectors';
 import { ActivitiesComponent } from './home/activities/activities';
 
+// Profile子页面组件导入
+import { AddressesComponent } from './profile/addresses/addresses';
+import { OrdersComponent } from './profile/orders/orders';
+import { FavoritesComponent } from './profile/favorites/favorites';
+import { SettingsComponent } from './profile/settings/settings';
+import { InviteFriendsComponent } from './profile/invite-friends/invite-friends';
+import { CustomerServiceComponent } from './profile/customer-service/customer-service';
+import { AboutUsPage } from './profile/about-us/about-us';
+import { UserAgreementPage } from './profile/user-agreement/user-agreement';
+import { PrivacyPolicyPage } from './profile/privacy-policy/privacy-policy';
+
 const routes: Routes = [
   { path: '', redirectTo: 'home', pathMatch: 'full' },
   { path: 'home', component: HomeComponent },
@@ -25,6 +36,19 @@ const routes: Routes = [
   { path: 'points-mall/eco-knowledge', component: EcoKnowledge },
   { path: 'ai-assistant', component: AiAssistant },
   { path: 'profile', component: Profile },
+  
+  // Profile子页面路由
+  { path: 'profile/addresses', component: AddressesComponent },
+  { path: 'profile/orders', component: OrdersComponent },
+  { path: 'profile/favorites', component: FavoritesComponent },
+  { path: 'profile/settings', component: SettingsComponent },
+  { path: 'profile/invite-friends', component: InviteFriendsComponent },
+  { path: 'profile/customer-service', component: CustomerServiceComponent },
+  { path: 'profile/about-us', component: AboutUsPage },
+  { path: 'profile/user-agreement', component: UserAgreementPage },
+  { path: 'profile/privacy-policy', component: PrivacyPolicyPage },
+  
+  // 其他页面路由
   { path: 'notifications', component: NotificationsComponent },
   { path: 'ar-recognition', component: ArRecognitionComponent },
   { path: 'drop-points', component: DropPointsComponent },

+ 22 - 11
src/app/consumer/earnings/earnings.html

@@ -47,18 +47,29 @@
       </div>
     </div>
     
+    <!-- 日期筛选 -->
     <div class="date-filter">
-      <input 
-        type="date" 
-        class="date-input" 
-        [(ngModel)]="startDate"
-        (change)="filterByDate()">
-      <span>至</span>
-      <input 
-        type="date" 
-        class="date-input" 
-        [(ngModel)]="endDate"
-        (change)="filterByDate()">
+      <div class="date-input-group">
+        <label>开始日期:</label>
+        <input 
+          type="date" 
+          class="date-input" 
+          [(ngModel)]="startDate"
+          (change)="filterByDate()"
+          placeholder="选择开始日期">
+      </div>
+      <div class="date-input-group">
+        <label>结束日期:</label>
+        <input 
+          type="date" 
+          class="date-input" 
+          [(ngModel)]="endDate"
+          (change)="filterByDate()"
+          placeholder="选择结束日期">
+      </div>
+      <button class="clear-date-btn" (click)="clearDateFilter()">
+        <i class="fas fa-times"></i> 清除
+      </button>
     </div>
     
     <!-- 收益列表 -->

+ 496 - 134
src/app/consumer/earnings/earnings.scss

@@ -48,62 +48,47 @@
   min-height: 100vh;
 }
 
-// 收益总览卡片
-.earnings-overview {
-  background: white;
-  border-radius: 15px;
-  padding: 20px;
-  margin-bottom: 20px;
-  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
-
-  .earnings-stats {
-    display: flex;
-    justify-content: space-around;
-    margin-bottom: 25px;
-
-    .stat-item {
-      text-align: center;
-
-      .stat-value {
-        font-size: 28px;
-        font-weight: bold;
-        color: #2e7d32;
-        margin-bottom: 5px;
-      }
-
-      .stat-label {
-        font-size: 14px;
-        color: #6c757d;
-      }
-    }
+// 动画定义
+@keyframes slideDown {
+  from {
+    opacity: 0;
+    transform: translateY(-10px) scale(0.95);
   }
+  to {
+    opacity: 1;
+    transform: translateY(0) scale(1);
+  }
+}
 
-  .carbon-section {
-    border-top: 1px solid #e9ecef;
-    padding-top: 20px;
-
-    .carbon-header {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      margin-bottom: 15px;
-
-      .carbon-title {
-        font-size: 16px;
-        color: #333;
-      }
+@keyframes slideUp {
+  from {
+    opacity: 1;
+    transform: translateY(0) scale(1);
+  }
+  to {
+    opacity: 0;
+    transform: translateY(-10px) scale(0.95);
+  }
+}
 
-      .carbon-value {
-        font-size: 20px;
-        font-weight: bold;
-        color: #1abc9c;
-      }
-    }
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
 
-    .chart-container {
-      height: 200px;
-      position: relative;
-    }
+@keyframes pulse {
+  0% {
+    transform: scale(1);
+  }
+  50% {
+    transform: scale(1.05);
+  }
+  100% {
+    transform: scale(1);
   }
 }
 
@@ -159,21 +144,79 @@
 // 日期筛选
 .date-filter {
   display: flex;
-  align-items: center;
-  gap: 10px;
+  flex-direction: column;
+  gap: 15px;
   margin-bottom: 20px;
+  padding: 15px;
+  background: #f8f9fa;
+  border-radius: 12px;
+  border: 1px solid #e9ecef;
 
-  .date-input {
-    flex: 1;
-    padding: 10px 12px;
-    border: 1px solid #e9ecef;
-    border-radius: 8px;
-    font-size: 14px;
+  .date-input-group {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+
+    label {
+      font-size: 14px;
+      color: #495057;
+      font-weight: 500;
+      min-width: 70px;
+    }
+
+    .date-input {
+      flex: 1;
+      padding: 10px 12px;
+      border: 1px solid #ced4da;
+      border-radius: 8px;
+      font-size: 14px;
+      background: white;
+      transition: all 0.3s ease;
+
+      &:focus {
+        outline: none;
+        border-color: #2e7d32;
+        box-shadow: 0 0 0 2px rgba(46, 125, 50, 0.1);
+      }
+    }
   }
 
-  span {
-    color: #6c757d;
-    font-size: 14px;
+  .clear-date-btn {
+    align-self: flex-end;
+    padding: 8px 16px;
+    background: #dc3545;
+    color: white;
+    border: none;
+    border-radius: 6px;
+    font-size: 12px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    display: flex;
+    align-items: center;
+    gap: 5px;
+
+    &:hover {
+      background: #c82333;
+      transform: translateY(-1px);
+    }
+
+    i {
+      font-size: 10px;
+    }
+  }
+
+  @media (min-width: 768px) {
+    flex-direction: row;
+    align-items: center;
+
+    .date-input-group {
+      flex: 1;
+    }
+
+    .clear-date-btn {
+      align-self: center;
+      margin-left: 10px;
+    }
   }
 }
 
@@ -268,142 +311,373 @@
   display: grid;
   grid-template-columns: repeat(2, 1fr);
   gap: 15px;
+  margin-top: 20px;
 
   .action-btn {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
+    background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+    border: 2px solid rgba(46, 125, 50, 0.1);
+    border-radius: 15px;
     padding: 20px;
-    background: #f8f9fa;
-    border-radius: 12px;
+    text-align: center;
     cursor: pointer;
-    transition: all 0.3s;
-    border: 1px solid #e9ecef;
+    transition: all 0.3s ease;
+    position: relative;
+    overflow: hidden;
+
+    &::before {
+      content: '';
+      position: absolute;
+      top: 0;
+      left: -100%;
+      width: 100%;
+      height: 100%;
+      background: linear-gradient(90deg, transparent, rgba(46, 125, 50, 0.1), transparent);
+      transition: left 0.5s;
+    }
 
     &:hover {
-      background: #e9ecef;
-      transform: translateY(-2px);
-      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+      transform: translateY(-5px);
+      box-shadow: 0 10px 25px rgba(46, 125, 50, 0.15);
+      border-color: rgba(46, 125, 50, 0.3);
+
+      &::before {
+        left: 100%;
+      }
+
+      i {
+        animation: pulse 0.6s ease-in-out;
+        color: #2e7d32;
+      }
+
+      div {
+        color: #2e7d32;
+        font-weight: 600;
+      }
     }
 
     i {
-      font-size: 24px;
-      color: #2e7d32;
-      margin-bottom: 8px;
+      font-size: 28px;
+      color: #4caf50;
+      margin-bottom: 10px;
+      display: block;
+      transition: all 0.3s ease;
     }
 
     div {
-      font-size: 14px;
+      font-size: 16px;
       color: #333;
       font-weight: 500;
+      transition: all 0.3s ease;
+    }
+
+    &:active {
+      transform: translateY(-2px);
     }
   }
 }
 
-// 模态框样式
+// 模态框样式优化
 .modal {
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
-  background: rgba(0, 0, 0, 0.5);
+  background: rgba(0, 0, 0, 0.6);
   display: flex;
-  align-items: center;
   justify-content: center;
-  z-index: 2000;
-  padding: 20px;
+  align-items: center;
+  z-index: 10000;
+  backdrop-filter: blur(5px);
+  animation: fadeIn 0.2s ease-out;
 
   .modal-content {
     background: white;
-    border-radius: 15px;
-    padding: 25px;
-    width: 100%;
+    border-radius: 20px;
+    padding: 30px;
+    width: 90%;
     max-width: 400px;
     max-height: 80vh;
     overflow-y: auto;
+    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
+    animation: slideDown 0.2s ease-out;
+    border: 1px solid rgba(46, 125, 50, 0.1);
 
     .modal-title {
       font-size: 20px;
-      font-weight: 600;
-      text-align: center;
+      font-weight: 700;
+      color: #2e7d32;
       margin-bottom: 20px;
-      color: #333;
-    }
-
-    .modal-buttons {
-      display: flex;
-      gap: 15px;
-      margin-top: 25px;
-
-      .modal-btn {
-        flex: 1;
-        padding: 12px 20px;
-        border: none;
-        border-radius: 8px;
-        font-size: 16px;
-        font-weight: 500;
-        cursor: pointer;
-        transition: all 0.3s;
-
-        &.cancel {
-          background: #f8f9fa;
-          color: #6c757d;
-          border: 1px solid #e9ecef;
-
-          &:hover {
-            background: #e9ecef;
-          }
-        }
-
-        &.confirm {
-          background: #2e7d32;
-          color: white;
+      text-align: center;
+      position: relative;
 
-          &:hover {
-            background: #1b5e20;
-          }
-        }
+      &::after {
+        content: '';
+        position: absolute;
+        bottom: -10px;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 50px;
+        height: 3px;
+        background: linear-gradient(135deg, #2e7d32, #4caf50);
+        border-radius: 2px;
       }
     }
   }
 }
 
-// 提现选项
+// 提现选项样式
 .withdraw-options {
   display: flex;
   gap: 15px;
-  margin-bottom: 20px;
+  margin: 20px 0;
 
   .withdraw-option {
     flex: 1;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
     padding: 15px;
     border: 2px solid #e9ecef;
     border-radius: 12px;
+    text-align: center;
     cursor: pointer;
-    transition: all 0.3s;
+    transition: all 0.3s ease;
+    background: #f8f9fa;
+
+    &:hover {
+      border-color: rgba(46, 125, 50, 0.3);
+      background: rgba(46, 125, 50, 0.05);
+    }
 
     &.active {
       border-color: #2e7d32;
-      background: #e8f5e8;
+      background: rgba(46, 125, 50, 0.1);
+      color: #2e7d32;
+      font-weight: 600;
+
+      .withdraw-icon i {
+        color: #2e7d32;
+      }
     }
 
     .withdraw-icon {
-      font-size: 24px;
-      color: #2e7d32;
       margin-bottom: 8px;
+
+      i {
+        font-size: 24px;
+        color: #6c757d;
+        transition: color 0.3s ease;
+      }
     }
+  }
+}
 
-    div {
-      font-size: 14px;
-      color: #333;
+// 模态框按钮样式
+.modal-buttons {
+  display: flex;
+  gap: 15px;
+  margin-top: 25px;
+
+  .modal-btn {
+    flex: 1;
+    padding: 12px 20px;
+    border: none;
+    border-radius: 10px;
+    font-size: 16px;
+    font-weight: 600;
+    cursor: pointer;
+    transition: all 0.3s ease;
+
+    &.cancel {
+      background: #f8f9fa;
+      color: #6c757d;
+      border: 2px solid #e9ecef;
+
+      &:hover {
+        background: #e9ecef;
+        color: #495057;
+      }
+    }
+
+    &.confirm {
+      background: linear-gradient(135deg, #2e7d32, #4caf50);
+      color: white;
+      box-shadow: 0 4px 15px rgba(46, 125, 50, 0.3);
+
+      &:hover {
+        transform: translateY(-2px);
+        box-shadow: 0 6px 20px rgba(46, 125, 50, 0.4);
+      }
+
+      &:active {
+        transform: translateY(0);
+      }
+    }
+  }
+}
+
+// 输入框样式优化
+input[type="number"], input[type="date"] {
+  width: 100%;
+  padding: 15px 20px;
+  border: 2px solid #e9ecef;
+  border-radius: 12px;
+  font-size: 16px;
+  transition: all 0.3s ease;
+  background: #f8f9fa;
+
+  &:focus {
+    outline: none;
+    border-color: #2e7d32;
+    background: white;
+    box-shadow: 0 0 0 3px rgba(46, 125, 50, 0.1);
+  }
+
+  &::placeholder {
+    color: #adb5bd;
+  }
+}
+
+// 收益列表项样式优化
+.earning-item {
+  background: white;
+  border-radius: 15px;
+  padding: 20px;
+  margin-bottom: 15px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  border: 1px solid rgba(46, 125, 50, 0.1);
+  position: relative;
+  overflow: hidden;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(46, 125, 50, 0.05), transparent);
+    transition: left 0.5s;
+  }
+
+  &:hover {
+    transform: translateY(-3px);
+    box-shadow: 0 8px 25px rgba(46, 125, 50, 0.15);
+    border-color: rgba(46, 125, 50, 0.2);
+
+    &::before {
+      left: 100%;
+    }
+
+    .earning-icon i {
+      animation: pulse 0.6s ease-in-out;
+    }
+  }
+
+  .earning-info {
+    display: flex;
+    align-items: center;
+
+    .earning-icon {
+      width: 50px;
+      height: 50px;
+      border-radius: 12px;
+      background: linear-gradient(135deg, rgba(46, 125, 50, 0.1), rgba(76, 175, 80, 0.1));
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-right: 15px;
+
+      i {
+        font-size: 20px;
+        color: #2e7d32;
+        transition: all 0.3s ease;
+      }
+    }
+
+    .earning-details {
+      .earning-category {
+        font-size: 16px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 5px;
+      }
+
+      .earning-time {
+        font-size: 12px;
+        color: #6c757d;
+      }
+    }
+  }
+
+  .earning-amount {
+    text-align: right;
+
+    .cash-amount {
+      font-size: 18px;
+      font-weight: 700;
+      color: #2e7d32;
+      margin-bottom: 3px;
+    }
+
+    .points-amount {
+      font-size: 12px;
+      color: #ff9800;
+      font-weight: 500;
     }
   }
 }
 
+// 筛选按钮样式优化
+.filter-btn {
+  padding: 10px 20px;
+  border: 2px solid #e9ecef;
+  border-radius: 25px;
+  background: white;
+  color: #6c757d;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  font-size: 14px;
+  font-weight: 500;
+
+  &:hover {
+    border-color: rgba(46, 125, 50, 0.3);
+    color: #2e7d32;
+    background: rgba(46, 125, 50, 0.05);
+  }
+
+  &.active {
+    background: linear-gradient(135deg, #2e7d32, #4caf50);
+    color: white;
+    border-color: #2e7d32;
+    box-shadow: 0 4px 15px rgba(46, 125, 50, 0.3);
+  }
+}
+
+// 空状态样式优化
+.empty-state {
+  text-align: center;
+  padding: 60px 20px;
+  color: #6c757d;
+
+  .empty-icon {
+    font-size: 48px;
+    margin-bottom: 20px;
+    opacity: 0.5;
+
+    i {
+      color: #adb5bd;
+    }
+  }
+
+  div:last-child {
+    font-size: 16px;
+    font-weight: 500;
+  }
+}
+
 // 底部导航栏
 .bottom-nav {
   position: fixed;
@@ -488,4 +762,92 @@
       padding: 20px;
     }
   }
+}
+
+// 收益总览卡片
+.earnings-overview {
+  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
+  border-radius: 20px;
+  padding: 25px;
+  margin-bottom: 25px;
+  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
+  animation: fadeIn 0.6s ease-out;
+  border: 1px solid rgba(46, 125, 50, 0.1);
+
+  .earnings-stats {
+    display: flex;
+    justify-content: space-around;
+    margin-bottom: 30px;
+
+    .stat-item {
+      text-align: center;
+      position: relative;
+      padding: 15px;
+      border-radius: 15px;
+      background: rgba(46, 125, 50, 0.05);
+      transition: all 0.3s ease;
+
+      &:hover {
+        transform: translateY(-5px);
+        box-shadow: 0 8px 20px rgba(46, 125, 50, 0.15);
+      }
+
+      .stat-value {
+        font-size: 32px;
+        font-weight: 700;
+        background: linear-gradient(135deg, #2e7d32, #4caf50);
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+        background-clip: text;
+        margin-bottom: 8px;
+        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+      }
+
+      .stat-label {
+        font-size: 14px;
+        color: #6c757d;
+        font-weight: 500;
+      }
+    }
+  }
+
+  .carbon-section {
+    border-top: 2px solid rgba(46, 125, 50, 0.1);
+    padding-top: 25px;
+    background: rgba(26, 188, 156, 0.05);
+    border-radius: 15px;
+    padding: 20px;
+    margin-top: 20px;
+
+    .carbon-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 20px;
+
+      .carbon-title {
+        font-size: 18px;
+        color: #333;
+        font-weight: 600;
+      }
+
+      .carbon-value {
+        font-size: 24px;
+        font-weight: 700;
+        background: linear-gradient(135deg, #1abc9c, #16a085);
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+        background-clip: text;
+      }
+    }
+
+    .chart-container {
+      height: 200px;
+      position: relative;
+      background: white;
+      border-radius: 12px;
+      padding: 15px;
+      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
+    }
+  }
 }

+ 379 - 47
src/app/consumer/earnings/earnings.ts

@@ -144,6 +144,146 @@ export class EarningsComponent implements OnInit, AfterViewInit {
       price: '¥8.00/kg',
       address: '北京市朝阳区建国路88号',
       collector: '孙师傅'
+    },
+    {
+      id: '6',
+      category: '玻璃回收',
+      time: '2024-01-10 11:25',
+      orderNo: 'RC202401100006',
+      cashAmount: 15.30,
+      pointsAmount: 76,
+      carbonReduction: 1.5,
+      icon: 'fas fa-wine-glass',
+      weight: '6.8kg',
+      price: '¥2.25/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '刘师傅'
+    },
+    {
+      id: '7',
+      category: '废纸回收',
+      time: '2024-01-09 15:40',
+      orderNo: 'RC202401090007',
+      cashAmount: 42.80,
+      pointsAmount: 214,
+      carbonReduction: 4.3,
+      icon: 'fas fa-newspaper',
+      weight: '8.7kg',
+      price: '¥4.92/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '陈师傅'
+    },
+    {
+      id: '8',
+      category: '塑料制品回收',
+      time: '2024-01-08 09:15',
+      orderNo: 'RC202401080008',
+      cashAmount: 28.60,
+      pointsAmount: 143,
+      carbonReduction: 2.9,
+      icon: 'fas fa-bottle-water',
+      weight: '4.3kg',
+      price: '¥6.65/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '周师傅'
+    },
+    {
+      id: '9',
+      category: '电子设备回收',
+      time: '2024-01-07 14:20',
+      orderNo: 'RC202401070009',
+      cashAmount: 85.00,
+      pointsAmount: 425,
+      carbonReduction: 8.5,
+      icon: 'fas fa-laptop',
+      weight: '2.1kg',
+      price: '¥40.48/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '吴师傅'
+    },
+    {
+      id: '10',
+      category: '金属回收',
+      time: '2024-01-06 16:30',
+      orderNo: 'RC202401060010',
+      cashAmount: 67.50,
+      pointsAmount: 337,
+      carbonReduction: 6.8,
+      icon: 'fas fa-wrench',
+      weight: '3.5kg',
+      price: '¥19.29/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '郑师傅'
+    },
+    {
+      id: '11',
+      category: '纺织品回收',
+      time: '2024-01-05 12:45',
+      orderNo: 'RC202401050011',
+      cashAmount: 24.00,
+      pointsAmount: 120,
+      carbonReduction: 2.4,
+      icon: 'fas fa-shirt',
+      weight: '3.0kg',
+      price: '¥8.00/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '马师傅'
+    },
+    {
+      id: '12',
+      category: '废纸回收',
+      time: '2024-01-04 10:30',
+      orderNo: 'RC202401040012',
+      cashAmount: 36.90,
+      pointsAmount: 184,
+      carbonReduction: 3.7,
+      icon: 'fas fa-file-alt',
+      weight: '7.5kg',
+      price: '¥4.92/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '黄师傅'
+    },
+    {
+      id: '13',
+      category: '塑料瓶回收',
+      time: '2024-01-03 13:15',
+      orderNo: 'RC202401030013',
+      cashAmount: 21.70,
+      pointsAmount: 108,
+      carbonReduction: 2.2,
+      icon: 'fas fa-wine-bottle',
+      weight: '4.4kg',
+      price: '¥4.93/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '徐师傅'
+    },
+    {
+      id: '14',
+      category: '电子设备回收',
+      time: '2024-01-02 11:50',
+      orderNo: 'RC202401020014',
+      cashAmount: 95.00,
+      pointsAmount: 475,
+      carbonReduction: 9.5,
+      icon: 'fas fa-tablet-alt',
+      weight: '1.8kg',
+      price: '¥52.78/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '朱师傅'
+    },
+    {
+      id: '15',
+      category: '玻璃回收',
+      time: '2024-01-01 14:35',
+      orderNo: 'RC202401010015',
+      cashAmount: 18.90,
+      pointsAmount: 94,
+      carbonReduction: 1.9,
+      icon: 'fas fa-wine-glass',
+      weight: '8.4kg',
+      price: '¥2.25/kg',
+      address: '北京市朝阳区建国路88号',
+      collector: '何师傅'
     }
   ];
   
@@ -202,14 +342,13 @@ export class EarningsComponent implements OnInit, AfterViewInit {
 
   // 初始化数据
   initializeData() {
+    // 初始显示全部数据,不启用日期筛选,避免列表为空
     this.filteredEarnings = [...this.earningsData];
-    
-    // 设置默认日期范围(最近30天)
-    const today = new Date();
-    const thirtyDaysAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000);
-    
-    this.endDate = today.toISOString().split('T')[0];
-    this.startDate = thirtyDaysAgo.toISOString().split('T')[0];
+    this.startDate = '';
+    this.endDate = '';
+
+    // 应用初始筛选
+    this.applyFilter();
   }
 
   // 初始化碳减排图表
@@ -325,36 +464,70 @@ export class EarningsComponent implements OnInit, AfterViewInit {
 
   // 应用筛选条件
   applyFilter() {
+    let filtered = [...this.earningsData];
+    
+    // 首先按类型筛选
     const activeFilter = this.filterOptions.find(f => f.active);
-    if (!activeFilter) return;
-
-    switch (activeFilter.id) {
-      case 'all':
-        this.filteredEarnings = [...this.earningsData];
-        break;
-      case 'cash':
-        this.filteredEarnings = this.earningsData.filter(e => e.cashAmount > 0);
-        break;
-      case 'points':
-        this.filteredEarnings = this.earningsData.filter(e => e.pointsAmount > 0);
-        break;
-      case 'carbon':
-        this.filteredEarnings = this.earningsData.filter(e => e.carbonReduction > 0);
-        break;
+    if (activeFilter) {
+      switch (activeFilter.id) {
+        case 'all':
+          // 显示所有记录
+          break;
+        case 'cash':
+          // 按现金收益排序,优先显示现金收益高的记录
+          filtered = filtered.filter(e => e.cashAmount > 0).sort((a, b) => b.cashAmount - a.cashAmount);
+          break;
+        case 'points':
+          // 按积分收益排序,优先显示积分收益高的记录
+          filtered = filtered.filter(e => e.pointsAmount > 0).sort((a, b) => b.pointsAmount - a.pointsAmount);
+          break;
+        case 'carbon':
+          // 按碳减排排序,优先显示碳减排高的记录
+          filtered = filtered.filter(e => e.carbonReduction > 0).sort((a, b) => b.carbonReduction - a.carbonReduction);
+          break;
+      }
+    }
+    
+    // 然后按日期筛选
+    if (this.startDate && this.endDate) {
+      const start = new Date(this.startDate);
+      const end = new Date(this.endDate);
+      end.setHours(23, 59, 59, 999); // 设置为当天的最后一刻
+      
+      filtered = filtered.filter(earning => {
+        const earningDate = new Date(earning.time);
+        return earningDate >= start && earningDate <= end;
+      });
+    } else if (this.startDate) {
+      // 只有开始日期
+      const start = new Date(this.startDate);
+      filtered = filtered.filter(earning => {
+        const earningDate = new Date(earning.time);
+        return earningDate >= start;
+      });
+    } else if (this.endDate) {
+      // 只有结束日期
+      const end = new Date(this.endDate);
+      end.setHours(23, 59, 59, 999);
+      filtered = filtered.filter(earning => {
+        const earningDate = new Date(earning.time);
+        return earningDate <= end;
+      });
     }
+    
+    this.filteredEarnings = filtered;
   }
 
   // 按日期筛选
   filterByDate() {
-    if (!this.startDate || !this.endDate) return;
+    this.applyFilter(); // 重新应用所有筛选条件
+  }
 
-    const start = new Date(this.startDate);
-    const end = new Date(this.endDate);
-    
-    this.filteredEarnings = this.earningsData.filter(earning => {
-      const earningDate = new Date(earning.time);
-      return earningDate >= start && earningDate <= end;
-    });
+  // 清除日期筛选
+  clearDateFilter() {
+    this.startDate = '';
+    this.endDate = '';
+    this.applyFilter();
   }
 
   // 显示订单详情
@@ -388,40 +561,120 @@ export class EarningsComponent implements OnInit, AfterViewInit {
   // 确认提现
   confirmWithdraw() {
     if (this.withdrawAmount <= 0) {
-      alert('请输入有效的提现金额');
+      this.showAlert('请输入有效的提现金额', 'warning');
       return;
     }
     
     if (this.withdrawAmount > this.totalCashEarnings) {
-      alert('提现金额不能超过可用余额');
+      this.showAlert('提现金额不能超过可用余额', 'error');
+      return;
+    }
+
+    if (this.withdrawAmount < 10) {
+      this.showAlert('最低提现金额为10元', 'warning');
       return;
     }
 
     const selectedOption = this.withdrawOptions.find(o => o.active);
-    console.log(`提现 ¥${this.withdrawAmount} 到 ${selectedOption?.name}`);
+    if (!selectedOption) {
+      this.showAlert('请选择提现方式', 'warning');
+      return;
+    }
+
+    // 显示确认对话框
+    if (confirm(`确认提现 ¥${this.withdrawAmount.toFixed(2)} 到${selectedOption.name}?`)) {
+      this.processWithdraw(selectedOption);
+    }
+  }
+
+  // 处理提现请求
+  private processWithdraw(option: WithdrawOption) {
+    // 模拟API调用
+    this.showAlert('正在处理提现申请...', 'info');
     
-    // 这里应该调用实际的提现API
-    alert(`提现申请已提交,将通过${selectedOption?.name}到账`);
-    this.closeModal('withdraw');
+    setTimeout(() => {
+      // 模拟成功响应
+      this.totalCashEarnings -= this.withdrawAmount;
+      this.showAlert(`提现申请已提交!预计1-3个工作日通过${option.name}到账`, 'success');
+      this.closeModal('withdraw');
+      
+      // 添加提现记录到收益明细
+      const withdrawRecord: EarningRecord = {
+        id: Date.now().toString(),
+        category: '提现',
+        time: new Date().toLocaleString('zh-CN'),
+        orderNo: `WD${Date.now()}`,
+        cashAmount: -this.withdrawAmount,
+        pointsAmount: 0,
+        carbonReduction: 0,
+        icon: 'fas fa-money-bill-wave',
+        weight: '-',
+        price: '-',
+        address: '-',
+        collector: option.name
+      };
+      
+      this.earningsData.unshift(withdrawRecord);
+      this.applyFilter();
+    }, 2000);
   }
 
   // 确认捐赠
   confirmDonation() {
     if (!this.selectedProject) {
-      alert('请选择捐赠项目');
+      this.showAlert('请选择捐赠项目', 'warning');
       return;
     }
     
     if (this.donationAmount <= 0) {
-      alert('请输入有效的捐赠金额');
+      this.showAlert('请输入有效的捐赠金额', 'warning');
       return;
     }
 
-    console.log(`捐赠 ¥${this.donationAmount} 到 ${this.selectedProject.name}`);
+    if (this.donationAmount > this.totalCashEarnings) {
+      this.showAlert('捐赠金额不能超过可用余额', 'error');
+      return;
+    }
+
+    // 显示确认对话框
+    if (confirm(`确认向"${this.selectedProject.name}"捐赠 ¥${this.donationAmount.toFixed(2)}?`)) {
+      this.processDonation();
+    }
+  }
+
+  // 处理捐赠请求
+  private processDonation() {
+    if (!this.selectedProject) return;
     
-    // 这里应该调用实际的捐赠API
-    alert(`感谢您的爱心捐赠!已向${this.selectedProject.name}捐赠 ¥${this.donationAmount}`);
-    this.closeModal('donation');
+    this.showAlert('正在处理捐赠...', 'info');
+    
+    setTimeout(() => {
+      // 模拟成功响应
+      this.totalCashEarnings -= this.donationAmount;
+      this.showAlert(`感谢您的爱心!已成功向"${this.selectedProject!.name}"捐赠 ¥${this.donationAmount.toFixed(2)}`, 'success');
+      this.closeModal('donation');
+      
+      // 添加捐赠记录到收益明细
+      const donationRecord: EarningRecord = {
+        id: Date.now().toString(),
+        category: '公益捐赠',
+        time: new Date().toLocaleString('zh-CN'),
+        orderNo: `DN${Date.now()}`,
+        cashAmount: -this.donationAmount,
+        pointsAmount: Math.floor(this.donationAmount * 2), // 捐赠获得双倍积分
+        carbonReduction: this.donationAmount * 0.1, // 每元捐赠相当于0.1kg碳减排
+        icon: 'fas fa-hand-holding-heart',
+        weight: '-',
+        price: '-',
+        address: '-',
+        collector: this.selectedProject!.name
+      };
+      
+      this.earningsData.unshift(donationRecord);
+      this.totalPointsEarnings += donationRecord.pointsAmount;
+      this.totalCarbonReduction += donationRecord.carbonReduction;
+      this.applyFilter();
+    }, 2000);
   }
 
   // 关闭模态框
@@ -445,15 +698,94 @@ export class EarningsComponent implements OnInit, AfterViewInit {
 
   // 跳转到商城
   goToMall() {
-    console.log('跳转到积分商城');
-    // 这里应该跳转到实际的商城页面
+    this.router.navigate(['/consumer/points-mall']);
   }
 
   // 导出账单
   exportBill() {
-    console.log('导出收益账单');
-    // 这里应该实现实际的账单导出功能
-    alert('账单导出功能开发中...');
+    this.showAlert('正在生成账单...', 'info');
+    
+    setTimeout(() => {
+      this.generateBillReport();
+    }, 1500);
+  }
+
+  // 生成账单报告
+  private generateBillReport() {
+    const billData = {
+      period: `${this.startDate} 至 ${this.endDate}`,
+      totalCash: this.totalCashEarnings,
+      totalPoints: this.totalPointsEarnings,
+      totalCarbon: this.totalCarbonReduction,
+      records: this.filteredEarnings
+    };
+
+    // 创建CSV格式的账单数据
+    let csvContent = "日期,类别,订单号,现金收益,积分收益,碳减排量\n";
+    
+    this.filteredEarnings.forEach(record => {
+      csvContent += `${record.time},${record.category},${record.orderNo},${record.cashAmount},${record.pointsAmount},${record.carbonReduction}\n`;
+    });
+
+    // 创建并下载文件
+    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
+    const link = document.createElement('a');
+    const url = URL.createObjectURL(blob);
+    link.setAttribute('href', url);
+    link.setAttribute('download', `收益账单_${new Date().toISOString().split('T')[0]}.csv`);
+    link.style.visibility = 'hidden';
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+
+    this.showAlert('账单已导出到下载文件夹', 'success');
+  }
+
+  // 显示提示信息
+  private showAlert(message: string, type: 'success' | 'error' | 'warning' | 'info') {
+    // 创建提示元素
+    const alertDiv = document.createElement('div');
+    alertDiv.className = `custom-alert alert-${type}`;
+    alertDiv.textContent = message;
+    
+    // 添加样式
+    alertDiv.style.cssText = `
+      position: fixed;
+      top: 80px;
+      left: 50%;
+      transform: translateX(-50%);
+      background: ${this.getAlertColor(type)};
+      color: white;
+      padding: 12px 24px;
+      border-radius: 8px;
+      z-index: 10000;
+      font-size: 14px;
+      box-shadow: 0 4px 12px rgba(0,0,0,0.15);
+      animation: slideDown 0.3s ease-out;
+    `;
+
+    document.body.appendChild(alertDiv);
+
+    // 3秒后自动移除
+    setTimeout(() => {
+      if (alertDiv.parentNode) {
+        alertDiv.style.animation = 'slideUp 0.3s ease-in';
+        setTimeout(() => {
+          document.body.removeChild(alertDiv);
+        }, 300);
+      }
+    }, 3000);
+  }
+
+  // 获取提示颜色
+  private getAlertColor(type: string): string {
+    switch (type) {
+      case 'success': return '#4caf50';
+      case 'error': return '#f44336';
+      case 'warning': return '#ff9800';
+      case 'info': return '#2196f3';
+      default: return '#6c757d';
+    }
   }
 
   // 组件销毁时清理图表

+ 1 - 1
src/app/consumer/home/ar-recognition/ar-recognition.scss

@@ -3,7 +3,7 @@
 
 .ar-recognition-container {
   min-height: 100vh;
-  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  background: linear-gradient(135deg, #e8f5e8 0%, #f0f8f0 100%);
   padding-bottom: 80px;
   position: relative;
 

+ 1 - 1
src/app/consumer/home/collectors/collectors.scss

@@ -3,7 +3,7 @@
 
 .collectors-container {
   min-height: 100vh;
-  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  background: linear-gradient(135deg, #e8f5e8 0%, #f0f8f0 100%);
   padding-bottom: 80px;
   position: relative;
 

+ 24 - 5
src/app/consumer/points-mall/points-mall.html

@@ -1,6 +1,6 @@
 <!-- 顶部标题栏 -->
 <div class="header">
-  <div class="back-btn" (click)="goBack()"><i class="fas fa-arrow-left"></i></div>
+  <div class="back-btn" (click)="goBack()"><app-svg-icon name="arrow-left" size="md" color="#2e7d32"></app-svg-icon></div>
   <div class="header-title">积分商城</div>
 </div>
 
@@ -43,7 +43,7 @@
     <!-- 环保知识学习板块 -->
     <div class="eco-knowledge-card" (click)="navigateToEcoKnowledge()">
       <div class="eco-knowledge-icon">
-        <app-svg-icon name="leaf" size="lg" color="#28a745"></app-svg-icon>
+        <app-svg-icon name="leaf" size="lg" color="#2e7d32"></app-svg-icon>
       </div>
       <div class="eco-knowledge-content">
         <div class="eco-knowledge-title">环保知识学习</div>
@@ -63,7 +63,13 @@
         class="category-item" 
         [class.active]="category.active"
         (click)="selectCategory(category)">
-        <div class="category-icon"><i [class]="category.icon"></i></div>
+        <div class="category-icon">
+          <app-svg-icon 
+            [name]="category.icon" 
+            size="lg" 
+            [color]="category.active ? 'primary' : 'secondary'">
+          </app-svg-icon>
+        </div>
         <div class="category-name">{{category.name}}</div>
       </div>
     </div>
@@ -77,7 +83,12 @@
         (click)="showProductDetail(product)">
         <div class="product-image">
           <img *ngIf="product.image" [src]="product.image" [alt]="product.name" class="product-img">
-          <i *ngIf="!product.image" [class]="product.icon + ' fa-2x'"></i>
+          <app-svg-icon 
+            *ngIf="!product.image && product.icon" 
+            [name]="product.icon" 
+            size="xl" 
+            color="secondary">
+          </app-svg-icon>
           <div class="product-tag" *ngIf="product.tag">{{product.tag}}</div>
         </div>
         <div class="product-info">
@@ -111,7 +122,15 @@
         *ngFor="let task of tasks"
         class="task-item">
         <div class="task-info">
-          <div class="task-icon"><i [class]="task.icon"></i></div>
+          <div class="task-icon">
+            <ng-container [ngSwitch]="task.icon">
+              <app-svg-icon *ngSwitchCase="'fas fa-calendar-check'" name="calendar" size="md" color="#2e7d32"></app-svg-icon>
+              <app-svg-icon *ngSwitchCase="'fas fa-recycle'" name="recycle" size="md" color="#2e7d32"></app-svg-icon>
+              <app-svg-icon *ngSwitchCase="'fas fa-user-friends'" name="user" size="md" color="#2e7d32"></app-svg-icon>
+              <app-svg-icon *ngSwitchCase="'fas fa-share-alt'" name="share" size="md" color="#2e7d32"></app-svg-icon>
+              <i *ngSwitchDefault [class]="task.icon"></i>
+            </ng-container>
+          </div>
           <div class="task-details">
             <div class="task-name">{{task.name}}</div>
             <div class="task-desc">{{task.description}}</div>

+ 10 - 10
src/app/consumer/points-mall/points-mall.ts

@@ -74,10 +74,10 @@ export class PointsMall {
   
   // 商品分类
   categories: Category[] = [
-    { id: 'all', name: '全部', icon: 'fas fa-th-large', active: true },
-    { id: 'electronics', name: '数码', icon: 'fas fa-mobile-alt', active: false },
-    { id: 'home', name: '家居', icon: 'fas fa-home', active: false },
-    { id: 'food', name: '食品', icon: 'fas fa-utensils', active: false }
+    { id: 'all', name: '全部', icon: 'grid', active: true },
+    { id: 'electronics', name: '数码', icon: 'electronics', active: false },
+    { id: 'home', name: '家居', icon: 'home', active: false },
+    { id: 'food', name: '食品', icon: 'utensils', active: false }
   ];
   
   // 活动轮播数据
@@ -121,7 +121,7 @@ export class PointsMall {
       description: '支持10W快充,兼容多种设备',
       stock: 50,
       tag: '热销',
-      icon: 'fas fa-mobile-alt'
+      icon: 'electronics'
     },
     {
       id: 2,
@@ -133,7 +133,7 @@ export class PointsMall {
       image: 'data:image/svg+xml;charset=utf-8,<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" rx="10" fill="%23f5f5f5"/><path d="M25 35h50v45c0 5-5 10-10 10H35c-5 0-10-5-10-10V35z" fill="%234caf50"/><path d="M35 35V25c0-5 5-10 10-10h10c5 0 10 5 10 10v10" stroke="%234caf50" stroke-width="3" fill="none"/></svg>',
       description: '可重复使用,环保材质',
       stock: 100,
-      icon: 'fas fa-shopping-bag'
+      icon: 'cart'
     },
     {
       id: 3,
@@ -145,7 +145,7 @@ export class PointsMall {
       image: 'data:image/svg+xml;charset=utf-8,<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" rx="10" fill="%23f5f5f5"/><rect x="20" y="20" width="60" height="60" rx="5" fill="%23fff" stroke="%23ddd" stroke-width="2"/><circle cx="35" cy="35" r="4" fill="%23ffc107"/><circle cx="50" cy="40" r="3" fill="%23ffc107"/><circle cx="65" cy="45" r="4" fill="%23ffc107"/><circle cx="40" cy="55" r="3" fill="%23ffc107"/><circle cx="60" cy="60" r="4" fill="%23ffc107"/></svg>',
       description: '营养丰富,健康早餐首选',
       stock: 30,
-      icon: 'fas fa-seedling'
+      icon: 'leaf'
     },
     {
       id: 4,
@@ -158,7 +158,7 @@ export class PointsMall {
       description: '高品质音效,长续航',
       stock: 25,
       tag: '新品',
-      icon: 'fas fa-headphones'
+      icon: 'electronics'
     },
     {
       id: 5,
@@ -170,7 +170,7 @@ export class PointsMall {
       image: 'data:image/svg+xml;charset=utf-8,<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" rx="10" fill="%23f5f5f5"/><rect x="20" y="30" width="60" height="40" rx="5" fill="%2387ceeb"/><line x1="25" y1="35" x2="75" y2="35" stroke="%235f9ea0" stroke-width="2"/><line x1="25" y1="45" x2="75" y2="45" stroke="%235f9ea0" stroke-width="2"/><line x1="25" y1="55" x2="75" y2="55" stroke="%235f9ea0" stroke-width="2"/><line x1="25" y1="65" x2="75" y2="65" stroke="%235f9ea0" stroke-width="2"/></svg>',
       description: '天然抗菌,柔软舒适',
       stock: 80,
-      icon: 'fas fa-bath'
+      icon: 'home'
     },
     {
       id: 6,
@@ -182,7 +182,7 @@ export class PointsMall {
       image: 'data:image/svg+xml;charset=utf-8,<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" rx="10" fill="%23f5f5f5"/><rect x="20" y="30" width="60" height="40" rx="5" fill="%23dd6b20"/><rect x="20" y="25" width="60" height="10" rx="5" fill="%23ffd700"/><circle cx="35" cy="45" r="4" fill="%238b4513"/><circle cx="50" cy="50" r="3" fill="%238b4513"/><circle cx="65" cy="55" r="4" fill="%238b4513"/><circle cx="40" cy="60" r="3" fill="%238b4513"/><circle cx="60" cy="40" r="3" fill="%238b4513"/></svg>',
       description: '精选坚果,营养健康',
       stock: 40,
-      icon: 'fas fa-gift'
+      icon: 'utensils'
     }
   ];
   

+ 250 - 0
src/app/consumer/profile/about-us/about-us.html

@@ -0,0 +1,250 @@
+<div class="about-us-page">
+  <!-- 头部 -->
+  <div class="header">
+    <button class="back-btn" (click)="goBack()">
+      <i class="fas fa-arrow-left"></i>
+    </button>
+    <span class="title">关于我们</span>
+  </div>
+
+  <div class="about-content">
+    <!-- 应用信息 -->
+    <div class="app-info-section">
+      <div class="app-logo">
+        <div class="logo-icon">
+          <i class="fas fa-recycle"></i>
+        </div>
+        <h2>再生视界</h2>
+        <p class="app-slogan">让回收更简单,让地球更美好</p>
+      </div>
+      
+      <div class="version-info">
+        <div class="version-item">
+          <span class="label">当前版本</span>
+          <span class="value">{{ appVersion }}</span>
+        </div>
+        <div class="version-item">
+          <span class="label">更新时间</span>
+          <span class="value">{{ updateDate }}</span>
+        </div>
+        <div class="version-item">
+          <span class="label">应用大小</span>
+          <span class="value">{{ appSize }}</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 应用介绍 -->
+    <div class="app-intro-section">
+      <h4>应用介绍</h4>
+      <div class="intro-content">
+        <p>再生视界是一款专注于环保回收的移动应用,致力于为用户提供便捷、高效的回收服务。我们通过创新的技术和贴心的服务,让每个人都能轻松参与到环保事业中来。</p>
+        
+        <div class="features-list">
+          <div class="feature-item">
+            <div class="feature-icon">
+              <i class="fas fa-mobile-alt"></i>
+            </div>
+            <div class="feature-content">
+              <h5>便捷预约</h5>
+              <p>一键预约上门回收服务,专业回收员准时上门</p>
+            </div>
+          </div>
+          
+          <div class="feature-item">
+            <div class="feature-icon">
+              <i class="fas fa-coins"></i>
+            </div>
+            <div class="feature-content">
+              <h5>实时收益</h5>
+              <p>透明的价格体系,实时查看回收收益和积分</p>
+            </div>
+          </div>
+          
+          <div class="feature-item">
+            <div class="feature-icon">
+              <i class="fas fa-leaf"></i>
+            </div>
+            <div class="feature-content">
+              <h5>环保知识</h5>
+              <p>丰富的环保知识库,提升环保意识</p>
+            </div>
+          </div>
+          
+          <div class="feature-item">
+            <div class="feature-icon">
+              <i class="fas fa-gift"></i>
+            </div>
+            <div class="feature-content">
+              <h5>积分商城</h5>
+              <p>积分兑换环保商品,让环保更有价值</p>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 数据统计 -->
+    <div class="statistics-section">
+      <h4>我们的成就</h4>
+      <div class="stats-grid">
+        <div class="stat-item">
+          <div class="stat-number">{{ totalUsers }}</div>
+          <div class="stat-label">注册用户</div>
+        </div>
+        <div class="stat-item">
+          <div class="stat-number">{{ totalOrders }}</div>
+          <div class="stat-label">回收订单</div>
+        </div>
+        <div class="stat-item">
+          <div class="stat-number">{{ totalWeight }}</div>
+          <div class="stat-label">回收重量(吨)</div>
+        </div>
+        <div class="stat-item">
+          <div class="stat-number">{{ carbonReduction }}</div>
+          <div class="stat-label">减碳量(吨)</div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 团队介绍 -->
+    <div class="team-section">
+      <h4>团队介绍</h4>
+      <div class="team-content">
+        <p>我们是一支充满激情的年轻团队,致力于通过技术创新推动环保事业的发展。团队成员来自互联网、环保、物流等多个领域,拥有丰富的行业经验。</p>
+        
+        <div class="team-values">
+          <div class="value-item">
+            <div class="value-icon">
+              <i class="fas fa-heart"></i>
+            </div>
+            <div class="value-content">
+              <h5>用心服务</h5>
+              <p>以用户为中心,提供贴心的服务体验</p>
+            </div>
+          </div>
+          
+          <div class="value-item">
+            <div class="value-icon">
+              <i class="fas fa-lightbulb"></i>
+            </div>
+            <div class="value-content">
+              <h5>持续创新</h5>
+              <p>不断探索新技术,优化产品体验</p>
+            </div>
+          </div>
+          
+          <div class="value-item">
+            <div class="value-icon">
+              <i class="fas fa-globe"></i>
+            </div>
+            <div class="value-content">
+              <h5>环保使命</h5>
+              <p>为地球环保事业贡献自己的力量</p>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 联系我们 -->
+    <div class="contact-section">
+      <h4>联系我们</h4>
+      <div class="contact-info">
+        <div class="contact-item">
+          <div class="contact-icon">
+            <i class="fas fa-envelope"></i>
+          </div>
+          <div class="contact-details">
+            <span class="contact-label">邮箱</span>
+            <span class="contact-value">contact@recycle-app.com</span>
+          </div>
+        </div>
+        
+        <div class="contact-item">
+          <div class="contact-icon">
+            <i class="fas fa-phone"></i>
+          </div>
+          <div class="contact-details">
+            <span class="contact-label">客服热线</span>
+            <span class="contact-value">400-888-6666</span>
+          </div>
+        </div>
+        
+        <div class="contact-item">
+          <div class="contact-icon">
+            <i class="fas fa-map-marker-alt"></i>
+          </div>
+          <div class="contact-details">
+            <span class="contact-label">地址</span>
+            <span class="contact-value">北京市朝阳区环保科技园区</span>
+          </div>
+        </div>
+        
+        <div class="contact-item">
+          <div class="contact-icon">
+            <i class="fas fa-globe"></i>
+          </div>
+          <div class="contact-details">
+            <span class="contact-label">官网</span>
+            <span class="contact-value">www.recycle-app.com</span>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 社交媒体 -->
+    <div class="social-section">
+      <h4>关注我们</h4>
+      <div class="social-links">
+        <button class="social-btn wechat" (click)="followWeChat()">
+          <i class="fab fa-weixin"></i>
+          <span>微信公众号</span>
+        </button>
+        <button class="social-btn weibo" (click)="followWeibo()">
+          <i class="fab fa-weibo"></i>
+          <span>官方微博</span>
+        </button>
+        <button class="social-btn douyin" (click)="followDouyin()">
+          <i class="fas fa-video"></i>
+          <span>抖音号</span>
+        </button>
+      </div>
+    </div>
+
+    <!-- 版权信息 -->
+    <div class="copyright-section">
+      <div class="copyright-content">
+        <p>© 2024 再生视界科技有限公司</p>
+        <p>版权所有 | 京ICP备2024000001号</p>
+        <div class="legal-links">
+          <button class="legal-link" (click)="viewUserAgreement()">用户协议</button>
+          <span class="separator">|</span>
+          <button class="legal-link" (click)="viewPrivacyPolicy()">隐私政策</button>
+        </div>
+      </div>
+    </div>
+
+    <!-- 更新日志 -->
+    <div class="changelog-section">
+      <div class="section-header">
+        <h4>更新日志</h4>
+        <button class="view-all-btn" (click)="viewAllChangelog()">查看全部</button>
+      </div>
+      
+      <div class="changelog-list">
+        <div class="changelog-item" *ngFor="let log of recentChangelogs">
+          <div class="changelog-header">
+            <span class="version">v{{ log.version }}</span>
+            <span class="date">{{ formatDate(log.date) }}</span>
+          </div>
+          <div class="changelog-content">
+            <ul>
+              <li *ngFor="let change of log.changes">{{ change }}</li>
+            </ul>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 530 - 0
src/app/consumer/profile/about-us/about-us.scss

@@ -0,0 +1,530 @@
+.about-us-page {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+
+  .header {
+    display: flex;
+    align-items: center;
+    padding: 12px 16px;
+    background: #fff;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    position: sticky;
+    top: 0;
+    z-index: 100;
+
+    .back-btn {
+      background: none;
+      border: none;
+      font-size: 18px;
+      color: #333;
+      padding: 8px;
+      margin-right: 12px;
+      border-radius: 50%;
+      transition: background-color 0.3s;
+
+      &:hover {
+        background-color: #f0f0f0;
+      }
+    }
+
+    .title {
+      font-size: 18px;
+      font-weight: 600;
+      color: #333;
+    }
+  }
+
+  .about-content {
+    padding: 0 16px 20px;
+
+    // 应用信息区域
+    .app-info-section {
+      background: #fff;
+      border-radius: 12px;
+      padding: 24px;
+      margin: 16px 0;
+      text-align: center;
+      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+
+      .app-logo {
+        margin-bottom: 20px;
+
+        .logo-icon {
+          width: 80px;
+          height: 80px;
+          background: linear-gradient(135deg, #4CAF50, #2E7D32);
+          border-radius: 20px;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          margin: 0 auto 16px;
+          box-shadow: 0 4px 16px rgba(76, 175, 80, 0.3);
+
+          i {
+            font-size: 40px;
+            color: #fff;
+          }
+        }
+
+        h2 {
+          font-size: 24px;
+          font-weight: 700;
+          color: #333;
+          margin: 0 0 8px;
+        }
+
+        .app-slogan {
+          font-size: 14px;
+          color: #666;
+          margin: 0;
+        }
+      }
+
+      .version-info {
+        .version-item {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          padding: 12px 0;
+          border-bottom: 1px solid #f0f0f0;
+
+          &:last-child {
+            border-bottom: none;
+          }
+
+          .label {
+            font-size: 14px;
+            color: #666;
+          }
+
+          .value {
+            font-size: 14px;
+            color: #333;
+            font-weight: 500;
+          }
+        }
+      }
+    }
+
+    // 通用区域样式
+    .app-intro-section,
+    .statistics-section,
+    .team-section,
+    .contact-section,
+    .social-section,
+    .copyright-section,
+    .changelog-section {
+      background: #fff;
+      border-radius: 12px;
+      padding: 20px;
+      margin: 16px 0;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+      h4 {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+        margin: 0 0 16px;
+        padding-bottom: 8px;
+        border-bottom: 2px solid #4CAF50;
+        display: inline-block;
+      }
+    }
+
+    // 应用介绍
+    .app-intro-section {
+      .intro-content {
+        p {
+          font-size: 14px;
+          line-height: 1.6;
+          color: #666;
+          margin-bottom: 20px;
+        }
+
+        .features-list {
+          .feature-item {
+            display: flex;
+            align-items: flex-start;
+            margin-bottom: 16px;
+            padding: 12px;
+            background: #f8f9fa;
+            border-radius: 8px;
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+
+            .feature-icon {
+              width: 40px;
+              height: 40px;
+              background: linear-gradient(135deg, #4CAF50, #2E7D32);
+              border-radius: 8px;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              margin-right: 12px;
+              flex-shrink: 0;
+
+              i {
+                font-size: 18px;
+                color: #fff;
+              }
+            }
+
+            .feature-content {
+              flex: 1;
+
+              h5 {
+                font-size: 16px;
+                font-weight: 600;
+                color: #333;
+                margin: 0 0 4px;
+              }
+
+              p {
+                font-size: 13px;
+                color: #666;
+                margin: 0;
+                line-height: 1.4;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    // 数据统计
+    .statistics-section {
+      .stats-grid {
+        display: grid;
+        grid-template-columns: repeat(2, 1fr);
+        gap: 16px;
+
+        .stat-item {
+          text-align: center;
+          padding: 16px;
+          background: linear-gradient(135deg, #f8f9fa, #e9ecef);
+          border-radius: 8px;
+          border: 1px solid #e0e0e0;
+
+          .stat-number {
+            font-size: 24px;
+            font-weight: 700;
+            color: #4CAF50;
+            margin-bottom: 4px;
+          }
+
+          .stat-label {
+            font-size: 12px;
+            color: #666;
+          }
+        }
+      }
+    }
+
+    // 团队介绍
+    .team-section {
+      .team-content {
+        p {
+          font-size: 14px;
+          line-height: 1.6;
+          color: #666;
+          margin-bottom: 20px;
+        }
+
+        .team-values {
+          .value-item {
+            display: flex;
+            align-items: center;
+            margin-bottom: 16px;
+            padding: 12px;
+            background: #f8f9fa;
+            border-radius: 8px;
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+
+            .value-icon {
+              width: 36px;
+              height: 36px;
+              background: linear-gradient(135deg, #FF9800, #F57C00);
+              border-radius: 50%;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              margin-right: 12px;
+              flex-shrink: 0;
+
+              i {
+                font-size: 16px;
+                color: #fff;
+              }
+            }
+
+            .value-content {
+              flex: 1;
+
+              h5 {
+                font-size: 15px;
+                font-weight: 600;
+                color: #333;
+                margin: 0 0 2px;
+              }
+
+              p {
+                font-size: 13px;
+                color: #666;
+                margin: 0;
+                line-height: 1.4;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    // 联系我们
+    .contact-section {
+      .contact-info {
+        .contact-item {
+          display: flex;
+          align-items: center;
+          padding: 12px 0;
+          border-bottom: 1px solid #f0f0f0;
+
+          &:last-child {
+            border-bottom: none;
+          }
+
+          .contact-icon {
+            width: 36px;
+            height: 36px;
+            background: linear-gradient(135deg, #2196F3, #1976D2);
+            border-radius: 50%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            margin-right: 12px;
+            flex-shrink: 0;
+
+            i {
+              font-size: 16px;
+              color: #fff;
+            }
+          }
+
+          .contact-details {
+            flex: 1;
+            display: flex;
+            flex-direction: column;
+
+            .contact-label {
+              font-size: 13px;
+              color: #666;
+              margin-bottom: 2px;
+            }
+
+            .contact-value {
+              font-size: 14px;
+              color: #333;
+              font-weight: 500;
+            }
+          }
+        }
+      }
+    }
+
+    // 社交媒体
+    .social-section {
+      .social-links {
+        display: flex;
+        gap: 12px;
+
+        .social-btn {
+          flex: 1;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          padding: 16px 8px;
+          border: none;
+          border-radius: 8px;
+          font-size: 12px;
+          color: #fff;
+          transition: transform 0.2s;
+
+          &:active {
+            transform: scale(0.95);
+          }
+
+          i {
+            font-size: 24px;
+            margin-bottom: 8px;
+          }
+
+          &.wechat {
+            background: linear-gradient(135deg, #1AAD19, #0D7377);
+          }
+
+          &.weibo {
+            background: linear-gradient(135deg, #E6162D, #C41E3A);
+          }
+
+          &.douyin {
+            background: linear-gradient(135deg, #000, #333);
+          }
+        }
+      }
+    }
+
+    // 版权信息
+    .copyright-section {
+      text-align: center;
+      background: #f8f9fa;
+      border: 1px solid #e0e0e0;
+
+      .copyright-content {
+        p {
+          font-size: 12px;
+          color: #666;
+          margin: 0 0 4px;
+          line-height: 1.4;
+
+          &:last-of-type {
+            margin-bottom: 12px;
+          }
+        }
+
+        .legal-links {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          gap: 8px;
+
+          .legal-link {
+            background: none;
+            border: none;
+            font-size: 12px;
+            color: #4CAF50;
+            text-decoration: underline;
+            padding: 4px;
+          }
+
+          .separator {
+            font-size: 12px;
+            color: #ccc;
+          }
+        }
+      }
+    }
+
+    // 更新日志
+    .changelog-section {
+      .section-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 16px;
+
+        .view-all-btn {
+          background: none;
+          border: 1px solid #4CAF50;
+          color: #4CAF50;
+          font-size: 12px;
+          padding: 6px 12px;
+          border-radius: 16px;
+          transition: all 0.3s;
+
+          &:hover {
+            background: #4CAF50;
+            color: #fff;
+          }
+        }
+      }
+
+      .changelog-list {
+        .changelog-item {
+          margin-bottom: 16px;
+          padding: 16px;
+          background: #f8f9fa;
+          border-radius: 8px;
+          border-left: 4px solid #4CAF50;
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          .changelog-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 8px;
+
+            .version {
+              font-size: 14px;
+              font-weight: 600;
+              color: #4CAF50;
+            }
+
+            .date {
+              font-size: 12px;
+              color: #666;
+            }
+          }
+
+          .changelog-content {
+            ul {
+              margin: 0;
+              padding-left: 16px;
+
+              li {
+                font-size: 13px;
+                color: #666;
+                line-height: 1.5;
+                margin-bottom: 4px;
+
+                &:last-child {
+                  margin-bottom: 0;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 480px) {
+  .about-us-page {
+    .about-content {
+      padding: 0 12px 20px;
+
+      .statistics-section {
+        .stats-grid {
+          grid-template-columns: 1fr;
+          gap: 12px;
+        }
+      }
+
+      .social-section {
+        .social-links {
+          flex-direction: column;
+          gap: 8px;
+
+          .social-btn {
+            flex-direction: row;
+            justify-content: center;
+            padding: 12px;
+
+            i {
+              margin-right: 8px;
+              margin-bottom: 0;
+            }
+          }
+        }
+      }
+    }
+  }
+}

+ 181 - 0
src/app/consumer/profile/about-us/about-us.ts

@@ -0,0 +1,181 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Router } from '@angular/router';
+
+interface ChangelogItem {
+  version: string;
+  date: Date;
+  changes: string[];
+}
+
+@Component({
+  selector: 'app-about-us',
+  standalone: true,
+  imports: [CommonModule],
+  templateUrl: './about-us.html',
+  styleUrls: ['./about-us.scss']
+})
+export class AboutUsPage implements OnInit {
+  // 应用信息
+  appVersion = '2.1.0';
+  updateDate = '2024-01-15';
+  appSize = '45.2MB';
+
+  // 统计数据
+  totalUsers = '50万+';
+  totalOrders = '120万+';
+  totalWeight = '8,500';
+  carbonReduction = '12,300';
+
+  // 最近更新日志
+  recentChangelogs: ChangelogItem[] = [
+    {
+      version: '2.1.0',
+      date: new Date('2024-01-15'),
+      changes: [
+        '新增积分商城功能',
+        '优化回收预约流程',
+        '修复已知问题,提升稳定性',
+        '新增环保知识分享功能'
+      ]
+    },
+    {
+      version: '2.0.5',
+      date: new Date('2023-12-20'),
+      changes: [
+        '优化用户界面设计',
+        '提升应用启动速度',
+        '修复部分机型兼容性问题'
+      ]
+    },
+    {
+      version: '2.0.0',
+      date: new Date('2023-11-30'),
+      changes: [
+        '全新UI设计',
+        '新增碳足迹追踪功能',
+        '支持多种回收物品类型',
+        '优化积分奖励机制'
+      ]
+    }
+  ];
+
+  constructor(
+    private router: Router
+  ) {}
+
+  ngOnInit() {
+    // 页面初始化
+  }
+
+  /**
+   * 返回上一页
+   */
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+
+  /**
+   * 关注微信公众号
+   */
+  async followWeChat() {
+    if (confirm('是否关注我们的微信公众号?')) {
+      try {
+        await this.copyToClipboard('绿色回收助手');
+        this.showAlert('公众号名称已复制到剪贴板');
+      } catch (error) {
+        this.showAlert('复制失败,请手动搜索:绿色回收助手');
+      }
+    }
+  }
+
+  /**
+   * 关注微博
+   */
+  async followWeibo() {
+    if (confirm('是否关注我们的官方微博?')) {
+      try {
+        await this.copyToClipboard('@绿色回收助手官方');
+        this.showAlert('微博账号已复制到剪贴板');
+      } catch (error) {
+        this.showAlert('复制失败,请手动搜索:@绿色回收助手官方');
+      }
+    }
+  }
+
+  /**
+   * 关注抖音号
+   */
+  async followDouyin() {
+    if (confirm('是否关注我们的抖音账号?')) {
+      try {
+        await this.copyToClipboard('绿色回收小助手');
+        this.showAlert('抖音账号已复制到剪贴板');
+      } catch (error) {
+        this.showAlert('复制失败,请手动搜索:绿色回收小助手');
+      }
+    }
+  }
+
+  /**
+   * 查看用户协议
+   */
+  viewUserAgreement() {
+    this.router.navigate(['/consumer/profile/user-agreement']);
+  }
+
+  /**
+   * 查看隐私政策
+   */
+  viewPrivacyPolicy() {
+    this.router.navigate(['/consumer/profile/privacy-policy']);
+  }
+
+  /**
+   * 查看完整更新日志
+   */
+  async viewAllChangelog() {
+    this.showAlert('完整更新日志功能开发中...');
+  }
+
+  /**
+   * 格式化日期
+   */
+  formatDate(date: Date): string {
+    const year = date.getFullYear();
+    const month = String(date.getMonth() + 1).padStart(2, '0');
+    const day = String(date.getDate()).padStart(2, '0');
+    return `${year}-${month}-${day}`;
+  }
+
+  /**
+   * 复制到剪贴板
+   */
+  private async copyToClipboard(text: string) {
+    try {
+      await navigator.clipboard.writeText(text);
+    } catch (err) {
+      // 降级方案
+      const textArea = document.createElement('textarea');
+      textArea.value = text;
+      document.body.appendChild(textArea);
+      textArea.select();
+      document.execCommand('copy');
+      document.body.removeChild(textArea);
+    }
+  }
+
+  /**
+   * 打开网站
+   */
+  private openWebsite(url: string) {
+    window.open(url, '_blank');
+  }
+
+  /**
+   * 显示提示信息
+   */
+  private showAlert(message: string) {
+    alert(message);
+  }
+}

+ 167 - 0
src/app/consumer/profile/addresses/addresses.html

@@ -0,0 +1,167 @@
+<!-- 顶部标题栏 -->
+<div class="header">
+  <div class="back-btn" (click)="goBack()"><i class="fas fa-arrow-left"></i></div>
+  <div class="header-title">我的地址</div>
+  <div class="add-btn" (click)="showAddModal()"><i class="fas fa-plus"></i></div>
+</div>
+
+<div class="container">
+  <!-- 地址列表 -->
+  <div class="addresses-list">
+    <div 
+      *ngFor="let address of addresses" 
+      class="address-card"
+      [class.default]="address.isDefault">
+      
+      <div class="address-header">
+        <div class="contact-info">
+          <span class="name">{{address.name}}</span>
+          <span class="phone">{{address.phone}}</span>
+        </div>
+        <div class="default-badge" *ngIf="address.isDefault">默认</div>
+      </div>
+      
+      <div class="address-content">
+        <div class="address-text">
+          <i class="fas fa-map-marker-alt"></i>
+          <span>{{address.fullAddress}}</span>
+        </div>
+        <div class="address-label" *ngIf="address.label">
+          <span class="label-tag" [class]="'label-' + address.label">
+            {{getLabelText(address.label)}}
+          </span>
+        </div>
+      </div>
+      
+      <div class="address-actions">
+        <button 
+          class="action-btn default-btn"
+          *ngIf="!address.isDefault"
+          (click)="setDefault(address)">
+          设为默认
+        </button>
+        <button 
+          class="action-btn edit-btn"
+          (click)="editAddress(address)">
+          <i class="fas fa-edit"></i>
+          编辑
+        </button>
+        <button 
+          class="action-btn delete-btn"
+          (click)="deleteAddress(address)">
+          <i class="fas fa-trash"></i>
+          删除
+        </button>
+      </div>
+    </div>
+    
+    <!-- 空状态 -->
+    <div class="empty-state" *ngIf="addresses.length === 0">
+      <div class="empty-icon">
+        <i class="fas fa-map-marker-alt"></i>
+      </div>
+      <div class="empty-text">暂无收货地址</div>
+      <button class="empty-action" (click)="showAddModal()">添加地址</button>
+    </div>
+  </div>
+</div>
+
+<!-- 添加/编辑地址模态框 -->
+<div class="modal" [style.display]="showModal ? 'flex' : 'none'" (click)="closeModal($event)">
+  <div class="modal-content address-modal">
+    <div class="modal-header">
+      <div class="modal-title">{{isEditing ? '编辑地址' : '添加地址'}}</div>
+      <div class="modal-close" (click)="showModal = false">
+        <i class="fas fa-times"></i>
+      </div>
+    </div>
+    
+    <div class="modal-body">
+      <form class="address-form">
+        <div class="form-group">
+          <label>联系人</label>
+          <input 
+            type="text" 
+            [(ngModel)]="currentAddress.name" 
+            name="name"
+            placeholder="请输入联系人姓名"
+            class="form-input">
+        </div>
+        
+        <div class="form-group">
+          <label>手机号</label>
+          <input 
+            type="tel" 
+            [(ngModel)]="currentAddress.phone" 
+            name="phone"
+            placeholder="请输入手机号"
+            class="form-input">
+        </div>
+        
+        <div class="form-group">
+          <label>所在地区</label>
+          <div class="region-selector">
+            <select [(ngModel)]="currentAddress.province" name="province" class="form-select">
+              <option value="">请选择省份</option>
+              <option value="北京市">北京市</option>
+              <option value="上海市">上海市</option>
+              <option value="广东省">广东省</option>
+              <option value="浙江省">浙江省</option>
+            </select>
+            <select [(ngModel)]="currentAddress.city" name="city" class="form-select">
+              <option value="">请选择城市</option>
+              <option value="北京市">北京市</option>
+              <option value="朝阳区">朝阳区</option>
+              <option value="海淀区">海淀区</option>
+            </select>
+            <select [(ngModel)]="currentAddress.district" name="district" class="form-select">
+              <option value="">请选择区县</option>
+              <option value="朝阳区">朝阳区</option>
+              <option value="建国门">建国门</option>
+            </select>
+          </div>
+        </div>
+        
+        <div class="form-group">
+          <label>详细地址</label>
+          <textarea 
+            [(ngModel)]="currentAddress.detail" 
+            name="detail"
+            placeholder="请输入详细地址(街道、门牌号等)"
+            class="form-textarea"
+            rows="3"></textarea>
+        </div>
+        
+        <div class="form-group">
+          <label>地址标签</label>
+          <div class="label-options">
+            <div 
+              *ngFor="let label of labelOptions" 
+              class="label-option"
+              [class.active]="currentAddress.label === label.value"
+              (click)="selectLabel(label.value)">
+              <i [class]="label.icon"></i>
+              <span>{{label.text}}</span>
+            </div>
+          </div>
+        </div>
+        
+        <div class="form-group">
+          <label class="checkbox-label">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="currentAddress.isDefault" 
+              name="isDefault">
+            <span class="checkmark"></span>
+            设为默认地址
+          </label>
+        </div>
+      </form>
+    </div>
+    
+    <div class="modal-footer">
+      <button class="btn-cancel" (click)="showModal = false">取消</button>
+      <button class="btn-save" (click)="saveAddress()">保存</button>
+    </div>
+  </div>
+</div>

+ 473 - 0
src/app/consumer/profile/addresses/addresses.scss

@@ -0,0 +1,473 @@
+// 全局重置
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+// 顶部标题栏
+.header {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 56px;
+  background: #2e7d32;
+  color: white;
+  position: relative;
+  
+  .back-btn, .add-btn {
+    position: absolute;
+    width: 40px;
+    height: 40px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 50%;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      background: rgba(255, 255, 255, 0.1);
+    }
+    
+    i {
+      font-size: 18px;
+    }
+  }
+  
+  .back-btn {
+    left: 16px;
+  }
+  
+  .add-btn {
+    right: 16px;
+  }
+  
+  .header-title {
+    font-size: 18px;
+    font-weight: 600;
+  }
+}
+
+// 容器
+.container {
+  padding: 16px;
+  min-height: calc(100vh - 56px);
+  background: #f5f5f5;
+}
+
+// 地址列表
+.addresses-list {
+  .address-card {
+    background: white;
+    border-radius: 12px;
+    padding: 16px;
+    margin-bottom: 12px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    transition: all 0.3s ease;
+    border: 2px solid transparent;
+    
+    &.default {
+      border-color: #2e7d32;
+    }
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+    }
+    
+    .address-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 12px;
+      
+      .contact-info {
+        display: flex;
+        align-items: center;
+        gap: 12px;
+        
+        .name {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+        }
+        
+        .phone {
+          font-size: 14px;
+          color: #666;
+        }
+      }
+      
+      .default-badge {
+        background: #2e7d32;
+        color: white;
+        padding: 4px 8px;
+        border-radius: 12px;
+        font-size: 12px;
+        font-weight: 600;
+      }
+    }
+    
+    .address-content {
+      margin-bottom: 16px;
+      
+      .address-text {
+        display: flex;
+        align-items: flex-start;
+        gap: 8px;
+        margin-bottom: 8px;
+        
+        i {
+          color: #2e7d32;
+          margin-top: 2px;
+          flex-shrink: 0;
+        }
+        
+        span {
+          font-size: 14px;
+          color: #333;
+          line-height: 1.4;
+        }
+      }
+      
+      .address-label {
+        .label-tag {
+          display: inline-block;
+          padding: 2px 8px;
+          border-radius: 8px;
+          font-size: 12px;
+          font-weight: 600;
+          
+          &.label-home {
+            background: #e3f2fd;
+            color: #1976d2;
+          }
+          
+          &.label-company {
+            background: #fff3e0;
+            color: #f57c00;
+          }
+          
+          &.label-school {
+            background: #f3e5f5;
+            color: #7b1fa2;
+          }
+          
+          &.label-other {
+            background: #e8f5e8;
+            color: #2e7d32;
+          }
+        }
+      }
+    }
+    
+    .address-actions {
+      display: flex;
+      justify-content: flex-end;
+      gap: 8px;
+      
+      .action-btn {
+        padding: 8px 12px;
+        border: none;
+        border-radius: 20px;
+        font-size: 12px;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        display: flex;
+        align-items: center;
+        gap: 4px;
+        
+        &.default-btn {
+          background: #e8f5e8;
+          color: #2e7d32;
+          
+          &:hover {
+            background: #d4edda;
+          }
+        }
+        
+        &.edit-btn {
+          background: #e3f2fd;
+          color: #1976d2;
+          
+          &:hover {
+            background: #bbdefb;
+          }
+        }
+        
+        &.delete-btn {
+          background: #ffebee;
+          color: #d32f2f;
+          
+          &:hover {
+            background: #ffcdd2;
+          }
+        }
+        
+        i {
+          font-size: 10px;
+        }
+      }
+    }
+  }
+}
+
+// 空状态
+.empty-state {
+  text-align: center;
+  padding: 60px 20px;
+  
+  .empty-icon {
+    margin-bottom: 16px;
+    
+    i {
+      font-size: 64px;
+      color: #ccc;
+    }
+  }
+  
+  .empty-text {
+    font-size: 16px;
+    color: #666;
+    margin-bottom: 24px;
+  }
+  
+  .empty-action {
+    background: #2e7d32;
+    color: white;
+    border: none;
+    padding: 12px 24px;
+    border-radius: 24px;
+    font-size: 14px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      background: #1b5e20;
+      transform: translateY(-2px);
+    }
+  }
+}
+
+// 模态框
+.modal {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1000;
+  
+  .modal-content {
+    background: white;
+    border-radius: 16px;
+    width: 90%;
+    max-width: 500px;
+    max-height: 90vh;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    
+    .modal-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20px;
+      border-bottom: 1px solid #eee;
+      flex-shrink: 0;
+      
+      .modal-title {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+      }
+      
+      .modal-close {
+        width: 32px;
+        height: 32px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 50%;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &:hover {
+          background: #f0f0f0;
+        }
+        
+        i {
+          font-size: 16px;
+          color: #666;
+        }
+      }
+    }
+    
+    .modal-body {
+      padding: 20px;
+      overflow-y: auto;
+      flex: 1;
+      
+      .address-form {
+        .form-group {
+          margin-bottom: 20px;
+          
+          label {
+            display: block;
+            font-size: 14px;
+            font-weight: 600;
+            color: #333;
+            margin-bottom: 8px;
+          }
+          
+          .form-input, .form-select, .form-textarea {
+            width: 100%;
+            padding: 12px;
+            border: 1px solid #ddd;
+            border-radius: 8px;
+            font-size: 14px;
+            transition: all 0.3s ease;
+            
+            &:focus {
+              outline: none;
+              border-color: #2e7d32;
+              box-shadow: 0 0 0 2px rgba(46, 125, 50, 0.1);
+            }
+          }
+          
+          .form-textarea {
+            resize: vertical;
+            min-height: 80px;
+          }
+          
+          .region-selector {
+            display: grid;
+            grid-template-columns: 1fr 1fr 1fr;
+            gap: 8px;
+          }
+          
+          .label-options {
+            display: grid;
+            grid-template-columns: repeat(4, 1fr);
+            gap: 8px;
+            
+            .label-option {
+              display: flex;
+              flex-direction: column;
+              align-items: center;
+              padding: 12px 8px;
+              border: 2px solid #eee;
+              border-radius: 8px;
+              cursor: pointer;
+              transition: all 0.3s ease;
+              
+              &:hover {
+                border-color: #2e7d32;
+              }
+              
+              &.active {
+                border-color: #2e7d32;
+                background: #e8f5e8;
+                color: #2e7d32;
+              }
+              
+              i {
+                font-size: 20px;
+                margin-bottom: 4px;
+              }
+              
+              span {
+                font-size: 12px;
+              }
+            }
+          }
+          
+          .checkbox-label {
+            display: flex;
+            align-items: center;
+            cursor: pointer;
+            font-weight: normal;
+            
+            input[type="checkbox"] {
+              display: none;
+            }
+            
+            .checkmark {
+              width: 20px;
+              height: 20px;
+              border: 2px solid #ddd;
+              border-radius: 4px;
+              margin-right: 8px;
+              position: relative;
+              transition: all 0.3s ease;
+              
+              &::after {
+                content: '';
+                position: absolute;
+                left: 6px;
+                top: 2px;
+                width: 6px;
+                height: 10px;
+                border: solid white;
+                border-width: 0 2px 2px 0;
+                transform: rotate(45deg);
+                opacity: 0;
+                transition: all 0.3s ease;
+              }
+            }
+            
+            input[type="checkbox"]:checked + .checkmark {
+              background: #2e7d32;
+              border-color: #2e7d32;
+              
+              &::after {
+                opacity: 1;
+              }
+            }
+          }
+        }
+      }
+    }
+    
+    .modal-footer {
+      display: flex;
+      justify-content: flex-end;
+      gap: 12px;
+      padding: 20px;
+      border-top: 1px solid #eee;
+      flex-shrink: 0;
+      
+      .btn-cancel, .btn-save {
+        padding: 12px 24px;
+        border: none;
+        border-radius: 24px;
+        font-size: 14px;
+        cursor: pointer;
+        transition: all 0.3s ease;
+      }
+      
+      .btn-cancel {
+        background: #f5f5f5;
+        color: #666;
+        
+        &:hover {
+          background: #e0e0e0;
+        }
+      }
+      
+      .btn-save {
+        background: #2e7d32;
+        color: white;
+        
+        &:hover {
+          background: #1b5e20;
+        }
+      }
+    }
+  }
+}

+ 253 - 0
src/app/consumer/profile/addresses/addresses.ts

@@ -0,0 +1,253 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+
+interface Address {
+  id: string;
+  name: string;
+  phone: string;
+  province: string;
+  city: string;
+  district: string;
+  detail: string;
+  fullAddress: string;
+  label?: 'home' | 'company' | 'school' | 'other';
+  isDefault: boolean;
+}
+
+interface LabelOption {
+  value: 'home' | 'company' | 'school' | 'other';
+  text: string;
+  icon: string;
+}
+
+@Component({
+  selector: 'app-addresses',
+  standalone: true,
+  imports: [CommonModule, FormsModule],
+  templateUrl: './addresses.html',
+  styleUrls: ['./addresses.scss']
+})
+export class AddressesComponent implements OnInit {
+  
+  // 地址列表
+  addresses: Address[] = [
+    {
+      id: '1',
+      name: '张三',
+      phone: '138****8888',
+      province: '北京市',
+      city: '北京市',
+      district: '朝阳区',
+      detail: '建国路88号SOHO现代城A座1201室',
+      fullAddress: '北京市朝阳区建国路88号SOHO现代城A座1201室',
+      label: 'home',
+      isDefault: true
+    },
+    {
+      id: '2',
+      name: '张三',
+      phone: '138****8888',
+      province: '北京市',
+      city: '北京市',
+      district: '海淀区',
+      detail: '中关村大街1号海龙大厦15层',
+      fullAddress: '北京市海淀区中关村大街1号海龙大厦15层',
+      label: 'company',
+      isDefault: false
+    }
+  ];
+  
+  // 标签选项
+  labelOptions: LabelOption[] = [
+    { value: 'home', text: '家', icon: 'fas fa-home' },
+    { value: 'company', text: '公司', icon: 'fas fa-building' },
+    { value: 'school', text: '学校', icon: 'fas fa-graduation-cap' },
+    { value: 'other', text: '其他', icon: 'fas fa-map-marker-alt' }
+  ];
+  
+  // 模态框状态
+  showModal = false;
+  isEditing = false;
+  currentAddress: Address = this.getEmptyAddress();
+  
+  constructor(private router: Router) {}
+  
+  ngOnInit() {
+    // 初始化
+  }
+  
+  // 获取空地址对象
+  getEmptyAddress(): Address {
+    return {
+      id: '',
+      name: '',
+      phone: '',
+      province: '',
+      city: '',
+      district: '',
+      detail: '',
+      fullAddress: '',
+      label: undefined,
+      isDefault: false
+    };
+  }
+  
+  // 获取标签文本
+  getLabelText(label: string): string {
+    const labelMap: { [key: string]: string } = {
+      'home': '家',
+      'company': '公司',
+      'school': '学校',
+      'other': '其他'
+    };
+    return labelMap[label] || '';
+  }
+  
+  // 显示添加模态框
+  showAddModal() {
+    this.isEditing = false;
+    this.currentAddress = this.getEmptyAddress();
+    this.showModal = true;
+  }
+  
+  // 编辑地址
+  editAddress(address: Address) {
+    this.isEditing = true;
+    this.currentAddress = { ...address };
+    this.showModal = true;
+  }
+  
+  // 删除地址
+  deleteAddress(address: Address) {
+    if (confirm('确定要删除这个地址吗?')) {
+      const index = this.addresses.findIndex(a => a.id === address.id);
+      if (index > -1) {
+        this.addresses.splice(index, 1);
+        
+        // 如果删除的是默认地址,设置第一个为默认
+        if (address.isDefault && this.addresses.length > 0) {
+          this.addresses[0].isDefault = true;
+        }
+        
+        this.showAlert('地址删除成功', 'success');
+      }
+    }
+  }
+  
+  // 设为默认地址
+  setDefault(address: Address) {
+    // 取消所有默认状态
+    this.addresses.forEach(a => a.isDefault = false);
+    // 设置当前为默认
+    address.isDefault = true;
+    this.showAlert('默认地址设置成功', 'success');
+  }
+  
+  // 选择标签
+  selectLabel(label: 'home' | 'company' | 'school' | 'other') {
+    this.currentAddress.label = label;
+  }
+  
+  // 保存地址
+  saveAddress() {
+    // 验证表单
+    if (!this.validateForm()) {
+      return;
+    }
+    
+    // 生成完整地址
+    this.currentAddress.fullAddress = 
+      `${this.currentAddress.province}${this.currentAddress.city}${this.currentAddress.district}${this.currentAddress.detail}`;
+    
+    if (this.isEditing) {
+      // 更新地址
+      const index = this.addresses.findIndex(a => a.id === this.currentAddress.id);
+      if (index > -1) {
+        // 如果设为默认,取消其他默认状态
+        if (this.currentAddress.isDefault) {
+          this.addresses.forEach(a => a.isDefault = false);
+        }
+        this.addresses[index] = { ...this.currentAddress };
+        this.showAlert('地址更新成功', 'success');
+      }
+    } else {
+      // 添加新地址
+      this.currentAddress.id = Date.now().toString();
+      
+      // 如果设为默认,取消其他默认状态
+      if (this.currentAddress.isDefault) {
+        this.addresses.forEach(a => a.isDefault = false);
+      }
+      
+      // 如果是第一个地址,自动设为默认
+      if (this.addresses.length === 0) {
+        this.currentAddress.isDefault = true;
+      }
+      
+      this.addresses.push({ ...this.currentAddress });
+      this.showAlert('地址添加成功', 'success');
+    }
+    
+    this.showModal = false;
+  }
+  
+  // 验证表单
+  validateForm(): boolean {
+    if (!this.currentAddress.name.trim()) {
+      this.showAlert('请输入联系人姓名', 'error');
+      return false;
+    }
+    
+    if (!this.currentAddress.phone.trim()) {
+      this.showAlert('请输入手机号', 'error');
+      return false;
+    }
+    
+    if (!/^1[3-9]\d{9}$/.test(this.currentAddress.phone.replace(/\*/g, '8'))) {
+      this.showAlert('请输入正确的手机号', 'error');
+      return false;
+    }
+    
+    if (!this.currentAddress.province) {
+      this.showAlert('请选择省份', 'error');
+      return false;
+    }
+    
+    if (!this.currentAddress.city) {
+      this.showAlert('请选择城市', 'error');
+      return false;
+    }
+    
+    if (!this.currentAddress.district) {
+      this.showAlert('请选择区县', 'error');
+      return false;
+    }
+    
+    if (!this.currentAddress.detail.trim()) {
+      this.showAlert('请输入详细地址', 'error');
+      return false;
+    }
+    
+    return true;
+  }
+  
+  // 关闭模态框
+  closeModal(event: Event) {
+    if (event.target === event.currentTarget) {
+      this.showModal = false;
+    }
+  }
+  
+  // 返回上一页
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+  
+  // 显示提示信息
+  private showAlert(message: string, type: 'success' | 'error' | 'info') {
+    // 简单的提示实现
+    alert(message);
+  }
+}

+ 225 - 0
src/app/consumer/profile/customer-service/customer-service.html

@@ -0,0 +1,225 @@
+<div class="customer-service-page">
+  <!-- 头部 -->
+  <div class="header">
+    <button class="back-btn" (click)="goBack()">
+      <i class="fas fa-arrow-left"></i>
+    </button>
+    <span class="title">客服与反馈</span>
+  </div>
+
+  <div class="service-content">
+    <!-- 快速联系方式 -->
+    <div class="quick-contact-section">
+      <h4>快速联系我们</h4>
+      <div class="contact-methods">
+        <div class="contact-item" (click)="startOnlineChat()">
+          <div class="contact-icon online-chat">
+            <i class="fas fa-comments"></i>
+          </div>
+          <div class="contact-info">
+            <h5>在线客服</h5>
+            <p>7×24小时在线服务</p>
+            <span class="status online">在线</span>
+          </div>
+          <i class="fas fa-chevron-right arrow"></i>
+        </div>
+        
+        <div class="contact-item" (click)="callService()">
+          <div class="contact-icon phone">
+            <i class="fas fa-phone"></i>
+          </div>
+          <div class="contact-info">
+            <h5>客服热线</h5>
+            <p>400-888-6666</p>
+            <span class="time">工作日 9:00-18:00</span>
+          </div>
+          <i class="fas fa-chevron-right arrow"></i>
+        </div>
+        
+        <div class="contact-item" (click)="sendEmail()">
+          <div class="contact-icon email">
+            <i class="fas fa-envelope"></i>
+          </div>
+          <div class="contact-info">
+            <h5>邮件反馈</h5>
+            <p>service@recycle-app.com</p>
+            <span class="time">24小时内回复</span>
+          </div>
+          <i class="fas fa-chevron-right arrow"></i>
+        </div>
+      </div>
+    </div>
+
+    <!-- 常见问题 -->
+    <div class="faq-section">
+      <div class="section-header">
+        <h4>常见问题</h4>
+        <button class="view-all-btn" (click)="viewAllFAQ()">查看全部</button>
+      </div>
+      
+      <div class="faq-list">
+        <div 
+          class="faq-item" 
+          *ngFor="let faq of faqList"
+          [class.expanded]="faq.expanded"
+          (click)="toggleFAQ(faq)">
+          <div class="faq-question">
+            <span>{{ faq.question }}</span>
+            <i class="fas fa-chevron-down" [class.rotated]="faq.expanded"></i>
+          </div>
+          <div class="faq-answer" *ngIf="faq.expanded">
+            <p>{{ faq.answer }}</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 意见反馈表单 -->
+    <div class="feedback-section">
+      <h4>意见反馈</h4>
+      <div class="feedback-form">
+        <!-- 反馈类型 -->
+        <div class="form-group">
+          <label>反馈类型</label>
+          <div class="feedback-types">
+            <button 
+              class="type-btn" 
+              *ngFor="let type of feedbackTypes"
+              [class.active]="selectedFeedbackType === type.value"
+              (click)="selectFeedbackType(type.value)">
+              <i [class]="type.icon"></i>
+              <span>{{ type.label }}</span>
+            </button>
+          </div>
+        </div>
+        
+        <!-- 问题描述 -->
+        <div class="form-group">
+          <label>问题描述 <span class="required">*</span></label>
+          <textarea 
+            [(ngModel)]="feedbackContent"
+            placeholder="请详细描述您遇到的问题或建议..."
+            rows="4"
+            maxlength="500"></textarea>
+          <div class="char-count">{{ feedbackContent.length }}/500</div>
+        </div>
+        
+        <!-- 联系方式 -->
+        <div class="form-group">
+          <label>联系方式</label>
+          <input 
+            type="text" 
+            [(ngModel)]="contactInfo"
+            placeholder="请留下您的手机号或邮箱,方便我们联系您">
+        </div>
+        
+        <!-- 图片上传 -->
+        <div class="form-group">
+          <label>相关截图</label>
+          <div class="image-upload">
+            <div 
+              class="upload-item" 
+              *ngFor="let image of uploadedImages; let i = index">
+              <img [src]="image.url" [alt]="image.name">
+              <button class="remove-btn" (click)="removeImage(i)">
+                <i class="fas fa-times"></i>
+              </button>
+            </div>
+            <button 
+              class="upload-btn" 
+              *ngIf="uploadedImages.length < 3"
+              (click)="uploadImage()">
+              <i class="fas fa-plus"></i>
+              <span>添加图片</span>
+            </button>
+          </div>
+          <div class="upload-tip">最多上传3张图片,支持jpg、png格式</div>
+        </div>
+        
+        <!-- 提交按钮 -->
+        <button 
+          class="submit-btn" 
+          [disabled]="!canSubmit()"
+          (click)="submitFeedback()">
+          提交反馈
+        </button>
+      </div>
+    </div>
+
+    <!-- 我的反馈记录 -->
+    <div class="feedback-history-section">
+      <div class="section-header">
+        <h4>我的反馈</h4>
+        <span class="count">{{ feedbackHistory.length }}条记录</span>
+      </div>
+      
+      <div class="history-list" *ngIf="feedbackHistory.length > 0">
+        <div 
+          class="history-item" 
+          *ngFor="let item of feedbackHistory"
+          (click)="viewFeedbackDetail(item)">
+          <div class="history-header">
+            <span class="feedback-type">{{ getFeedbackTypeLabel(item.type) }}</span>
+            <span class="feedback-status" [ngClass]="item.status">
+              {{ getStatusLabel(item.status) }}
+            </span>
+          </div>
+          <div class="history-content">
+            <p class="feedback-title">{{ item.title }}</p>
+            <p class="feedback-time">{{ formatDate(item.createTime) }}</p>
+          </div>
+          <i class="fas fa-chevron-right arrow"></i>
+        </div>
+      </div>
+      
+      <div class="empty-state" *ngIf="feedbackHistory.length === 0">
+        <i class="fas fa-comment-dots"></i>
+        <p>暂无反馈记录</p>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- 在线客服模态框 -->
+<div class="modal-overlay" *ngIf="showChatModal" (click)="closeModal($event)">
+  <div class="modal-content chat-modal">
+    <div class="modal-header">
+      <span class="modal-title">在线客服</span>
+      <button class="close-btn" (click)="closeChatModal()">
+        <i class="fas fa-times"></i>
+      </button>
+    </div>
+    
+    <div class="chat-container">
+      <div class="chat-messages">
+        <div 
+          class="message" 
+          *ngFor="let message of chatMessages"
+          [class.user]="message.sender === 'user'"
+          [class.service]="message.sender === 'service'">
+          <div class="message-avatar" *ngIf="message.sender === 'service'">
+            <i class="fas fa-headset"></i>
+          </div>
+          <div class="message-content">
+            <div class="message-text">{{ message.content }}</div>
+            <div class="message-time">{{ formatTime(message.time) }}</div>
+          </div>
+          <div class="message-avatar" *ngIf="message.sender === 'user'">
+            <i class="fas fa-user"></i>
+          </div>
+        </div>
+      </div>
+      
+      <div class="chat-input">
+        <input 
+          type="text" 
+          [(ngModel)]="chatInputText"
+          placeholder="请输入您的问题..."
+          (keyup.enter)="sendMessage()">
+        <button class="send-btn" (click)="sendMessage()" [disabled]="!chatInputText.trim()">
+          <i class="fas fa-paper-plane"></i>
+        </button>
+      </div>
+    </div>
+  </div>
+</div>

+ 740 - 0
src/app/consumer/profile/customer-service/customer-service.scss

@@ -0,0 +1,740 @@
+.customer-service-page {
+  min-height: 100vh;
+  background-color: #f5f5f5;
+  
+  .header {
+    background: linear-gradient(135deg, #4CAF50, #45a049);
+    color: white;
+    padding: 12px 16px;
+    display: flex;
+    align-items: center;
+    position: sticky;
+    top: 0;
+    z-index: 100;
+    
+    .back-btn {
+      background: none;
+      border: none;
+      color: white;
+      font-size: 18px;
+      margin-right: 12px;
+      cursor: pointer;
+      padding: 8px;
+      border-radius: 50%;
+      transition: background-color 0.3s;
+      
+      &:hover {
+        background-color: rgba(255, 255, 255, 0.1);
+      }
+    }
+    
+    .title {
+      font-size: 18px;
+      font-weight: 600;
+    }
+  }
+  
+  .service-content {
+    padding: 16px;
+    
+    // 快速联系方式
+    .quick-contact-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      h4 {
+        font-size: 16px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 16px;
+      }
+      
+      .contact-methods {
+        .contact-item {
+          display: flex;
+          align-items: center;
+          padding: 16px 0;
+          border-bottom: 1px solid #f0f0f0;
+          cursor: pointer;
+          transition: background-color 0.3s;
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          &:hover {
+            background-color: #f8f9fa;
+            margin: 0 -20px;
+            padding-left: 20px;
+            padding-right: 20px;
+            border-radius: 8px;
+          }
+          
+          .contact-icon {
+            width: 48px;
+            height: 48px;
+            border-radius: 50%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            margin-right: 16px;
+            font-size: 20px;
+            
+            &.online-chat {
+              background: #e8f5e8;
+              color: #4CAF50;
+            }
+            
+            &.phone {
+              background: #e3f2fd;
+              color: #2196F3;
+            }
+            
+            &.email {
+              background: #fff3e0;
+              color: #FF9800;
+            }
+          }
+          
+          .contact-info {
+            flex: 1;
+            
+            h5 {
+              font-size: 15px;
+              font-weight: 600;
+              color: #333;
+              margin-bottom: 4px;
+            }
+            
+            p {
+              font-size: 14px;
+              color: #666;
+              margin-bottom: 2px;
+            }
+            
+            .status {
+              font-size: 12px;
+              padding: 2px 8px;
+              border-radius: 12px;
+              
+              &.online {
+                background: #e8f5e8;
+                color: #4CAF50;
+              }
+            }
+            
+            .time {
+              font-size: 12px;
+              color: #999;
+            }
+          }
+          
+          .arrow {
+            color: #ccc;
+            font-size: 14px;
+          }
+        }
+      }
+    }
+    
+    // 常见问题
+    .faq-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      .section-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 16px;
+        
+        h4 {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+        }
+        
+        .view-all-btn {
+          background: none;
+          border: none;
+          color: #4CAF50;
+          font-size: 14px;
+          cursor: pointer;
+          
+          &:hover {
+            text-decoration: underline;
+          }
+        }
+      }
+      
+      .faq-list {
+        .faq-item {
+          border-bottom: 1px solid #f0f0f0;
+          cursor: pointer;
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          .faq-question {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 16px 0;
+            font-size: 15px;
+            color: #333;
+            
+            i {
+              color: #999;
+              transition: transform 0.3s;
+              
+              &.rotated {
+                transform: rotate(180deg);
+              }
+            }
+          }
+          
+          .faq-answer {
+            padding-bottom: 16px;
+            
+            p {
+              font-size: 14px;
+              color: #666;
+              line-height: 1.5;
+              background: #f8f9fa;
+              padding: 12px;
+              border-radius: 8px;
+            }
+          }
+        }
+      }
+    }
+    
+    // 意见反馈表单
+    .feedback-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      h4 {
+        font-size: 16px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 20px;
+      }
+      
+      .feedback-form {
+        .form-group {
+          margin-bottom: 20px;
+          
+          label {
+            display: block;
+            font-size: 14px;
+            font-weight: 500;
+            color: #333;
+            margin-bottom: 8px;
+            
+            .required {
+              color: #ff4757;
+            }
+          }
+          
+          .feedback-types {
+            display: grid;
+            grid-template-columns: repeat(2, 1fr);
+            gap: 12px;
+            
+            .type-btn {
+              background: white;
+              border: 1px solid #e9ecef;
+              border-radius: 8px;
+              padding: 12px;
+              display: flex;
+              align-items: center;
+              gap: 8px;
+              cursor: pointer;
+              transition: all 0.3s;
+              
+              &:hover {
+                border-color: #4CAF50;
+              }
+              
+              &.active {
+                border-color: #4CAF50;
+                background: #e8f5e8;
+                color: #4CAF50;
+              }
+              
+              i {
+                font-size: 16px;
+              }
+              
+              span {
+                font-size: 14px;
+              }
+            }
+          }
+          
+          textarea {
+            width: 100%;
+            border: 1px solid #e9ecef;
+            border-radius: 8px;
+            padding: 12px;
+            font-size: 14px;
+            resize: vertical;
+            min-height: 100px;
+            
+            &:focus {
+              outline: none;
+              border-color: #4CAF50;
+            }
+          }
+          
+          input[type="text"] {
+            width: 100%;
+            border: 1px solid #e9ecef;
+            border-radius: 8px;
+            padding: 12px;
+            font-size: 14px;
+            
+            &:focus {
+              outline: none;
+              border-color: #4CAF50;
+            }
+          }
+          
+          .char-count {
+            text-align: right;
+            font-size: 12px;
+            color: #999;
+            margin-top: 4px;
+          }
+          
+          .image-upload {
+            display: flex;
+            gap: 12px;
+            flex-wrap: wrap;
+            
+            .upload-item {
+              position: relative;
+              width: 80px;
+              height: 80px;
+              border-radius: 8px;
+              overflow: hidden;
+              
+              img {
+                width: 100%;
+                height: 100%;
+                object-fit: cover;
+              }
+              
+              .remove-btn {
+                position: absolute;
+                top: 4px;
+                right: 4px;
+                width: 20px;
+                height: 20px;
+                background: rgba(0, 0, 0, 0.6);
+                color: white;
+                border: none;
+                border-radius: 50%;
+                font-size: 12px;
+                cursor: pointer;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+              }
+            }
+            
+            .upload-btn {
+              width: 80px;
+              height: 80px;
+              border: 2px dashed #ddd;
+              border-radius: 8px;
+              background: none;
+              display: flex;
+              flex-direction: column;
+              align-items: center;
+              justify-content: center;
+              gap: 4px;
+              cursor: pointer;
+              color: #999;
+              transition: all 0.3s;
+              
+              &:hover {
+                border-color: #4CAF50;
+                color: #4CAF50;
+              }
+              
+              i {
+                font-size: 20px;
+              }
+              
+              span {
+                font-size: 12px;
+              }
+            }
+          }
+          
+          .upload-tip {
+            font-size: 12px;
+            color: #999;
+            margin-top: 8px;
+          }
+        }
+        
+        .submit-btn {
+          width: 100%;
+          background: #4CAF50;
+          color: white;
+          border: none;
+          border-radius: 8px;
+          padding: 14px;
+          font-size: 16px;
+          font-weight: 600;
+          cursor: pointer;
+          transition: background-color 0.3s;
+          
+          &:hover:not(:disabled) {
+            background: #45a049;
+          }
+          
+          &:disabled {
+            background: #ccc;
+            cursor: not-allowed;
+          }
+        }
+      }
+    }
+    
+    // 反馈历史记录
+    .feedback-history-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      .section-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 16px;
+        
+        h4 {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+        }
+        
+        .count {
+          font-size: 13px;
+          color: #666;
+        }
+      }
+      
+      .history-list {
+        .history-item {
+          display: flex;
+          align-items: center;
+          padding: 16px 0;
+          border-bottom: 1px solid #f0f0f0;
+          cursor: pointer;
+          transition: background-color 0.3s;
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          &:hover {
+            background-color: #f8f9fa;
+            margin: 0 -20px;
+            padding-left: 20px;
+            padding-right: 20px;
+            border-radius: 8px;
+          }
+          
+          .history-header {
+            margin-right: 12px;
+            
+            .feedback-type {
+              font-size: 12px;
+              background: #e9ecef;
+              color: #666;
+              padding: 2px 8px;
+              border-radius: 12px;
+              margin-bottom: 4px;
+              display: inline-block;
+            }
+            
+            .feedback-status {
+              font-size: 12px;
+              padding: 2px 8px;
+              border-radius: 12px;
+              
+              &.pending {
+                background: #fff3cd;
+                color: #856404;
+              }
+              
+              &.processing {
+                background: #cce5ff;
+                color: #004085;
+              }
+              
+              &.resolved {
+                background: #d4edda;
+                color: #155724;
+              }
+              
+              &.closed {
+                background: #f8d7da;
+                color: #721c24;
+              }
+            }
+          }
+          
+          .history-content {
+            flex: 1;
+            
+            .feedback-title {
+              font-size: 15px;
+              color: #333;
+              margin-bottom: 4px;
+              font-weight: 500;
+            }
+            
+            .feedback-time {
+              font-size: 13px;
+              color: #999;
+            }
+          }
+          
+          .arrow {
+            color: #ccc;
+            font-size: 14px;
+          }
+        }
+      }
+      
+      .empty-state {
+        text-align: center;
+        padding: 40px 20px;
+        color: #999;
+        
+        i {
+          font-size: 48px;
+          margin-bottom: 16px;
+          opacity: 0.5;
+        }
+        
+        p {
+          font-size: 14px;
+        }
+      }
+    }
+  }
+  
+  // 在线客服模态框
+  .modal-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.5);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    z-index: 1000;
+    
+    .modal-content {
+      background: white;
+      border-radius: 12px;
+      width: 90%;
+      max-width: 500px;
+      max-height: 80vh;
+      overflow: hidden;
+      
+      &.chat-modal {
+        height: 600px;
+        display: flex;
+        flex-direction: column;
+      }
+      
+      .modal-header {
+        padding: 16px 20px;
+        border-bottom: 1px solid #e9ecef;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        
+        .modal-title {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+        }
+        
+        .close-btn {
+          background: none;
+          border: none;
+          font-size: 18px;
+          color: #999;
+          cursor: pointer;
+          padding: 4px;
+          
+          &:hover {
+            color: #333;
+          }
+        }
+      }
+      
+      .chat-container {
+        flex: 1;
+        display: flex;
+        flex-direction: column;
+        
+        .chat-messages {
+          flex: 1;
+          padding: 16px;
+          overflow-y: auto;
+          
+          .message {
+            display: flex;
+            margin-bottom: 16px;
+            
+            &.user {
+              justify-content: flex-end;
+              
+              .message-content {
+                background: #4CAF50;
+                color: white;
+                margin-left: 40px;
+              }
+            }
+            
+            &.service {
+              justify-content: flex-start;
+              
+              .message-content {
+                background: #f1f3f4;
+                color: #333;
+                margin-right: 40px;
+              }
+            }
+            
+            .message-avatar {
+              width: 32px;
+              height: 32px;
+              border-radius: 50%;
+              background: #e9ecef;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              font-size: 14px;
+              color: #666;
+              flex-shrink: 0;
+            }
+            
+            .message-content {
+              max-width: 70%;
+              padding: 12px 16px;
+              border-radius: 18px;
+              margin: 0 8px;
+              
+              .message-text {
+                font-size: 14px;
+                line-height: 1.4;
+                margin-bottom: 4px;
+              }
+              
+              .message-time {
+                font-size: 11px;
+                opacity: 0.7;
+              }
+            }
+          }
+        }
+        
+        .chat-input {
+          padding: 16px;
+          border-top: 1px solid #e9ecef;
+          display: flex;
+          gap: 12px;
+          
+          input {
+            flex: 1;
+            border: 1px solid #e9ecef;
+            border-radius: 20px;
+            padding: 10px 16px;
+            font-size: 14px;
+            
+            &:focus {
+              outline: none;
+              border-color: #4CAF50;
+            }
+          }
+          
+          .send-btn {
+            width: 40px;
+            height: 40px;
+            background: #4CAF50;
+            color: white;
+            border: none;
+            border-radius: 50%;
+            cursor: pointer;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            transition: background-color 0.3s;
+            
+            &:hover:not(:disabled) {
+              background: #45a049;
+            }
+            
+            &:disabled {
+              background: #ccc;
+              cursor: not-allowed;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 480px) {
+  .customer-service-page {
+    .service-content {
+      padding: 12px;
+      
+      .feedback-section {
+        .feedback-form {
+          .form-group {
+            .feedback-types {
+              grid-template-columns: 1fr;
+            }
+          }
+        }
+      }
+    }
+    
+    .modal-overlay {
+      .modal-content {
+        width: 95%;
+        
+        &.chat-modal {
+          height: 70vh;
+        }
+      }
+    }
+  }
+}

+ 354 - 0
src/app/consumer/profile/customer-service/customer-service.ts

@@ -0,0 +1,354 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+
+interface FAQ {
+  id: string;
+  question: string;
+  answer: string;
+  expanded: boolean;
+}
+
+interface FeedbackType {
+  value: string;
+  label: string;
+  icon: string;
+}
+
+interface UploadedImage {
+  name: string;
+  url: string;
+  file?: File;
+}
+
+interface FeedbackHistory {
+  id: string;
+  type: string;
+  title: string;
+  content: string;
+  status: 'pending' | 'processing' | 'resolved' | 'closed';
+  createTime: Date;
+  updateTime: Date;
+  reply?: string;
+}
+
+interface ChatMessage {
+  id: string;
+  sender: 'user' | 'service';
+  content: string;
+  time: Date;
+}
+
+@Component({
+  selector: 'app-customer-service',
+  standalone: true,
+  imports: [CommonModule, FormsModule],
+  templateUrl: './customer-service.html',
+  styleUrls: ['./customer-service.scss']
+})
+export class CustomerServiceComponent implements OnInit {
+  
+  // 常见问题
+  faqList: FAQ[] = [
+    {
+      id: '1',
+      question: '如何预约上门回收服务?',
+      answer: '您可以在首页点击"预约回收",选择回收物品类型、重量和上门时间,填写地址信息后提交预约。我们的回收员会按时上门服务。',
+      expanded: false
+    },
+    {
+      id: '2',
+      question: '回收价格是如何计算的?',
+      answer: '回收价格根据物品类型、重量、品质等因素综合计算。您可以在预约时查看预估价格,实际价格以回收员现场评估为准。',
+      expanded: false
+    },
+    {
+      id: '3',
+      question: '积分如何兑换现金?',
+      answer: '在"我的收益"页面,您可以将积分兑换为现金。100积分=1元,满10元即可提现到支付宝或微信。',
+      expanded: false
+    },
+    {
+      id: '4',
+      question: '如何查看我的回收记录?',
+      answer: '在个人中心的"我的订单"中,您可以查看所有的回收记录,包括订单状态、回收详情和收益情况。',
+      expanded: false
+    }
+  ];
+  
+  // 反馈类型
+  feedbackTypes: FeedbackType[] = [
+    { value: 'bug', label: '功能异常', icon: 'fas fa-bug' },
+    { value: 'suggestion', label: '功能建议', icon: 'fas fa-lightbulb' },
+    { value: 'service', label: '服务问题', icon: 'fas fa-user-tie' },
+    { value: 'other', label: '其他问题', icon: 'fas fa-question-circle' }
+  ];
+  
+  // 反馈表单数据
+  selectedFeedbackType = '';
+  feedbackContent = '';
+  contactInfo = '';
+  uploadedImages: UploadedImage[] = [];
+  
+  // 反馈历史记录
+  feedbackHistory: FeedbackHistory[] = [
+    {
+      id: '1',
+      type: 'bug',
+      title: '预约页面无法选择时间',
+      content: '在预约回收时,时间选择器无法正常显示,点击没有反应。',
+      status: 'resolved',
+      createTime: new Date('2024-01-15'),
+      updateTime: new Date('2024-01-16'),
+      reply: '感谢您的反馈,该问题已修复,请更新到最新版本。'
+    },
+    {
+      id: '2',
+      type: 'suggestion',
+      title: '希望增加夜间回收服务',
+      content: '建议增加夜间回收时段,方便上班族用户。',
+      status: 'processing',
+      createTime: new Date('2024-01-10'),
+      updateTime: new Date('2024-01-12')
+    }
+  ];
+  
+  // 在线客服相关
+  showChatModal = false;
+  chatInputText = '';
+  chatMessages: ChatMessage[] = [
+    {
+      id: '1',
+      sender: 'service',
+      content: '您好!我是智能客服小绿,很高兴为您服务。请问有什么可以帮助您的吗?',
+      time: new Date()
+    }
+  ];
+  
+  constructor(private router: Router) {}
+  
+  ngOnInit() {
+    // 初始化数据
+  }
+  
+  // 开始在线聊天
+  startOnlineChat() {
+    this.showChatModal = true;
+  }
+  
+  // 拨打客服电话
+  callService() {
+    if (confirm('是否拨打客服热线 400-888-6666?')) {
+      // 在移动端可以直接拨打电话
+      window.location.href = 'tel:400-888-6666';
+    }
+  }
+  
+  // 发送邮件
+  sendEmail() {
+    const subject = encodeURIComponent('回收应用反馈');
+    const body = encodeURIComponent('请在此处描述您的问题或建议...');
+    window.location.href = `mailto:service@recycle-app.com?subject=${subject}&body=${body}`;
+  }
+  
+  // 查看全部FAQ
+  viewAllFAQ() {
+    this.showAlert('跳转到帮助中心页面', 'info');
+  }
+  
+  // 切换FAQ展开状态
+  toggleFAQ(faq: FAQ) {
+    faq.expanded = !faq.expanded;
+  }
+  
+  // 选择反馈类型
+  selectFeedbackType(type: string) {
+    this.selectedFeedbackType = type;
+  }
+  
+  // 上传图片
+  uploadImage() {
+    const input = document.createElement('input');
+    input.type = 'file';
+    input.accept = 'image/jpeg,image/png';
+    input.onchange = (event: any) => {
+      const file = event.target.files[0];
+      if (file) {
+        if (file.size > 5 * 1024 * 1024) {
+          this.showAlert('图片大小不能超过5MB', 'error');
+          return;
+        }
+        
+        const reader = new FileReader();
+        reader.onload = (e: any) => {
+          this.uploadedImages.push({
+            name: file.name,
+            url: e.target.result,
+            file: file
+          });
+        };
+        reader.readAsDataURL(file);
+      }
+    };
+    input.click();
+  }
+  
+  // 移除图片
+  removeImage(index: number) {
+    this.uploadedImages.splice(index, 1);
+  }
+  
+  // 检查是否可以提交
+  canSubmit(): boolean {
+    return this.selectedFeedbackType !== '' && 
+           this.feedbackContent.trim() !== '';
+  }
+  
+  // 提交反馈
+  submitFeedback() {
+    if (!this.canSubmit()) {
+      this.showAlert('请填写必要信息', 'error');
+      return;
+    }
+    
+    const newFeedback: FeedbackHistory = {
+      id: Date.now().toString(),
+      type: this.selectedFeedbackType,
+      title: this.feedbackContent.substring(0, 20) + (this.feedbackContent.length > 20 ? '...' : ''),
+      content: this.feedbackContent,
+      status: 'pending',
+      createTime: new Date(),
+      updateTime: new Date()
+    };
+    
+    this.feedbackHistory.unshift(newFeedback);
+    
+    // 重置表单
+    this.selectedFeedbackType = '';
+    this.feedbackContent = '';
+    this.contactInfo = '';
+    this.uploadedImages = [];
+    
+    this.showAlert('反馈提交成功,我们会尽快处理', 'success');
+  }
+  
+  // 获取反馈类型标签
+  getFeedbackTypeLabel(type: string): string {
+    const typeObj = this.feedbackTypes.find(t => t.value === type);
+    return typeObj ? typeObj.label : type;
+  }
+  
+  // 获取状态标签
+  getStatusLabel(status: string): string {
+    const statusMap: { [key: string]: string } = {
+      'pending': '待处理',
+      'processing': '处理中',
+      'resolved': '已解决',
+      'closed': '已关闭'
+    };
+    return statusMap[status] || status;
+  }
+  
+  // 查看反馈详情
+  viewFeedbackDetail(item: FeedbackHistory) {
+    this.showAlert(`查看反馈详情: ${item.title}`, 'info');
+  }
+  
+  // 关闭聊天模态框
+  closeChatModal() {
+    this.showChatModal = false;
+  }
+  
+  // 发送消息
+  sendMessage() {
+    if (!this.chatInputText.trim()) return;
+    
+    // 添加用户消息
+    const userMessage: ChatMessage = {
+      id: Date.now().toString(),
+      sender: 'user',
+      content: this.chatInputText,
+      time: new Date()
+    };
+    this.chatMessages.push(userMessage);
+    
+    const userInput = this.chatInputText;
+    this.chatInputText = '';
+    
+    // 模拟客服回复
+    setTimeout(() => {
+      const serviceReply = this.generateServiceReply(userInput);
+      const serviceMessage: ChatMessage = {
+        id: (Date.now() + 1).toString(),
+        sender: 'service',
+        content: serviceReply,
+        time: new Date()
+      };
+      this.chatMessages.push(serviceMessage);
+    }, 1000);
+  }
+  
+  // 生成客服回复
+  private generateServiceReply(userInput: string): string {
+    const input = userInput.toLowerCase();
+    
+    if (input.includes('预约') || input.includes('回收')) {
+      return '关于预约回收服务,您可以在首页点击"预约回收"按钮,选择回收物品和时间。如果遇到问题,我可以为您详细介绍操作步骤。';
+    } else if (input.includes('价格') || input.includes('多少钱')) {
+      return '回收价格会根据物品类型、重量和品质来计算。您可以在预约时查看预估价格,具体价格以回收员现场评估为准。';
+    } else if (input.includes('积分') || input.includes('兑换')) {
+      return '积分可以在"我的收益"页面兑换现金,100积分=1元。您也可以在积分商城兑换各种环保商品。';
+    } else if (input.includes('问题') || input.includes('bug') || input.includes('异常')) {
+      return '如果您遇到了技术问题,建议您先尝试重启应用。如果问题仍然存在,请通过意见反馈功能详细描述问题,我们会尽快修复。';
+    } else {
+      return '感谢您的咨询。如果您有其他问题,可以详细描述,我会尽力为您解答。您也可以拨打客服热线400-888-6666获得人工服务。';
+    }
+  }
+  
+  // 关闭模态框
+  closeModal(event: Event) {
+    if (event.target === event.currentTarget) {
+      this.showChatModal = false;
+    }
+  }
+  
+  // 格式化日期
+  formatDate(date: Date): string {
+    const now = new Date();
+    const diffTime = now.getTime() - date.getTime();
+    const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
+    
+    if (diffDays === 0) {
+      return '今天';
+    } else if (diffDays === 1) {
+      return '昨天';
+    } else if (diffDays < 7) {
+      return `${diffDays}天前`;
+    } else {
+      return date.toLocaleDateString('zh-CN', {
+        month: 'short',
+        day: 'numeric'
+      });
+    }
+  }
+  
+  // 格式化时间
+  formatTime(date: Date): string {
+    return date.toLocaleTimeString('zh-CN', {
+      hour: '2-digit',
+      minute: '2-digit'
+    });
+  }
+  
+  // 返回上一页
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+  
+  // 显示提示信息
+  private showAlert(message: string, type: 'success' | 'error' | 'info') {
+    // 简单的提示实现
+    alert(message);
+  }
+}

+ 174 - 0
src/app/consumer/profile/favorites/favorites.html

@@ -0,0 +1,174 @@
+<!-- 顶部标题栏 -->
+<div class="header">
+  <div class="back-btn" (click)="goBack()"><i class="fas fa-arrow-left"></i></div>
+  <div class="header-title">我的收藏</div>
+</div>
+
+<div class="container">
+  <!-- 分类标签 -->
+  <div class="category-tabs">
+    <div 
+      *ngFor="let tab of categoryTabs" 
+      class="category-tab" 
+      [class.active]="tab.active"
+      (click)="selectTab(tab)">
+      <i [class]="tab.icon"></i>
+      <span>{{tab.name}}</span>
+      <span class="tab-count" *ngIf="tab.count > 0">({{tab.count}})</span>
+    </div>
+  </div>
+
+  <!-- 商品收藏列表 -->
+  <div class="products-section" *ngIf="activeTab === 'products'">
+    <div class="section-header">
+      <div class="section-title">收藏商品</div>
+      <div class="batch-actions" *ngIf="favoriteProducts.length > 0">
+        <button 
+          class="batch-btn" 
+          [class.active]="isEditMode"
+          (click)="toggleEditMode()">
+          {{isEditMode ? '完成' : '编辑'}}
+        </button>
+      </div>
+    </div>
+    
+    <div class="products-grid">
+      <div 
+        *ngFor="let product of favoriteProducts" 
+        class="product-card"
+        [class.edit-mode]="isEditMode">
+        
+        <div class="product-checkbox" *ngIf="isEditMode">
+          <input 
+            type="checkbox" 
+            [(ngModel)]="product.selected"
+            (change)="updateSelection()">
+        </div>
+        
+        <div class="product-image">
+          <img [src]="product.image" [alt]="product.name">
+          <div class="favorite-btn active" (click)="toggleProductFavorite(product)">
+            <i class="fas fa-heart"></i>
+          </div>
+        </div>
+        
+        <div class="product-info">
+          <div class="product-name">{{product.name}}</div>
+          <div class="product-points">{{product.points}}积分</div>
+          <div class="product-stock">库存:{{product.stock}}件</div>
+        </div>
+        
+        <div class="product-actions" *ngIf="!isEditMode">
+          <button class="exchange-btn" (click)="exchangeProduct(product)">
+            立即兑换
+          </button>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 批量操作栏 -->
+    <div class="batch-toolbar" *ngIf="isEditMode && favoriteProducts.length > 0">
+      <label class="select-all">
+        <input 
+          type="checkbox" 
+          [checked]="isAllSelected"
+          (change)="toggleSelectAll()">
+        <span>全选</span>
+      </label>
+      <button 
+        class="batch-delete-btn" 
+        [disabled]="selectedCount === 0"
+        (click)="batchDeleteProducts()">
+        删除选中 ({{selectedCount}})
+      </button>
+    </div>
+    
+    <!-- 商品空状态 -->
+    <div class="empty-state" *ngIf="favoriteProducts.length === 0">
+      <div class="empty-icon">
+        <i class="fas fa-shopping-bag"></i>
+      </div>
+      <div class="empty-text">暂无收藏商品</div>
+      <button class="empty-action" (click)="goToMall()">去积分商城看看</button>
+    </div>
+  </div>
+
+  <!-- 知识收藏列表 -->
+  <div class="knowledge-section" *ngIf="activeTab === 'knowledge'">
+    <div class="section-header">
+      <div class="section-title">收藏知识</div>
+      <div class="batch-actions" *ngIf="favoriteKnowledge.length > 0">
+        <button 
+          class="batch-btn" 
+          [class.active]="isEditMode"
+          (click)="toggleEditMode()">
+          {{isEditMode ? '完成' : '编辑'}}
+        </button>
+      </div>
+    </div>
+    
+    <div class="knowledge-list">
+      <div 
+        *ngFor="let article of favoriteKnowledge" 
+        class="knowledge-card"
+        [class.edit-mode]="isEditMode"
+        (click)="!isEditMode && viewArticle(article)">
+        
+        <div class="knowledge-checkbox" *ngIf="isEditMode">
+          <input 
+            type="checkbox" 
+            [(ngModel)]="article.selected"
+            (change)="updateSelection()">
+        </div>
+        
+        <div class="knowledge-image">
+          <img [src]="article.image" [alt]="article.title">
+        </div>
+        
+        <div class="knowledge-content">
+          <div class="knowledge-title">{{article.title}}</div>
+          <div class="knowledge-summary">{{article.summary}}</div>
+          <div class="knowledge-meta">
+            <span class="knowledge-category">
+              <i [class]="article.categoryIcon"></i>
+              {{article.category}}
+            </span>
+            <span class="knowledge-time">{{article.collectTime}}</span>
+          </div>
+        </div>
+        
+        <div class="knowledge-actions">
+          <div class="favorite-btn active" (click)="toggleKnowledgeFavorite(article, $event)">
+            <i class="fas fa-heart"></i>
+          </div>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 批量操作栏 -->
+    <div class="batch-toolbar" *ngIf="isEditMode && favoriteKnowledge.length > 0">
+      <label class="select-all">
+        <input 
+          type="checkbox" 
+          [checked]="isAllSelected"
+          (change)="toggleSelectAll()">
+        <span>全选</span>
+      </label>
+      <button 
+        class="batch-delete-btn" 
+        [disabled]="selectedCount === 0"
+        (click)="batchDeleteKnowledge()">
+        删除选中 ({{selectedCount}})
+      </button>
+    </div>
+    
+    <!-- 知识空状态 -->
+    <div class="empty-state" *ngIf="favoriteKnowledge.length === 0">
+      <div class="empty-icon">
+        <i class="fas fa-book"></i>
+      </div>
+      <div class="empty-text">暂无收藏知识</div>
+      <button class="empty-action" (click)="goToKnowledge()">去发现环保知识</button>
+    </div>
+  </div>
+</div>

+ 508 - 0
src/app/consumer/profile/favorites/favorites.scss

@@ -0,0 +1,508 @@
+// 全局重置
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+// 顶部标题栏
+.header {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 56px;
+  background: #2e7d32;
+  color: white;
+  position: relative;
+  
+  .back-btn {
+    position: absolute;
+    left: 16px;
+    width: 40px;
+    height: 40px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 50%;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      background: rgba(255, 255, 255, 0.1);
+    }
+    
+    i {
+      font-size: 18px;
+    }
+  }
+  
+  .header-title {
+    font-size: 18px;
+    font-weight: 600;
+  }
+}
+
+// 容器
+.container {
+  min-height: calc(100vh - 56px);
+  background: #f5f5f5;
+}
+
+// 分类标签
+.category-tabs {
+  display: flex;
+  background: white;
+  padding: 0 16px;
+  
+  .category-tab {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap: 8px;
+    padding: 16px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    border-bottom: 3px solid transparent;
+    color: #666;
+    
+    &.active {
+      color: #2e7d32;
+      border-bottom-color: #2e7d32;
+    }
+    
+    &:hover:not(.active) {
+      color: #333;
+    }
+    
+    i {
+      font-size: 16px;
+    }
+    
+    span {
+      font-size: 14px;
+      font-weight: 600;
+    }
+    
+    .tab-count {
+      font-size: 12px;
+      opacity: 0.8;
+    }
+  }
+}
+
+// 区域标题
+.section-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 16px;
+  background: white;
+  border-bottom: 1px solid #eee;
+  
+  .section-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #333;
+  }
+  
+  .batch-actions {
+    .batch-btn {
+      background: none;
+      border: 1px solid #2e7d32;
+      color: #2e7d32;
+      padding: 6px 16px;
+      border-radius: 16px;
+      font-size: 12px;
+      cursor: pointer;
+      transition: all 0.3s ease;
+      
+      &.active {
+        background: #2e7d32;
+        color: white;
+      }
+      
+      &:hover:not(.active) {
+        background: #e8f5e8;
+      }
+    }
+  }
+}
+
+// 商品网格
+.products-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 12px;
+  padding: 16px;
+  
+  .product-card {
+    background: white;
+    border-radius: 12px;
+    overflow: hidden;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    transition: all 0.3s ease;
+    position: relative;
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+    }
+    
+    &.edit-mode {
+      .product-checkbox {
+        display: block;
+      }
+    }
+    
+    .product-checkbox {
+      display: none;
+      position: absolute;
+      top: 8px;
+      left: 8px;
+      z-index: 2;
+      
+      input[type="checkbox"] {
+        width: 20px;
+        height: 20px;
+        accent-color: #2e7d32;
+      }
+    }
+    
+    .product-image {
+      position: relative;
+      height: 120px;
+      overflow: hidden;
+      
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+      }
+      
+      .favorite-btn {
+        position: absolute;
+        top: 8px;
+        right: 8px;
+        width: 32px;
+        height: 32px;
+        background: rgba(255, 255, 255, 0.9);
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &.active {
+          color: #e91e63;
+        }
+        
+        &:hover {
+          background: white;
+          transform: scale(1.1);
+        }
+        
+        i {
+          font-size: 14px;
+        }
+      }
+    }
+    
+    .product-info {
+      padding: 12px;
+      
+      .product-name {
+        font-size: 14px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 8px;
+        line-height: 1.3;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        line-clamp: 2;
+        -webkit-box-orient: vertical;
+        overflow: hidden;
+      }
+      
+      .product-points {
+        font-size: 16px;
+        font-weight: 700;
+        color: #ff9800;
+        margin-bottom: 4px;
+      }
+      
+      .product-stock {
+        font-size: 12px;
+        color: #666;
+      }
+    }
+    
+    .product-actions {
+      padding: 0 12px 12px;
+      
+      .exchange-btn {
+        width: 100%;
+        background: #2e7d32;
+        color: white;
+        border: none;
+        padding: 8px;
+        border-radius: 20px;
+        font-size: 12px;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &:hover {
+          background: #1b5e20;
+        }
+      }
+    }
+  }
+}
+
+// 知识列表
+.knowledge-list {
+  padding: 16px;
+  
+  .knowledge-card {
+    background: white;
+    border-radius: 12px;
+    padding: 16px;
+    margin-bottom: 12px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    display: flex;
+    gap: 12px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    position: relative;
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+    }
+    
+    &.edit-mode {
+      cursor: default;
+      
+      .knowledge-checkbox {
+        display: block;
+      }
+    }
+    
+    .knowledge-checkbox {
+      display: none;
+      position: absolute;
+      top: 16px;
+      left: 16px;
+      z-index: 2;
+      
+      input[type="checkbox"] {
+        width: 20px;
+        height: 20px;
+        accent-color: #2e7d32;
+      }
+    }
+    
+    .knowledge-image {
+      width: 80px;
+      height: 80px;
+      border-radius: 8px;
+      overflow: hidden;
+      flex-shrink: 0;
+      
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+      }
+    }
+    
+    .knowledge-content {
+      flex: 1;
+      
+      .knowledge-title {
+        font-size: 14px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 8px;
+        line-height: 1.4;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        line-clamp: 2;
+        -webkit-box-orient: vertical;
+        overflow: hidden;
+      }
+      
+      .knowledge-summary {
+        font-size: 12px;
+        color: #666;
+        line-height: 1.4;
+        margin-bottom: 8px;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        line-clamp: 2;
+        -webkit-box-orient: vertical;
+        overflow: hidden;
+      }
+      
+      .knowledge-meta {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        
+        .knowledge-category {
+          display: flex;
+          align-items: center;
+          gap: 4px;
+          font-size: 12px;
+          color: #2e7d32;
+          
+          i {
+            font-size: 10px;
+          }
+        }
+        
+        .knowledge-time {
+          font-size: 12px;
+          color: #999;
+        }
+      }
+    }
+    
+    .knowledge-actions {
+      display: flex;
+      align-items: flex-start;
+      
+      .favorite-btn {
+        width: 32px;
+        height: 32px;
+        background: #f5f5f5;
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &.active {
+          color: #e91e63;
+          background: #fce4ec;
+        }
+        
+        &:hover {
+          transform: scale(1.1);
+        }
+        
+        i {
+          font-size: 14px;
+        }
+      }
+    }
+  }
+}
+
+// 批量操作栏
+.batch-toolbar {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background: white;
+  padding: 16px;
+  border-top: 1px solid #eee;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  z-index: 100;
+  
+  .select-all {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    cursor: pointer;
+    
+    input[type="checkbox"] {
+      width: 18px;
+      height: 18px;
+      accent-color: #2e7d32;
+    }
+    
+    span {
+      font-size: 14px;
+      color: #333;
+    }
+  }
+  
+  .batch-delete-btn {
+    background: #f44336;
+    color: white;
+    border: none;
+    padding: 10px 20px;
+    border-radius: 20px;
+    font-size: 14px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:disabled {
+      background: #ccc;
+      cursor: not-allowed;
+    }
+    
+    &:not(:disabled):hover {
+      background: #d32f2f;
+    }
+  }
+}
+
+// 空状态
+.empty-state {
+  text-align: center;
+  padding: 60px 20px;
+  background: white;
+  margin: 16px;
+  border-radius: 12px;
+  
+  .empty-icon {
+    margin-bottom: 16px;
+    
+    i {
+      font-size: 64px;
+      color: #ccc;
+    }
+  }
+  
+  .empty-text {
+    font-size: 16px;
+    color: #666;
+    margin-bottom: 24px;
+  }
+  
+  .empty-action {
+    background: #2e7d32;
+    color: white;
+    border: none;
+    padding: 12px 24px;
+    border-radius: 24px;
+    font-size: 14px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      background: #1b5e20;
+      transform: translateY(-2px);
+    }
+  }
+}
+
+// 响应式设计
+@media (min-width: 768px) {
+  .products-grid {
+    grid-template-columns: repeat(3, 1fr);
+  }
+}
+
+@media (min-width: 1024px) {
+  .products-grid {
+    grid-template-columns: repeat(4, 1fr);
+  }
+}

+ 280 - 0
src/app/consumer/profile/favorites/favorites.ts

@@ -0,0 +1,280 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+
+interface FavoriteProduct {
+  id: string;
+  name: string;
+  image: string;
+  points: number;
+  stock: number;
+  selected?: boolean;
+}
+
+interface FavoriteKnowledge {
+  id: string;
+  title: string;
+  summary: string;
+  image: string;
+  category: string;
+  categoryIcon: string;
+  collectTime: string;
+  selected?: boolean;
+}
+
+interface CategoryTab {
+  id: 'products' | 'knowledge';
+  name: string;
+  icon: string;
+  active: boolean;
+  count: number;
+}
+
+@Component({
+  selector: 'app-favorites',
+  standalone: true,
+  imports: [CommonModule, FormsModule],
+  templateUrl: './favorites.html',
+  styleUrls: ['./favorites.scss']
+})
+export class FavoritesComponent implements OnInit {
+  
+  // 分类标签
+  categoryTabs: CategoryTab[] = [
+    { id: 'products', name: '商品', icon: 'fas fa-shopping-bag', active: true, count: 0 },
+    { id: 'knowledge', name: '知识', icon: 'fas fa-book', active: false, count: 0 }
+  ];
+  
+  // 收藏商品
+  favoriteProducts: FavoriteProduct[] = [
+    {
+      id: '1',
+      name: '环保购物袋',
+      image: 'assets/images/eco-bag.jpg',
+      points: 200,
+      stock: 50
+    },
+    {
+      id: '2',
+      name: '竹纤维牙刷套装',
+      image: 'assets/images/bamboo-toothbrush.jpg',
+      points: 150,
+      stock: 30
+    },
+    {
+      id: '3',
+      name: '可降解餐具套装',
+      image: 'assets/images/eco-utensils.jpg',
+      points: 300,
+      stock: 25
+    },
+    {
+      id: '4',
+      name: '太阳能充电宝',
+      image: 'assets/images/solar-powerbank.jpg',
+      points: 800,
+      stock: 15
+    }
+  ];
+  
+  // 收藏知识
+  favoriteKnowledge: FavoriteKnowledge[] = [
+    {
+      id: '1',
+      title: '垃圾分类小贴士:如何正确分类生活垃圾',
+      summary: '详细介绍生活中常见垃圾的分类方法,帮助大家养成正确的垃圾分类习惯...',
+      image: 'assets/images/waste-sorting.jpg',
+      category: '垃圾分类',
+      categoryIcon: 'fas fa-recycle',
+      collectTime: '2024-01-15'
+    },
+    {
+      id: '2',
+      title: '废纸回收的环保价值:每吨废纸可以拯救多少棵树',
+      summary: '废纸回收不仅能减少垃圾填埋,还能大大减少对森林资源的消耗...',
+      image: 'assets/images/paper-recycle.jpg',
+      category: '回收知识',
+      categoryIcon: 'fas fa-newspaper',
+      collectTime: '2024-01-14'
+    },
+    {
+      id: '3',
+      title: '塑料制品的生命周期:从生产到回收的环保之路',
+      summary: '了解塑料制品的完整生命周期,学习如何减少塑料污染...',
+      image: 'assets/images/plastic-lifecycle.jpg',
+      category: '环保科普',
+      categoryIcon: 'fas fa-leaf',
+      collectTime: '2024-01-13'
+    }
+  ];
+  
+  // 当前激活的标签
+  activeTab: 'products' | 'knowledge' = 'products';
+  
+  // 编辑模式
+  isEditMode = false;
+  
+  constructor(private router: Router) {}
+  
+  ngOnInit() {
+    this.updateTabCounts();
+  }
+  
+  // 更新标签计数
+  updateTabCounts() {
+    this.categoryTabs.forEach(tab => {
+      if (tab.id === 'products') {
+        tab.count = this.favoriteProducts.length;
+      } else if (tab.id === 'knowledge') {
+        tab.count = this.favoriteKnowledge.length;
+      }
+    });
+  }
+  
+  // 选择标签
+  selectTab(selectedTab: CategoryTab) {
+    this.categoryTabs.forEach(tab => tab.active = false);
+    selectedTab.active = true;
+    this.activeTab = selectedTab.id;
+    this.isEditMode = false; // 切换标签时退出编辑模式
+  }
+  
+  // 切换编辑模式
+  toggleEditMode() {
+    this.isEditMode = !this.isEditMode;
+    if (!this.isEditMode) {
+      // 退出编辑模式时清除所有选择
+      this.clearAllSelections();
+    }
+  }
+  
+  // 清除所有选择
+  clearAllSelections() {
+    this.favoriteProducts.forEach(product => product.selected = false);
+    this.favoriteKnowledge.forEach(article => article.selected = false);
+  }
+  
+  // 更新选择状态
+  updateSelection() {
+    // 这个方法会在复选框状态改变时被调用
+  }
+  
+  // 获取选中数量
+  get selectedCount(): number {
+    if (this.activeTab === 'products') {
+      return this.favoriteProducts.filter(p => p.selected).length;
+    } else {
+      return this.favoriteKnowledge.filter(a => a.selected).length;
+    }
+  }
+  
+  // 是否全选
+  get isAllSelected(): boolean {
+    if (this.activeTab === 'products') {
+      return this.favoriteProducts.length > 0 && 
+             this.favoriteProducts.every(p => p.selected);
+    } else {
+      return this.favoriteKnowledge.length > 0 && 
+             this.favoriteKnowledge.every(a => a.selected);
+    }
+  }
+  
+  // 切换全选
+  toggleSelectAll() {
+    const selectAll = !this.isAllSelected;
+    if (this.activeTab === 'products') {
+      this.favoriteProducts.forEach(product => product.selected = selectAll);
+    } else {
+      this.favoriteKnowledge.forEach(article => article.selected = selectAll);
+    }
+  }
+  
+  // 切换商品收藏状态
+  toggleProductFavorite(product: FavoriteProduct) {
+    if (confirm('确定要取消收藏这个商品吗?')) {
+      const index = this.favoriteProducts.findIndex(p => p.id === product.id);
+      if (index > -1) {
+        this.favoriteProducts.splice(index, 1);
+        this.updateTabCounts();
+        this.showAlert('已取消收藏', 'success');
+      }
+    }
+  }
+  
+  // 切换知识收藏状态
+  toggleKnowledgeFavorite(article: FavoriteKnowledge, event: Event) {
+    event.stopPropagation();
+    if (confirm('确定要取消收藏这篇文章吗?')) {
+      const index = this.favoriteKnowledge.findIndex(a => a.id === article.id);
+      if (index > -1) {
+        this.favoriteKnowledge.splice(index, 1);
+        this.updateTabCounts();
+        this.showAlert('已取消收藏', 'success');
+      }
+    }
+  }
+  
+  // 兑换商品
+  exchangeProduct(product: FavoriteProduct) {
+    this.showAlert('跳转到商品详情页面', 'info');
+  }
+  
+  // 查看文章
+  viewArticle(article: FavoriteKnowledge) {
+    this.showAlert('跳转到文章详情页面', 'info');
+  }
+  
+  // 批量删除商品
+  batchDeleteProducts() {
+    const selectedProducts = this.favoriteProducts.filter(p => p.selected);
+    if (selectedProducts.length === 0) {
+      this.showAlert('请选择要删除的商品', 'error');
+      return;
+    }
+    
+    if (confirm(`确定要删除选中的 ${selectedProducts.length} 个商品吗?`)) {
+      this.favoriteProducts = this.favoriteProducts.filter(p => !p.selected);
+      this.updateTabCounts();
+      this.isEditMode = false;
+      this.showAlert(`已删除 ${selectedProducts.length} 个商品`, 'success');
+    }
+  }
+  
+  // 批量删除知识
+  batchDeleteKnowledge() {
+    const selectedArticles = this.favoriteKnowledge.filter(a => a.selected);
+    if (selectedArticles.length === 0) {
+      this.showAlert('请选择要删除的文章', 'error');
+      return;
+    }
+    
+    if (confirm(`确定要删除选中的 ${selectedArticles.length} 篇文章吗?`)) {
+      this.favoriteKnowledge = this.favoriteKnowledge.filter(a => !a.selected);
+      this.updateTabCounts();
+      this.isEditMode = false;
+      this.showAlert(`已删除 ${selectedArticles.length} 篇文章`, 'success');
+    }
+  }
+  
+  // 跳转到积分商城
+  goToMall() {
+    this.router.navigate(['/consumer/points-mall']);
+  }
+  
+  // 跳转到环保知识
+  goToKnowledge() {
+    this.showAlert('跳转到环保知识页面', 'info');
+  }
+  
+  // 返回上一页
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+  
+  // 显示提示信息
+  private showAlert(message: string, type: 'success' | 'error' | 'info') {
+    // 简单的提示实现
+    alert(message);
+  }
+}

+ 198 - 0
src/app/consumer/profile/invite-friends/invite-friends.html

@@ -0,0 +1,198 @@
+<div class="invite-friends-page">
+  <!-- 头部 -->
+  <div class="header">
+    <button class="back-btn" (click)="goBack()">
+      <i class="fas fa-arrow-left"></i>
+    </button>
+    <span class="title">邀请好友</span>
+  </div>
+
+  <div class="invite-content">
+    <!-- 邀请奖励说明 -->
+    <div class="reward-banner">
+      <div class="banner-bg">
+        <div class="reward-info">
+          <h3>邀请好友,共享绿色奖励</h3>
+          <p>邀请好友注册并完成首次回收,您和好友都可获得丰厚奖励</p>
+        </div>
+        <div class="reward-icon">
+          <i class="fas fa-gift"></i>
+        </div>
+      </div>
+    </div>
+
+    <!-- 我的邀请码 -->
+    <div class="invite-code-section">
+      <div class="section-header">
+        <h4>我的邀请码</h4>
+        <span class="code-desc">分享给好友,双方都有奖励</span>
+      </div>
+      
+      <div class="invite-code-card">
+        <div class="code-display">
+          <span class="code-label">邀请码</span>
+          <span class="code-value">{{ inviteCode }}</span>
+          <button class="copy-btn" (click)="copyInviteCode()">
+            <i class="fas fa-copy"></i>
+            复制
+          </button>
+        </div>
+        
+        <div class="qr-code">
+          <div class="qr-placeholder">
+            <i class="fas fa-qrcode"></i>
+            <span>二维码</span>
+          </div>
+          <button class="save-qr-btn" (click)="saveQRCode()">保存二维码</button>
+        </div>
+      </div>
+    </div>
+
+    <!-- 分享方式 -->
+    <div class="share-section">
+      <h4>分享给好友</h4>
+      <div class="share-methods">
+        <button class="share-btn wechat" (click)="shareToWeChat()">
+          <i class="fab fa-weixin"></i>
+          <span>微信</span>
+        </button>
+        <button class="share-btn qq" (click)="shareToQQ()">
+          <i class="fab fa-qq"></i>
+          <span>QQ</span>
+        </button>
+        <button class="share-btn weibo" (click)="shareToWeibo()">
+          <i class="fab fa-weibo"></i>
+          <span>微博</span>
+        </button>
+        <button class="share-btn link" (click)="shareLink()">
+          <i class="fas fa-link"></i>
+          <span>复制链接</span>
+        </button>
+      </div>
+    </div>
+
+    <!-- 奖励规则 -->
+    <div class="reward-rules-section">
+      <h4>奖励规则</h4>
+      <div class="rules-list">
+        <div class="rule-item">
+          <div class="rule-icon">
+            <i class="fas fa-user-plus"></i>
+          </div>
+          <div class="rule-content">
+            <h5>好友注册</h5>
+            <p>好友通过您的邀请码注册成功</p>
+            <span class="reward">奖励:10积分</span>
+          </div>
+        </div>
+        
+        <div class="rule-item">
+          <div class="rule-icon">
+            <i class="fas fa-recycle"></i>
+          </div>
+          <div class="rule-content">
+            <h5>首次回收</h5>
+            <p>好友完成首次回收订单</p>
+            <span class="reward">奖励:您和好友各得20积分</span>
+          </div>
+        </div>
+        
+        <div class="rule-item">
+          <div class="rule-icon">
+            <i class="fas fa-coins"></i>
+          </div>
+          <div class="rule-content">
+            <h5>持续回收</h5>
+            <p>好友每完成一次回收,您都可获得奖励</p>
+            <span class="reward">奖励:5积分/次</span>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 邀请记录 -->
+    <div class="invite-records-section">
+      <div class="section-header">
+        <h4>邀请记录</h4>
+        <span class="total-count">已邀请 {{ totalInvites }} 人</span>
+      </div>
+      
+      <div class="records-tabs">
+        <button 
+          class="tab-btn" 
+          [class.active]="activeTab === 'all'"
+          (click)="switchTab('all')">
+          全部 ({{ inviteRecords.length }})
+        </button>
+        <button 
+          class="tab-btn" 
+          [class.active]="activeTab === 'success'"
+          (click)="switchTab('success')">
+          成功 ({{ getSuccessCount() }})
+        </button>
+        <button 
+          class="tab-btn" 
+          [class.active]="activeTab === 'pending'"
+          (click)="switchTab('pending')">
+          待完成 ({{ getPendingCount() }})
+        </button>
+      </div>
+      
+      <div class="records-list" *ngIf="getFilteredRecords().length > 0">
+        <div 
+          class="record-item" 
+          *ngFor="let record of getFilteredRecords()"
+          [class.success]="record.status === 'success'"
+          [class.pending]="record.status === 'pending'">
+          <div class="record-avatar">
+            <img [src]="record.avatar" [alt]="record.nickname" *ngIf="record.avatar">
+            <div class="default-avatar" *ngIf="!record.avatar">
+              <i class="fas fa-user"></i>
+            </div>
+          </div>
+          
+          <div class="record-info">
+            <div class="record-name">{{ record.nickname }}</div>
+            <div class="record-time">{{ formatDate(record.inviteTime) }}</div>
+            <div class="record-status" [ngClass]="record.status">
+              {{ getStatusText(record.status) }}
+            </div>
+          </div>
+          
+          <div class="record-reward" *ngIf="record.status === 'success'">
+            <span class="reward-points">+{{ record.rewardPoints }}</span>
+            <span class="reward-label">积分</span>
+          </div>
+        </div>
+      </div>
+      
+      <div class="empty-state" *ngIf="getFilteredRecords().length === 0">
+        <i class="fas fa-user-friends"></i>
+        <p>{{ getEmptyMessage() }}</p>
+      </div>
+    </div>
+
+    <!-- 我的奖励统计 -->
+    <div class="reward-stats-section">
+      <h4>我的邀请奖励</h4>
+      <div class="stats-grid">
+        <div class="stat-item">
+          <div class="stat-value">{{ totalRewardPoints }}</div>
+          <div class="stat-label">累计积分</div>
+        </div>
+        <div class="stat-item">
+          <div class="stat-value">{{ totalRewardCash }}</div>
+          <div class="stat-label">累计现金(元)</div>
+        </div>
+        <div class="stat-item">
+          <div class="stat-value">{{ successfulInvites }}</div>
+          <div class="stat-label">成功邀请</div>
+        </div>
+        <div class="stat-item">
+          <div class="stat-value">{{ thisMonthRewards }}</div>
+          <div class="stat-label">本月奖励</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 575 - 0
src/app/consumer/profile/invite-friends/invite-friends.scss

@@ -0,0 +1,575 @@
+.invite-friends-page {
+  min-height: 100vh;
+  background-color: #f5f5f5;
+  
+  .header {
+    background: linear-gradient(135deg, #4CAF50, #45a049);
+    color: white;
+    padding: 12px 16px;
+    display: flex;
+    align-items: center;
+    position: sticky;
+    top: 0;
+    z-index: 100;
+    
+    .back-btn {
+      background: none;
+      border: none;
+      color: white;
+      font-size: 18px;
+      margin-right: 12px;
+      cursor: pointer;
+      padding: 8px;
+      border-radius: 50%;
+      transition: background-color 0.3s;
+      
+      &:hover {
+        background-color: rgba(255, 255, 255, 0.1);
+      }
+    }
+    
+    .title {
+      font-size: 18px;
+      font-weight: 600;
+    }
+  }
+  
+  .invite-content {
+    padding: 16px;
+    
+    // 奖励横幅
+    .reward-banner {
+      margin-bottom: 20px;
+      
+      .banner-bg {
+        background: linear-gradient(135deg, #FF6B6B, #FF8E8E);
+        border-radius: 16px;
+        padding: 20px;
+        color: white;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        position: relative;
+        overflow: hidden;
+        
+        &::before {
+          content: '';
+          position: absolute;
+          top: -50%;
+          right: -20%;
+          width: 100px;
+          height: 100px;
+          background: rgba(255, 255, 255, 0.1);
+          border-radius: 50%;
+        }
+        
+        .reward-info {
+          flex: 1;
+          
+          h3 {
+            font-size: 18px;
+            font-weight: 600;
+            margin-bottom: 8px;
+          }
+          
+          p {
+            font-size: 14px;
+            opacity: 0.9;
+            line-height: 1.4;
+          }
+        }
+        
+        .reward-icon {
+          font-size: 32px;
+          opacity: 0.8;
+        }
+      }
+    }
+    
+    // 邀请码区域
+    .invite-code-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      .section-header {
+        margin-bottom: 16px;
+        
+        h4 {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+          margin-bottom: 4px;
+        }
+        
+        .code-desc {
+          font-size: 13px;
+          color: #666;
+        }
+      }
+      
+      .invite-code-card {
+        display: flex;
+        gap: 16px;
+        
+        .code-display {
+          flex: 1;
+          background: #f8f9fa;
+          border-radius: 12px;
+          padding: 16px;
+          display: flex;
+          align-items: center;
+          gap: 12px;
+          
+          .code-label {
+            font-size: 14px;
+            color: #666;
+          }
+          
+          .code-value {
+            font-size: 20px;
+            font-weight: 600;
+            color: #4CAF50;
+            letter-spacing: 2px;
+            flex: 1;
+          }
+          
+          .copy-btn {
+            background: #4CAF50;
+            color: white;
+            border: none;
+            border-radius: 8px;
+            padding: 8px 12px;
+            font-size: 13px;
+            cursor: pointer;
+            display: flex;
+            align-items: center;
+            gap: 4px;
+            transition: background-color 0.3s;
+            
+            &:hover {
+              background: #45a049;
+            }
+          }
+        }
+        
+        .qr-code {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          gap: 8px;
+          
+          .qr-placeholder {
+            width: 80px;
+            height: 80px;
+            background: #f0f0f0;
+            border-radius: 8px;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            color: #999;
+            
+            i {
+              font-size: 24px;
+              margin-bottom: 4px;
+            }
+            
+            span {
+              font-size: 12px;
+            }
+          }
+          
+          .save-qr-btn {
+            background: none;
+            border: 1px solid #ddd;
+            color: #666;
+            border-radius: 6px;
+            padding: 4px 8px;
+            font-size: 12px;
+            cursor: pointer;
+            transition: all 0.3s;
+            
+            &:hover {
+              border-color: #4CAF50;
+              color: #4CAF50;
+            }
+          }
+        }
+      }
+    }
+    
+    // 分享区域
+    .share-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      h4 {
+        font-size: 16px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 16px;
+      }
+      
+      .share-methods {
+        display: grid;
+        grid-template-columns: repeat(4, 1fr);
+        gap: 12px;
+        
+        .share-btn {
+          background: white;
+          border: 1px solid #e9ecef;
+          border-radius: 12px;
+          padding: 16px 8px;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          gap: 8px;
+          cursor: pointer;
+          transition: all 0.3s;
+          
+          &:hover {
+            transform: translateY(-2px);
+            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+          }
+          
+          i {
+            font-size: 24px;
+          }
+          
+          span {
+            font-size: 13px;
+            color: #333;
+          }
+          
+          &.wechat {
+            i { color: #07C160; }
+            &:hover { border-color: #07C160; }
+          }
+          
+          &.qq {
+            i { color: #12B7F5; }
+            &:hover { border-color: #12B7F5; }
+          }
+          
+          &.weibo {
+            i { color: #E6162D; }
+            &:hover { border-color: #E6162D; }
+          }
+          
+          &.link {
+            i { color: #666; }
+            &:hover { border-color: #666; }
+          }
+        }
+      }
+    }
+    
+    // 奖励规则
+    .reward-rules-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      h4 {
+        font-size: 16px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 16px;
+      }
+      
+      .rules-list {
+        .rule-item {
+          display: flex;
+          align-items: flex-start;
+          gap: 12px;
+          padding: 16px 0;
+          border-bottom: 1px solid #f0f0f0;
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          .rule-icon {
+            width: 40px;
+            height: 40px;
+            background: #e8f5e8;
+            border-radius: 50%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            color: #4CAF50;
+            font-size: 18px;
+            flex-shrink: 0;
+          }
+          
+          .rule-content {
+            flex: 1;
+            
+            h5 {
+              font-size: 15px;
+              font-weight: 600;
+              color: #333;
+              margin-bottom: 4px;
+            }
+            
+            p {
+              font-size: 13px;
+              color: #666;
+              line-height: 1.4;
+              margin-bottom: 6px;
+            }
+            
+            .reward {
+              font-size: 13px;
+              color: #4CAF50;
+              font-weight: 600;
+            }
+          }
+        }
+      }
+    }
+    
+    // 邀请记录
+    .invite-records-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      .section-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: 16px;
+        
+        h4 {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+        }
+        
+        .total-count {
+          font-size: 13px;
+          color: #666;
+        }
+      }
+      
+      .records-tabs {
+        display: flex;
+        gap: 8px;
+        margin-bottom: 16px;
+        
+        .tab-btn {
+          background: #f8f9fa;
+          border: none;
+          border-radius: 20px;
+          padding: 8px 16px;
+          font-size: 13px;
+          color: #666;
+          cursor: pointer;
+          transition: all 0.3s;
+          
+          &.active {
+            background: #4CAF50;
+            color: white;
+          }
+          
+          &:hover:not(.active) {
+            background: #e9ecef;
+          }
+        }
+      }
+      
+      .records-list {
+        .record-item {
+          display: flex;
+          align-items: center;
+          gap: 12px;
+          padding: 12px 0;
+          border-bottom: 1px solid #f0f0f0;
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          .record-avatar {
+            width: 40px;
+            height: 40px;
+            border-radius: 50%;
+            overflow: hidden;
+            flex-shrink: 0;
+            
+            img {
+              width: 100%;
+              height: 100%;
+              object-fit: cover;
+            }
+            
+            .default-avatar {
+              width: 100%;
+              height: 100%;
+              background: #e9ecef;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              color: #999;
+              font-size: 16px;
+            }
+          }
+          
+          .record-info {
+            flex: 1;
+            
+            .record-name {
+              font-size: 15px;
+              font-weight: 500;
+              color: #333;
+              margin-bottom: 2px;
+            }
+            
+            .record-time {
+              font-size: 12px;
+              color: #999;
+              margin-bottom: 2px;
+            }
+            
+            .record-status {
+              font-size: 12px;
+              
+              &.success {
+                color: #4CAF50;
+              }
+              
+              &.pending {
+                color: #FF9800;
+              }
+              
+              &.expired {
+                color: #999;
+              }
+            }
+          }
+          
+          .record-reward {
+            text-align: right;
+            
+            .reward-points {
+              font-size: 16px;
+              font-weight: 600;
+              color: #4CAF50;
+            }
+            
+            .reward-label {
+              font-size: 12px;
+              color: #666;
+            }
+          }
+        }
+      }
+      
+      .empty-state {
+        text-align: center;
+        padding: 40px 20px;
+        color: #999;
+        
+        i {
+          font-size: 48px;
+          margin-bottom: 16px;
+          opacity: 0.5;
+        }
+        
+        p {
+          font-size: 14px;
+        }
+      }
+    }
+    
+    // 奖励统计
+    .reward-stats-section {
+      background: white;
+      border-radius: 16px;
+      padding: 20px;
+      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+      
+      h4 {
+        font-size: 16px;
+        font-weight: 600;
+        color: #333;
+        margin-bottom: 16px;
+      }
+      
+      .stats-grid {
+        display: grid;
+        grid-template-columns: repeat(2, 1fr);
+        gap: 16px;
+        
+        .stat-item {
+          text-align: center;
+          padding: 16px;
+          background: #f8f9fa;
+          border-radius: 12px;
+          
+          .stat-value {
+            font-size: 20px;
+            font-weight: 600;
+            color: #4CAF50;
+            margin-bottom: 4px;
+          }
+          
+          .stat-label {
+            font-size: 13px;
+            color: #666;
+          }
+        }
+      }
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 480px) {
+  .invite-friends-page {
+    .invite-content {
+      padding: 12px;
+      
+      .invite-code-section {
+        .invite-code-card {
+          flex-direction: column;
+          
+          .qr-code {
+            align-self: center;
+            flex-direction: row;
+            gap: 12px;
+          }
+        }
+      }
+      
+      .share-section {
+        .share-methods {
+          grid-template-columns: repeat(2, 1fr);
+          gap: 8px;
+          
+          .share-btn {
+            padding: 12px 8px;
+          }
+        }
+      }
+      
+      .reward-stats-section {
+        .stats-grid {
+          grid-template-columns: 1fr;
+          gap: 12px;
+        }
+      }
+    }
+  }
+}

+ 257 - 0
src/app/consumer/profile/invite-friends/invite-friends.ts

@@ -0,0 +1,257 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Router } from '@angular/router';
+
+interface InviteRecord {
+  id: string;
+  nickname: string;
+  avatar?: string;
+  inviteTime: Date;
+  status: 'pending' | 'success' | 'expired';
+  rewardPoints: number;
+  completedOrders: number;
+}
+
+type TabType = 'all' | 'success' | 'pending';
+
+@Component({
+  selector: 'app-invite-friends',
+  standalone: true,
+  imports: [CommonModule],
+  templateUrl: './invite-friends.html',
+  styleUrls: ['./invite-friends.scss']
+})
+export class InviteFriendsComponent implements OnInit {
+  
+  // 邀请码
+  inviteCode = 'RCY2024';
+  
+  // 当前选中的标签
+  activeTab: TabType = 'all';
+  
+  // 邀请记录
+  inviteRecords: InviteRecord[] = [
+    {
+      id: '1',
+      nickname: '环保小达人',
+      avatar: '',
+      inviteTime: new Date('2024-01-15'),
+      status: 'success',
+      rewardPoints: 35,
+      completedOrders: 3
+    },
+    {
+      id: '2',
+      nickname: '绿色生活家',
+      avatar: '',
+      inviteTime: new Date('2024-01-10'),
+      status: 'success',
+      rewardPoints: 25,
+      completedOrders: 1
+    },
+    {
+      id: '3',
+      nickname: '回收新手',
+      avatar: '',
+      inviteTime: new Date('2024-01-08'),
+      status: 'pending',
+      rewardPoints: 10,
+      completedOrders: 0
+    },
+    {
+      id: '4',
+      nickname: '地球守护者',
+      avatar: '',
+      inviteTime: new Date('2024-01-05'),
+      status: 'success',
+      rewardPoints: 45,
+      completedOrders: 5
+    },
+    {
+      id: '5',
+      nickname: '环保志愿者',
+      avatar: '',
+      inviteTime: new Date('2024-01-03'),
+      status: 'pending',
+      rewardPoints: 10,
+      completedOrders: 0
+    }
+  ];
+  
+  // 统计数据
+  totalInvites = 0;
+  totalRewardPoints = 0;
+  totalRewardCash = 0;
+  successfulInvites = 0;
+  thisMonthRewards = 0;
+  
+  constructor(private router: Router) {}
+  
+  ngOnInit() {
+    this.calculateStats();
+  }
+  
+  // 计算统计数据
+  calculateStats() {
+    this.totalInvites = this.inviteRecords.length;
+    this.successfulInvites = this.inviteRecords.filter(r => r.status === 'success').length;
+    this.totalRewardPoints = this.inviteRecords.reduce((sum, r) => sum + r.rewardPoints, 0);
+    this.totalRewardCash = Math.floor(this.totalRewardPoints / 100 * 10) / 10; // 100积分=1元
+    
+    // 计算本月奖励
+    const currentMonth = new Date().getMonth();
+    const currentYear = new Date().getFullYear();
+    this.thisMonthRewards = this.inviteRecords
+      .filter(r => {
+        const recordDate = new Date(r.inviteTime);
+        return recordDate.getMonth() === currentMonth && 
+               recordDate.getFullYear() === currentYear;
+      })
+      .reduce((sum, r) => sum + r.rewardPoints, 0);
+  }
+  
+  // 复制邀请码
+  copyInviteCode() {
+    navigator.clipboard.writeText(this.inviteCode).then(() => {
+      this.showAlert('邀请码已复制到剪贴板', 'success');
+    }).catch(() => {
+      // 降级方案
+      const textArea = document.createElement('textarea');
+      textArea.value = this.inviteCode;
+      document.body.appendChild(textArea);
+      textArea.select();
+      document.execCommand('copy');
+      document.body.removeChild(textArea);
+      this.showAlert('邀请码已复制到剪贴板', 'success');
+    });
+  }
+  
+  // 保存二维码
+  saveQRCode() {
+    this.showAlert('二维码保存功能开发中', 'info');
+  }
+  
+  // 分享到微信
+  shareToWeChat() {
+    const shareText = `我在使用一个很棒的回收应用,邀请你一起加入环保行动!使用我的邀请码 ${this.inviteCode} 注册,我们都能获得奖励哦!`;
+    this.shareContent(shareText, 'wechat');
+  }
+  
+  // 分享到QQ
+  shareToQQ() {
+    const shareText = `我在使用一个很棒的回收应用,邀请你一起加入环保行动!使用我的邀请码 ${this.inviteCode} 注册,我们都能获得奖励哦!`;
+    this.shareContent(shareText, 'qq');
+  }
+  
+  // 分享到微博
+  shareToWeibo() {
+    const shareText = `我在使用一个很棒的回收应用,邀请你一起加入环保行动!使用我的邀请码 ${this.inviteCode} 注册,我们都能获得奖励哦!#环保回收# #绿色生活#`;
+    this.shareContent(shareText, 'weibo');
+  }
+  
+  // 复制分享链接
+  shareLink() {
+    const shareLink = `https://recycle-app.com/invite?code=${this.inviteCode}`;
+    navigator.clipboard.writeText(shareLink).then(() => {
+      this.showAlert('邀请链接已复制到剪贴板', 'success');
+    }).catch(() => {
+      this.showAlert('复制失败,请手动复制', 'error');
+    });
+  }
+  
+  // 通用分享内容处理
+  private shareContent(text: string, platform: string) {
+    // 在实际应用中,这里会调用相应平台的分享API
+    this.showAlert(`正在打开${this.getPlatformName(platform)}分享`, 'info');
+  }
+  
+  // 获取平台名称
+  private getPlatformName(platform: string): string {
+    const names: { [key: string]: string } = {
+      'wechat': '微信',
+      'qq': 'QQ',
+      'weibo': '微博'
+    };
+    return names[platform] || platform;
+  }
+  
+  // 切换标签
+  switchTab(tab: TabType) {
+    this.activeTab = tab;
+  }
+  
+  // 获取过滤后的记录
+  getFilteredRecords(): InviteRecord[] {
+    switch (this.activeTab) {
+      case 'success':
+        return this.inviteRecords.filter(r => r.status === 'success');
+      case 'pending':
+        return this.inviteRecords.filter(r => r.status === 'pending');
+      default:
+        return this.inviteRecords;
+    }
+  }
+  
+  // 获取成功邀请数量
+  getSuccessCount(): number {
+    return this.inviteRecords.filter(r => r.status === 'success').length;
+  }
+  
+  // 获取待完成数量
+  getPendingCount(): number {
+    return this.inviteRecords.filter(r => r.status === 'pending').length;
+  }
+  
+  // 获取状态文本
+  getStatusText(status: string): string {
+    const statusMap: { [key: string]: string } = {
+      'success': '已完成首次回收',
+      'pending': '已注册,待首次回收',
+      'expired': '邀请已过期'
+    };
+    return statusMap[status] || status;
+  }
+  
+  // 格式化日期
+  formatDate(date: Date): string {
+    const now = new Date();
+    const diffTime = now.getTime() - date.getTime();
+    const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
+    
+    if (diffDays === 0) {
+      return '今天';
+    } else if (diffDays === 1) {
+      return '昨天';
+    } else if (diffDays < 7) {
+      return `${diffDays}天前`;
+    } else {
+      return date.toLocaleDateString('zh-CN', {
+        month: 'short',
+        day: 'numeric'
+      });
+    }
+  }
+  
+  // 获取空状态消息
+  getEmptyMessage(): string {
+    switch (this.activeTab) {
+      case 'success':
+        return '还没有成功的邀请记录';
+      case 'pending':
+        return '没有待完成的邀请';
+      default:
+        return '还没有邀请记录,快去邀请好友吧!';
+    }
+  }
+  
+  // 返回上一页
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+  
+  // 显示提示信息
+  private showAlert(message: string, type: 'success' | 'error' | 'info') {
+    // 简单的提示实现
+    alert(message);
+  }
+}

+ 159 - 0
src/app/consumer/profile/orders/orders.html

@@ -0,0 +1,159 @@
+<!-- 顶部标题栏 -->
+<div class="header">
+  <div class="back-btn" (click)="goBack()"><i class="fas fa-arrow-left"></i></div>
+  <div class="header-title">我的订单</div>
+</div>
+
+<div class="container">
+  <!-- 订单状态筛选 -->
+  <div class="filter-tabs">
+    <div 
+      *ngFor="let tab of filterTabs" 
+      class="filter-tab" 
+      [class.active]="tab.active"
+      (click)="selectTab(tab)">
+      {{tab.name}}
+      <span class="tab-count" *ngIf="tab.count > 0">({{tab.count}})</span>
+    </div>
+  </div>
+
+  <!-- 订单列表 -->
+  <div class="orders-list">
+    <div 
+      *ngFor="let order of filteredOrders" 
+      class="order-card"
+      (click)="showOrderDetail(order)">
+      
+      <div class="order-header">
+        <div class="order-info">
+          <div class="order-no">订单号:{{order.orderNo}}</div>
+          <div class="order-time">{{order.createTime}}</div>
+        </div>
+        <div class="order-status" [class]="'status-' + order.status">
+          {{getStatusText(order.status)}}
+        </div>
+      </div>
+      
+      <div class="order-content">
+        <div class="waste-info">
+          <div class="waste-icon">
+            <i [class]="order.wasteIcon"></i>
+          </div>
+          <div class="waste-details">
+            <div class="waste-category">{{order.wasteCategory}}</div>
+            <div class="waste-weight">重量:{{order.weight}}kg</div>
+            <div class="waste-address">地址:{{order.address}}</div>
+          </div>
+        </div>
+        
+        <div class="order-earnings">
+          <div class="cash-earning">
+            <span class="label">现金收益</span>
+            <span class="value">¥{{order.cashAmount}}</span>
+          </div>
+          <div class="points-earning">
+            <span class="label">积分收益</span>
+            <span class="value">{{order.pointsAmount}}积分</span>
+          </div>
+        </div>
+      </div>
+      
+      <div class="order-actions">
+        <button 
+          *ngIf="order.status === 'pending'" 
+          class="action-btn cancel"
+          (click)="cancelOrder(order, $event)">
+          取消订单
+        </button>
+        <button 
+          *ngIf="order.status === 'completed'" 
+          class="action-btn rate"
+          (click)="rateOrder(order, $event)">
+          评价
+        </button>
+        <button 
+          class="action-btn detail"
+          (click)="showOrderDetail(order)">
+          查看详情
+        </button>
+      </div>
+    </div>
+    
+    <!-- 空状态 -->
+    <div class="empty-state" *ngIf="filteredOrders.length === 0">
+      <div class="empty-icon">
+        <i class="fas fa-clipboard-list"></i>
+      </div>
+      <div class="empty-text">暂无相关订单</div>
+      <button class="empty-action" (click)="goToBooking()">立即预约回收</button>
+    </div>
+  </div>
+</div>
+
+<!-- 订单详情模态框 -->
+<div class="modal" [style.display]="showDetailModal ? 'flex' : 'none'" (click)="closeModal($event)">
+  <div class="modal-content order-detail-modal">
+    <div class="modal-header">
+      <div class="modal-title">订单详情</div>
+      <div class="modal-close" (click)="showDetailModal = false">
+        <i class="fas fa-times"></i>
+      </div>
+    </div>
+    
+    <div class="modal-body" *ngIf="selectedOrder">
+      <div class="detail-section">
+        <div class="section-title">订单信息</div>
+        <div class="detail-item">
+          <span class="label">订单号:</span>
+          <span class="value">{{selectedOrder.orderNo}}</span>
+        </div>
+        <div class="detail-item">
+          <span class="label">下单时间:</span>
+          <span class="value">{{selectedOrder.createTime}}</span>
+        </div>
+        <div class="detail-item">
+          <span class="label">订单状态:</span>
+          <span class="value status" [class]="'status-' + selectedOrder.status">
+            {{getStatusText(selectedOrder.status)}}
+          </span>
+        </div>
+      </div>
+      
+      <div class="detail-section">
+        <div class="section-title">废品信息</div>
+        <div class="detail-item">
+          <span class="label">废品类型:</span>
+          <span class="value">{{selectedOrder.wasteCategory}}</span>
+        </div>
+        <div class="detail-item">
+          <span class="label">重量:</span>
+          <span class="value">{{selectedOrder.weight}}kg</span>
+        </div>
+        <div class="detail-item">
+          <span class="label">回收地址:</span>
+          <span class="value">{{selectedOrder.address}}</span>
+        </div>
+        <div class="detail-item" *ngIf="selectedOrder.collector">
+          <span class="label">回收员:</span>
+          <span class="value">{{selectedOrder.collector}}</span>
+        </div>
+      </div>
+      
+      <div class="detail-section">
+        <div class="section-title">收益明细</div>
+        <div class="detail-item">
+          <span class="label">现金收益:</span>
+          <span class="value cash">¥{{selectedOrder.cashAmount}}</span>
+        </div>
+        <div class="detail-item">
+          <span class="label">积分收益:</span>
+          <span class="value points">{{selectedOrder.pointsAmount}}积分</span>
+        </div>
+        <div class="detail-item">
+          <span class="label">碳减排:</span>
+          <span class="value carbon">{{selectedOrder.carbonReduction}}kg</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 454 - 0
src/app/consumer/profile/orders/orders.scss

@@ -0,0 +1,454 @@
+// 全局重置
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+// 顶部标题栏
+.header {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 56px;
+  background: #2e7d32;
+  color: white;
+  position: relative;
+  
+  .back-btn {
+    position: absolute;
+    left: 16px;
+    width: 40px;
+    height: 40px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 50%;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      background: rgba(255, 255, 255, 0.1);
+    }
+    
+    i {
+      font-size: 18px;
+    }
+  }
+  
+  .header-title {
+    font-size: 18px;
+    font-weight: 600;
+  }
+}
+
+// 容器
+.container {
+  padding: 16px;
+  min-height: calc(100vh - 56px);
+  background: #f5f5f5;
+}
+
+// 筛选标签
+.filter-tabs {
+  display: flex;
+  background: white;
+  border-radius: 12px;
+  padding: 8px;
+  margin-bottom: 16px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  overflow-x: auto;
+  
+  .filter-tab {
+    flex: 1;
+    min-width: 80px;
+    padding: 12px 16px;
+    text-align: center;
+    border-radius: 8px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    font-size: 14px;
+    color: #666;
+    white-space: nowrap;
+    
+    &.active {
+      background: #2e7d32;
+      color: white;
+    }
+    
+    &:not(.active):hover {
+      background: #f0f0f0;
+    }
+    
+    .tab-count {
+      font-size: 12px;
+      margin-left: 4px;
+      opacity: 0.8;
+    }
+  }
+}
+
+// 订单列表
+.orders-list {
+  .order-card {
+    background: white;
+    border-radius: 12px;
+    padding: 16px;
+    margin-bottom: 12px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+    }
+    
+    .order-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: flex-start;
+      margin-bottom: 12px;
+      
+      .order-info {
+        .order-no {
+          font-size: 14px;
+          color: #333;
+          font-weight: 600;
+          margin-bottom: 4px;
+        }
+        
+        .order-time {
+          font-size: 12px;
+          color: #999;
+        }
+      }
+      
+      .order-status {
+        padding: 4px 12px;
+        border-radius: 12px;
+        font-size: 12px;
+        font-weight: 600;
+        
+        &.status-pending {
+          background: #fff3cd;
+          color: #856404;
+        }
+        
+        &.status-processing {
+          background: #cce5ff;
+          color: #0066cc;
+        }
+        
+        &.status-completed {
+          background: #d4edda;
+          color: #155724;
+        }
+        
+        &.status-cancelled {
+          background: #f8d7da;
+          color: #721c24;
+        }
+      }
+    }
+    
+    .order-content {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 12px;
+      
+      .waste-info {
+        display: flex;
+        align-items: center;
+        flex: 1;
+        
+        .waste-icon {
+          width: 48px;
+          height: 48px;
+          background: #e8f5e8;
+          border-radius: 12px;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          margin-right: 12px;
+          
+          i {
+            font-size: 20px;
+            color: #2e7d32;
+          }
+        }
+        
+        .waste-details {
+          .waste-category {
+            font-size: 16px;
+            color: #333;
+            font-weight: 600;
+            margin-bottom: 4px;
+          }
+          
+          .waste-weight, .waste-address {
+            font-size: 12px;
+            color: #666;
+            margin-bottom: 2px;
+          }
+          
+          .waste-address {
+            max-width: 200px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+          }
+        }
+      }
+      
+      .order-earnings {
+        text-align: right;
+        
+        .cash-earning, .points-earning {
+          display: flex;
+          align-items: center;
+          justify-content: flex-end;
+          margin-bottom: 4px;
+          
+          .label {
+            font-size: 12px;
+            color: #666;
+            margin-right: 8px;
+          }
+          
+          .value {
+            font-size: 14px;
+            font-weight: 600;
+            color: #2e7d32;
+          }
+        }
+      }
+    }
+    
+    .order-actions {
+      display: flex;
+      justify-content: flex-end;
+      gap: 8px;
+      
+      .action-btn {
+        padding: 8px 16px;
+        border: none;
+        border-radius: 20px;
+        font-size: 12px;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &.cancel {
+          background: #f8d7da;
+          color: #721c24;
+          
+          &:hover {
+            background: #f5c6cb;
+          }
+        }
+        
+        &.rate {
+          background: #fff3cd;
+          color: #856404;
+          
+          &:hover {
+            background: #ffeaa7;
+          }
+        }
+        
+        &.detail {
+          background: #e8f5e8;
+          color: #2e7d32;
+          
+          &:hover {
+            background: #d4edda;
+          }
+        }
+      }
+    }
+  }
+}
+
+// 空状态
+.empty-state {
+  text-align: center;
+  padding: 60px 20px;
+  
+  .empty-icon {
+    margin-bottom: 16px;
+    
+    i {
+      font-size: 64px;
+      color: #ccc;
+    }
+  }
+  
+  .empty-text {
+    font-size: 16px;
+    color: #666;
+    margin-bottom: 24px;
+  }
+  
+  .empty-action {
+    background: #2e7d32;
+    color: white;
+    border: none;
+    padding: 12px 24px;
+    border-radius: 24px;
+    font-size: 14px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    
+    &:hover {
+      background: #1b5e20;
+      transform: translateY(-2px);
+    }
+  }
+}
+
+// 模态框
+.modal {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1000;
+  
+  .modal-content {
+    background: white;
+    border-radius: 16px;
+    width: 90%;
+    max-width: 500px;
+    max-height: 80vh;
+    overflow: hidden;
+    
+    .modal-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20px;
+      border-bottom: 1px solid #eee;
+      
+      .modal-title {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+      }
+      
+      .modal-close {
+        width: 32px;
+        height: 32px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 50%;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        
+        &:hover {
+          background: #f0f0f0;
+        }
+        
+        i {
+          font-size: 16px;
+          color: #666;
+        }
+      }
+    }
+    
+    .modal-body {
+      padding: 20px;
+      max-height: 60vh;
+      overflow-y: auto;
+      
+      .detail-section {
+        margin-bottom: 24px;
+        
+        &:last-child {
+          margin-bottom: 0;
+        }
+        
+        .section-title {
+          font-size: 16px;
+          font-weight: 600;
+          color: #333;
+          margin-bottom: 12px;
+          padding-bottom: 8px;
+          border-bottom: 2px solid #2e7d32;
+        }
+        
+        .detail-item {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          padding: 8px 0;
+          border-bottom: 1px solid #f0f0f0;
+          
+          &:last-child {
+            border-bottom: none;
+          }
+          
+          .label {
+            font-size: 14px;
+            color: #666;
+            flex-shrink: 0;
+          }
+          
+          .value {
+            font-size: 14px;
+            color: #333;
+            text-align: right;
+            
+            &.status {
+              padding: 2px 8px;
+              border-radius: 8px;
+              font-size: 12px;
+              font-weight: 600;
+              
+              &.status-pending {
+                background: #fff3cd;
+                color: #856404;
+              }
+              
+              &.status-processing {
+                background: #cce5ff;
+                color: #0066cc;
+              }
+              
+              &.status-completed {
+                background: #d4edda;
+                color: #155724;
+              }
+              
+              &.status-cancelled {
+                background: #f8d7da;
+                color: #721c24;
+              }
+            }
+            
+            &.cash {
+              color: #2e7d32;
+              font-weight: 600;
+            }
+            
+            &.points {
+              color: #ff9800;
+              font-weight: 600;
+            }
+            
+            &.carbon {
+              color: #4caf50;
+              font-weight: 600;
+            }
+          }
+        }
+      }
+    }
+  }
+}

+ 212 - 0
src/app/consumer/profile/orders/orders.ts

@@ -0,0 +1,212 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Router } from '@angular/router';
+
+interface Order {
+  id: string;
+  orderNo: string;
+  createTime: string;
+  status: 'pending' | 'processing' | 'completed' | 'cancelled';
+  wasteCategory: string;
+  wasteIcon: string;
+  weight: number;
+  address: string;
+  collector?: string;
+  cashAmount: number;
+  pointsAmount: number;
+  carbonReduction: number;
+}
+
+interface FilterTab {
+  id: string;
+  name: string;
+  active: boolean;
+  count: number;
+}
+
+@Component({
+  selector: 'app-orders',
+  standalone: true,
+  imports: [CommonModule],
+  templateUrl: './orders.html',
+  styleUrls: ['./orders.scss']
+})
+export class OrdersComponent implements OnInit {
+  
+  // 筛选标签
+  filterTabs: FilterTab[] = [
+    { id: 'all', name: '全部', active: true, count: 0 },
+    { id: 'pending', name: '待处理', active: false, count: 0 },
+    { id: 'processing', name: '处理中', active: false, count: 0 },
+    { id: 'completed', name: '已完成', active: false, count: 0 },
+    { id: 'cancelled', name: '已取消', active: false, count: 0 }
+  ];
+  
+  // 订单数据
+  orders: Order[] = [
+    {
+      id: '1',
+      orderNo: 'RC202401150001',
+      createTime: '2024-01-15 14:30',
+      status: 'completed',
+      wasteCategory: '废纸回收',
+      wasteIcon: 'fas fa-newspaper',
+      weight: 5.2,
+      address: '北京市朝阳区建国路88号SOHO现代城',
+      collector: '张师傅',
+      cashAmount: 25.60,
+      pointsAmount: 128,
+      carbonReduction: 2.5
+    },
+    {
+      id: '2',
+      orderNo: 'RC202401140002',
+      createTime: '2024-01-14 10:15',
+      status: 'completed',
+      wasteCategory: '塑料瓶回收',
+      wasteIcon: 'fas fa-wine-bottle',
+      weight: 3.7,
+      address: '北京市朝阳区建国路88号SOHO现代城',
+      collector: '李师傅',
+      cashAmount: 18.40,
+      pointsAmount: 92,
+      carbonReduction: 1.8
+    },
+    {
+      id: '3',
+      orderNo: 'RC202401130003',
+      createTime: '2024-01-13 16:45',
+      status: 'processing',
+      wasteCategory: '金属回收',
+      wasteIcon: 'fas fa-cog',
+      weight: 2.8,
+      address: '北京市朝阳区建国路88号SOHO现代城',
+      collector: '王师傅',
+      cashAmount: 45.20,
+      pointsAmount: 226,
+      carbonReduction: 4.5
+    },
+    {
+      id: '4',
+      orderNo: 'RC202401120004',
+      createTime: '2024-01-12 09:20',
+      status: 'pending',
+      wasteCategory: '电子设备回收',
+      wasteIcon: 'fas fa-mobile-alt',
+      weight: 1.5,
+      address: '北京市朝阳区建国路88号SOHO现代城',
+      cashAmount: 120.00,
+      pointsAmount: 600,
+      carbonReduction: 12.0
+    },
+    {
+      id: '5',
+      orderNo: 'RC202401110005',
+      createTime: '2024-01-11 13:10',
+      status: 'cancelled',
+      wasteCategory: '纺织品回收',
+      wasteIcon: 'fas fa-tshirt',
+      weight: 4.1,
+      address: '北京市朝阳区建国路88号SOHO现代城',
+      cashAmount: 32.80,
+      pointsAmount: 164,
+      carbonReduction: 3.3
+    }
+  ];
+  
+  filteredOrders: Order[] = [];
+  selectedOrder: Order | null = null;
+  showDetailModal = false;
+  
+  constructor(private router: Router) {}
+  
+  ngOnInit() {
+    this.updateFilterCounts();
+    this.applyFilter();
+  }
+  
+  // 更新筛选标签计数
+  updateFilterCounts() {
+    this.filterTabs.forEach(tab => {
+      if (tab.id === 'all') {
+        tab.count = this.orders.length;
+      } else {
+        tab.count = this.orders.filter(order => order.status === tab.id).length;
+      }
+    });
+  }
+  
+  // 选择筛选标签
+  selectTab(selectedTab: FilterTab) {
+    this.filterTabs.forEach(tab => tab.active = false);
+    selectedTab.active = true;
+    this.applyFilter();
+  }
+  
+  // 应用筛选
+  applyFilter() {
+    const activeTab = this.filterTabs.find(tab => tab.active);
+    if (activeTab?.id === 'all') {
+      this.filteredOrders = [...this.orders];
+    } else {
+      this.filteredOrders = this.orders.filter(order => order.status === activeTab?.id);
+    }
+  }
+  
+  // 获取状态文本
+  getStatusText(status: string): string {
+    const statusMap: { [key: string]: string } = {
+      'pending': '待处理',
+      'processing': '处理中',
+      'completed': '已完成',
+      'cancelled': '已取消'
+    };
+    return statusMap[status] || status;
+  }
+  
+  // 显示订单详情
+  showOrderDetail(order: Order) {
+    this.selectedOrder = order;
+    this.showDetailModal = true;
+  }
+  
+  // 取消订单
+  cancelOrder(order: Order, event: Event) {
+    event.stopPropagation();
+    if (confirm('确定要取消这个订单吗?')) {
+      order.status = 'cancelled';
+      this.updateFilterCounts();
+      this.applyFilter();
+      this.showAlert('订单已取消', 'success');
+    }
+  }
+  
+  // 评价订单
+  rateOrder(order: Order, event: Event) {
+    event.stopPropagation();
+    this.showAlert('评价功能开发中', 'info');
+  }
+  
+  // 关闭模态框
+  closeModal(event: Event) {
+    if (event.target === event.currentTarget) {
+      this.showDetailModal = false;
+    }
+  }
+  
+  // 跳转到预约回收
+  goToBooking() {
+    this.router.navigate(['/consumer/booking-recycle']);
+  }
+  
+  // 返回上一页
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+  
+  // 显示提示信息
+  private showAlert(message: string, type: 'success' | 'error' | 'info') {
+    // 简单的提示实现
+    alert(message);
+  }
+}

+ 247 - 0
src/app/consumer/profile/privacy-policy/privacy-policy.html

@@ -0,0 +1,247 @@
+<div class="privacy-policy-page">
+  <!-- 头部 -->
+  <div class="header">
+    <button class="back-btn" (click)="goBack()">
+      <i class="fas fa-arrow-left"></i>
+    </button>
+    <span class="title">隐私政策</span>
+  </div>
+
+  <div class="policy-content">
+    <!-- 政策标题 -->
+    <div class="policy-header">
+      <h1>绿色回收隐私政策</h1>
+      <div class="update-info">
+        <span class="update-date">更新日期:{{ updateDate }}</span>
+        <span class="effective-date">生效日期:{{ effectiveDate }}</span>
+      </div>
+    </div>
+
+    <!-- 政策内容 -->
+    <div class="policy-sections">
+      <!-- 引言 -->
+      <div class="section">
+        <h3>引言</h3>
+        <div class="content">
+          <p>绿色回收科技有限公司(以下简称"我们")深知个人信息对您的重要性,并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任,恪守以下原则,保护您的个人信息:权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公开透明原则等。</p>
+          <p>本隐私政策适用于您使用绿色回收提供的所有产品和服务。</p>
+        </div>
+      </div>
+
+      <!-- 第一部分:我们收集的信息 -->
+      <div class="section">
+        <h3>第一部分 我们收集的信息</h3>
+        <div class="content">
+          <p>为了向您提供更好的服务,我们可能会收集以下信息:</p>
+          
+          <h4>1.1 您主动提供的信息</h4>
+          <ul>
+            <li>注册信息:手机号码、昵称、头像等</li>
+            <li>身份信息:实名认证时的姓名、身份证号等</li>
+            <li>联系信息:收货地址、联系电话等</li>
+            <li>回收信息:回收物品类型、数量、照片等</li>
+            <li>反馈信息:客服咨询、意见反馈等</li>
+          </ul>
+
+          <h4>1.2 我们自动收集的信息</h4>
+          <ul>
+            <li>设备信息:设备型号、操作系统、唯一设备标识符等</li>
+            <li>位置信息:GPS位置、IP地址等(需要您的授权)</li>
+            <li>使用信息:访问时间、使用功能、操作记录等</li>
+            <li>网络信息:网络类型、运营商信息等</li>
+          </ul>
+
+          <h4>1.3 第三方提供的信息</h4>
+          <ul>
+            <li>第三方登录:微信、QQ等第三方平台授权的基本信息</li>
+            <li>支付信息:第三方支付平台提供的交易信息</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第二部分:信息使用目的 -->
+      <div class="section">
+        <h3>第二部分 信息使用目的</h3>
+        <div class="content">
+          <p>我们收集和使用您的个人信息主要用于以下目的:</p>
+          
+          <h4>2.1 提供服务</h4>
+          <ul>
+            <li>用户注册和身份验证</li>
+            <li>回收服务预约和配送</li>
+            <li>积分奖励和兑换</li>
+            <li>客户服务和技术支持</li>
+          </ul>
+
+          <h4>2.2 改善服务</h4>
+          <ul>
+            <li>分析用户使用习惯,优化产品功能</li>
+            <li>进行数据统计和分析</li>
+            <li>开发新的产品和服务</li>
+          </ul>
+
+          <h4>2.3 安全保障</h4>
+          <ul>
+            <li>防范安全风险,保护账户安全</li>
+            <li>检测和防止欺诈行为</li>
+            <li>遵守法律法规要求</li>
+          </ul>
+
+          <h4>2.4 营销推广</h4>
+          <ul>
+            <li>向您推送相关活动信息(需要您的同意)</li>
+            <li>个性化推荐服务</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第三部分:信息共享和披露 -->
+      <div class="section">
+        <h3>第三部分 信息共享和披露</h3>
+        <div class="content">
+          <p>我们不会向第三方出售、出租或以其他方式披露您的个人信息,除非:</p>
+          
+          <h4>3.1 获得您的明确同意</h4>
+          <p>在获得您的明确同意后,我们会与第三方共享您的个人信息。</p>
+
+          <h4>3.2 服务提供商</h4>
+          <p>我们可能会与以下服务提供商共享必要信息:</p>
+          <ul>
+            <li>物流配送服务商:为完成回收服务</li>
+            <li>支付服务商:为完成支付交易</li>
+            <li>云服务提供商:为存储和处理数据</li>
+            <li>数据分析服务商:为改善服务质量</li>
+          </ul>
+
+          <h4>3.3 法律要求</h4>
+          <p>在以下情况下,我们可能会披露您的个人信息:</p>
+          <ul>
+            <li>遵守适用的法律法规</li>
+            <li>遵守法院命令或其他法律程序</li>
+            <li>遵守相关政府机关的要求</li>
+            <li>为维护我们的合法权益</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第四部分:信息存储和保护 -->
+      <div class="section">
+        <h3>第四部分 信息存储和保护</h3>
+        <div class="content">
+          <h4>4.1 存储地点</h4>
+          <p>您的个人信息将存储在中华人民共和国境内。如需跨境传输,我们将严格按照法律法规要求执行。</p>
+
+          <h4>4.2 存储期限</h4>
+          <p>我们仅在为实现本政策所述目的所需的期间内保留您的个人信息:</p>
+          <ul>
+            <li>账户信息:账户存续期间</li>
+            <li>交易记录:交易完成后5年</li>
+            <li>日志信息:6个月</li>
+          </ul>
+
+          <h4>4.3 安全措施</h4>
+          <p>我们采用多种安全措施保护您的个人信息:</p>
+          <ul>
+            <li>数据加密:采用SSL等加密技术</li>
+            <li>访问控制:严格限制数据访问权限</li>
+            <li>安全审计:定期进行安全评估</li>
+            <li>员工培训:对员工进行隐私保护培训</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第五部分:您的权利 -->
+      <div class="section">
+        <h3>第五部分 您的权利</h3>
+        <div class="content">
+          <p>根据相关法律法规,您享有以下权利:</p>
+          
+          <h4>5.1 访问权</h4>
+          <p>您有权了解我们收集、使用您个人信息的情况,并可以通过应用内设置查看您的个人信息。</p>
+
+          <h4>5.2 更正权</h4>
+          <p>当您发现我们处理的关于您的个人信息有错误时,您有权要求我们做出更正。</p>
+
+          <h4>5.3 删除权</h4>
+          <p>在以下情形中,您可以要求我们删除个人信息:</p>
+          <ul>
+            <li>处理目的已实现、无法实现或为实现处理目的不再必要</li>
+            <li>我们停止提供产品或服务,或保存期限已届满</li>
+            <li>您撤回同意</li>
+            <li>我们违法处理您的个人信息</li>
+          </ul>
+
+          <h4>5.4 撤回同意权</h4>
+          <p>您可以通过应用内设置或联系我们撤回您此前给予的同意。</p>
+
+          <h4>5.5 注销权</h4>
+          <p>您可以通过应用内设置或联系客服注销您的账户。</p>
+        </div>
+      </div>
+
+      <!-- 第六部分:未成年人保护 -->
+      <div class="section">
+        <h3>第六部分 未成年人保护</h3>
+        <div class="content">
+          <p>我们非常重视对未成年人个人信息的保护:</p>
+          <ul>
+            <li>我们不会主动收集未满14周岁儿童的个人信息</li>
+            <li>如果您是14周岁以下的儿童,请在监护人指导下使用我们的服务</li>
+            <li>如果您是未成年人的监护人,当您对您所监护的未成年人的个人信息处理存在疑问时,请联系我们</li>
+            <li>如果我们发现自己在未事先获得可证实的监护人同意的情况下收集了未满14周岁儿童的个人信息,则会设法尽快删除相关数据</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第七部分:政策更新 -->
+      <div class="section">
+        <h3>第七部分 政策更新</h3>
+        <div class="content">
+          <p>我们可能会适时更新本隐私政策:</p>
+          <ul>
+            <li>当更新后的政策可能对您的权利产生重大影响时,我们会在生效前通过应用内通知、弹窗提醒等方式告知您</li>
+            <li>对于重大变更,我们还会提供更为显著的通知</li>
+            <li>如果您不同意修改后的隐私政策,您可以停止使用我们的服务</li>
+            <li>如果您继续使用我们的服务,即表示您接受修改后的隐私政策</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第八部分:适用范围 -->
+      <div class="section">
+        <h3>第八部分 适用范围</h3>
+        <div class="content">
+          <p>本隐私政策适用于绿色回收提供的所有服务,包括:</p>
+          <ul>
+            <li>绿色回收移动应用程序</li>
+            <li>绿色回收官方网站</li>
+            <li>绿色回收微信小程序</li>
+            <li>其他绿色回收提供的产品和服务</li>
+          </ul>
+          <p>本隐私政策不适用于第三方提供的产品和服务,请您仔细阅读第三方的隐私政策。</p>
+        </div>
+      </div>
+    </div>
+
+    <!-- 联系我们 -->
+    <div class="contact-section">
+      <h3>联系我们</h3>
+      <div class="contact-info">
+        <p>如果您对本隐私政策有任何疑问、意见或建议,请通过以下方式联系我们:</p>
+        <ul>
+          <li>客服电话:400-888-6666</li>
+          <li>客服邮箱:privacy@recycle-app.com</li>
+          <li>公司地址:北京市朝阳区环保科技园区</li>
+          <li>邮政编码:100000</li>
+        </ul>
+        <p>我们将在15个工作日内回复您的请求。</p>
+      </div>
+    </div>
+
+    <!-- 同意按钮 -->
+    <div class="policy-actions" *ngIf="showActions">
+      <button class="disagree-btn" (click)="disagree()">不同意</button>
+      <button class="agree-btn" (click)="agree()">同意并继续</button>
+    </div>
+  </div>
+</div>

+ 409 - 0
src/app/consumer/profile/privacy-policy/privacy-policy.scss

@@ -0,0 +1,409 @@
+.privacy-policy-page {
+  min-height: 100vh;
+  background: #f8f9fa;
+
+  .header {
+    display: flex;
+    align-items: center;
+    padding: 12px 16px;
+    background: #fff;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    position: sticky;
+    top: 0;
+    z-index: 100;
+
+    .back-btn {
+      background: none;
+      border: none;
+      font-size: 18px;
+      color: #333;
+      padding: 8px;
+      margin-right: 12px;
+      border-radius: 50%;
+      transition: background-color 0.3s;
+
+      &:hover {
+        background-color: #f0f0f0;
+      }
+    }
+
+    .title {
+      font-size: 18px;
+      font-weight: 600;
+      color: #333;
+    }
+  }
+
+  .policy-content {
+    padding: 20px 16px;
+    max-width: 800px;
+    margin: 0 auto;
+
+    // 政策标题
+    .policy-header {
+      background: #fff;
+      border-radius: 12px;
+      padding: 24px;
+      margin-bottom: 20px;
+      text-align: center;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+      h1 {
+        font-size: 24px;
+        font-weight: 700;
+        color: #333;
+        margin: 0 0 16px;
+        line-height: 1.3;
+      }
+
+      .update-info {
+        display: flex;
+        justify-content: center;
+        gap: 20px;
+        font-size: 14px;
+        color: #666;
+
+        .update-date,
+        .effective-date {
+          padding: 6px 12px;
+          background: #f8f9fa;
+          border-radius: 16px;
+          border: 1px solid #e0e0e0;
+        }
+      }
+    }
+
+    // 政策章节
+    .policy-sections {
+      .section {
+        background: #fff;
+        border-radius: 12px;
+        padding: 24px;
+        margin-bottom: 16px;
+        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+        h3 {
+          font-size: 18px;
+          font-weight: 600;
+          color: #333;
+          margin: 0 0 16px;
+          padding-bottom: 8px;
+          border-bottom: 2px solid #2196F3;
+          display: inline-block;
+        }
+
+        h4 {
+          font-size: 16px;
+          font-weight: 600;
+          color: #444;
+          margin: 16px 0 8px;
+          
+          &:first-of-type {
+            margin-top: 0;
+          }
+        }
+
+        .content {
+          line-height: 1.8;
+
+          p {
+            font-size: 14px;
+            color: #555;
+            margin: 0 0 12px;
+            text-align: justify;
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+          }
+
+          ul {
+            margin: 12px 0;
+            padding-left: 20px;
+
+            li {
+              font-size: 14px;
+              color: #555;
+              margin-bottom: 8px;
+              line-height: 1.6;
+
+              &:last-child {
+                margin-bottom: 0;
+              }
+            }
+          }
+
+          // 强调文本
+          strong {
+            color: #333;
+            font-weight: 600;
+          }
+
+          // 重要提示
+          .highlight {
+            background: #e3f2fd;
+            border: 1px solid #90caf9;
+            border-radius: 6px;
+            padding: 12px;
+            margin: 12px 0;
+            font-size: 14px;
+            color: #1565c0;
+          }
+
+          // 警告信息
+          .warning {
+            background: #fff3e0;
+            border: 1px solid #ffb74d;
+            border-radius: 6px;
+            padding: 12px;
+            margin: 12px 0;
+            font-size: 14px;
+            color: #ef6c00;
+          }
+        }
+      }
+    }
+
+    // 联系信息
+    .contact-section {
+      background: #fff;
+      border-radius: 12px;
+      padding: 24px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+      h3 {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+        margin: 0 0 16px;
+        padding-bottom: 8px;
+        border-bottom: 2px solid #FF9800;
+        display: inline-block;
+      }
+
+      .contact-info {
+        p {
+          font-size: 14px;
+          color: #555;
+          margin: 0 0 12px;
+          line-height: 1.6;
+        }
+
+        ul {
+          margin: 12px 0;
+          padding-left: 20px;
+
+          li {
+            font-size: 14px;
+            color: #555;
+            margin-bottom: 8px;
+            line-height: 1.6;
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+          }
+        }
+      }
+    }
+
+    // 同意按钮区域
+    .policy-actions {
+      display: flex;
+      gap: 12px;
+      padding: 20px 0;
+      position: sticky;
+      bottom: 0;
+      background: #f8f9fa;
+      margin: 0 -16px -20px;
+      padding: 20px 16px;
+      border-top: 1px solid #e0e0e0;
+
+      .disagree-btn,
+      .agree-btn {
+        flex: 1;
+        height: 48px;
+        border: none;
+        border-radius: 24px;
+        font-size: 16px;
+        font-weight: 600;
+        transition: all 0.3s;
+
+        &:active {
+          transform: scale(0.98);
+        }
+      }
+
+      .disagree-btn {
+        background: #fff;
+        color: #666;
+        border: 1px solid #ddd;
+
+        &:hover {
+          background: #f5f5f5;
+          border-color: #ccc;
+        }
+      }
+
+      .agree-btn {
+        background: linear-gradient(135deg, #2196F3, #1976D2);
+        color: #fff;
+        box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);
+
+        &:hover {
+          box-shadow: 0 6px 16px rgba(33, 150, 243, 0.4);
+          transform: translateY(-1px);
+        }
+      }
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 768px) {
+  .privacy-policy-page {
+    .policy-content {
+      padding: 16px 12px;
+
+      .policy-header {
+        padding: 20px 16px;
+
+        h1 {
+          font-size: 20px;
+        }
+
+        .update-info {
+          flex-direction: column;
+          gap: 8px;
+
+          .update-date,
+          .effective-date {
+            font-size: 13px;
+          }
+        }
+      }
+
+      .policy-sections {
+        .section {
+          padding: 20px 16px;
+
+          h3 {
+            font-size: 16px;
+          }
+
+          h4 {
+            font-size: 15px;
+          }
+
+          .content {
+            p,
+            li {
+              font-size: 13px;
+            }
+          }
+        }
+      }
+
+      .contact-section {
+        padding: 20px 16px;
+
+        h3 {
+          font-size: 16px;
+        }
+
+        .contact-info {
+          p,
+          li {
+            font-size: 13px;
+          }
+        }
+      }
+
+      .policy-actions {
+        padding: 16px 12px;
+        margin: 0 -12px -16px;
+
+        .disagree-btn,
+        .agree-btn {
+          height: 44px;
+          font-size: 15px;
+        }
+      }
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .privacy-policy-page {
+    .policy-content {
+      padding: 12px 8px;
+
+      .policy-header {
+        padding: 16px 12px;
+        margin-bottom: 16px;
+
+        h1 {
+          font-size: 18px;
+        }
+      }
+
+      .policy-sections {
+        .section {
+          padding: 16px 12px;
+          margin-bottom: 12px;
+
+          h3 {
+            font-size: 15px;
+            margin-bottom: 12px;
+          }
+
+          h4 {
+            font-size: 14px;
+            margin: 12px 0 6px;
+          }
+        }
+      }
+
+      .contact-section {
+        padding: 16px 12px;
+      }
+
+      .policy-actions {
+        padding: 12px 8px;
+        margin: 0 -8px -12px;
+
+        .disagree-btn,
+        .agree-btn {
+          height: 40px;
+          font-size: 14px;
+        }
+      }
+    }
+  }
+}
+
+// 打印样式
+@media print {
+  .privacy-policy-page {
+    .header {
+      display: none;
+    }
+
+    .policy-actions {
+      display: none;
+    }
+
+    .policy-content {
+      padding: 0;
+      max-width: none;
+
+      .policy-sections .section,
+      .contact-section {
+        box-shadow: none;
+        border: 1px solid #ddd;
+        page-break-inside: avoid;
+      }
+    }
+  }
+}

+ 82 - 0
src/app/consumer/profile/privacy-policy/privacy-policy.ts

@@ -0,0 +1,82 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-privacy-policy',
+  standalone: true,
+  imports: [CommonModule],
+  templateUrl: './privacy-policy.html',
+  styleUrls: ['./privacy-policy.scss']
+})
+export class PrivacyPolicyPage implements OnInit {
+  // 政策信息
+  updateDate = '2024年1月15日';
+  effectiveDate = '2024年1月20日';
+  
+  // 是否显示同意/不同意按钮(用于注册流程)
+  showActions = false;
+  
+  // 来源页面(用于判断是否来自注册流程)
+  fromPage = '';
+
+  constructor(
+    private router: Router
+  ) {}
+
+  ngOnInit() {
+    // 可以从路由参数获取信息
+    // this.fromPage = this.route.snapshot.queryParams['from'] || '';
+    // this.showActions = this.fromPage === 'register';
+  }
+
+  /**
+   * 返回上一页
+   */
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+
+  /**
+   * 用户同意政策
+   */
+  agree() {
+    if (this.fromPage === 'register') {
+      // 如果是从注册页面来的,返回注册页面并传递同意状态
+      this.router.navigate(['/register'], { queryParams: { privacyAgreed: 'true' } });
+    } else {
+      this.showAlert('感谢您同意我们的隐私政策!');
+    }
+  }
+
+  /**
+   * 用户不同意政策
+   */
+  disagree() {
+    if (this.fromPage === 'register') {
+      if (confirm('不同意隐私政策将无法完成注册,确定要返回吗?')) {
+        this.router.navigate(['/register']);
+      }
+    } else {
+      this.showAlert('您选择了不同意隐私政策。');
+    }
+  }
+
+  // 滚动到顶部
+  scrollToTop() {
+    window.scrollTo({ top: 0, behavior: 'smooth' });
+  }
+
+  // 滚动到指定章节
+  scrollToSection(sectionId: string) {
+    const element = document.getElementById(sectionId);
+    if (element) {
+      element.scrollIntoView({ behavior: 'smooth' });
+    }
+  }
+
+  // 显示提示
+  private showAlert(message: string) {
+    alert(message);
+  }
+}

+ 17 - 12
src/app/consumer/profile/profile.ts

@@ -76,20 +76,25 @@ export class Profile {
     this.router.navigate(['/auth/login']);
   }
 
-  // 菜单跳转(示例占位
+  // 菜单跳转(实现实际路由导航
   goToPage(page: string): void {
-    const pageNames: Record<string, string> = {
-      orders: '我的订单',
-      address: '我的地址',
-      favorites: '我的收藏',
-      invite: '邀请好友',
-      customerService: '客服与反馈',
-      settings: '设置',
-      about: '关于我们',
-      agreement: '用户协议',
-      privacy: '隐私政策'
+    const routeMap: Record<string, string> = {
+      orders: '/consumer/profile/orders',
+      address: '/consumer/profile/addresses',
+      favorites: '/consumer/profile/favorites',
+      invite: '/consumer/profile/invite-friends',
+      customerService: '/consumer/profile/customer-service',
+      settings: '/consumer/profile/settings',
+      about: '/consumer/profile/about-us',
+      agreement: '/consumer/profile/user-agreement',
+      privacy: '/consumer/profile/privacy-policy'
     };
-    alert(`跳转到${pageNames[page] || page}页面`);
+    const target = routeMap[page];
+    if (target) {
+      this.router.navigate([target]);
+    } else {
+      console.warn(`Unknown page key: ${page}`);
+    }
   }
 
   // 显示所有徽章

+ 389 - 0
src/app/consumer/profile/settings/settings.html

@@ -0,0 +1,389 @@
+<!-- 顶部标题栏 -->
+<div class="header">
+  <button class="back-btn" (click)="goBack()">
+    <i class="fas fa-arrow-left"></i>
+  </button>
+  <div class="header-title">设置</div>
+</div>
+
+<div class="settings-container">
+  <!-- 账户设置 -->
+  <div class="settings-section">
+    <div class="section-title">
+      <i class="fas fa-user-cog"></i>
+      <span>账户设置</span>
+    </div>
+    <div class="settings-list">
+      <div class="setting-item" (click)="editProfile()">
+        <div class="setting-info">
+          <div class="setting-icon user-icon">
+            <i class="fas fa-user"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">个人资料</div>
+            <div class="setting-desc">修改头像、昵称等信息</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+      
+      <div class="setting-item" (click)="changePassword()">
+        <div class="setting-info">
+          <div class="setting-icon lock-icon">
+            <i class="fas fa-lock"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">修改密码</div>
+            <div class="setting-desc">定期修改密码保障账户安全</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+      
+      <div class="setting-item" (click)="bindPhone()">
+        <div class="setting-info">
+          <div class="setting-icon phone-icon">
+            <i class="fas fa-mobile-alt"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">手机绑定</div>
+            <div class="setting-desc">{{userPhone || '未绑定手机号'}}</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 通知设置 -->
+  <div class="settings-section">
+    <div class="section-title">
+      <i class="fas fa-bell"></i>
+      <span>通知设置</span>
+    </div>
+    <div class="settings-list">
+      <div class="setting-item">
+        <div class="setting-info">
+          <div class="setting-icon notification-icon">
+            <i class="fas fa-bell"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">推送通知</div>
+            <div class="setting-desc">接收订单状态、活动等通知</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <label class="switch">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="notificationSettings.push"
+              (change)="updateNotificationSetting('push', $event)">
+            <span class="slider"></span>
+          </label>
+        </div>
+      </div>
+      
+      <div class="setting-item">
+        <div class="setting-info">
+          <div class="setting-icon sms-icon">
+            <i class="fas fa-sms"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">短信通知</div>
+            <div class="setting-desc">重要消息短信提醒</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <label class="switch">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="notificationSettings.sms"
+              (change)="updateNotificationSetting('sms', $event)">
+            <span class="slider"></span>
+          </label>
+        </div>
+      </div>
+      
+      <div class="setting-item">
+        <div class="setting-info">
+          <div class="setting-icon email-icon">
+            <i class="fas fa-envelope"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">邮件通知</div>
+            <div class="setting-desc">账单、活动邮件提醒</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <label class="switch">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="notificationSettings.email"
+              (change)="updateNotificationSetting('email', $event)">
+            <span class="slider"></span>
+          </label>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 隐私设置 -->
+  <div class="settings-section">
+    <div class="section-title">
+      <i class="fas fa-shield-alt"></i>
+      <span>隐私设置</span>
+    </div>
+    <div class="settings-list">
+      <div class="setting-item">
+        <div class="setting-info">
+          <div class="setting-icon location-icon">
+            <i class="fas fa-map-marker-alt"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">位置服务</div>
+            <div class="setting-desc">允许获取位置信息</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <label class="switch">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="privacySettings.location"
+              (change)="updatePrivacySetting('location', $event)">
+            <span class="slider"></span>
+          </label>
+        </div>
+      </div>
+      
+      <div class="setting-item">
+        <div class="setting-info">
+          <div class="setting-icon analytics-icon">
+            <i class="fas fa-chart-line"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">数据分析</div>
+            <div class="setting-desc">允许收集使用数据用于改进服务</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <label class="switch">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="privacySettings.analytics"
+              (change)="updatePrivacySetting('analytics', $event)">
+            <span class="slider"></span>
+          </label>
+        </div>
+      </div>
+      
+      <div class="setting-item">
+        <div class="setting-info">
+          <div class="setting-icon personalization-icon">
+            <i class="fas fa-user-tag"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">个性化推荐</div>
+            <div class="setting-desc">基于使用习惯推荐内容</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <label class="switch">
+            <input 
+              type="checkbox" 
+              [(ngModel)]="privacySettings.personalization"
+              (change)="updatePrivacySetting('personalization', $event)">
+            <span class="slider"></span>
+          </label>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 应用设置 -->
+  <div class="settings-section">
+    <div class="section-title">
+      <i class="fas fa-cog"></i>
+      <span>应用设置</span>
+    </div>
+    <div class="settings-list">
+      <div class="setting-item" (click)="selectLanguage()">
+        <div class="setting-info">
+          <div class="setting-icon language-icon">
+            <i class="fas fa-language"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">语言设置</div>
+            <div class="setting-desc">{{currentLanguage}}</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+      
+      <div class="setting-item" (click)="clearCache()">
+        <div class="setting-info">
+          <div class="setting-icon cache-icon">
+            <i class="fas fa-broom"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">清理缓存</div>
+            <div class="setting-desc">清理应用缓存数据 ({{cacheSize}})</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+      
+      <div class="setting-item" (click)="checkUpdate()">
+        <div class="setting-info">
+          <div class="setting-icon update-icon">
+            <i class="fas fa-download"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">版本更新</div>
+            <div class="setting-desc">当前版本 {{appVersion}}</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 其他设置 -->
+  <div class="settings-section">
+    <div class="section-title">
+      <i class="fas fa-ellipsis-h"></i>
+      <span>其他</span>
+    </div>
+    <div class="settings-list">
+      <div class="setting-item" (click)="viewAgreement()">
+        <div class="setting-info">
+          <div class="setting-icon agreement-icon">
+            <i class="fas fa-file-contract"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">用户协议</div>
+            <div class="setting-desc">查看用户服务协议</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+      
+      <div class="setting-item" (click)="viewPrivacyPolicy()">
+        <div class="setting-info">
+          <div class="setting-icon privacy-icon">
+            <i class="fas fa-user-shield"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">隐私政策</div>
+            <div class="setting-desc">查看隐私保护政策</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+      
+      <div class="setting-item" (click)="contactSupport()">
+        <div class="setting-info">
+          <div class="setting-icon support-icon">
+            <i class="fas fa-headset"></i>
+          </div>
+          <div class="setting-content">
+            <div class="setting-name">联系客服</div>
+            <div class="setting-desc">获取帮助和技术支持</div>
+          </div>
+        </div>
+        <div class="setting-action">
+          <i class="fas fa-chevron-right"></i>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 退出登录 -->
+  <div class="logout-section">
+    <button class="logout-btn" (click)="logout()">
+      <i class="fas fa-sign-out-alt"></i>
+      <span>退出登录</span>
+    </button>
+  </div>
+</div>
+
+<!-- 语言选择模态框 -->
+<div class="modal" [style.display]="showLanguageModal ? 'flex' : 'none'" (click)="closeLanguageModal($event)">
+  <div class="modal-content language-modal">
+    <div class="modal-header">
+      <div class="modal-title">选择语言</div>
+      <button class="modal-close" (click)="showLanguageModal = false">
+        <i class="fas fa-times"></i>
+      </button>
+    </div>
+    <div class="modal-body">
+      <div class="language-list">
+        <div 
+          *ngFor="let lang of languages" 
+          class="language-option"
+          [class.active]="lang.code === selectedLanguage"
+          (click)="selectLanguageOption(lang)">
+          <span class="language-name">{{lang.name}}</span>
+          <i class="fas fa-check" *ngIf="lang.code === selectedLanguage"></i>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- 个人资料编辑模态框 -->
+<div class="modal" [style.display]="showProfileModal ? 'flex' : 'none'" (click)="closeProfileModal($event)">
+  <div class="modal-content profile-modal">
+    <div class="modal-header">
+      <div class="modal-title">编辑个人资料</div>
+      <button class="modal-close" (click)="showProfileModal = false">
+        <i class="fas fa-times"></i>
+      </button>
+    </div>
+    <div class="modal-body">
+      <div class="profile-form">
+        <div class="form-group">
+          <label class="form-label">头像</label>
+          <div class="avatar-upload">
+            <div class="avatar-preview" *ngIf="avatarPreview || userInfo.avatar">
+              <img [src]="avatarPreview || userInfo.avatar" alt="头像预览">
+            </div>
+            <div class="avatar-placeholder" *ngIf="!avatarPreview && !userInfo.avatar">
+              <i class="fas fa-user"></i>
+            </div>
+            <input type="file" accept="image/*" (change)="onAvatarSelected($event)" class="avatar-input">
+            <div class="upload-hint">点击上传头像</div>
+          </div>
+        </div>
+        <div class="form-group">
+          <label class="form-label">昵称</label>
+          <input type="text" [(ngModel)]="userInfo.nickname" placeholder="请输入昵称" class="form-input">
+        </div>
+      </div>
+    </div>
+    <div class="modal-footer">
+      <button class="btn btn-secondary" (click)="showProfileModal = false">取消</button>
+      <button class="btn btn-primary" (click)="saveProfile()">保存</button>
+    </div>
+  </div>
+</div>
+
+<!-- 提示消息 -->
+<div class="alert" [class]="alertType" [style.display]="showAlert ? 'block' : 'none'">
+  {{alertMessage}}
+</div>

+ 799 - 0
src/app/consumer/profile/settings/settings.scss

@@ -0,0 +1,799 @@
+// 全局样式变量
+:root {
+  --primary-color: #4CAF50;
+  --primary-light: #81C784;
+  --primary-dark: #388E3C;
+  --secondary-color: #FFC107;
+  --background-color: #F5F5F5;
+  --surface-color: #FFFFFF;
+  --text-primary: #212121;
+  --text-secondary: #757575;
+  --text-hint: #BDBDBD;
+  --divider-color: #E0E0E0;
+  --error-color: #F44336;
+  --success-color: #4CAF50;
+  --warning-color: #FF9800;
+  --border-radius: 12px;
+  --shadow-light: 0 2px 8px rgba(0, 0, 0, 0.1);
+  --shadow-medium: 0 4px 16px rgba(0, 0, 0, 0.15);
+  --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+}
+
+// 页面容器
+.settings-container {
+  min-height: 100vh;
+  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+  padding-bottom: 20px;
+}
+
+// 顶部标题栏
+.header {
+  position: sticky;
+  top: 0;
+  z-index: 100;
+  display: flex;
+  align-items: center;
+  padding: 16px 20px;
+  background: var(--surface-color);
+  box-shadow: var(--shadow-light);
+  border-bottom: 1px solid var(--divider-color);
+
+  .back-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 40px;
+    height: 40px;
+    border: none;
+    border-radius: 50%;
+    background: transparent;
+    color: var(--text-primary);
+    cursor: pointer;
+    transition: var(--transition);
+    margin-right: 16px;
+
+    &:hover {
+      background: rgba(0, 0, 0, 0.05);
+      transform: translateX(-2px);
+    }
+
+    &:active {
+      transform: translateX(-2px) scale(0.95);
+    }
+
+    i {
+      font-size: 18px;
+    }
+  }
+
+  .header-title {
+    font-size: 20px;
+    font-weight: 600;
+    color: var(--text-primary);
+    flex: 1;
+  }
+}
+
+// 设置区块
+.settings-section {
+  margin: 20px 16px;
+  background: var(--surface-color);
+  border-radius: var(--border-radius);
+  box-shadow: var(--shadow-light);
+  overflow: hidden;
+  transition: var(--transition);
+
+  &:hover {
+    box-shadow: var(--shadow-medium);
+    transform: translateY(-2px);
+  }
+
+  .section-title {
+    display: flex;
+    align-items: center;
+    padding: 20px 20px 16px;
+    font-size: 18px;
+    font-weight: 600;
+    color: var(--text-primary);
+    border-bottom: 1px solid var(--divider-color);
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    color: white;
+
+    i {
+      margin-right: 12px;
+      font-size: 20px;
+      opacity: 0.9;
+    }
+
+    span {
+      flex: 1;
+    }
+  }
+
+  .settings-list {
+    .setting-item {
+      display: flex;
+      align-items: center;
+      padding: 20px;
+      cursor: pointer;
+      transition: var(--transition);
+      border-bottom: 1px solid var(--divider-color);
+      position: relative;
+
+      &:last-child {
+        border-bottom: none;
+      }
+
+      &:hover {
+        background: rgba(76, 175, 80, 0.05);
+        transform: translateX(4px);
+      }
+
+      &:active {
+        background: rgba(76, 175, 80, 0.1);
+        transform: translateX(4px) scale(0.98);
+      }
+
+      .setting-info {
+        display: flex;
+        align-items: center;
+        flex: 1;
+
+        .setting-icon {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 48px;
+          height: 48px;
+          border-radius: 50%;
+          margin-right: 16px;
+          transition: var(--transition);
+
+          i {
+            font-size: 20px;
+          }
+
+          // 不同类型图标的颜色
+          &.user-icon {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+          }
+
+          &.lock-icon {
+            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+            color: white;
+          }
+
+          &.phone-icon {
+            background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+            color: white;
+          }
+
+          &.notification-icon {
+            background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
+            color: white;
+          }
+
+          &.sms-icon {
+            background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
+            color: white;
+          }
+
+          &.email-icon {
+            background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
+            color: #666;
+          }
+
+          &.location-icon {
+            background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
+            color: white;
+          }
+
+          &.analytics-icon {
+            background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%);
+            color: white;
+          }
+
+          &.personalization-icon {
+            background: linear-gradient(135deg, #fad0c4 0%, #ffd1ff 100%);
+            color: #666;
+          }
+
+          &.language-icon {
+            background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
+            color: white;
+          }
+
+          &.cache-icon {
+            background: linear-gradient(135deg, #cfd9df 0%, #e2ebf0 100%);
+            color: #666;
+          }
+
+          &.update-icon {
+            background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
+            color: #666;
+          }
+
+          &.agreement-icon {
+            background: linear-gradient(135deg, #d299c2 0%, #fef9d7 100%);
+            color: #666;
+          }
+
+          &.privacy-icon {
+            background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
+            color: white;
+          }
+
+          &.support-icon {
+            background: linear-gradient(135deg, #fdbb2d 0%, #22c1c3 100%);
+            color: white;
+          }
+        }
+
+        .setting-content {
+          flex: 1;
+
+          .setting-name {
+            font-size: 16px;
+            font-weight: 500;
+            color: var(--text-primary);
+            margin-bottom: 4px;
+          }
+
+          .setting-desc {
+            font-size: 14px;
+            color: var(--text-secondary);
+            line-height: 1.4;
+          }
+        }
+      }
+
+      .setting-action {
+        display: flex;
+        align-items: center;
+        margin-left: 16px;
+
+        i {
+          font-size: 16px;
+          color: var(--text-hint);
+          transition: var(--transition);
+        }
+
+        .switch {
+          position: relative;
+          display: inline-block;
+          width: 52px;
+          height: 28px;
+          margin-right: 8px;
+
+          input {
+            opacity: 0;
+            width: 0;
+            height: 0;
+
+            &:checked + .slider {
+              background-color: var(--primary-color);
+
+              &:before {
+                transform: translateX(24px);
+              }
+            }
+
+            &:focus + .slider {
+              box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.2);
+            }
+          }
+
+          .slider {
+            position: absolute;
+            cursor: pointer;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background-color: #ccc;
+            transition: var(--transition);
+            border-radius: 28px;
+
+            &:before {
+              position: absolute;
+              content: "";
+              height: 20px;
+              width: 20px;
+              left: 4px;
+              bottom: 4px;
+              background-color: white;
+              transition: var(--transition);
+              border-radius: 50%;
+              box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+            }
+          }
+        }
+      }
+
+      &:hover .setting-action i {
+        color: var(--primary-color);
+        transform: translateX(4px);
+      }
+    }
+  }
+}
+
+// 退出登录区块
+.logout-section {
+  margin: 20px 16px;
+  padding: 0;
+
+  .logout-btn {
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 16px;
+    background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
+    color: white;
+    border: none;
+    border-radius: var(--border-radius);
+    font-size: 16px;
+    font-weight: 500;
+    cursor: pointer;
+    transition: var(--transition);
+    box-shadow: var(--shadow-light);
+
+    &:hover {
+      background: linear-gradient(135deg, #ff5252 0%, #d32f2f 100%);
+      box-shadow: var(--shadow-medium);
+      transform: translateY(-2px);
+    }
+
+    &:active {
+      transform: translateY(-2px) scale(0.98);
+    }
+
+    i {
+      margin-right: 8px;
+      font-size: 18px;
+    }
+  }
+}
+
+// 模态框样式
+.modal {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1000;
+  backdrop-filter: blur(4px);
+  animation: fadeIn 0.3s ease-out;
+
+  .modal-content {
+    background: var(--surface-color);
+    border-radius: var(--border-radius);
+    box-shadow: var(--shadow-medium);
+    max-width: 90%;
+    max-height: 80%;
+    overflow: hidden;
+    animation: slideUp 0.3s ease-out;
+
+    &.language-modal {
+      width: 320px;
+    }
+
+    &.profile-modal {
+      width: 400px;
+    }
+
+    .modal-header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 20px;
+      border-bottom: 1px solid var(--divider-color);
+      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+      color: white;
+
+      .modal-title {
+        font-size: 18px;
+        font-weight: 600;
+      }
+
+      .modal-close {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 32px;
+        height: 32px;
+        border: none;
+        border-radius: 50%;
+        background: rgba(255, 255, 255, 0.2);
+        color: white;
+        cursor: pointer;
+        transition: var(--transition);
+
+        &:hover {
+          background: rgba(255, 255, 255, 0.3);
+          transform: rotate(90deg);
+        }
+
+        i {
+          font-size: 14px;
+        }
+      }
+    }
+
+    .modal-body {
+      padding: 20px;
+      max-height: 400px;
+      overflow-y: auto;
+
+      .language-list {
+        .language-option {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          padding: 16px;
+          cursor: pointer;
+          border-radius: 8px;
+          transition: var(--transition);
+          margin-bottom: 8px;
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          &:hover {
+            background: rgba(76, 175, 80, 0.05);
+          }
+
+          &.active {
+            background: rgba(76, 175, 80, 0.1);
+            color: var(--primary-color);
+
+            .language-name {
+              font-weight: 500;
+            }
+          }
+
+          .language-name {
+            font-size: 16px;
+          }
+
+          i {
+            font-size: 16px;
+            color: var(--primary-color);
+          }
+        }
+      }
+
+      .profile-form {
+        .form-group {
+          margin-bottom: 24px;
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          .form-label {
+            display: block;
+            font-size: 14px;
+            font-weight: 500;
+            color: var(--text-primary);
+            margin-bottom: 8px;
+          }
+
+          .form-input {
+            width: 100%;
+            padding: 12px 16px;
+            border: 2px solid var(--divider-color);
+            border-radius: 8px;
+            font-size: 16px;
+            transition: var(--transition);
+            background: var(--surface-color);
+
+            &:focus {
+              outline: none;
+              border-color: var(--primary-color);
+              box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.1);
+            }
+
+            &::placeholder {
+              color: var(--text-hint);
+            }
+          }
+
+          .avatar-upload {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            padding: 20px;
+            border: 2px dashed var(--divider-color);
+            border-radius: 8px;
+            cursor: pointer;
+            transition: var(--transition);
+
+            &:hover {
+              border-color: var(--primary-color);
+              background: rgba(76, 175, 80, 0.02);
+            }
+
+            .avatar-preview {
+              width: 80px;
+              height: 80px;
+              border-radius: 50%;
+              overflow: hidden;
+              margin-bottom: 12px;
+              box-shadow: var(--shadow-light);
+
+              img {
+                width: 100%;
+                height: 100%;
+                object-fit: cover;
+              }
+            }
+
+            .avatar-placeholder {
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              width: 80px;
+              height: 80px;
+              border-radius: 50%;
+              background: var(--divider-color);
+              color: var(--text-hint);
+              margin-bottom: 12px;
+
+              i {
+                font-size: 32px;
+              }
+            }
+
+            .avatar-input {
+              position: absolute;
+              opacity: 0;
+              width: 0;
+              height: 0;
+            }
+
+            .upload-hint {
+              font-size: 14px;
+              color: var(--text-secondary);
+            }
+          }
+        }
+      }
+    }
+
+    .modal-footer {
+      display: flex;
+      justify-content: flex-end;
+      gap: 12px;
+      padding: 20px;
+      border-top: 1px solid var(--divider-color);
+      background: #fafafa;
+
+      .btn {
+        padding: 10px 20px;
+        border: none;
+        border-radius: 6px;
+        font-size: 14px;
+        font-weight: 500;
+        cursor: pointer;
+        transition: var(--transition);
+
+        &.btn-secondary {
+          background: var(--divider-color);
+          color: var(--text-primary);
+
+          &:hover {
+            background: #bdbdbd;
+          }
+        }
+
+        &.btn-primary {
+          background: var(--primary-color);
+          color: white;
+
+          &:hover {
+            background: var(--primary-dark);
+          }
+        }
+      }
+    }
+  }
+}
+
+// 提示消息
+.alert {
+  position: fixed;
+  top: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+  padding: 12px 20px;
+  border-radius: 6px;
+  font-size: 14px;
+  font-weight: 500;
+  z-index: 1100;
+  box-shadow: var(--shadow-medium);
+  animation: slideDown 0.3s ease-out;
+
+  &.alert-success {
+    background: var(--success-color);
+    color: white;
+  }
+
+  &.alert-error {
+    background: var(--error-color);
+    color: white;
+  }
+
+  &.alert-warning {
+    background: var(--warning-color);
+    color: white;
+  }
+
+  &.alert-info {
+    background: #2196F3;
+    color: white;
+  }
+}
+
+// 动画
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
+@keyframes slideUp {
+  from {
+    opacity: 0;
+    transform: translateY(30px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+@keyframes slideDown {
+  from {
+    opacity: 0;
+    transform: translateX(-50%) translateY(-20px);
+  }
+  to {
+    opacity: 1;
+    transform: translateX(-50%) translateY(0);
+  }
+}
+
+// 响应式设计
+@media (max-width: 768px) {
+  .settings-section {
+    margin: 16px 12px;
+    border-radius: 8px;
+
+    .section-title {
+      padding: 16px;
+      font-size: 16px;
+
+      i {
+        font-size: 18px;
+      }
+    }
+
+    .settings-list .setting-item {
+      padding: 16px;
+
+      .setting-info {
+        .setting-icon {
+          width: 40px;
+          height: 40px;
+          margin-right: 12px;
+
+          i {
+            font-size: 18px;
+          }
+        }
+
+        .setting-content {
+          .setting-name {
+            font-size: 15px;
+          }
+
+          .setting-desc {
+            font-size: 13px;
+          }
+        }
+      }
+    }
+  }
+
+  .logout-section {
+    margin: 16px 12px;
+
+    .logout-btn {
+      padding: 14px;
+      font-size: 15px;
+    }
+  }
+
+  .modal .modal-content {
+    &.language-modal,
+    &.profile-modal {
+      width: 95%;
+      max-width: 350px;
+    }
+
+    .modal-header {
+      padding: 16px;
+
+      .modal-title {
+        font-size: 16px;
+      }
+    }
+
+    .modal-body {
+      padding: 16px;
+    }
+
+    .modal-footer {
+      padding: 16px;
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .header {
+    padding: 12px 16px;
+
+    .header-title {
+      font-size: 18px;
+    }
+
+    .back-btn {
+      width: 36px;
+      height: 36px;
+      margin-right: 12px;
+
+      i {
+        font-size: 16px;
+      }
+    }
+  }
+
+  .settings-section {
+    margin: 12px 8px;
+
+    .section-title {
+      padding: 12px 16px;
+      font-size: 15px;
+    }
+
+    .settings-list .setting-item {
+      padding: 12px 16px;
+
+      .setting-info .setting-icon {
+        width: 36px;
+        height: 36px;
+        margin-right: 10px;
+
+        i {
+          font-size: 16px;
+        }
+      }
+    }
+  }
+
+  .logout-section {
+    margin: 12px 8px;
+  }
+}

+ 344 - 0
src/app/consumer/profile/settings/settings.ts

@@ -0,0 +1,344 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { Location } from '@angular/common';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+interface Language {
+  code: string;
+  name: string;
+}
+
+interface UserInfo {
+  nickname: string;
+  avatar?: string;
+  phone?: string;
+  email?: string;
+}
+
+interface NotificationSettings {
+  push: boolean;
+  sms: boolean;
+  email: boolean;
+}
+
+interface PrivacySettings {
+  location: boolean;
+  analytics: boolean;
+  personalization: boolean;
+}
+
+@Component({
+  selector: 'app-settings',
+  imports: [CommonModule, FormsModule],
+  templateUrl: './settings.html',
+  styleUrls: ['./settings.scss']
+})
+export class SettingsComponent implements OnInit {
+  // 用户信息
+  userInfo: UserInfo = {
+    nickname: '用户昵称',
+    avatar: '',
+    phone: '',
+    email: ''
+  };
+
+  // 通知设置
+  notificationSettings: NotificationSettings = {
+    push: true,
+    sms: false,
+    email: true
+  };
+
+  // 隐私设置
+  privacySettings: PrivacySettings = {
+    location: true,
+    analytics: false,
+    personalization: true
+  };
+
+  // 语言设置
+  languages: Language[] = [
+    { code: 'zh-CN', name: '简体中文' },
+    { code: 'zh-TW', name: '繁體中文' },
+    { code: 'en-US', name: 'English' },
+    { code: 'ja-JP', name: '日本語' },
+    { code: 'ko-KR', name: '한국어' }
+  ];
+
+  selectedLanguage = 'zh-CN';
+  currentLanguage = '简体中文';
+
+  // 应用信息
+  appVersion = '1.2.3';
+  cacheSize = '12.5MB';
+
+  // 模态框状态
+  showLanguageModal = false;
+  showProfileModal = false;
+
+  // 头像预览
+  avatarPreview: string | null = null;
+
+  // 提示消息
+  showAlert = false;
+  alertMessage = '';
+  alertType = 'alert-success';
+
+  // 用户手机号
+  userPhone = '';
+
+  constructor(
+    private router: Router,
+    private location: Location
+  ) {}
+
+  ngOnInit() {
+    this.loadUserInfo();
+    this.loadSettings();
+  }
+
+  // 加载用户信息
+  loadUserInfo() {
+    // 从本地存储或API获取用户信息
+    const savedUserInfo = localStorage.getItem('userInfo');
+    if (savedUserInfo) {
+      this.userInfo = { ...this.userInfo, ...JSON.parse(savedUserInfo) };
+    }
+
+    const savedPhone = localStorage.getItem('userPhone');
+    if (savedPhone) {
+      this.userPhone = savedPhone;
+    }
+  }
+
+  // 加载设置
+  loadSettings() {
+    // 加载通知设置
+    const savedNotificationSettings = localStorage.getItem('notificationSettings');
+    if (savedNotificationSettings) {
+      this.notificationSettings = { ...this.notificationSettings, ...JSON.parse(savedNotificationSettings) };
+    }
+
+    // 加载隐私设置
+    const savedPrivacySettings = localStorage.getItem('privacySettings');
+    if (savedPrivacySettings) {
+      this.privacySettings = { ...this.privacySettings, ...JSON.parse(savedPrivacySettings) };
+    }
+
+    // 加载语言设置
+    const savedLanguage = localStorage.getItem('selectedLanguage');
+    if (savedLanguage) {
+      this.selectedLanguage = savedLanguage;
+      const lang = this.languages.find(l => l.code === savedLanguage);
+      if (lang) {
+        this.currentLanguage = lang.name;
+      }
+    }
+  }
+
+  // 返回上一页
+  goBack() {
+    this.location.back();
+  }
+
+  // 编辑个人资料
+  editProfile() {
+    this.showProfileModal = true;
+  }
+
+  // 修改密码
+  changePassword() {
+    this.router.navigate(['/consumer/profile/change-password']);
+  }
+
+  // 绑定手机
+  bindPhone() {
+    this.router.navigate(['/consumer/profile/bind-phone']);
+  }
+
+  // 更新通知设置
+  updateNotificationSetting(type: keyof NotificationSettings, event: any) {
+    this.notificationSettings[type] = event.target.checked;
+    localStorage.setItem('notificationSettings', JSON.stringify(this.notificationSettings));
+    
+    this.showAlertMessage(
+      `${this.getNotificationTypeName(type)}${event.target.checked ? '已开启' : '已关闭'}`,
+      'alert-success'
+    );
+  }
+
+  // 更新隐私设置
+  updatePrivacySetting(type: keyof PrivacySettings, event: any) {
+    this.privacySettings[type] = event.target.checked;
+    localStorage.setItem('privacySettings', JSON.stringify(this.privacySettings));
+    
+    this.showAlertMessage(
+      `${this.getPrivacyTypeName(type)}${event.target.checked ? '已开启' : '已关闭'}`,
+      'alert-success'
+    );
+  }
+
+  // 获取通知类型名称
+  getNotificationTypeName(type: keyof NotificationSettings): string {
+    const names = {
+      push: '推送通知',
+      sms: '短信通知',
+      email: '邮件通知'
+    };
+    return names[type];
+  }
+
+  // 获取隐私类型名称
+  getPrivacyTypeName(type: keyof PrivacySettings): string {
+    const names = {
+      location: '位置服务',
+      analytics: '数据分析',
+      personalization: '个性化推荐'
+    };
+    return names[type];
+  }
+
+  // 选择语言
+  selectLanguage() {
+    this.showLanguageModal = true;
+  }
+
+  // 选择语言选项
+  selectLanguageOption(language: Language) {
+    this.selectedLanguage = language.code;
+    this.currentLanguage = language.name;
+    localStorage.setItem('selectedLanguage', language.code);
+    this.showLanguageModal = false;
+    
+    this.showAlertMessage(`语言已切换为${language.name}`, 'alert-success');
+  }
+
+  // 清理缓存
+  clearCache() {
+    // 模拟清理缓存
+    setTimeout(() => {
+      this.cacheSize = '0MB';
+      this.showAlertMessage('缓存清理完成', 'alert-success');
+    }, 1000);
+    
+    this.showAlertMessage('正在清理缓存...', 'alert-info');
+  }
+
+  // 检查更新
+  checkUpdate() {
+    this.showAlertMessage('正在检查更新...', 'alert-info');
+    
+    // 模拟检查更新
+    setTimeout(() => {
+      this.showAlertMessage('当前已是最新版本', 'alert-success');
+    }, 2000);
+  }
+
+  // 查看用户协议
+  viewAgreement() {
+    this.router.navigate(['/consumer/agreement']);
+  }
+
+  // 查看隐私政策
+  viewPrivacyPolicy() {
+    this.router.navigate(['/consumer/privacy-policy']);
+  }
+
+  // 联系客服
+  contactSupport() {
+    this.router.navigate(['/consumer/support']);
+  }
+
+  // 退出登录
+  logout() {
+    if (confirm('确定要退出登录吗?')) {
+      // 清除本地存储
+      localStorage.removeItem('userToken');
+      localStorage.removeItem('userInfo');
+      
+      // 跳转到登录页
+      this.router.navigate(['/auth/login']);
+    }
+  }
+
+  // 关闭语言模态框
+  closeLanguageModal(event: any) {
+    if (event.target === event.currentTarget) {
+      this.showLanguageModal = false;
+    }
+  }
+
+  // 关闭个人资料模态框
+  closeProfileModal(event: any) {
+    if (event.target === event.currentTarget) {
+      this.showProfileModal = false;
+      this.avatarPreview = null;
+    }
+  }
+
+  // 选择头像
+  onAvatarSelected(event: any) {
+    const file = event.target.files[0];
+    if (file) {
+      // 验证文件类型
+      if (!file.type.startsWith('image/')) {
+        this.showAlertMessage('请选择图片文件', 'alert-error');
+        return;
+      }
+
+      // 验证文件大小(限制为2MB)
+      if (file.size > 2 * 1024 * 1024) {
+        this.showAlertMessage('图片大小不能超过2MB', 'alert-error');
+        return;
+      }
+
+      // 创建预览
+      const reader = new FileReader();
+      reader.onload = (e: any) => {
+        this.avatarPreview = e.target.result;
+      };
+      reader.readAsDataURL(file);
+    }
+  }
+
+  // 保存个人资料
+  saveProfile() {
+    // 验证昵称
+    if (!this.userInfo.nickname || this.userInfo.nickname.trim().length === 0) {
+      this.showAlertMessage('请输入昵称', 'alert-error');
+      return;
+    }
+
+    if (this.userInfo.nickname.trim().length > 20) {
+      this.showAlertMessage('昵称长度不能超过20个字符', 'alert-error');
+      return;
+    }
+
+    // 更新头像
+    if (this.avatarPreview) {
+      this.userInfo.avatar = this.avatarPreview;
+    }
+
+    // 保存到本地存储
+    localStorage.setItem('userInfo', JSON.stringify(this.userInfo));
+
+    // 关闭模态框
+    this.showProfileModal = false;
+    this.avatarPreview = null;
+
+    this.showAlertMessage('个人资料保存成功', 'alert-success');
+  }
+
+  // 显示提示消息
+  showAlertMessage(message: string, type: string) {
+    this.alertMessage = message;
+    this.alertType = type;
+    this.showAlert = true;
+
+    // 3秒后自动隐藏
+    setTimeout(() => {
+      this.showAlert = false;
+    }, 3000);
+  }
+}

+ 202 - 0
src/app/consumer/profile/user-agreement/user-agreement.html

@@ -0,0 +1,202 @@
+<div class="user-agreement-page">
+  <!-- 头部 -->
+  <div class="header">
+    <button class="back-btn" (click)="goBack()">
+      <i class="fas fa-arrow-left"></i>
+    </button>
+    <span class="title">用户协议</span>
+  </div>
+
+  <div class="agreement-content">
+    <!-- 协议标题 -->
+    <div class="agreement-header">
+      <h1>绿色回收用户服务协议</h1>
+      <div class="update-info">
+        <span class="update-date">更新日期:{{ updateDate }}</span>
+        <span class="effective-date">生效日期:{{ effectiveDate }}</span>
+      </div>
+    </div>
+
+    <!-- 协议内容 -->
+    <div class="agreement-sections">
+      <!-- 前言 -->
+      <div class="section">
+        <h3>前言</h3>
+        <div class="content">
+          <p>欢迎使用绿色回收服务!</p>
+          <p>《绿色回收用户服务协议》(以下简称"本协议")是您与绿色回收科技有限公司(以下简称"我们"或"绿色回收")之间关于您使用绿色回收服务所订立的协议。</p>
+          <p>请您仔细阅读本协议的全部条款,特别是免除或者限制责任的条款、法律适用和争议解决条款。如果您不同意本协议的任意内容,或者无法准确理解我们对条款的解释,请不要进行后续操作。</p>
+        </div>
+      </div>
+
+      <!-- 第一条:协议的范围 -->
+      <div class="section">
+        <h3>第一条 协议的范围</h3>
+        <div class="content">
+          <p>1.1 本协议是您与绿色回收之间关于您使用绿色回收服务所订立的协议。</p>
+          <p>1.2 "绿色回收服务"是指绿色回收向用户提供的包括但不限于回收预约、积分兑换、环保知识分享等服务。</p>
+          <p>1.3 本协议适用于您使用绿色回收提供的所有服务,包括但不限于移动应用程序、网站、小程序等。</p>
+        </div>
+      </div>
+
+      <!-- 第二条:服务内容 -->
+      <div class="section">
+        <h3>第二条 服务内容</h3>
+        <div class="content">
+          <p>2.1 绿色回收为用户提供以下服务:</p>
+          <ul>
+            <li>回收物品预约上门服务</li>
+            <li>回收物品价格查询和估算</li>
+            <li>积分奖励和兑换服务</li>
+            <li>环保知识和资讯分享</li>
+            <li>用户社区和互动功能</li>
+            <li>其他相关增值服务</li>
+          </ul>
+          <p>2.2 绿色回收有权根据业务发展需要,增加、修改或终止部分服务功能。</p>
+        </div>
+      </div>
+
+      <!-- 第三条:用户注册 -->
+      <div class="section">
+        <h3>第三条 用户注册</h3>
+        <div class="content">
+          <p>3.1 用户需要注册账户才能使用绿色回收的完整服务。</p>
+          <p>3.2 用户应提供真实、准确、完整的个人信息,并及时更新。</p>
+          <p>3.3 用户应妥善保管账户信息,不得将账户转让、出借或以其他方式提供给第三方使用。</p>
+          <p>3.4 用户对其账户下的所有活动承担责任。</p>
+        </div>
+      </div>
+
+      <!-- 第四条:用户权利和义务 -->
+      <div class="section">
+        <h3>第四条 用户权利和义务</h3>
+        <div class="content">
+          <p>4.1 用户权利:</p>
+          <ul>
+            <li>享受绿色回收提供的各项服务</li>
+            <li>获得积分奖励和相应权益</li>
+            <li>对服务质量进行监督和反馈</li>
+            <li>要求保护个人隐私和信息安全</li>
+          </ul>
+          <p>4.2 用户义务:</p>
+          <ul>
+            <li>遵守国家法律法规和本协议</li>
+            <li>提供真实有效的回收物品信息</li>
+            <li>配合回收员完成回收服务</li>
+            <li>不得利用服务从事违法违规活动</li>
+            <li>尊重其他用户和工作人员</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第五条:服务规范 -->
+      <div class="section">
+        <h3>第五条 服务规范</h3>
+        <div class="content">
+          <p>5.1 回收服务规范:</p>
+          <ul>
+            <li>用户应准确描述回收物品的类型、数量和状态</li>
+            <li>预约时间确定后,用户应按时等候回收员上门</li>
+            <li>回收物品应符合回收标准,不得包含危险品</li>
+            <li>回收价格以现场评估为准</li>
+          </ul>
+          <p>5.2 积分规则:</p>
+          <ul>
+            <li>积分获取规则以平台公布为准</li>
+            <li>积分不得转让、买卖或以其他方式变现</li>
+            <li>积分有效期为获得之日起一年</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第六条:隐私保护 -->
+      <div class="section">
+        <h3>第六条 隐私保护</h3>
+        <div class="content">
+          <p>6.1 绿色回收重视用户隐私保护,具体内容请参阅《隐私政策》。</p>
+          <p>6.2 绿色回收承诺不会向第三方泄露用户个人信息,法律法规另有规定的除外。</p>
+          <p>6.3 为提供更好的服务,绿色回收可能会收集和使用用户的相关信息,但会严格按照隐私政策执行。</p>
+        </div>
+      </div>
+
+      <!-- 第七条:知识产权 -->
+      <div class="section">
+        <h3>第七条 知识产权</h3>
+        <div class="content">
+          <p>7.1 绿色回收服务中的所有内容,包括但不限于文字、图片、音频、视频、软件、程序、版面设计等均受知识产权法保护。</p>
+          <p>7.2 未经绿色回收书面许可,用户不得复制、传播、展示、镜像、上载、下载使用上述内容。</p>
+          <p>7.3 用户在使用服务过程中产生的内容,授权绿色回收在服务范围内使用。</p>
+        </div>
+      </div>
+
+      <!-- 第八条:免责声明 -->
+      <div class="section">
+        <h3>第八条 免责声明</h3>
+        <div class="content">
+          <p>8.1 因以下情况造成的服务中断或其他缺陷,绿色回收不承担责任:</p>
+          <ul>
+            <li>系统停机维护期间</li>
+            <li>电信设备出现故障不能进行数据传输</li>
+            <li>因台风、地震、海啸、洪水、停电、战争、恐怖袭击等不可抗力因素</li>
+            <li>因病毒、木马、恶意程序攻击、网络拥堵、系统不稳定等</li>
+          </ul>
+          <p>8.2 用户理解并同意,绿色回收不对因以下事由产生的损失承担责任:</p>
+          <ul>
+            <li>用户自身原因导致的任何损失</li>
+            <li>第三方行为导致的损失</li>
+            <li>不可抗力导致的损失</li>
+          </ul>
+        </div>
+      </div>
+
+      <!-- 第九条:协议修改 -->
+      <div class="section">
+        <h3>第九条 协议修改</h3>
+        <div class="content">
+          <p>9.1 绿色回收有权根据需要修改本协议条款。</p>
+          <p>9.2 协议修改后,绿色回收会在应用内或官网发布公告。</p>
+          <p>9.3 如果用户不同意修改后的协议,可以停止使用服务;继续使用服务则视为接受修改后的协议。</p>
+        </div>
+      </div>
+
+      <!-- 第十条:争议解决 -->
+      <div class="section">
+        <h3>第十条 争议解决</h3>
+        <div class="content">
+          <p>10.1 本协议的签订、履行、解释及争议解决均适用中华人民共和国法律。</p>
+          <p>10.2 如就本协议内容或其执行发生任何争议,双方应尽量友好协商解决。</p>
+          <p>10.3 协商不成时,任何一方均可向绿色回收所在地人民法院提起诉讼。</p>
+        </div>
+      </div>
+
+      <!-- 第十一条:其他条款 -->
+      <div class="section">
+        <h3>第十一条 其他条款</h3>
+        <div class="content">
+          <p>11.1 本协议构成双方对本协议之约定事项及其他有关事宜的完整协议。</p>
+          <p>11.2 本协议中的标题仅为方便而设,在解释本协议时应被忽略。</p>
+          <p>11.3 本协议部分条款被认定为违法或无效不影响其余条款的效力。</p>
+        </div>
+      </div>
+    </div>
+
+    <!-- 联系信息 -->
+    <div class="contact-section">
+      <h3>联系我们</h3>
+      <div class="contact-info">
+        <p>如果您对本协议有任何疑问,请通过以下方式联系我们:</p>
+        <ul>
+          <li>客服电话:400-888-6666</li>
+          <li>客服邮箱:service@recycle-app.com</li>
+          <li>公司地址:北京市朝阳区环保科技园区</li>
+        </ul>
+      </div>
+    </div>
+
+    <!-- 同意按钮 -->
+    <div class="agreement-actions" *ngIf="showActions">
+      <button class="disagree-btn" (click)="disagree()">不同意</button>
+      <button class="agree-btn" (click)="agree()">同意并继续</button>
+    </div>
+  </div>
+</div>

+ 378 - 0
src/app/consumer/profile/user-agreement/user-agreement.scss

@@ -0,0 +1,378 @@
+.user-agreement-page {
+  min-height: 100vh;
+  background: #f8f9fa;
+
+  .header {
+    display: flex;
+    align-items: center;
+    padding: 12px 16px;
+    background: #fff;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+    position: sticky;
+    top: 0;
+    z-index: 100;
+
+    .back-btn {
+      background: none;
+      border: none;
+      font-size: 18px;
+      color: #333;
+      padding: 8px;
+      margin-right: 12px;
+      border-radius: 50%;
+      transition: background-color 0.3s;
+
+      &:hover {
+        background-color: #f0f0f0;
+      }
+    }
+
+    .title {
+      font-size: 18px;
+      font-weight: 600;
+      color: #333;
+    }
+  }
+
+  .agreement-content {
+    padding: 20px 16px;
+    max-width: 800px;
+    margin: 0 auto;
+
+    // 协议标题
+    .agreement-header {
+      background: #fff;
+      border-radius: 12px;
+      padding: 24px;
+      margin-bottom: 20px;
+      text-align: center;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+      h1 {
+        font-size: 24px;
+        font-weight: 700;
+        color: #333;
+        margin: 0 0 16px;
+        line-height: 1.3;
+      }
+
+      .update-info {
+        display: flex;
+        justify-content: center;
+        gap: 20px;
+        font-size: 14px;
+        color: #666;
+
+        .update-date,
+        .effective-date {
+          padding: 6px 12px;
+          background: #f8f9fa;
+          border-radius: 16px;
+          border: 1px solid #e0e0e0;
+        }
+      }
+    }
+
+    // 协议章节
+    .agreement-sections {
+      .section {
+        background: #fff;
+        border-radius: 12px;
+        padding: 24px;
+        margin-bottom: 16px;
+        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+        h3 {
+          font-size: 18px;
+          font-weight: 600;
+          color: #333;
+          margin: 0 0 16px;
+          padding-bottom: 8px;
+          border-bottom: 2px solid #4CAF50;
+          display: inline-block;
+        }
+
+        .content {
+          line-height: 1.8;
+
+          p {
+            font-size: 14px;
+            color: #555;
+            margin: 0 0 12px;
+            text-align: justify;
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+          }
+
+          ul {
+            margin: 12px 0;
+            padding-left: 20px;
+
+            li {
+              font-size: 14px;
+              color: #555;
+              margin-bottom: 8px;
+              line-height: 1.6;
+
+              &:last-child {
+                margin-bottom: 0;
+              }
+            }
+          }
+
+          // 强调文本
+          strong {
+            color: #333;
+            font-weight: 600;
+          }
+
+          // 重要提示
+          .highlight {
+            background: #fff3cd;
+            border: 1px solid #ffeaa7;
+            border-radius: 6px;
+            padding: 12px;
+            margin: 12px 0;
+            font-size: 14px;
+            color: #856404;
+          }
+        }
+      }
+    }
+
+    // 联系信息
+    .contact-section {
+      background: #fff;
+      border-radius: 12px;
+      padding: 24px;
+      margin-bottom: 20px;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+
+      h3 {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+        margin: 0 0 16px;
+        padding-bottom: 8px;
+        border-bottom: 2px solid #2196F3;
+        display: inline-block;
+      }
+
+      .contact-info {
+        p {
+          font-size: 14px;
+          color: #555;
+          margin: 0 0 12px;
+          line-height: 1.6;
+        }
+
+        ul {
+          margin: 0;
+          padding-left: 20px;
+
+          li {
+            font-size: 14px;
+            color: #555;
+            margin-bottom: 8px;
+            line-height: 1.6;
+
+            &:last-child {
+              margin-bottom: 0;
+            }
+          }
+        }
+      }
+    }
+
+    // 同意按钮区域
+    .agreement-actions {
+      display: flex;
+      gap: 12px;
+      padding: 20px 0;
+      position: sticky;
+      bottom: 0;
+      background: #f8f9fa;
+      margin: 0 -16px -20px;
+      padding: 20px 16px;
+      border-top: 1px solid #e0e0e0;
+
+      .disagree-btn,
+      .agree-btn {
+        flex: 1;
+        height: 48px;
+        border: none;
+        border-radius: 24px;
+        font-size: 16px;
+        font-weight: 600;
+        transition: all 0.3s;
+
+        &:active {
+          transform: scale(0.98);
+        }
+      }
+
+      .disagree-btn {
+        background: #fff;
+        color: #666;
+        border: 1px solid #ddd;
+
+        &:hover {
+          background: #f5f5f5;
+          border-color: #ccc;
+        }
+      }
+
+      .agree-btn {
+        background: linear-gradient(135deg, #4CAF50, #2E7D32);
+        color: #fff;
+        box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
+
+        &:hover {
+          box-shadow: 0 6px 16px rgba(76, 175, 80, 0.4);
+          transform: translateY(-1px);
+        }
+      }
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 768px) {
+  .user-agreement-page {
+    .agreement-content {
+      padding: 16px 12px;
+
+      .agreement-header {
+        padding: 20px 16px;
+
+        h1 {
+          font-size: 20px;
+        }
+
+        .update-info {
+          flex-direction: column;
+          gap: 8px;
+
+          .update-date,
+          .effective-date {
+            font-size: 13px;
+          }
+        }
+      }
+
+      .agreement-sections {
+        .section {
+          padding: 20px 16px;
+
+          h3 {
+            font-size: 16px;
+          }
+
+          .content {
+            p,
+            li {
+              font-size: 13px;
+            }
+          }
+        }
+      }
+
+      .contact-section {
+        padding: 20px 16px;
+
+        h3 {
+          font-size: 16px;
+        }
+
+        .contact-info {
+          p,
+          li {
+            font-size: 13px;
+          }
+        }
+      }
+
+      .agreement-actions {
+        padding: 16px 12px;
+        margin: 0 -12px -16px;
+
+        .disagree-btn,
+        .agree-btn {
+          height: 44px;
+          font-size: 15px;
+        }
+      }
+    }
+  }
+}
+
+@media (max-width: 480px) {
+  .user-agreement-page {
+    .agreement-content {
+      padding: 12px 8px;
+
+      .agreement-header {
+        padding: 16px 12px;
+        margin-bottom: 16px;
+
+        h1 {
+          font-size: 18px;
+        }
+      }
+
+      .agreement-sections {
+        .section {
+          padding: 16px 12px;
+          margin-bottom: 12px;
+
+          h3 {
+            font-size: 15px;
+            margin-bottom: 12px;
+          }
+        }
+      }
+
+      .contact-section {
+        padding: 16px 12px;
+      }
+
+      .agreement-actions {
+        padding: 12px 8px;
+        margin: 0 -8px -12px;
+
+        .disagree-btn,
+        .agree-btn {
+          height: 40px;
+          font-size: 14px;
+        }
+      }
+    }
+  }
+}
+
+// 打印样式
+@media print {
+  .user-agreement-page {
+    .header {
+      display: none;
+    }
+
+    .agreement-actions {
+      display: none;
+    }
+
+    .agreement-content {
+      padding: 0;
+      max-width: none;
+
+      .agreement-sections .section,
+      .contact-section {
+        box-shadow: none;
+        border: 1px solid #ddd;
+        page-break-inside: avoid;
+      }
+    }
+  }
+}

+ 82 - 0
src/app/consumer/profile/user-agreement/user-agreement.ts

@@ -0,0 +1,82 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-user-agreement',
+  standalone: true,
+  imports: [CommonModule],
+  templateUrl: './user-agreement.html',
+  styleUrls: ['./user-agreement.scss']
+})
+export class UserAgreementPage implements OnInit {
+  // 协议信息
+  updateDate = '2024年1月15日';
+  effectiveDate = '2024年1月20日';
+  
+  // 是否显示同意/不同意按钮(用于注册流程)
+  showActions = false;
+  
+  // 来源页面(用于判断是否来自注册流程)
+  fromPage = '';
+
+  constructor(
+    private router: Router
+  ) {}
+
+  ngOnInit() {
+    // 可以从路由参数获取信息
+    // this.fromPage = this.route.snapshot.queryParams['from'] || '';
+    // this.showActions = this.fromPage === 'register';
+  }
+
+  /**
+   * 返回上一页
+   */
+  goBack() {
+    this.router.navigate(['/consumer/profile']);
+  }
+
+  /**
+   * 用户同意协议
+   */
+  agree() {
+    if (this.fromPage === 'register') {
+      // 如果是从注册页面来的,返回注册页面并传递同意状态
+      this.router.navigate(['/register'], { queryParams: { agreed: 'true' } });
+    } else {
+      this.showAlert('感谢您同意我们的用户协议!');
+    }
+  }
+
+  /**
+   * 用户不同意协议
+   */
+  disagree() {
+    if (this.fromPage === 'register') {
+      if (confirm('不同意用户协议将无法完成注册,确定要返回吗?')) {
+        this.router.navigate(['/register']);
+      }
+    } else {
+      this.showAlert('您选择了不同意用户协议。');
+    }
+  }
+
+  // 滚动到顶部
+  scrollToTop() {
+    window.scrollTo({ top: 0, behavior: 'smooth' });
+  }
+
+  // 滚动到指定章节
+  scrollToSection(sectionId: string) {
+    const element = document.getElementById(sectionId);
+    if (element) {
+      element.scrollIntoView({ behavior: 'smooth' });
+    }
+  }
+
+  // 显示提示
+  private showAlert(message: string) {
+    alert(message);
+  }
+}

+ 20 - 2
src/app/shared/components/svg-icons/svg-icons.component.ts

@@ -7,8 +7,9 @@ import { CommonModule } from '@angular/common';
   standalone: true,
   template: `
     <svg 
-      class="recycle-icon" 
-      [class]="size + ' ' + color + ' ' + (hover ? 'icon-hover' : '')"
+      class="recycle-icon"
+      [attr.class]="'recycle-icon ' + size + (hover ? ' icon-hover' : '') + (isPresetColor ? ' ' + color : '')"
+      [style.color]="colorStyle"
       [attr.width]="sizePx" 
       [attr.height]="sizePx"
       viewBox="0 0 24 24"
@@ -40,6 +41,15 @@ import { CommonModule } from '@angular/common';
         <path *ngSwitchCase="'edit'" d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
         <path *ngSwitchCase="'camera'" d="M12 15.2C13.767 15.2 15.2 13.767 15.2 12 15.2 10.233 13.767 8.8 12 8.8 10.233 8.8 8.8 10.233 8.8 12 8.8 13.767 10.233 15.2 12 15.2zM9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/>
         
+        <!-- 新增分类/页面图标 -->
+        <path *ngSwitchCase="'electronics'" d="M17 1H7c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 18H7V5h10v14zM12 21a1 1 0 100-2 1 1 0 000 2z"/>
+        <path *ngSwitchCase="'utensils'" d="M8.1 13.34l2.83-2.83L3.91 3.5a4.008 4.008 0 000 5.66l4.19 4.18zm6.78-1.81c1.53.71 3.68.21 5.27-1.38 1.91-1.91 2.28-4.65.81-6.12-1.46-1.46-4.20-1.10-6.12.81-1.59 1.59-2.09 3.74-1.38 5.27L3.7 19.87l1.41 1.41L12 14.41l6.88 6.88 1.41-1.41-6.88-6.88 1.37-1.37z"/>
+        <path *ngSwitchCase="'waste-info'" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
+        <path *ngSwitchCase="'recycle-method'" d="M3 6h11v6h4l2 3v3h-2a2 2 0 11-4 0H9a2 2 0 11-4 0H3V6zm2 9a1 1 0 102 0 1 1 0 00-2 0zm10 0a1 1 0 102 0 1 1 0 00-2 0z"/>
+        <path *ngSwitchCase="'service'" d="M12 2a6 6 0 016 6v3h1a1 1 0 110 2H5a1 1 0 110-2h1V8a6 6 0 016-6zm-4 16h8a2 2 0 01-2 2H10a2 2 0 01-2-2z"/>
+        <path *ngSwitchCase="'address'" d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
+        <path *ngSwitchCase="'clock'" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
+        
         <!-- 状态图标 -->
         <path *ngSwitchCase="'favorite-filled'" d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
         <path *ngSwitchCase="'cart-full'" d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM17 18c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2zM12.5 2h-1c-.28 0-.5.22-.5.5V3h2v-.5c0-.28-.22-.5-.5-.5zM19 5H5c-.55 0-1 .45-1 1v1h16V6c0-.55-.45-1-1-1zm-1 4H6L5.78 5.94l-.65-1.88C5.01 3.95 5.45 3 6.12 3h11.76c.67 0 1.11.95.65 1.88L18.22 5.94 18 9z"/>
@@ -91,4 +101,12 @@ export class SvgIconComponent {
     const sizes = { sm: '14', md: '18', lg: '24', xl: '32' };
     return sizes[this.size];
   }
+
+  get isPresetColor(): boolean {
+    return ['primary', 'secondary'].includes(this.color);
+  }
+
+  get colorStyle(): string | null {
+    return this.isPresetColor ? null : this.color;
+  }
 }