本章将通过一个完整的企业级应用项目,整合前面所有章节学到的 TypeScript 知识和最佳实践。我们将构建一个现代化的企业资源管理系统(ERP),涵盖用户管理、权限控制、数据分析、实时通信等核心功能。

15.1 项目概述与架构设计

15.1.1 项目需求分析

// src/types/requirements.ts - 项目需求定义

// 功能需求
interface FunctionalRequirements {
  userManagement: {
    authentication: boolean;
    authorization: boolean;
    roleBasedAccess: boolean;
    multiTenant: boolean;
  };
  
  dataManagement: {
    crud: boolean;
    search: boolean;
    filtering: boolean;
    sorting: boolean;
    pagination: boolean;
    export: boolean;
  };
  
  realTimeFeatures: {
    notifications: boolean;
    chat: boolean;
    collaboration: boolean;
    liveUpdates: boolean;
  };
  
  analytics: {
    dashboard: boolean;
    reports: boolean;
    charts: boolean;
    kpi: boolean;
  };
}

// 非功能需求
interface NonFunctionalRequirements {
  performance: {
    responseTime: number; // ms
    throughput: number; // requests/second
    concurrentUsers: number;
  };
  
  scalability: {
    horizontal: boolean;
    vertical: boolean;
    microservices: boolean;
  };
  
  security: {
    encryption: boolean;
    audit: boolean;
    compliance: string[];
  };
  
  reliability: {
    uptime: number; // percentage
    backup: boolean;
    disaster_recovery: boolean;
  };
}

// 技术约束
interface TechnicalConstraints {
  frontend: {
    framework: 'React' | 'Vue' | 'Angular';
    stateManagement: 'Redux' | 'Zustand' | 'MobX';
    styling: 'CSS-in-JS' | 'Tailwind' | 'SCSS';
  };
  
  backend: {
    runtime: 'Node.js' | 'Deno' | 'Bun';
    framework: 'Express' | 'Fastify' | 'Koa';
    database: 'PostgreSQL' | 'MongoDB' | 'MySQL';
  };
  
  infrastructure: {
    cloud: 'AWS' | 'Azure' | 'GCP';
    containerization: 'Docker' | 'Podman';
    orchestration: 'Kubernetes' | 'Docker Swarm';
  };
}

15.1.2 系统架构设计

// src/architecture/system-design.ts - 系统架构设计

// 微服务架构
interface MicroserviceArchitecture {
  services: {
    gateway: APIGatewayService;
    auth: AuthenticationService;
    user: UserManagementService;
    notification: NotificationService;
    analytics: AnalyticsService;
    file: FileManagementService;
  };
  
  communication: {
    synchronous: RESTfulAPI | GraphQLAPI;
    asynchronous: MessageQueue;
  };
  
  dataStorage: {
    relational: PostgreSQLDatabase;
    document: MongoDBDatabase;
    cache: RedisCache;
    search: ElasticsearchIndex;
  };
}

// API 网关服务
interface APIGatewayService {
  routing: {
    rules: RoutingRule[];
    loadBalancing: LoadBalancingStrategy;
    failover: FailoverStrategy;
  };
  
  security: {
    authentication: AuthenticationMiddleware;
    authorization: AuthorizationMiddleware;
    rateLimiting: RateLimitingMiddleware;
    cors: CORSMiddleware;
  };
  
  monitoring: {
    logging: LoggingMiddleware;
    metrics: MetricsMiddleware;
    tracing: TracingMiddleware;
  };
}

// 认证服务
interface AuthenticationService {
  providers: {
    local: LocalAuthProvider;
    oauth: OAuthProvider[];
    saml: SAMLProvider;
    ldap: LDAPProvider;
  };
  
  tokens: {
    jwt: JWTTokenManager;
    refresh: RefreshTokenManager;
    session: SessionManager;
  };
  
  security: {
    encryption: EncryptionService;
    hashing: HashingService;
    validation: ValidationService;
  };
}

// 用户管理服务
interface UserManagementService {
  entities: {
    user: UserEntity;
    role: RoleEntity;
    permission: PermissionEntity;
    organization: OrganizationEntity;
  };
  
  operations: {
    crud: CRUDOperations<UserEntity>;
    search: SearchOperations<UserEntity>;
    bulk: BulkOperations<UserEntity>;
  };
  
  policies: {
    access: AccessPolicy[];
    data: DataPolicy[];
    retention: RetentionPolicy[];
  };
}

15.1.3 前端架构设计

// src/frontend/architecture.ts - 前端架构设计

// 应用架构
interface FrontendArchitecture {
  structure: {
    presentation: PresentationLayer;
    business: BusinessLogicLayer;
    data: DataAccessLayer;
    infrastructure: InfrastructureLayer;
  };
  
  patterns: {
    stateManagement: StateManagementPattern;
    routing: RoutingPattern;
    componentComposition: ComponentCompositionPattern;
    errorHandling: ErrorHandlingPattern;
  };
  
  optimization: {
    bundling: BundlingStrategy;
    caching: CachingStrategy;
    lazyLoading: LazyLoadingStrategy;
    performance: PerformanceOptimization;
  };
}

// 表现层
interface PresentationLayer {
  components: {
    atoms: AtomicComponent[];
    molecules: MolecularComponent[];
    organisms: OrganismComponent[];
    templates: TemplateComponent[];
    pages: PageComponent[];
  };
  
  styling: {
    system: DesignSystem;
    tokens: DesignTokens;
    themes: ThemeConfiguration[];
  };
  
  accessibility: {
    standards: AccessibilityStandard[];
    testing: AccessibilityTesting;
    automation: AccessibilityAutomation;
  };
}

// 业务逻辑层
interface BusinessLogicLayer {
  services: {
    domain: DomainService[];
    application: ApplicationService[];
    integration: IntegrationService[];
  };
  
  models: {
    entities: DomainEntity[];
    valueObjects: ValueObject[];
    aggregates: Aggregate[];
  };
  
  workflows: {
    processes: BusinessProcess[];
    rules: BusinessRule[];
    validations: ValidationRule[];
  };
}

// 数据访问层
interface DataAccessLayer {
  repositories: {
    api: APIRepository[];
    cache: CacheRepository[];
    local: LocalStorageRepository[];
  };
  
  synchronization: {
    offline: OfflineSyncStrategy;
    conflict: ConflictResolutionStrategy;
    merge: DataMergeStrategy;
  };
  
  optimization: {
    batching: RequestBatching;
    deduplication: RequestDeduplication;
    prefetching: DataPrefetching;
  };
}

15.2 核心模块实现

15.2.1 类型系统设计

// src/types/core.ts - 核心类型系统

// 基础类型
type ID = string;
type Timestamp = number;
type Email = `${string}@${string}.${string}`;
type PhoneNumber = `+${number}`;
type URL = `http${'s' | ''}://${string}`;

// 实体基类
interface BaseEntity {
  id: ID;
  createdAt: Timestamp;
  updatedAt: Timestamp;
  version: number;
}

// 软删除支持
interface SoftDeletable {
  deletedAt?: Timestamp;
  isDeleted: boolean;
}

// 审计支持
interface Auditable {
  createdBy: ID;
  updatedBy: ID;
  deletedBy?: ID;
}

// 多租户支持
interface MultiTenant {
  tenantId: ID;
}

// 完整实体类型
type Entity<T = {}> = BaseEntity & SoftDeletable & Auditable & MultiTenant & T;

// 用户实体
interface UserData {
  email: Email;
  username: string;
  firstName: string;
  lastName: string;
  phoneNumber?: PhoneNumber;
  avatar?: URL;
  status: 'active' | 'inactive' | 'suspended';
  lastLoginAt?: Timestamp;
  emailVerifiedAt?: Timestamp;
  phoneVerifiedAt?: Timestamp;
}

type User = Entity<UserData>;

// 角色实体
interface RoleData {
  name: string;
  description: string;
  permissions: Permission[];
  isSystem: boolean;
  priority: number;
}

type Role = Entity<RoleData>;

// 权限实体
interface PermissionData {
  resource: string;
  action: string;
  conditions?: Record<string, any>;
  effect: 'allow' | 'deny';
}

type Permission = Entity<PermissionData>;

// 组织实体
interface OrganizationData {
  name: string;
  description: string;
  parentId?: ID;
  level: number;
  path: string;
  settings: OrganizationSettings;
}

type Organization = Entity<OrganizationData>;

interface OrganizationSettings {
  timezone: string;
  locale: string;
  currency: string;
  features: string[];
  limits: {
    users: number;
    storage: number;
    apiCalls: number;
  };
}

15.2.2 状态管理系统

// src/store/index.ts - 状态管理系统

import { create } from 'zustand';
import { devtools, persist, subscribeWithSelector } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';

// 状态类型定义
interface AppState {
  // 认证状态
  auth: AuthState;
  
  // 用户状态
  user: UserState;
  
  // 应用状态
  app: ApplicationState;
  
  // 通知状态
  notifications: NotificationState;
  
  // 操作
  actions: AppActions;
}

// 认证状态
interface AuthState {
  isAuthenticated: boolean;
  user: User | null;
  token: string | null;
  refreshToken: string | null;
  permissions: Permission[];
  roles: Role[];
  expiresAt: Timestamp | null;
}

// 用户状态
interface UserState {
  profile: User | null;
  preferences: UserPreferences;
  organizations: Organization[];
  currentOrganization: Organization | null;
}

// 应用状态
interface ApplicationState {
  theme: 'light' | 'dark' | 'auto';
  locale: string;
  timezone: string;
  sidebarCollapsed: boolean;
  loading: Record<string, boolean>;
  errors: Record<string, string | null>;
}

// 通知状态
interface NotificationState {
  items: Notification[];
  unreadCount: number;
  settings: NotificationSettings;
}

// 操作接口
interface AppActions {
  // 认证操作
  auth: {
    login: (credentials: LoginCredentials) => Promise<void>;
    logout: () => Promise<void>;
    refreshToken: () => Promise<void>;
    updatePermissions: (permissions: Permission[]) => void;
  };
  
  // 用户操作
  user: {
    updateProfile: (profile: Partial<UserData>) => Promise<void>;
    updatePreferences: (preferences: Partial<UserPreferences>) => void;
    switchOrganization: (organizationId: ID) => Promise<void>;
  };
  
  // 应用操作
  app: {
    setTheme: (theme: ApplicationState['theme']) => void;
    setLocale: (locale: string) => void;
    toggleSidebar: () => void;
    setLoading: (key: string, loading: boolean) => void;
    setError: (key: string, error: string | null) => void;
  };
  
  // 通知操作
  notifications: {
    add: (notification: Omit<Notification, 'id' | 'createdAt'>) => void;
    remove: (id: ID) => void;
    markAsRead: (id: ID) => void;
    markAllAsRead: () => void;
    updateSettings: (settings: Partial<NotificationSettings>) => void;
  };
}

// 创建状态存储
export const useAppStore = create<AppState>()()
  devtools(
    persist(
      subscribeWithSelector(
        immer((set, get) => ({
          // 初始状态
          auth: {
            isAuthenticated: false,
            user: null,
            token: null,
            refreshToken: null,
            permissions: [],
            roles: [],
            expiresAt: null,
          },
          
          user: {
            profile: null,
            preferences: {
              theme: 'auto',
              locale: 'en-US',
              timezone: 'UTC',
              notifications: {
                email: true,
                push: true,
                sms: false,
              },
            },
            organizations: [],
            currentOrganization: null,
          },
          
          app: {
            theme: 'auto',
            locale: 'en-US',
            timezone: 'UTC',
            sidebarCollapsed: false,
            loading: {},
            errors: {},
          },
          
          notifications: {
            items: [],
            unreadCount: 0,
            settings: {
              email: true,
              push: true,
              sms: false,
              categories: {
                system: true,
                security: true,
                updates: true,
                marketing: false,
              },
            },
          },
          
          // 操作实现
          actions: {
            auth: {
              login: async (credentials) => {
                set((state) => {
                  state.app.loading.auth = true;
                  state.app.errors.auth = null;
                });
                
                try {
                  const response = await authService.login(credentials);
                  
                  set((state) => {
                    state.auth.isAuthenticated = true;
                    state.auth.user = response.user;
                    state.auth.token = response.token;
                    state.auth.refreshToken = response.refreshToken;
                    state.auth.permissions = response.permissions;
                    state.auth.roles = response.roles;
                    state.auth.expiresAt = response.expiresAt;
                    state.user.profile = response.user;
                    state.app.loading.auth = false;
                  });
                } catch (error) {
                  set((state) => {
                    state.app.loading.auth = false;
                    state.app.errors.auth = error.message;
                  });
                  throw error;
                }
              },
              
              logout: async () => {
                try {
                  await authService.logout();
                } finally {
                  set((state) => {
                    state.auth.isAuthenticated = false;
                    state.auth.user = null;
                    state.auth.token = null;
                    state.auth.refreshToken = null;
                    state.auth.permissions = [];
                    state.auth.roles = [];
                    state.auth.expiresAt = null;
                    state.user.profile = null;
                    state.user.organizations = [];
                    state.user.currentOrganization = null;
                  });
                }
              },
              
              refreshToken: async () => {
                const { refreshToken } = get().auth;
                if (!refreshToken) throw new Error('No refresh token available');
                
                try {
                  const response = await authService.refreshToken(refreshToken);
                  
                  set((state) => {
                    state.auth.token = response.token;
                    state.auth.expiresAt = response.expiresAt;
                  });
                } catch (error) {
                  // 刷新失败,清除认证状态
                  get().actions.auth.logout();
                  throw error;
                }
              },
              
              updatePermissions: (permissions) => {
                set((state) => {
                  state.auth.permissions = permissions;
                });
              },
            },
            
            user: {
              updateProfile: async (profile) => {
                set((state) => {
                  state.app.loading.profile = true;
                  state.app.errors.profile = null;
                });
                
                try {
                  const updatedProfile = await userService.updateProfile(profile);
                  
                  set((state) => {
                    state.user.profile = updatedProfile;
                    state.auth.user = updatedProfile;
                    state.app.loading.profile = false;
                  });
                } catch (error) {
                  set((state) => {
                    state.app.loading.profile = false;
                    state.app.errors.profile = error.message;
                  });
                  throw error;
                }
              },
              
              updatePreferences: (preferences) => {
                set((state) => {
                  Object.assign(state.user.preferences, preferences);
                });
              },
              
              switchOrganization: async (organizationId) => {
                const organization = get().user.organizations.find(org => org.id === organizationId);
                if (!organization) throw new Error('Organization not found');
                
                set((state) => {
                  state.user.currentOrganization = organization;
                });
                
                // 重新获取权限
                const permissions = await authService.getPermissions(organizationId);
                get().actions.auth.updatePermissions(permissions);
              },
            },
            
            app: {
              setTheme: (theme) => {
                set((state) => {
                  state.app.theme = theme;
                });
              },
              
              setLocale: (locale) => {
                set((state) => {
                  state.app.locale = locale;
                });
              },
              
              toggleSidebar: () => {
                set((state) => {
                  state.app.sidebarCollapsed = !state.app.sidebarCollapsed;
                });
              },
              
              setLoading: (key, loading) => {
                set((state) => {
                  state.app.loading[key] = loading;
                });
              },
              
              setError: (key, error) => {
                set((state) => {
                  state.app.errors[key] = error;
                });
              },
            },
            
            notifications: {
              add: (notification) => {
                const newNotification: Notification = {
                  ...notification,
                  id: generateId(),
                  createdAt: Date.now(),
                };
                
                set((state) => {
                  state.notifications.items.unshift(newNotification);
                  if (!newNotification.read) {
                    state.notifications.unreadCount++;
                  }
                });
              },
              
              remove: (id) => {
                set((state) => {
                  const index = state.notifications.items.findIndex(item => item.id === id);
                  if (index !== -1) {
                    const notification = state.notifications.items[index];
                    if (!notification.read) {
                      state.notifications.unreadCount--;
                    }
                    state.notifications.items.splice(index, 1);
                  }
                });
              },
              
              markAsRead: (id) => {
                set((state) => {
                  const notification = state.notifications.items.find(item => item.id === id);
                  if (notification && !notification.read) {
                    notification.read = true;
                    state.notifications.unreadCount--;
                  }
                });
              },
              
              markAllAsRead: () => {
                set((state) => {
                  state.notifications.items.forEach(item => {
                    item.read = true;
                  });
                  state.notifications.unreadCount = 0;
                });
              },
              
              updateSettings: (settings) => {
                set((state) => {
                  Object.assign(state.notifications.settings, settings);
                });
              },
            },
          },
        }))
      ),
      {
        name: 'app-store',
        partialize: (state) => ({
          user: {
            preferences: state.user.preferences,
          },
          app: {
            theme: state.app.theme,
            locale: state.app.locale,
            sidebarCollapsed: state.app.sidebarCollapsed,
          },
          notifications: {
            settings: state.notifications.settings,
          },
        }),
      }
    )
  )
);

// 选择器 Hooks
export const useAuth = () => useAppStore((state) => state.auth);
export const useUser = () => useAppStore((state) => state.user);
export const useApp = () => useAppStore((state) => state.app);
export const useNotifications = () => useAppStore((state) => state.notifications);
export const useActions = () => useAppStore((state) => state.actions);

// 类型定义
interface LoginCredentials {
  email: string;
  password: string;
  rememberMe?: boolean;
}

interface UserPreferences {
  theme: 'light' | 'dark' | 'auto';
  locale: string;
  timezone: string;
  notifications: {
    email: boolean;
    push: boolean;
    sms: boolean;
  };
}

interface Notification {
  id: ID;
  title: string;
  message: string;
  type: 'info' | 'success' | 'warning' | 'error';
  category: 'system' | 'security' | 'updates' | 'marketing';
  read: boolean;
  createdAt: Timestamp;
  actionUrl?: URL;
  actionText?: string;
}

interface NotificationSettings {
  email: boolean;
  push: boolean;
  sms: boolean;
  categories: {
    system: boolean;
    security: boolean;
    updates: boolean;
    marketing: boolean;
  };
}

// 工具函数
function generateId(): ID {
  return Math.random().toString(36).substr(2, 9);
}

// 服务接口(需要实现)
declare const authService: {
  login: (credentials: LoginCredentials) => Promise<{
    user: User;
    token: string;
    refreshToken: string;
    permissions: Permission[];
    roles: Role[];
    expiresAt: Timestamp;
  }>;
  logout: () => Promise<void>;
  refreshToken: (token: string) => Promise<{
    token: string;
    expiresAt: Timestamp;
  }>;
  getPermissions: (organizationId: ID) => Promise<Permission[]>;
};

declare const userService: {
  updateProfile: (profile: Partial<UserData>) => Promise<User>;
};

15.2.3 权限控制系统

// src/auth/permission-system.ts - 权限控制系统

// 权限检查器
class PermissionChecker {
  private permissions: Permission[];
  private roles: Role[];
  private context: PermissionContext;
  
  constructor(permissions: Permission[], roles: Role[], context: PermissionContext) {
    this.permissions = permissions;
    this.roles = roles;
    this.context = context;
  }
  
  // 检查是否有权限
  can(resource: string, action: string, target?: any): boolean {
    // 检查直接权限
    const directPermission = this.checkDirectPermission(resource, action, target);
    if (directPermission !== null) return directPermission;
    
    // 检查角色权限
    const rolePermission = this.checkRolePermission(resource, action, target);
    if (rolePermission !== null) return rolePermission;
    
    // 默认拒绝
    return false;
  }
  
  // 检查多个权限(AND 逻辑)
  canAll(checks: PermissionCheck[]): boolean {
    return checks.every(check => this.can(check.resource, check.action, check.target));
  }
  
  // 检查多个权限(OR 逻辑)
  canAny(checks: PermissionCheck[]): boolean {
    return checks.some(check => this.can(check.resource, check.action, check.target));
  }
  
  // 获取资源的可用操作
  getAvailableActions(resource: string, target?: any): string[] {
    const actions = new Set<string>();
    
    // 从权限中获取
    this.permissions
      .filter(p => p.resource === resource && this.evaluateConditions(p.conditions, target))
      .forEach(p => {
        if (p.effect === 'allow') {
          actions.add(p.action);
        } else {
          actions.delete(p.action);
        }
      });
    
    // 从角色中获取
    this.roles.forEach(role => {
      role.permissions
        .filter(p => p.resource === resource && this.evaluateConditions(p.conditions, target))
        .forEach(p => {
          if (p.effect === 'allow') {
            actions.add(p.action);
          } else {
            actions.delete(p.action);
          }
        });
    });
    
    return Array.from(actions);
  }
  
  // 过滤数据(基于权限)
  filterData<T extends Record<string, any>>(data: T[], resource: string, action: string = 'read'): T[] {
    return data.filter(item => this.can(resource, action, item));
  }
  
  private checkDirectPermission(resource: string, action: string, target?: any): boolean | null {
    const relevantPermissions = this.permissions.filter(p => 
      p.resource === resource && p.action === action
    );
    
    if (relevantPermissions.length === 0) return null;
    
    // 评估条件并应用效果
    let result: boolean | null = null;
    
    for (const permission of relevantPermissions) {
      if (this.evaluateConditions(permission.conditions, target)) {
        result = permission.effect === 'allow';
      }
    }
    
    return result;
  }
  
  private checkRolePermission(resource: string, action: string, target?: any): boolean | null {
    let result: boolean | null = null;
    
    for (const role of this.roles) {
      const roleResult = this.checkRolePermissions(role.permissions, resource, action, target);
      if (roleResult !== null) {
        result = roleResult;
      }
    }
    
    return result;
  }
  
  private checkRolePermissions(permissions: Permission[], resource: string, action: string, target?: any): boolean | null {
    const relevantPermissions = permissions.filter(p => 
      p.resource === resource && p.action === action
    );
    
    if (relevantPermissions.length === 0) return null;
    
    let result: boolean | null = null;
    
    for (const permission of relevantPermissions) {
      if (this.evaluateConditions(permission.conditions, target)) {
        result = permission.effect === 'allow';
      }
    }
    
    return result;
  }
  
  private evaluateConditions(conditions?: Record<string, any>, target?: any): boolean {
    if (!conditions) return true;
    if (!target) return false;
    
    return Object.entries(conditions).every(([key, expectedValue]) => {
      const actualValue = this.getNestedValue(target, key);
      return this.compareValues(actualValue, expectedValue);
    });
  }
  
  private getNestedValue(obj: any, path: string): any {
    return path.split('.').reduce((current, key) => current?.[key], obj);
  }
  
  private compareValues(actual: any, expected: any): boolean {
    if (typeof expected === 'object' && expected !== null) {
      // 支持操作符
      if ('$eq' in expected) return actual === expected.$eq;
      if ('$ne' in expected) return actual !== expected.$ne;
      if ('$gt' in expected) return actual > expected.$gt;
      if ('$gte' in expected) return actual >= expected.$gte;
      if ('$lt' in expected) return actual < expected.$lt;
      if ('$lte' in expected) return actual <= expected.$lte;
      if ('$in' in expected) return expected.$in.includes(actual);
      if ('$nin' in expected) return !expected.$nin.includes(actual);
      if ('$regex' in expected) return new RegExp(expected.$regex).test(actual);
    }
    
    return actual === expected;
  }
}

// 权限上下文
interface PermissionContext {
  userId: ID;
  organizationId: ID;
  tenantId: ID;
  ip?: string;
  userAgent?: string;
  timestamp: Timestamp;
}

// 权限检查项
interface PermissionCheck {
  resource: string;
  action: string;
  target?: any;
}

// 权限装饰器
function RequirePermission(resource: string, action: string) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = function (...args: any[]) {
      const permissionChecker = getPermissionChecker(); // 从上下文获取
      
      if (!permissionChecker.can(resource, action)) {
        throw new ForbiddenError(`Permission denied: ${resource}:${action}`);
      }
      
      return originalMethod.apply(this, args);
    };
    
    return descriptor;
  };
}

// 权限 Hook
function usePermission() {
  const auth = useAuth();
  
  const permissionChecker = useMemo(() => {
    if (!auth.isAuthenticated) {
      return new PermissionChecker([], [], {
        userId: '',
        organizationId: '',
        tenantId: '',
        timestamp: Date.now(),
      });
    }
    
    return new PermissionChecker(
      auth.permissions,
      auth.roles,
      {
        userId: auth.user!.id,
        organizationId: auth.user!.tenantId, // 假设 tenantId 就是组织 ID
        tenantId: auth.user!.tenantId,
        timestamp: Date.now(),
      }
    );
  }, [auth]);
  
  return {
    can: permissionChecker.can.bind(permissionChecker),
    canAll: permissionChecker.canAll.bind(permissionChecker),
    canAny: permissionChecker.canAny.bind(permissionChecker),
    getAvailableActions: permissionChecker.getAvailableActions.bind(permissionChecker),
    filterData: permissionChecker.filterData.bind(permissionChecker),
  };
}

// 权限组件
interface PermissionGuardProps {
  resource: string;
  action: string;
  target?: any;
  fallback?: React.ReactNode;
  children: React.ReactNode;
}

function PermissionGuard({ resource, action, target, fallback, children }: PermissionGuardProps) {
  const { can } = usePermission();
  
  if (!can(resource, action, target)) {
    return <>{fallback || null}</>;
  }
  
  return <>{children}</>;
}

// 错误类
class ForbiddenError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ForbiddenError';
  }
}

// 工具函数
function getPermissionChecker(): PermissionChecker {
  // 从全局上下文或依赖注入容器获取
  throw new Error('Not implemented');
}

export {
  PermissionChecker,
  RequirePermission,
  usePermission,
  PermissionGuard,
  ForbiddenError,
};

export type {
  PermissionContext,
  PermissionCheck,
  PermissionGuardProps,
};

15.3 高级功能实现

15.3.1 实时通信系统

// src/realtime/websocket-manager.ts - WebSocket 管理器

class WebSocketManager {
  private ws: WebSocket | null = null;
  private url: string;
  private protocols?: string[];
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 1000;
  private heartbeatInterval = 30000;
  private heartbeatTimer: NodeJS.Timeout | null = null;
  private messageQueue: QueuedMessage[] = [];
  private eventHandlers = new Map<string, Set<EventHandler>>();
  private connectionState: ConnectionState = 'disconnected';
  
  constructor(url: string, protocols?: string[]) {
    this.url = url;
    this.protocols = protocols;
  }
  
  // 连接
  async connect(): Promise<void> {
    if (this.connectionState === 'connected' || this.connectionState === 'connecting') {
      return;
    }
    
    this.connectionState = 'connecting';
    this.emit('connecting');
    
    try {
      this.ws = new WebSocket(this.url, this.protocols);
      
      this.ws.onopen = this.handleOpen.bind(this);
      this.ws.onmessage = this.handleMessage.bind(this);
      this.ws.onclose = this.handleClose.bind(this);
      this.ws.onerror = this.handleError.bind(this);
      
      await this.waitForConnection();
    } catch (error) {
      this.connectionState = 'disconnected';
      this.emit('error', error);
      throw error;
    }
  }
  
  // 断开连接
  disconnect(): void {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
    
    if (this.ws) {
      this.ws.close(1000, 'Client disconnect');
      this.ws = null;
    }
    
    this.connectionState = 'disconnected';
    this.reconnectAttempts = 0;
    this.emit('disconnected');
  }
  
  // 发送消息
  send<T = any>(type: string, data: T): void {
    const message: WebSocketMessage<T> = {
      id: generateId(),
      type,
      data,
      timestamp: Date.now(),
    };
    
    if (this.connectionState === 'connected' && this.ws) {
      this.ws.send(JSON.stringify(message));
    } else {
      // 排队等待连接
      this.messageQueue.push({
        message,
        retries: 0,
        maxRetries: 3,
      });
    }
  }
  
  // 订阅事件
  on(event: string, handler: EventHandler): () => void {
    if (!this.eventHandlers.has(event)) {
      this.eventHandlers.set(event, new Set());
    }
    
    this.eventHandlers.get(event)!.add(handler);
    
    // 返回取消订阅函数
    return () => {
      this.eventHandlers.get(event)?.delete(handler);
    };
  }
  
  // 一次性事件监听
  once(event: string, handler: EventHandler): () => void {
    const wrappedHandler = (...args: any[]) => {
      handler(...args);
      unsubscribe();
    };
    
    const unsubscribe = this.on(event, wrappedHandler);
    return unsubscribe;
  }
  
  // 获取连接状态
  getConnectionState(): ConnectionState {
    return this.connectionState;
  }
  
  // 获取连接统计
  getStats(): ConnectionStats {
    return {
      connectionState: this.connectionState,
      reconnectAttempts: this.reconnectAttempts,
      queuedMessages: this.messageQueue.length,
      lastConnectedAt: this.lastConnectedAt,
      lastDisconnectedAt: this.lastDisconnectedAt,
    };
  }
  
  private lastConnectedAt: Timestamp | null = null;
  private lastDisconnectedAt: Timestamp | null = null;
  
  private async waitForConnection(): Promise<void> {
    return new Promise((resolve, reject) => {
      if (!this.ws) {
        reject(new Error('WebSocket not initialized'));
        return;
      }
      
      const timeout = setTimeout(() => {
        reject(new Error('Connection timeout'));
      }, 10000);
      
      this.ws.addEventListener('open', () => {
        clearTimeout(timeout);
        resolve();
      }, { once: true });
      
      this.ws.addEventListener('error', (error) => {
        clearTimeout(timeout);
        reject(error);
      }, { once: true });
    });
  }
  
  private handleOpen(): void {
    this.connectionState = 'connected';
    this.lastConnectedAt = Date.now();
    this.reconnectAttempts = 0;
    
    this.emit('connected');
    this.startHeartbeat();
    this.processMessageQueue();
  }
  
  private handleMessage(event: MessageEvent): void {
    try {
      const message = JSON.parse(event.data) as WebSocketMessage;
      this.emit('message', message);
      this.emit(`message:${message.type}`, message);
    } catch (error) {
      this.emit('error', new Error('Failed to parse message'));
    }
  }
  
  private handleClose(event: CloseEvent): void {
    this.connectionState = 'disconnected';
    this.lastDisconnectedAt = Date.now();
    
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
    
    this.emit('disconnected', {
      code: event.code,
      reason: event.reason,
      wasClean: event.wasClean,
    });
    
    // 自动重连(除非是正常关闭)
    if (event.code !== 1000 && this.reconnectAttempts < this.maxReconnectAttempts) {
      this.scheduleReconnect();
    }
  }
  
  private handleError(event: Event): void {
    this.emit('error', new Error('WebSocket error'));
  }
  
  private scheduleReconnect(): void {
    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);
    
    setTimeout(() => {
      this.reconnectAttempts++;
      this.emit('reconnecting', this.reconnectAttempts);
      this.connect().catch(() => {
        // 重连失败,会在 handleClose 中再次尝试
      });
    }, delay);
  }
  
  private startHeartbeat(): void {
    this.heartbeatTimer = setInterval(() => {
      if (this.connectionState === 'connected') {
        this.send('ping', { timestamp: Date.now() });
      }
    }, this.heartbeatInterval);
  }
  
  private processMessageQueue(): void {
    while (this.messageQueue.length > 0 && this.connectionState === 'connected') {
      const queuedMessage = this.messageQueue.shift()!;
      
      try {
        this.ws!.send(JSON.stringify(queuedMessage.message));
      } catch (error) {
        // 发送失败,重新排队
        if (queuedMessage.retries < queuedMessage.maxRetries) {
          queuedMessage.retries++;
          this.messageQueue.unshift(queuedMessage);
        }
        break;
      }
    }
  }
  
  private emit(event: string, ...args: any[]): void {
    const handlers = this.eventHandlers.get(event);
    if (handlers) {
      handlers.forEach(handler => {
        try {
          handler(...args);
        } catch (error) {
          console.error(`Error in event handler for ${event}:`, error);
        }
      });
    }
  }
}

// 类型定义
type ConnectionState = 'disconnected' | 'connecting' | 'connected';

interface WebSocketMessage<T = any> {
  id: string;
  type: string;
  data: T;
  timestamp: Timestamp;
}

interface QueuedMessage {
  message: WebSocketMessage;
  retries: number;
  maxRetries: number;
}

type EventHandler = (...args: any[]) => void;

interface ConnectionStats {
  connectionState: ConnectionState;
  reconnectAttempts: number;
  queuedMessages: number;
  lastConnectedAt: Timestamp | null;
  lastDisconnectedAt: Timestamp | null;
}

// React Hook
function useWebSocket(url: string, protocols?: string[]) {
  const [manager] = useState(() => new WebSocketManager(url, protocols));
  const [connectionState, setConnectionState] = useState<ConnectionState>('disconnected');
  const [stats, setStats] = useState<ConnectionStats>(manager.getStats());
  
  useEffect(() => {
    const unsubscribeConnecting = manager.on('connecting', () => {
      setConnectionState('connecting');
    });
    
    const unsubscribeConnected = manager.on('connected', () => {
      setConnectionState('connected');
      setStats(manager.getStats());
    });
    
    const unsubscribeDisconnected = manager.on('disconnected', () => {
      setConnectionState('disconnected');
      setStats(manager.getStats());
    });
    
    const unsubscribeReconnecting = manager.on('reconnecting', () => {
      setStats(manager.getStats());
    });
    
    return () => {
      unsubscribeConnecting();
      unsubscribeConnected();
      unsubscribeDisconnected();
      unsubscribeReconnecting();
    };
  }, [manager]);
  
  useEffect(() => {
    return () => {
      manager.disconnect();
    };
  }, [manager]);
  
  const connect = useCallback(() => manager.connect(), [manager]);
  const disconnect = useCallback(() => manager.disconnect(), [manager]);
  const send = useCallback(<T>(type: string, data: T) => manager.send(type, data), [manager]);
  const on = useCallback((event: string, handler: EventHandler) => manager.on(event, handler), [manager]);
  const once = useCallback((event: string, handler: EventHandler) => manager.once(event, handler), [manager]);
  
  return {
    connectionState,
    stats,
    connect,
    disconnect,
    send,
    on,
    once,
  };
}

export {
  WebSocketManager,
  useWebSocket,
};

export type {
  ConnectionState,
  WebSocketMessage,
  EventHandler,
  ConnectionStats,
};

15.3.2 数据分析与可视化

// src/analytics/dashboard-system.ts - 仪表板系统

// 仪表板配置
interface DashboardConfig {
  id: ID;
  name: string;
  description: string;
  layout: DashboardLayout;
  widgets: WidgetConfig[];
  filters: FilterConfig[];
  permissions: {
    view: string[];
    edit: string[];
    share: string[];
  };
  settings: DashboardSettings;
}

// 布局配置
interface DashboardLayout {
  type: 'grid' | 'flex' | 'masonry';
  columns: number;
  gap: number;
  responsive: {
    breakpoints: Record<string, number>;
    columns: Record<string, number>;
  };
}

// 组件配置
interface WidgetConfig {
  id: ID;
  type: WidgetType;
  title: string;
  position: {
    x: number;
    y: number;
    width: number;
    height: number;
  };
  dataSource: DataSourceConfig;
  visualization: VisualizationConfig;
  interactions: InteractionConfig[];
  styling: StylingConfig;
}

// 组件类型
type WidgetType = 
  | 'chart'
  | 'table'
  | 'metric'
  | 'text'
  | 'image'
  | 'map'
  | 'calendar'
  | 'timeline';

// 数据源配置
interface DataSourceConfig {
  type: 'api' | 'websocket' | 'static' | 'computed';
  endpoint?: string;
  query?: QueryConfig;
  transform?: TransformConfig;
  cache?: CacheConfig;
  refresh?: RefreshConfig;
}

// 查询配置
interface QueryConfig {
  sql?: string;
  graphql?: string;
  rest?: {
    method: 'GET' | 'POST' | 'PUT' | 'DELETE';
    headers?: Record<string, string>;
    params?: Record<string, any>;
    body?: any;
  };
  filters?: FilterValue[];
  aggregations?: AggregationConfig[];
  sorting?: SortConfig[];
  pagination?: PaginationConfig;
}

// 可视化配置
interface VisualizationConfig {
  chartType?: ChartType;
  axes?: AxesConfig;
  series?: SeriesConfig[];
  colors?: ColorConfig;
  legend?: LegendConfig;
  tooltip?: TooltipConfig;
  animation?: AnimationConfig;
}

// 图表类型
type ChartType = 
  | 'line'
  | 'bar'
  | 'pie'
  | 'doughnut'
  | 'scatter'
  | 'bubble'
  | 'radar'
  | 'polar'
  | 'area'
  | 'heatmap'
  | 'treemap'
  | 'sankey'
  | 'funnel';

// 仪表板管理器
class DashboardManager {
  private dashboards = new Map<ID, DashboardConfig>();
  private widgets = new Map<ID, WidgetInstance>();
  private dataCache = new Map<string, CachedData>();
  private eventBus = new EventEmitter();
  
  // 创建仪表板
  async createDashboard(config: Omit<DashboardConfig, 'id'>): Promise<DashboardConfig> {
    const dashboard: DashboardConfig = {
      ...config,
      id: generateId(),
    };
    
    this.dashboards.set(dashboard.id, dashboard);
    this.eventBus.emit('dashboard:created', dashboard);
    
    return dashboard;
  }
  
  // 更新仪表板
  async updateDashboard(id: ID, updates: Partial<DashboardConfig>): Promise<DashboardConfig> {
    const dashboard = this.dashboards.get(id);
    if (!dashboard) {
      throw new Error(`Dashboard ${id} not found`);
    }
    
    const updatedDashboard = { ...dashboard, ...updates };
    this.dashboards.set(id, updatedDashboard);
    this.eventBus.emit('dashboard:updated', updatedDashboard);
    
    return updatedDashboard;
  }
  
  // 删除仪表板
  async deleteDashboard(id: ID): Promise<void> {
    const dashboard = this.dashboards.get(id);
    if (!dashboard) {
      throw new Error(`Dashboard ${id} not found`);
    }
    
    // 清理相关组件
    dashboard.widgets.forEach(widget => {
      this.widgets.delete(widget.id);
    });
    
    this.dashboards.delete(id);
    this.eventBus.emit('dashboard:deleted', { id });
  }
  
  // 添加组件
  async addWidget(dashboardId: ID, config: Omit<WidgetConfig, 'id'>): Promise<WidgetConfig> {
    const dashboard = this.dashboards.get(dashboardId);
    if (!dashboard) {
      throw new Error(`Dashboard ${dashboardId} not found`);
    }
    
    const widget: WidgetConfig = {
      ...config,
      id: generateId(),
    };
    
    dashboard.widgets.push(widget);
    
    // 创建组件实例
    const instance = await this.createWidgetInstance(widget);
    this.widgets.set(widget.id, instance);
    
    this.eventBus.emit('widget:added', { dashboardId, widget });
    
    return widget;
  }
  
  // 更新组件
  async updateWidget(id: ID, updates: Partial<WidgetConfig>): Promise<WidgetConfig> {
    const instance = this.widgets.get(id);
    if (!instance) {
      throw new Error(`Widget ${id} not found`);
    }
    
    const updatedConfig = { ...instance.config, ...updates };
    instance.config = updatedConfig;
    
    // 如果数据源配置改变,重新加载数据
    if (updates.dataSource) {
      await instance.loadData();
    }
    
    this.eventBus.emit('widget:updated', { widget: updatedConfig });
    
    return updatedConfig;
  }
  
  // 删除组件
  async removeWidget(dashboardId: ID, widgetId: ID): Promise<void> {
    const dashboard = this.dashboards.get(dashboardId);
    if (!dashboard) {
      throw new Error(`Dashboard ${dashboardId} not found`);
    }
    
    const widgetIndex = dashboard.widgets.findIndex(w => w.id === widgetId);
    if (widgetIndex === -1) {
      throw new Error(`Widget ${widgetId} not found in dashboard`);
    }
    
    dashboard.widgets.splice(widgetIndex, 1);
    this.widgets.delete(widgetId);
    
    this.eventBus.emit('widget:removed', { dashboardId, widgetId });
  }
  
  // 获取仪表板数据
  async getDashboardData(id: ID): Promise<DashboardData> {
    const dashboard = this.dashboards.get(id);
    if (!dashboard) {
      throw new Error(`Dashboard ${id} not found`);
    }
    
    const widgetData = await Promise.all(
      dashboard.widgets.map(async (widget) => {
        const instance = this.widgets.get(widget.id);
        if (!instance) {
          throw new Error(`Widget instance ${widget.id} not found`);
        }
        
        return {
          widgetId: widget.id,
          data: await instance.getData(),
          metadata: instance.getMetadata(),
        };
      })
    );
    
    return {
      dashboard,
      widgets: widgetData,
      timestamp: Date.now(),
    };
  }
  
  // 刷新仪表板数据
  async refreshDashboard(id: ID): Promise<void> {
    const dashboard = this.dashboards.get(id);
    if (!dashboard) {
      throw new Error(`Dashboard ${id} not found`);
    }
    
    await Promise.all(
      dashboard.widgets.map(async (widget) => {
        const instance = this.widgets.get(widget.id);
        if (instance) {
          await instance.loadData(true); // 强制刷新
        }
      })
    );
    
    this.eventBus.emit('dashboard:refreshed', { id });
  }
  
  // 导出仪表板
  async exportDashboard(id: ID, format: 'json' | 'pdf' | 'png'): Promise<Blob> {
    const dashboardData = await this.getDashboardData(id);
    
    switch (format) {
      case 'json':
        return new Blob([JSON.stringify(dashboardData, null, 2)], {
          type: 'application/json',
        });
      
      case 'pdf':
        return await this.generatePDF(dashboardData);
      
      case 'png':
        return await this.generateImage(dashboardData);
      
      default:
        throw new Error(`Unsupported export format: ${format}`);
    }
  }
  
  // 订阅事件
  on(event: string, handler: (...args: any[]) => void): () => void {
    this.eventBus.on(event, handler);
    return () => this.eventBus.off(event, handler);
  }
  
  private async createWidgetInstance(config: WidgetConfig): Promise<WidgetInstance> {
    const instance = new WidgetInstance(config, this.dataCache);
    await instance.initialize();
    return instance;
  }
  
  private async generatePDF(data: DashboardData): Promise<Blob> {
    // 实现 PDF 生成逻辑
    throw new Error('PDF generation not implemented');
  }
  
  private async generateImage(data: DashboardData): Promise<Blob> {
    // 实现图片生成逻辑
    throw new Error('Image generation not implemented');
  }
}

// 组件实例
class WidgetInstance {
  public config: WidgetConfig;
  private dataCache: Map<string, CachedData>;
  private data: any = null;
  private metadata: WidgetMetadata = {
    lastUpdated: null,
    dataPoints: 0,
    status: 'idle',
  };
  
  constructor(config: WidgetConfig, dataCache: Map<string, CachedData>) {
    this.config = config;
    this.dataCache = dataCache;
  }
  
  async initialize(): Promise<void> {
    await this.loadData();
  }
  
  async loadData(forceRefresh = false): Promise<void> {
    this.metadata.status = 'loading';
    
    try {
      const cacheKey = this.generateCacheKey();
      
      if (!forceRefresh && this.dataCache.has(cacheKey)) {
        const cached = this.dataCache.get(cacheKey)!;
        if (Date.now() - cached.timestamp < (this.config.dataSource.cache?.ttl || 300000)) {
          this.data = cached.data;
          this.metadata.status = 'success';
          this.metadata.lastUpdated = cached.timestamp;
          return;
        }
      }
      
      const rawData = await this.fetchData();
      const transformedData = await this.transformData(rawData);
      
      this.data = transformedData;
      this.metadata.status = 'success';
      this.metadata.lastUpdated = Date.now();
      this.metadata.dataPoints = Array.isArray(transformedData) ? transformedData.length : 1;
      
      // 缓存数据
      this.dataCache.set(cacheKey, {
        data: transformedData,
        timestamp: Date.now(),
      });
    } catch (error) {
      this.metadata.status = 'error';
      throw error;
    }
  }
  
  async getData(): Promise<any> {
    return this.data;
  }
  
  getMetadata(): WidgetMetadata {
    return { ...this.metadata };
  }
  
  private generateCacheKey(): string {
    return `widget:${this.config.id}:${JSON.stringify(this.config.dataSource)}`;
  }
  
  private async fetchData(): Promise<any> {
    const { dataSource } = this.config;
    
    switch (dataSource.type) {
      case 'api':
        return await this.fetchFromAPI(dataSource);
      
      case 'websocket':
        return await this.fetchFromWebSocket(dataSource);
      
      case 'static':
        return dataSource.query?.rest?.body || [];
      
      case 'computed':
        return await this.computeData(dataSource);
      
      default:
        throw new Error(`Unsupported data source type: ${dataSource.type}`);
    }
  }
  
  private async fetchFromAPI(dataSource: DataSourceConfig): Promise<any> {
    if (!dataSource.endpoint) {
      throw new Error('API endpoint is required');
    }
    
    const { query } = dataSource;
    const response = await fetch(dataSource.endpoint, {
      method: query?.rest?.method || 'GET',
      headers: {
        'Content-Type': 'application/json',
        ...query?.rest?.headers,
      },
      body: query?.rest?.body ? JSON.stringify(query.rest.body) : undefined,
    });
    
    if (!response.ok) {
      throw new Error(`API request failed: ${response.statusText}`);
    }
    
    return await response.json();
  }
  
  private async fetchFromWebSocket(dataSource: DataSourceConfig): Promise<any> {
    // WebSocket 数据获取实现
    throw new Error('WebSocket data source not implemented');
  }
  
  private async computeData(dataSource: DataSourceConfig): Promise<any> {
    // 计算数据实现
    throw new Error('Computed data source not implemented');
  }
  
  private async transformData(data: any): Promise<any> {
    const { transform } = this.config.dataSource;
    if (!transform) return data;
    
    // 应用数据转换
    let result = data;
    
    if (transform.filter) {
      result = this.applyFilter(result, transform.filter);
    }
    
    if (transform.map) {
      result = this.applyMapping(result, transform.map);
    }
    
    if (transform.aggregate) {
      result = this.applyAggregation(result, transform.aggregate);
    }
    
    if (transform.sort) {
      result = this.applySort(result, transform.sort);
    }
    
    return result;
  }
  
  private applyFilter(data: any[], filter: FilterConfig): any[] {
    return data.filter(item => {
      return filter.conditions.every(condition => {
        const value = this.getNestedValue(item, condition.field);
        return this.evaluateCondition(value, condition.operator, condition.value);
      });
    });
  }
  
  private applyMapping(data: any[], mapping: MappingConfig): any[] {
    return data.map(item => {
      const mapped: any = {};
      
      Object.entries(mapping.fields).forEach(([targetField, sourceField]) => {
        mapped[targetField] = this.getNestedValue(item, sourceField);
      });
      
      return mapped;
    });
  }
  
  private applyAggregation(data: any[], aggregation: AggregationConfig): any {
    const grouped = this.groupBy(data, aggregation.groupBy);
    
    return Object.entries(grouped).map(([key, items]) => {
      const result: any = { [aggregation.groupBy]: key };
      
      aggregation.metrics.forEach(metric => {
        const values = items.map(item => this.getNestedValue(item, metric.field));
        result[metric.alias || metric.field] = this.calculateMetric(values, metric.function);
      });
      
      return result;
    });
  }
  
  private applySort(data: any[], sort: SortConfig[]): any[] {
    return data.sort((a, b) => {
      for (const sortRule of sort) {
        const aValue = this.getNestedValue(a, sortRule.field);
        const bValue = this.getNestedValue(b, sortRule.field);
        
        const comparison = this.compareValues(aValue, bValue);
        if (comparison !== 0) {
          return sortRule.direction === 'desc' ? -comparison : comparison;
        }
      }
      return 0;
    });
  }
  
  private getNestedValue(obj: any, path: string): any {
    return path.split('.').reduce((current, key) => current?.[key], obj);
  }
  
  private evaluateCondition(value: any, operator: string, expected: any): boolean {
    switch (operator) {
      case 'eq': return value === expected;
      case 'ne': return value !== expected;
      case 'gt': return value > expected;
      case 'gte': return value >= expected;
      case 'lt': return value < expected;
      case 'lte': return value <= expected;
      case 'in': return Array.isArray(expected) && expected.includes(value);
      case 'nin': return Array.isArray(expected) && !expected.includes(value);
      case 'contains': return String(value).includes(String(expected));
      case 'startsWith': return String(value).startsWith(String(expected));
      case 'endsWith': return String(value).endsWith(String(expected));
      default: return false;
    }
  }
  
  private groupBy(data: any[], field: string): Record<string, any[]> {
    return data.reduce((groups, item) => {
      const key = this.getNestedValue(item, field);
      if (!groups[key]) groups[key] = [];
      groups[key].push(item);
      return groups;
    }, {});
  }
  
  private calculateMetric(values: any[], func: string): any {
    const numbers = values.filter(v => typeof v === 'number');
    
    switch (func) {
      case 'sum': return numbers.reduce((sum, val) => sum + val, 0);
      case 'avg': return numbers.length > 0 ? numbers.reduce((sum, val) => sum + val, 0) / numbers.length : 0;
      case 'min': return numbers.length > 0 ? Math.min(...numbers) : null;
      case 'max': return numbers.length > 0 ? Math.max(...numbers) : null;
      case 'count': return values.length;
      case 'countDistinct': return new Set(values).size;
      default: return null;
    }
  }
  
  private compareValues(a: any, b: any): number {
    if (a === b) return 0;
    if (a == null) return -1;
    if (b == null) return 1;
    
    if (typeof a === 'number' && typeof b === 'number') {
      return a - b;
    }
    
    return String(a).localeCompare(String(b));
  }
}

// 类型定义
interface DashboardData {
  dashboard: DashboardConfig;
  widgets: {
    widgetId: ID;
    data: any;
    metadata: WidgetMetadata;
  }[];
  timestamp: Timestamp;
}

interface WidgetMetadata {
  lastUpdated: Timestamp | null;
  dataPoints: number;
  status: 'idle' | 'loading' | 'success' | 'error';
}

interface CachedData {
  data: any;
  timestamp: Timestamp;
}

interface TransformConfig {
  filter?: FilterConfig;
  map?: MappingConfig;
  aggregate?: AggregationConfig;
  sort?: SortConfig[];
}

interface FilterConfig {
  conditions: {
    field: string;
    operator: string;
    value: any;
  }[];
}

interface MappingConfig {
  fields: Record<string, string>;
}

interface AggregationConfig {
  groupBy: string;
  metrics: {
    field: string;
    function: string;
    alias?: string;
  }[];
}

interface SortConfig {
  field: string;
  direction: 'asc' | 'desc';
}

interface CacheConfig {
  ttl: number; // Time to live in milliseconds
  maxSize?: number;
}

interface RefreshConfig {
  interval?: number; // Auto refresh interval in milliseconds
  onFocus?: boolean; // Refresh when window gains focus
  onVisible?: boolean; // Refresh when widget becomes visible
}

interface FilterValue {
  field: string;
  operator: string;
  value: any;
}

interface PaginationConfig {
  page: number;
  size: number;
}

interface AxesConfig {
  x?: AxisConfig;
  y?: AxisConfig;
}

interface AxisConfig {
  label?: string;
  min?: number;
  max?: number;
  type?: 'linear' | 'logarithmic' | 'category' | 'time';
}

interface SeriesConfig {
  name: string;
  data: string; // Field name
  color?: string;
  type?: ChartType;
}

interface ColorConfig {
  scheme?: string;
  custom?: string[];
}

interface LegendConfig {
  show: boolean;
  position: 'top' | 'bottom' | 'left' | 'right';
}

interface TooltipConfig {
  show: boolean;
  format?: string;
}

interface AnimationConfig {
  enabled: boolean;
  duration?: number;
  easing?: string;
}

interface InteractionConfig {
  type: 'click' | 'hover' | 'select';
  action: 'filter' | 'navigate' | 'highlight' | 'custom';
  target?: string;
  params?: Record<string, any>;
}

interface StylingConfig {
  theme?: string;
  colors?: ColorConfig;
  fonts?: FontConfig;
  spacing?: SpacingConfig;
}

interface FontConfig {
  family?: string;
  size?: number;
  weight?: string;
}

interface SpacingConfig {
  padding?: number;
  margin?: number;
}

interface DashboardSettings {
  autoRefresh?: boolean;
  refreshInterval?: number;
  theme?: string;
  timezone?: string;
  locale?: string;
}

// React Hook
function useDashboard(dashboardId: ID) {
  const [dashboard, setDashboard] = useState<DashboardConfig | null>(null);
  const [data, setData] = useState<DashboardData | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  
  const manager = useMemo(() => new DashboardManager(), []);
  
  const loadDashboard = useCallback(async () => {
    setLoading(true);
    setError(null);
    
    try {
      const dashboardData = await manager.getDashboardData(dashboardId);
      setDashboard(dashboardData.dashboard);
      setData(dashboardData);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unknown error');
    } finally {
      setLoading(false);
    }
  }, [manager, dashboardId]);
  
  const refreshDashboard = useCallback(async () => {
    try {
      await manager.refreshDashboard(dashboardId);
      await loadDashboard();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unknown error');
    }
  }, [manager, dashboardId, loadDashboard]);
  
  useEffect(() => {
    loadDashboard();
  }, [loadDashboard]);
  
  return {
    dashboard,
    data,
    loading,
    error,
    refresh: refreshDashboard,
    manager,
  };
}

export {
  DashboardManager,
  WidgetInstance,
  useDashboard,
};

export type {
  DashboardConfig,
  WidgetConfig,
  DashboardData,
  WidgetMetadata,
};

6.6 API 网关实现

// src/gateway/types.ts
interface RouteConfig {
  id: ID;
  path: string;
  method: HttpMethod;
  target: {
    service: string;
    path: string;
    timeout?: number;
  };
  middleware?: MiddlewareConfig[];
  rateLimit?: RateLimitConfig;
  auth?: AuthConfig;
  cache?: CacheConfig;
  transform?: {
    request?: TransformConfig;
    response?: TransformConfig;
  };
}

interface MiddlewareConfig {
  name: string;
  config?: Record<string, any>;
  order: number;
}

interface RateLimitConfig {
  windowMs: number;
  maxRequests: number;
  keyGenerator?: (req: Request) => string;
}

interface AuthConfig {
  required: boolean;
  roles?: string[];
  permissions?: string[];
  skipPaths?: string[];
}

interface TransformConfig {
  headers?: Record<string, string>;
  body?: {
    add?: Record<string, any>;
    remove?: string[];
    transform?: Record<string, string>;
  };
}

interface ServiceRegistry {
  services: Map<string, ServiceInstance[]>;
  healthChecks: Map<string, HealthCheckConfig>;
}

interface ServiceInstance {
  id: ID;
  name: string;
  host: string;
  port: number;
  protocol: 'http' | 'https';
  weight: number;
  status: 'healthy' | 'unhealthy' | 'unknown';
  metadata: Record<string, any>;
  lastHealthCheck: Timestamp;
}

interface HealthCheckConfig {
  path: string;
  interval: number;
  timeout: number;
  retries: number;
  successThreshold: number;
  failureThreshold: number;
}

// API 网关核心类
class APIGateway {
  private routes: Map<string, RouteConfig> = new Map();
  private serviceRegistry: ServiceRegistry;
  private loadBalancer: LoadBalancer;
  private circuitBreaker: CircuitBreaker;
  private rateLimiter: RateLimiter;
  private cache: CacheManager;
  private metrics: MetricsCollector;
  private logger: Logger;
  
  constructor(config: GatewayConfig) {
    this.serviceRegistry = new ServiceRegistryImpl(config.registry);
    this.loadBalancer = new LoadBalancer(config.loadBalancing);
    this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);
    this.rateLimiter = new RateLimiter(config.rateLimit);
    this.cache = new CacheManager(config.cache);
    this.metrics = new MetricsCollector();
    this.logger = new Logger('APIGateway');
  }
  
  async handleRequest(req: Request, res: Response): Promise<void> {
    const startTime = Date.now();
    const requestId = this.generateRequestId();
    
    try {
      // 1. 路由匹配
      const route = this.matchRoute(req);
      if (!route) {
        return this.sendError(res, 404, 'Route not found');
      }
      
      // 2. 中间件执行
      const middlewareResult = await this.executeMiddleware(req, res, route);
      if (!middlewareResult.continue) {
        return;
      }
      
      // 3. 认证授权
      if (route.auth?.required) {
        const authResult = await this.authenticate(req, route.auth);
        if (!authResult.success) {
          return this.sendError(res, 401, authResult.message);
        }
        req.user = authResult.user;
      }
      
      // 4. 限流检查
      if (route.rateLimit) {
        const rateLimitResult = await this.rateLimiter.check(req, route.rateLimit);
        if (!rateLimitResult.allowed) {
          return this.sendError(res, 429, 'Rate limit exceeded');
        }
      }
      
      // 5. 缓存检查
      if (route.cache && req.method === 'GET') {
        const cachedResponse = await this.cache.get(this.generateCacheKey(req));
        if (cachedResponse) {
          return this.sendCachedResponse(res, cachedResponse);
        }
      }
      
      // 6. 服务发现
      const serviceInstance = await this.discoverService(route.target.service);
      if (!serviceInstance) {
        return this.sendError(res, 503, 'Service unavailable');
      }
      
      // 7. 请求转发
      const response = await this.forwardRequest(req, route, serviceInstance);
      
      // 8. 响应缓存
      if (route.cache && req.method === 'GET' && response.status === 200) {
        await this.cache.set(
          this.generateCacheKey(req),
          response,
          route.cache.ttl
        );
      }
      
      // 9. 响应转换
      const transformedResponse = await this.transformResponse(response, route);
      
      // 10. 发送响应
      this.sendResponse(res, transformedResponse);
      
      // 11. 记录指标
      this.metrics.recordRequest({
        route: route.id,
        method: req.method,
        status: response.status,
        duration: Date.now() - startTime,
        service: serviceInstance.name,
      });
      
    } catch (error) {
      this.logger.error('Request handling failed', {
        requestId,
        error: error.message,
        stack: error.stack,
      });
      
      this.sendError(res, 500, 'Internal server error');
    }
  }
  
  private matchRoute(req: Request): RouteConfig | null {
    const path = req.path;
    const method = req.method.toLowerCase() as HttpMethod;
    
    for (const [routeKey, route] of this.routes) {
      if (route.method === method && this.pathMatches(path, route.path)) {
        return route;
      }
    }
    
    return null;
  }
  
  private pathMatches(requestPath: string, routePath: string): boolean {
    // 支持路径参数和通配符
    const routeRegex = routePath
      .replace(/:[^/]+/g, '([^/]+)')
      .replace(/\*/g, '.*');
    
    return new RegExp(`^${routeRegex}$`).test(requestPath);
  }
  
  private async executeMiddleware(
    req: Request,
    res: Response,
    route: RouteConfig
  ): Promise<{ continue: boolean }> {
    if (!route.middleware) {
      return { continue: true };
    }
    
    const sortedMiddleware = route.middleware.sort((a, b) => a.order - b.order);
    
    for (const middleware of sortedMiddleware) {
      const handler = this.getMiddlewareHandler(middleware.name);
      if (!handler) {
        this.logger.warn(`Middleware not found: ${middleware.name}`);
        continue;
      }
      
      const result = await handler(req, res, middleware.config);
      if (!result.continue) {
        return { continue: false };
      }
    }
    
    return { continue: true };
  }
  
  private async authenticate(
    req: Request,
    authConfig: AuthConfig
  ): Promise<{ success: boolean; user?: User; message?: string }> {
    const token = this.extractToken(req);
    if (!token) {
      return { success: false, message: 'No token provided' };
    }
    
    try {
      const user = await this.verifyToken(token);
      
      // 角色检查
      if (authConfig.roles && !this.hasRole(user, authConfig.roles)) {
        return { success: false, message: 'Insufficient role' };
      }
      
      // 权限检查
      if (authConfig.permissions && !this.hasPermission(user, authConfig.permissions)) {
        return { success: false, message: 'Insufficient permissions' };
      }
      
      return { success: true, user };
    } catch (error) {
      return { success: false, message: 'Invalid token' };
    }
  }
  
  private async discoverService(serviceName: string): Promise<ServiceInstance | null> {
    const instances = this.serviceRegistry.services.get(serviceName);
    if (!instances || instances.length === 0) {
      return null;
    }
    
    const healthyInstances = instances.filter(instance => instance.status === 'healthy');
    if (healthyInstances.length === 0) {
      return null;
    }
    
    return this.loadBalancer.selectInstance(healthyInstances);
  }
  
  private async forwardRequest(
    req: Request,
    route: RouteConfig,
    serviceInstance: ServiceInstance
  ): Promise<any> {
    const targetUrl = `${serviceInstance.protocol}://${serviceInstance.host}:${serviceInstance.port}${route.target.path}`;
    
    // 请求转换
    const transformedReq = await this.transformRequest(req, route);
    
    // 熔断器检查
    const circuitBreakerKey = `${serviceInstance.name}:${route.target.path}`;
    if (this.circuitBreaker.isOpen(circuitBreakerKey)) {
      throw new Error('Circuit breaker is open');
    }
    
    try {
      const response = await fetch(targetUrl, {
        method: transformedReq.method,
        headers: transformedReq.headers,
        body: transformedReq.body,
        timeout: route.target.timeout || 30000,
      });
      
      this.circuitBreaker.recordSuccess(circuitBreakerKey);
      return response;
    } catch (error) {
      this.circuitBreaker.recordFailure(circuitBreakerKey);
      throw error;
    }
  }
  
  private async transformRequest(req: Request, route: RouteConfig): Promise<any> {
    const transform = route.transform?.request;
    if (!transform) return req;
    
    const headers = { ...req.headers };
    const body = req.body;
    
    // 头部转换
    if (transform.headers) {
      Object.assign(headers, transform.headers);
    }
    
    // 请求体转换
    let transformedBody = body;
    if (transform.body) {
      if (transform.body.add) {
        transformedBody = { ...body, ...transform.body.add };
      }
      
      if (transform.body.remove) {
        transform.body.remove.forEach(key => {
          delete transformedBody[key];
        });
      }
      
      if (transform.body.transform) {
        Object.entries(transform.body.transform).forEach(([from, to]) => {
          if (transformedBody[from] !== undefined) {
            transformedBody[to] = transformedBody[from];
            delete transformedBody[from];
          }
        });
      }
    }
    
    return {
      ...req,
      headers,
      body: transformedBody,
    };
  }
  
  private async transformResponse(response: any, route: RouteConfig): Promise<any> {
    const transform = route.transform?.response;
    if (!transform) return response;
    
    // 响应转换逻辑
    return response;
  }
  
  private generateRequestId(): string {
    return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  private generateCacheKey(req: Request): string {
    return `${req.method}:${req.path}:${JSON.stringify(req.query)}`;
  }
  
  private extractToken(req: Request): string | null {
    const authHeader = req.headers.authorization;
    if (authHeader && authHeader.startsWith('Bearer ')) {
      return authHeader.substring(7);
    }
    return null;
  }
  
  private async verifyToken(token: string): Promise<User> {
    // JWT 验证逻辑
    throw new Error('Not implemented');
  }
  
  private hasRole(user: User, requiredRoles: string[]): boolean {
    return requiredRoles.some(role => user.roles.includes(role));
  }
  
  private hasPermission(user: User, requiredPermissions: string[]): boolean {
    return requiredPermissions.every(permission => 
      user.permissions.includes(permission)
    );
  }
  
  private getMiddlewareHandler(name: string): MiddlewareHandler | null {
    // 中间件处理器注册表
    const handlers: Record<string, MiddlewareHandler> = {
      cors: this.corsMiddleware,
      logging: this.loggingMiddleware,
      compression: this.compressionMiddleware,
    };
    
    return handlers[name] || null;
  }
  
  private corsMiddleware: MiddlewareHandler = async (req, res, config) => {
    res.setHeader('Access-Control-Allow-Origin', config?.origin || '*');
    res.setHeader('Access-Control-Allow-Methods', config?.methods || 'GET,POST,PUT,DELETE');
    res.setHeader('Access-Control-Allow-Headers', config?.headers || 'Content-Type,Authorization');
    
    if (req.method === 'OPTIONS') {
      res.status(200).end();
      return { continue: false };
    }
    
    return { continue: true };
  };
  
  private loggingMiddleware: MiddlewareHandler = async (req, res, config) => {
    this.logger.info('Request received', {
      method: req.method,
      path: req.path,
      userAgent: req.headers['user-agent'],
      ip: req.ip,
    });
    
    return { continue: true };
  };
  
  private compressionMiddleware: MiddlewareHandler = async (req, res, config) => {
    const acceptEncoding = req.headers['accept-encoding'] || '';
    
    if (acceptEncoding.includes('gzip')) {
      res.setHeader('Content-Encoding', 'gzip');
    } else if (acceptEncoding.includes('deflate')) {
      res.setHeader('Content-Encoding', 'deflate');
    }
    
    return { continue: true };
  };
  
  private sendResponse(res: Response, response: any): void {
    res.status(response.status);
    
    Object.entries(response.headers || {}).forEach(([key, value]) => {
      res.setHeader(key, value as string);
    });
    
    res.json(response.body);
  }
  
  private sendCachedResponse(res: Response, cachedResponse: any): void {
    res.setHeader('X-Cache', 'HIT');
    this.sendResponse(res, cachedResponse);
  }
  
  private sendError(res: Response, status: number, message: string): void {
    res.status(status).json({
      error: {
        code: status,
        message,
        timestamp: new Date().toISOString(),
      },
    });
  }
}

// 负载均衡器
class LoadBalancer {
  private strategy: LoadBalancingStrategy;
  private roundRobinIndex: Map<string, number> = new Map();
  
  constructor(config: LoadBalancingConfig) {
    this.strategy = config.strategy || 'round-robin';
  }
  
  selectInstance(instances: ServiceInstance[]): ServiceInstance {
    switch (this.strategy) {
      case 'round-robin':
        return this.roundRobin(instances);
      
      case 'weighted':
        return this.weighted(instances);
      
      case 'least-connections':
        return this.leastConnections(instances);
      
      case 'random':
        return this.random(instances);
      
      default:
        return instances[0];
    }
  }
  
  private roundRobin(instances: ServiceInstance[]): ServiceInstance {
    const key = instances.map(i => i.id).join(',');
    const currentIndex = this.roundRobinIndex.get(key) || 0;
    const nextIndex = (currentIndex + 1) % instances.length;
    
    this.roundRobinIndex.set(key, nextIndex);
    return instances[currentIndex];
  }
  
  private weighted(instances: ServiceInstance[]): ServiceInstance {
    const totalWeight = instances.reduce((sum, instance) => sum + instance.weight, 0);
    let random = Math.random() * totalWeight;
    
    for (const instance of instances) {
      random -= instance.weight;
      if (random <= 0) {
        return instance;
      }
    }
    
    return instances[instances.length - 1];
  }
  
  private leastConnections(instances: ServiceInstance[]): ServiceInstance {
    // 简化实现,实际应该跟踪连接数
    return instances[0];
  }
  
  private random(instances: ServiceInstance[]): ServiceInstance {
    const randomIndex = Math.floor(Math.random() * instances.length);
    return instances[randomIndex];
  }
}

// 熔断器
class CircuitBreaker {
  private circuits: Map<string, CircuitState> = new Map();
  private config: CircuitBreakerConfig;
  
  constructor(config: CircuitBreakerConfig) {
    this.config = config;
  }
  
  isOpen(key: string): boolean {
    const circuit = this.getCircuit(key);
    
    if (circuit.state === 'open') {
      if (Date.now() - circuit.lastFailureTime > this.config.timeout) {
        circuit.state = 'half-open';
        return false;
      }
      return true;
    }
    
    return false;
  }
  
  recordSuccess(key: string): void {
    const circuit = this.getCircuit(key);
    circuit.successCount++;
    circuit.failureCount = 0;
    
    if (circuit.state === 'half-open' && circuit.successCount >= this.config.successThreshold) {
      circuit.state = 'closed';
    }
  }
  
  recordFailure(key: string): void {
    const circuit = this.getCircuit(key);
    circuit.failureCount++;
    circuit.lastFailureTime = Date.now();
    
    if (circuit.failureCount >= this.config.failureThreshold) {
      circuit.state = 'open';
    }
  }
  
  private getCircuit(key: string): CircuitState {
    if (!this.circuits.has(key)) {
      this.circuits.set(key, {
        state: 'closed',
        failureCount: 0,
        successCount: 0,
        lastFailureTime: 0,
      });
    }
    
    return this.circuits.get(key)!;
  }
}

// 类型定义
type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';
type LoadBalancingStrategy = 'round-robin' | 'weighted' | 'least-connections' | 'random';
type CircuitState = 'closed' | 'open' | 'half-open';

interface GatewayConfig {
  registry: ServiceRegistryConfig;
  loadBalancing: LoadBalancingConfig;
  circuitBreaker: CircuitBreakerConfig;
  rateLimit: RateLimitConfig;
  cache: CacheConfig;
}

interface ServiceRegistryConfig {
  type: 'consul' | 'etcd' | 'zookeeper' | 'static';
  endpoints: string[];
  healthCheckInterval: number;
}

interface LoadBalancingConfig {
  strategy: LoadBalancingStrategy;
}

interface CircuitBreakerConfig {
  failureThreshold: number;
  successThreshold: number;
  timeout: number;
}

interface CircuitState {
  state: 'closed' | 'open' | 'half-open';
  failureCount: number;
  successCount: number;
  lastFailureTime: number;
}

type MiddlewareHandler = (
  req: Request,
  res: Response,
  config?: Record<string, any>
) => Promise<{ continue: boolean }>;

export {
  APIGateway,
  LoadBalancer,
  CircuitBreaker,
};

export type {
  RouteConfig,
  ServiceInstance,
  GatewayConfig,
};

6.7 监控与日志系统

// src/monitoring/metrics.ts
interface MetricData {
  name: string;
  value: number;
  timestamp: Timestamp;
  labels: Record<string, string>;
  type: MetricType;
}

type MetricType = 'counter' | 'gauge' | 'histogram' | 'summary';

class MetricsCollector {
  private metrics: Map<string, MetricData[]> = new Map();
  private exporters: MetricExporter[] = [];
  private aggregationInterval: number = 60000; // 1 minute
  
  constructor(config: MetricsConfig) {
    this.aggregationInterval = config.aggregationInterval || 60000;
    this.setupExporters(config.exporters);
    this.startAggregation();
  }
  
  // 计数器指标
  incrementCounter(name: string, labels: Record<string, string> = {}, value: number = 1): void {
    this.recordMetric({
      name,
      value,
      timestamp: Date.now(),
      labels,
      type: 'counter',
    });
  }
  
  // 仪表盘指标
  setGauge(name: string, value: number, labels: Record<string, string> = {}): void {
    this.recordMetric({
      name,
      value,
      timestamp: Date.now(),
      labels,
      type: 'gauge',
    });
  }
  
  // 直方图指标
  recordHistogram(name: string, value: number, labels: Record<string, string> = {}): void {
    this.recordMetric({
      name,
      value,
      timestamp: Date.now(),
      labels,
      type: 'histogram',
    });
  }
  
  // 记录请求指标
  recordRequest(data: {
    route: string;
    method: string;
    status: number;
    duration: number;
    service: string;
  }): void {
    const labels = {
      route: data.route,
      method: data.method,
      status: data.status.toString(),
      service: data.service,
    };
    
    // 请求计数
    this.incrementCounter('http_requests_total', labels);
    
    // 请求持续时间
    this.recordHistogram('http_request_duration_ms', data.duration, labels);
    
    // 错误率
    if (data.status >= 400) {
      this.incrementCounter('http_requests_errors_total', labels);
    }
  }
  
  // 记录业务指标
  recordBusinessMetric(name: string, value: number, labels: Record<string, string> = {}): void {
    this.recordMetric({
      name: `business_${name}`,
      value,
      timestamp: Date.now(),
      labels,
      type: 'gauge',
    });
  }
  
  private recordMetric(metric: MetricData): void {
    const key = this.generateMetricKey(metric);
    
    if (!this.metrics.has(key)) {
      this.metrics.set(key, []);
    }
    
    this.metrics.get(key)!.push(metric);
  }
  
  private generateMetricKey(metric: MetricData): string {
    const labelString = Object.entries(metric.labels)
      .sort(([a], [b]) => a.localeCompare(b))
      .map(([key, value]) => `${key}=${value}`)
      .join(',');
    
    return `${metric.name}{${labelString}}`;
  }
  
  private setupExporters(exporterConfigs: ExporterConfig[]): void {
    exporterConfigs.forEach(config => {
      switch (config.type) {
        case 'prometheus':
          this.exporters.push(new PrometheusExporter(config));
          break;
        
        case 'influxdb':
          this.exporters.push(new InfluxDBExporter(config));
          break;
        
        case 'console':
          this.exporters.push(new ConsoleExporter(config));
          break;
      }
    });
  }
  
  private startAggregation(): void {
    setInterval(() => {
      this.aggregateAndExport();
    }, this.aggregationInterval);
  }
  
  private async aggregateAndExport(): Promise<void> {
    const aggregatedMetrics = this.aggregateMetrics();
    
    for (const exporter of this.exporters) {
      try {
        await exporter.export(aggregatedMetrics);
      } catch (error) {
        console.error(`Failed to export metrics to ${exporter.constructor.name}:`, error);
      }
    }
    
    // 清理旧数据
    this.cleanupOldMetrics();
  }
  
  private aggregateMetrics(): AggregatedMetric[] {
    const aggregated: AggregatedMetric[] = [];
    
    for (const [key, metrics] of this.metrics) {
      if (metrics.length === 0) continue;
      
      const firstMetric = metrics[0];
      const values = metrics.map(m => m.value);
      
      switch (firstMetric.type) {
        case 'counter':
          aggregated.push({
            name: firstMetric.name,
            labels: firstMetric.labels,
            type: 'counter',
            value: values.reduce((sum, val) => sum + val, 0),
            timestamp: Date.now(),
          });
          break;
        
        case 'gauge':
          aggregated.push({
            name: firstMetric.name,
            labels: firstMetric.labels,
            type: 'gauge',
            value: values[values.length - 1], // 最新值
            timestamp: Date.now(),
          });
          break;
        
        case 'histogram':
          aggregated.push({
            name: firstMetric.name,
            labels: firstMetric.labels,
            type: 'histogram',
            value: this.calculateHistogramStats(values),
            timestamp: Date.now(),
          });
          break;
      }
    }
    
    return aggregated;
  }
  
  private calculateHistogramStats(values: number[]): HistogramStats {
    const sorted = values.sort((a, b) => a - b);
    const count = values.length;
    const sum = values.reduce((acc, val) => acc + val, 0);
    
    return {
      count,
      sum,
      min: sorted[0],
      max: sorted[count - 1],
      avg: sum / count,
      p50: this.percentile(sorted, 0.5),
      p90: this.percentile(sorted, 0.9),
      p95: this.percentile(sorted, 0.95),
      p99: this.percentile(sorted, 0.99),
    };
  }
  
  private percentile(sortedValues: number[], p: number): number {
    const index = Math.ceil(sortedValues.length * p) - 1;
    return sortedValues[Math.max(0, index)];
  }
  
  private cleanupOldMetrics(): void {
    const cutoff = Date.now() - this.aggregationInterval * 2;
    
    for (const [key, metrics] of this.metrics) {
      const filtered = metrics.filter(m => m.timestamp > cutoff);
      if (filtered.length === 0) {
        this.metrics.delete(key);
      } else {
        this.metrics.set(key, filtered);
      }
    }
  }
}

// 日志系统
class Logger {
  private context: string;
  private level: LogLevel;
  private appenders: LogAppender[] = [];
  
  constructor(context: string, config: LoggerConfig = {}) {
    this.context = context;
    this.level = config.level || 'info';
    this.setupAppenders(config.appenders || []);
  }
  
  debug(message: string, meta?: Record<string, any>): void {
    this.log('debug', message, meta);
  }
  
  info(message: string, meta?: Record<string, any>): void {
    this.log('info', message, meta);
  }
  
  warn(message: string, meta?: Record<string, any>): void {
    this.log('warn', message, meta);
  }
  
  error(message: string, meta?: Record<string, any>): void {
    this.log('error', message, meta);
  }
  
  fatal(message: string, meta?: Record<string, any>): void {
    this.log('fatal', message, meta);
  }
  
  private log(level: LogLevel, message: string, meta?: Record<string, any>): void {
    if (!this.shouldLog(level)) {
      return;
    }
    
    const logEntry: LogEntry = {
      timestamp: new Date().toISOString(),
      level,
      context: this.context,
      message,
      meta: meta || {},
      traceId: this.getTraceId(),
    };
    
    this.appenders.forEach(appender => {
      try {
        appender.append(logEntry);
      } catch (error) {
        console.error('Failed to append log:', error);
      }
    });
  }
  
  private shouldLog(level: LogLevel): boolean {
    const levels: LogLevel[] = ['debug', 'info', 'warn', 'error', 'fatal'];
    const currentLevelIndex = levels.indexOf(this.level);
    const messageLevelIndex = levels.indexOf(level);
    
    return messageLevelIndex >= currentLevelIndex;
  }
  
  private setupAppenders(appenderConfigs: AppenderConfig[]): void {
    appenderConfigs.forEach(config => {
      switch (config.type) {
        case 'console':
          this.appenders.push(new ConsoleAppender(config));
          break;
        
        case 'file':
          this.appenders.push(new FileAppender(config));
          break;
        
        case 'elasticsearch':
          this.appenders.push(new ElasticsearchAppender(config));
          break;
        
        case 'syslog':
          this.appenders.push(new SyslogAppender(config));
          break;
      }
    });
  }
  
  private getTraceId(): string {
    // 从异步上下文获取追踪ID
    return 'trace-id-placeholder';
  }
}

// 健康检查系统
class HealthChecker {
  private checks: Map<string, HealthCheck> = new Map();
  private results: Map<string, HealthCheckResult> = new Map();
  private interval: number = 30000; // 30 seconds
  
  constructor(config: HealthCheckConfig) {
    this.interval = config.interval || 30000;
    this.setupChecks(config.checks);
    this.startChecking();
  }
  
  registerCheck(name: string, check: HealthCheck): void {
    this.checks.set(name, check);
  }
  
  async getHealth(): Promise<HealthStatus> {
    const results = Array.from(this.results.values());
    const healthy = results.every(result => result.status === 'healthy');
    
    return {
      status: healthy ? 'healthy' : 'unhealthy',
      timestamp: new Date().toISOString(),
      checks: Object.fromEntries(this.results),
      uptime: process.uptime(),
      version: process.env.APP_VERSION || 'unknown',
    };
  }
  
  private setupChecks(checkConfigs: HealthCheckConfig[]): void {
    checkConfigs.forEach(config => {
      const check = this.createCheck(config);
      if (check) {
        this.checks.set(config.name, check);
      }
    });
  }
  
  private createCheck(config: HealthCheckConfig): HealthCheck | null {
    switch (config.type) {
      case 'database':
        return new DatabaseHealthCheck(config);
      
      case 'redis':
        return new RedisHealthCheck(config);
      
      case 'http':
        return new HttpHealthCheck(config);
      
      case 'memory':
        return new MemoryHealthCheck(config);
      
      case 'disk':
        return new DiskHealthCheck(config);
      
      default:
        return null;
    }
  }
  
  private startChecking(): void {
    setInterval(() => {
      this.runAllChecks();
    }, this.interval);
    
    // 立即运行一次
    this.runAllChecks();
  }
  
  private async runAllChecks(): Promise<void> {
    const promises = Array.from(this.checks.entries()).map(async ([name, check]) => {
      try {
        const result = await Promise.race([
          check.check(),
          this.timeout(check.timeout || 5000),
        ]);
        
        this.results.set(name, {
          name,
          status: 'healthy',
          message: result.message || 'OK',
          timestamp: new Date().toISOString(),
          duration: result.duration,
        });
      } catch (error) {
        this.results.set(name, {
          name,
          status: 'unhealthy',
          message: error.message,
          timestamp: new Date().toISOString(),
          duration: 0,
        });
      }
    });
    
    await Promise.allSettled(promises);
  }
  
  private timeout(ms: number): Promise<never> {
    return new Promise((_, reject) => {
      setTimeout(() => reject(new Error('Health check timeout')), ms);
    });
  }
}

// 类型定义
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';

interface LogEntry {
  timestamp: string;
  level: LogLevel;
  context: string;
  message: string;
  meta: Record<string, any>;
  traceId: string;
}

interface LoggerConfig {
  level?: LogLevel;
  appenders?: AppenderConfig[];
}

interface AppenderConfig {
  type: 'console' | 'file' | 'elasticsearch' | 'syslog';
  config?: Record<string, any>;
}

interface LogAppender {
  append(entry: LogEntry): void;
}

interface MetricsConfig {
  aggregationInterval?: number;
  exporters: ExporterConfig[];
}

interface ExporterConfig {
  type: 'prometheus' | 'influxdb' | 'console';
  config?: Record<string, any>;
}

interface MetricExporter {
  export(metrics: AggregatedMetric[]): Promise<void>;
}

interface AggregatedMetric {
  name: string;
  labels: Record<string, string>;
  type: MetricType;
  value: number | HistogramStats;
  timestamp: Timestamp;
}

interface HistogramStats {
  count: number;
  sum: number;
  min: number;
  max: number;
  avg: number;
  p50: number;
  p90: number;
  p95: number;
  p99: number;
}

interface HealthCheck {
  check(): Promise<{ message?: string; duration: number }>;
  timeout?: number;
}

interface HealthCheckResult {
  name: string;
  status: 'healthy' | 'unhealthy';
  message: string;
  timestamp: string;
  duration: number;
}

interface HealthStatus {
  status: 'healthy' | 'unhealthy';
  timestamp: string;
  checks: Record<string, HealthCheckResult>;
  uptime: number;
  version: string;
}

export {
  MetricsCollector,
  Logger,
  HealthChecker,
};

export type {
  MetricData,
  LogEntry,
  HealthStatus,
};

6.8 部署配置

# docker-compose.yml
version: '3.8'

services:
  # API 网关
  api-gateway:
    build:
      context: ./gateway
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - NODE_ENV=production
      - REDIS_URL=redis://redis:6379
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_NAME=erp_gateway
      - DB_USER=gateway_user
      - DB_PASSWORD=gateway_pass
    depends_on:
      - redis
      - postgres
    networks:
      - erp-network
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # 认证服务
  auth-service:
    build:
      context: ./services/auth
      dockerfile: Dockerfile
    ports:
      - "8081:8080"
    environment:
      - NODE_ENV=production
      - JWT_SECRET=${JWT_SECRET}
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_NAME=erp_auth
      - DB_USER=auth_user
      - DB_PASSWORD=auth_pass
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
    networks:
      - erp-network
    restart: unless-stopped

  # 用户管理服务
  user-service:
    build:
      context: ./services/user
      dockerfile: Dockerfile
    ports:
      - "8082:8080"
    environment:
      - NODE_ENV=production
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_NAME=erp_users
      - DB_USER=user_user
      - DB_PASSWORD=user_pass
      - AUTH_SERVICE_URL=http://auth-service:8080
    depends_on:
      - postgres
      - auth-service
    networks:
      - erp-network
    restart: unless-stopped

  # 前端应用
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:80"
    environment:
      - REACT_APP_API_URL=http://api-gateway:8080
    depends_on:
      - api-gateway
    networks:
      - erp-network
    restart: unless-stopped

  # PostgreSQL 数据库
  postgres:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=erp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./database/init:/docker-entrypoint-initdb.d
    networks:
      - erp-network
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 30s
      timeout: 10s
      retries: 5

  # Redis 缓存
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - erp-network
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Elasticsearch (日志存储)
  elasticsearch:
    image: elasticsearch:8.8.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data
    networks:
      - erp-network
    restart: unless-stopped

  # Kibana (日志可视化)
  kibana:
    image: kibana:8.8.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
    networks:
      - erp-network
    restart: unless-stopped

  # Prometheus (指标收集)
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--storage.tsdb.retention.time=200h'
      - '--web.enable-lifecycle'
    networks:
      - erp-network
    restart: unless-stopped

  # Grafana (指标可视化)
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
      - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources
    depends_on:
      - prometheus
    networks:
      - erp-network
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:
  elasticsearch_data:
  prometheus_data:
  grafana_data:

networks:
  erp-network:
    driver: bridge
# kubernetes/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: erp-system
  labels:
    name: erp-system

---
# kubernetes/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: erp-config
  namespace: erp-system
data:
  NODE_ENV: "production"
  LOG_LEVEL: "info"
  METRICS_ENABLED: "true"
  HEALTH_CHECK_INTERVAL: "30000"

---
# kubernetes/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: erp-secrets
  namespace: erp-system
type: Opaque
data:
  JWT_SECRET: <base64-encoded-jwt-secret>
  DB_PASSWORD: <base64-encoded-db-password>
  REDIS_PASSWORD: <base64-encoded-redis-password>

---
# kubernetes/api-gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
  namespace: erp-system
  labels:
    app: api-gateway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
    spec:
      containers:
      - name: api-gateway
        image: erp/api-gateway:latest
        ports:
        - containerPort: 8080
        env:
        - name: NODE_ENV
          valueFrom:
            configMapKeyRef:
              name: erp-config
              key: NODE_ENV
        - name: JWT_SECRET
          valueFrom:
            secretKeyRef:
              name: erp-secrets
              key: JWT_SECRET
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

---
# kubernetes/api-gateway-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api-gateway-service
  namespace: erp-system
spec:
  selector:
    app: api-gateway
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer

---
# kubernetes/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-gateway-hpa
  namespace: erp-system
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-gateway
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

本章练习

练习1:扩展权限系统

  1. 实现基于资源的权限控制(RBAC)
  2. 添加动态权限分配功能
  3. 实现权限继承机制
  4. 创建权限审计日志

练习2:优化API网关

  1. 实现请求限流算法(令牌桶、滑动窗口)
  2. 添加API版本管理
  3. 实现请求/响应缓存策略
  4. 添加API文档自动生成

练习3:完善监控系统

  1. 实现分布式链路追踪
  2. 添加业务指标监控
  3. 创建告警规则和通知系统
  4. 实现性能基线和异常检测

练习4:数据库优化

  1. 实现读写分离
  2. 添加数据库连接池管理
  3. 实现数据分片策略
  4. 创建数据备份和恢复机制

练习5:部署优化

  1. 实现蓝绿部署策略
  2. 添加滚动更新配置
  3. 创建灾难恢复方案
  4. 实现多环境配置管理

本章总结

本章通过一个完整的企业级ERP系统项目,展示了如何运用TypeScript构建大型应用架构。我们涵盖了:

核心架构设计

  • 微服务架构:服务拆分、通信机制、服务发现
  • 领域驱动设计:实体建模、聚合根、值对象
  • 分层架构:表现层、业务层、数据访问层

技术实现要点

  • 类型系统设计:基础类型、实体定义、业务模型
  • 状态管理:Zustand集成、异步状态处理
  • 权限控制:RBAC模型、装饰器模式、组件级权限
  • API网关:路由管理、负载均衡、熔断机制

工程化实践

  • 监控系统:指标收集、日志管理、健康检查
  • 部署策略:容器化、Kubernetes、自动扩缩容
  • 质量保证:类型检查、单元测试、集成测试

最佳实践总结

  1. 类型安全优先:充分利用TypeScript的类型系统
  2. 模块化设计:清晰的模块边界和依赖关系
  3. 可观测性:完善的监控、日志和追踪
  4. 可扩展性:支持水平扩展和垂直扩展
  5. 可维护性:代码组织、文档、测试覆盖

通过本章的学习,你应该能够: - 设计和实现企业级TypeScript应用架构 - 运用现代化的开发工具和最佳实践 - 构建可扩展、可维护的大型系统 - 实现完整的DevOps流程

这个综合项目展示了TypeScript在企业级应用开发中的强大能力,为你在实际工作中应用这些技术奠定了坚实的基础。