Files
telegram-management-system/frontend-vben/apps/web-antd/docs/ARCHITECTURE.md
你的用户名 237c7802e5
Some checks failed
Deploy / deploy (push) Has been cancelled
Initial commit: Telegram Management System
Full-stack web application for Telegram management
- Frontend: Vue 3 + Vben Admin
- Backend: NestJS
- Features: User management, group broadcast, statistics

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 15:37:50 +08:00

51 KiB
Raw Blame History

Telegram 管理系统架构文档

版本: v2.0.0
更新时间: 2024-01-20
维护者: 开发团队

📋 文档目录


🏗️ 系统概述

系统简介

Telegram 管理系统是一个基于现代Web技术栈构建的企业级营销管理平台专注于Telegram渠道的用户管理、消息群发、营销活动等核心功能。

核心特性

  • 🚀 高性能: 基于Vue 3 + Vite构建支持秒级响应
  • 🔒 安全可靠: 完整的权限控制体系,支持多角色管理
  • 🌐 国际化: 支持中英文双语,可扩展更多语言
  • 📱 响应式设计: 完美适配桌面端、平板和移动端
  • 实时通信: 基于WebSocket的实时状态同步
  • 🔧 高度可配置: 支持灵活的系统配置和个性化定制

业务模块

graph TB
    A[Telegram管理系统] --> B[用户管理]
    A --> C[消息管理]
    A --> D[营销中心]
    A --> E[系统管理]

    B --> B1[账号管理]
    B --> B2[权限控制]
    B --> B3[角色管理]

    C --> C1[私信群发]
    C --> C2[群组管理]
    C --> C3[消息模板]
    C --> C4[发送记录]

    D --> D1[营销活动]
    D --> D2[客户分析]
    D --> D3[效果统计]
    D --> D4[智能推荐]

    E --> E1[系统配置]
    E --> E2[日志管理]
    E --> E3[监控报警]
    E --> E4[数据统计]

🏛️ 技术架构

整体架构图

graph TB
    subgraph "前端层"
        A1[Vue 3 + TypeScript]
        A2[Vben Admin Framework]
        A3[Ant Design Vue]
        A4[Vite 构建工具]
    end

    subgraph "API网关层"
        B1[Nginx 反向代理]
        B2[API Gateway]
        B3[负载均衡]
        B4[SSL终端]
    end

    subgraph "应用服务层"
        C1[Node.js/Express]
        C2[业务逻辑层]
        C3[权限中间件]
        C4[WebSocket 服务]
    end

    subgraph "数据存储层"
        D1[MySQL 主数据库]
        D2[Redis 缓存]
        D3[MongoDB 日志]
        D4[文件存储 OSS]
    end

    subgraph "外部服务"
        E1[Telegram Bot API]
        E2[短信服务商]
        E3[邮件服务]
        E4[CDN 服务]
    end

    A1 --> B1
    A2 --> B2
    B1 --> C1
    B2 --> C2
    C1 --> D1
    C2 --> D2
    C3 --> D3
    C4 --> E1

技术栈选型

前端技术栈

技术 版本 用途 选型理由
Vue 3 ^3.4.0 前端框架 组合式API更好的TypeScript支持性能提升
TypeScript ^5.0.0 类型系统 提供类型安全,减少运行时错误
Vben Admin ^5.5.8 管理后台框架 功能丰富,开发效率高,社区活跃
Ant Design Vue ^4.0.0 UI组件库 组件丰富,设计规范,企业级应用首选
Vite ^5.0.0 构建工具 快速的开发服务器,优化的生产构建
Pinia ^2.1.0 状态管理 Vue 3官方推荐简洁的API
Vue Router ^4.2.0 路由管理 Vue 3官方路由器
VueUse ^10.0.0 组合式工具库 丰富的组合式函数

后端技术栈

技术 版本 用途 选型理由
Node.js ^18.0.0 运行时环境 高性能,丰富的生态系统
Express ^4.18.0 Web框架 成熟稳定,中间件丰富
MySQL ^8.0.0 关系型数据库 ACID特性适合业务数据存储
Redis ^7.0.0 内存数据库 高性能缓存,会话存储
MongoDB ^6.0.0 文档数据库 适合日志和非结构化数据
Socket.io ^4.7.0 实时通信 可靠的WebSocket实现

开发工具

工具 版本 用途
ESLint ^8.50.0 代码规范检查
Prettier ^3.0.0 代码格式化
Husky ^8.0.0 Git钩子管理
Commitizen ^4.3.0 规范化提交信息
Playwright ^1.40.0 端到端测试

🎨 前端架构

项目结构

apps/web-antd/
├── build/                  # 构建相关配置
│   ├── compression.ts      # 资源压缩配置
│   ├── image-optimizer.ts  # 图片优化工具
│   ├── cdn-config.ts       # CDN配置
│   └── optimize.ts         # 构建优化脚本
├── docs/                   # 项目文档
├── public/                 # 静态资源
├── src/                    # 源码目录
│   ├── api/               # API接口层
│   ├── assets/            # 静态资源
│   ├── components/        # 通用组件
│   ├── hooks/             # 组合式函数
│   ├── layouts/           # 布局组件
│   ├── locales/           # 国际化资源
│   ├── router/            # 路由配置
│   ├── stores/            # 状态管理
│   ├── types/             # 类型定义
│   ├── utils/             # 工具函数
│   └── views/             # 页面组件
├── tests/                 # 测试文件
│   ├── e2e/              # 端到端测试
│   ├── global-setup.ts   # 全局测试设置
│   └── global-teardown.ts # 全局测试清理
└── types/                 # 全局类型定义

组件架构

graph TB
    subgraph "页面层 (Views)"
        A1[业务页面组件]
        A2[路由页面组件]
    end

    subgraph "布局层 (Layouts)"
        B1[主布局 Layout]
        B2[侧边栏 Sidebar]
        B3[头部 Header]
        B4[内容区 Content]
    end

    subgraph "组件层 (Components)"
        C1[业务组件]
        C2[通用组件]
        C3[基础组件]
    end

    subgraph "基础层 (Base)"
        D1[Ant Design Vue]
        D2[Vue 3 内置组件]
    end

    A1 --> B1
    A2 --> B2
    B1 --> C1
    B2 --> C2
    C1 --> D1
    C2 --> D2

状态管理架构

采用 Pinia 进行状态管理,按模块划分:

// stores/index.ts
export interface AppState {
  // 用户状态
  user: UserState;
  // 权限状态
  permission: PermissionState;
  // 应用设置
  settings: SettingsState;
  // 业务数据
  business: BusinessState;
}

// 状态模块示例
export const useUserStore = defineStore('user', () => {
  const userInfo = ref<UserInfo | null>(null);
  const token = ref<string>('');
  const permissions = ref<string[]>([]);

  const login = async (credentials: LoginCredentials) => {
    // 登录逻辑
  };

  const logout = async () => {
    // 登出逻辑
  };

  return {
    userInfo,
    token,
    permissions,
    login,
    logout,
  };
});

路由架构

采用动态路由 + 权限控制的方式:

// router/index.ts
const router = createRouter({
  history: createWebHistory(),
  routes: [
    // 静态路由
    {
      path: '/login',
      component: LoginView,
      meta: { requiresAuth: false },
    },
    // 动态路由(根据权限加载)
    {
      path: '/dashboard',
      component: DashboardLayout,
      meta: { requiresAuth: true },
      children: dynamicRoutes,
    },
  ],
});

// 路由守卫
router.beforeEach(async (to, from, next) => {
  const userStore = useUserStore();

  if (to.meta.requiresAuth && !userStore.token) {
    next('/login');
  } else {
    // 权限验证
    const hasPermission = await checkPermission(to);
    hasPermission ? next() : next('/403');
  }
});

API架构

统一的API请求层

// api/base.ts
class ApiClient {
  private instance: AxiosInstance;

  constructor() {
    this.instance = axios.create({
      baseURL: import.meta.env.VITE_API_URL,
      timeout: 10000,
    });

    this.setupInterceptors();
  }

  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use((config) => {
      const token = getToken();
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    });

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response) => response.data,
      (error) => this.handleError(error),
    );
  }
}

// API模块化
export const accountApi = {
  getList: (params: AccountListParams) =>
    apiClient.get<AccountListResponse>('/accounts', { params }),

  create: (data: CreateAccountData) =>
    apiClient.post<Account>('/accounts', data),

  update: (id: string, data: UpdateAccountData) =>
    apiClient.put<Account>(`/accounts/${id}`, data),
};

⚙️ 后端架构

分层架构

graph TB
    subgraph "控制层 (Controller)"
        A1[路由控制器]
        A2[参数验证]
        A3[权限验证]
    end

    subgraph "服务层 (Service)"
        B1[业务逻辑]
        B2[数据处理]
        B3[外部服务调用]
    end

    subgraph "数据访问层 (DAO)"
        C1[MySQL 操作]
        C2[Redis 操作]
        C3[MongoDB 操作]
    end

    subgraph "中间件层 (Middleware)"
        D1[认证中间件]
        D2[日志中间件]
        D3[错误处理]
        D4[限流中间件]
    end

    A1 --> B1
    A2 --> B2
    B1 --> C1
    B2 --> C2
    D1 --> A1
    D2 --> A2

核心模块

1. 用户认证模块

// auth/auth.service.js
class AuthService {
  async login(credentials) {
    // 用户验证
    const user = await this.validateUser(credentials);

    // 生成token
    const token = this.generateJWT(user);

    // 记录登录日志
    await this.logLoginActivity(user);

    return { user, token };
  }

  async validateToken(token) {
    try {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      const user = await User.findById(decoded.userId);
      return user;
    } catch (error) {
      throw new UnauthorizedError('Invalid token');
    }
  }
}

2. 权限控制模块

// permission/permission.service.js
class PermissionService {
  async checkPermission(userId, resource, action) {
    const userRoles = await this.getUserRoles(userId);
    const permissions = await this.getRolePermissions(userRoles);

    return permissions.some(
      (permission) =>
        permission.resource === resource && permission.action === action,
    );
  }

  middleware() {
    return async (req, res, next) => {
      const { user } = req;
      const { resource, action } = req.route.meta;

      const hasPermission = await this.checkPermission(
        user.id,
        resource,
        action,
      );

      if (hasPermission) {
        next();
      } else {
        res.status(403).json({ error: 'Forbidden' });
      }
    };
  }
}

3. 消息处理模块

// message/message.service.js
class MessageService {
  async sendBulkMessage(taskData) {
    const { templateId, targetUsers, scheduledTime } = taskData;

    // 创建发送任务
    const task = await this.createTask(taskData);

    // 如果是定时发送
    if (scheduledTime) {
      await this.scheduleTask(task, scheduledTime);
    } else {
      await this.executeTask(task);
    }

    return task;
  }

  async executeTask(task) {
    const { id, targetUsers, template } = task;
    const results = [];

    for (const user of targetUsers) {
      try {
        // 渲染消息模板
        const message = this.renderTemplate(template, user);

        // 发送消息
        const result = await this.sendTelegramMessage(user.telegramId, message);

        // 记录发送结果
        await this.recordSendResult(task.id, user.id, result);

        results.push({ userId: user.id, status: 'success' });
      } catch (error) {
        results.push({
          userId: user.id,
          status: 'failed',
          error: error.message,
        });
      }
    }

    // 更新任务状态
    await this.updateTaskStatus(id, 'completed', results);
  }
}

数据模型

用户模型

// models/User.js
const UserSchema = new Schema({
  username: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  profile: {
    firstName: String,
    lastName: String,
    avatar: String,
    phone: String,
  },
  roles: [{ type: Schema.Types.ObjectId, ref: 'Role' }],
  settings: {
    language: { type: String, default: 'zh-CN' },
    timezone: { type: String, default: 'Asia/Shanghai' },
    notifications: {
      email: { type: Boolean, default: true },
      sms: { type: Boolean, default: false },
    },
  },
  status: {
    type: String,
    enum: ['active', 'inactive', 'suspended'],
    default: 'active',
  },
  lastLogin: Date,
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date, default: Date.now },
});

消息任务模型

// models/MessageTask.js
const MessageTaskSchema = new Schema({
  name: { type: String, required: true },
  description: String,
  template: { type: Schema.Types.ObjectId, ref: 'MessageTemplate' },
  targetUsers: [{ type: Schema.Types.ObjectId, ref: 'TelegramAccount' }],
  scheduling: {
    type: { type: String, enum: ['immediate', 'scheduled', 'recurring'] },
    scheduledTime: Date,
    recurrence: {
      frequency: { type: String, enum: ['daily', 'weekly', 'monthly'] },
      interval: Number,
      endDate: Date,
    },
  },
  status: {
    type: String,
    enum: ['pending', 'running', 'completed', 'failed', 'cancelled'],
    default: 'pending',
  },
  progress: {
    total: { type: Number, default: 0 },
    sent: { type: Number, default: 0 },
    failed: { type: Number, default: 0 },
    percentage: { type: Number, default: 0 },
  },
  results: [
    {
      userId: { type: Schema.Types.ObjectId, ref: 'TelegramAccount' },
      status: { type: String, enum: ['success', 'failed'] },
      sentAt: Date,
      error: String,
    },
  ],
  createdBy: { type: Schema.Types.ObjectId, ref: 'User' },
  createdAt: { type: Date, default: Date.now },
  updatedAt: { type: Date, default: Date.now },
});

🗄️ 数据库设计

数据库架构

erDiagram
    User ||--o{ UserRole : has
    Role ||--o{ RolePermission : has
    Permission ||--o{ RolePermission : belongs

    User ||--o{ MessageTask : creates
    MessageTask ||--o{ MessageResult : contains
    MessageTemplate ||--o{ MessageTask : used_in

    TelegramAccount ||--o{ MessageResult : receives
    TelegramAccount }o--|| User : managed_by

    User {
        string id PK
        string username UK
        string email UK
        string password_hash
        json profile
        enum status
        datetime created_at
        datetime updated_at
    }

    Role {
        string id PK
        string name UK
        string description
        boolean is_system
        datetime created_at
    }

    Permission {
        string id PK
        string resource
        string action
        string description
    }

    TelegramAccount {
        string id PK
        string telegram_id UK
        string username
        string first_name
        string last_name
        string phone
        enum status
        json metadata
        string managed_by FK
        datetime created_at
        datetime updated_at
    }

    MessageTask {
        string id PK
        string name
        string description
        string template_id FK
        json target_users
        json scheduling
        enum status
        json progress
        string created_by FK
        datetime created_at
        datetime updated_at
    }

    MessageTemplate {
        string id PK
        string name
        string content
        json variables
        enum type
        string created_by FK
        datetime created_at
        datetime updated_at
    }

数据表设计

核心业务表

  1. 用户表 (users)
CREATE TABLE users (
  id VARCHAR(36) PRIMARY KEY,
  username VARCHAR(50) UNIQUE NOT NULL,
  email VARCHAR(100) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  profile JSON,
  status ENUM('active', 'inactive', 'suspended') DEFAULT 'active',
  last_login TIMESTAMP NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  INDEX idx_username (username),
  INDEX idx_email (email),
  INDEX idx_status (status)
);
  1. Telegram账号表 (telegram_accounts)
CREATE TABLE telegram_accounts (
  id VARCHAR(36) PRIMARY KEY,
  telegram_id VARCHAR(20) UNIQUE NOT NULL,
  username VARCHAR(50),
  first_name VARCHAR(50),
  last_name VARCHAR(50),
  phone VARCHAR(20),
  status ENUM('active', 'inactive', 'blocked') DEFAULT 'active',
  metadata JSON,
  managed_by VARCHAR(36),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  INDEX idx_telegram_id (telegram_id),
  INDEX idx_username (username),
  INDEX idx_managed_by (managed_by),
  FOREIGN KEY (managed_by) REFERENCES users(id)
);
  1. 消息任务表 (message_tasks)
CREATE TABLE message_tasks (
  id VARCHAR(36) PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  description TEXT,
  template_id VARCHAR(36),
  target_users JSON NOT NULL,
  scheduling JSON,
  status ENUM('pending', 'running', 'completed', 'failed', 'cancelled') DEFAULT 'pending',
  progress JSON,
  created_by VARCHAR(36) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  INDEX idx_status (status),
  INDEX idx_created_by (created_by),
  INDEX idx_created_at (created_at),
  FOREIGN KEY (created_by) REFERENCES users(id),
  FOREIGN KEY (template_id) REFERENCES message_templates(id)
);

缓存策略

Redis 数据结构设计

// 缓存键命名规范
const CACHE_KEYS = {
  // 用户相关
  USER_INFO: 'user:info:{userId}',
  USER_PERMISSIONS: 'user:permissions:{userId}',
  USER_SESSION: 'session:{sessionId}',

  // 任务相关
  TASK_STATUS: 'task:status:{taskId}',
  TASK_PROGRESS: 'task:progress:{taskId}',
  TASK_QUEUE: 'task:queue',

  // 统计数据
  DAILY_STATS: 'stats:daily:{date}',
  USER_ACTIVITY: 'activity:user:{userId}',

  // 配置缓存
  SYSTEM_CONFIG: 'config:system',
  RATE_LIMIT: 'rate_limit:{userId}:{endpoint}',
};

// 缓存操作示例
class CacheService {
  async getUserInfo(userId) {
    const cacheKey = CACHE_KEYS.USER_INFO.replace('{userId}', userId);
    let userInfo = await redis.get(cacheKey);

    if (!userInfo) {
      userInfo = await User.findById(userId);
      await redis.setex(cacheKey, 3600, JSON.stringify(userInfo)); // 1小时过期
    } else {
      userInfo = JSON.parse(userInfo);
    }

    return userInfo;
  }

  async setTaskProgress(taskId, progress) {
    const cacheKey = CACHE_KEYS.TASK_PROGRESS.replace('{taskId}', taskId);
    await redis.setex(cacheKey, 86400, JSON.stringify(progress)); // 24小时过期

    // 发布进度更新事件
    await redis.publish(
      'task:progress:update',
      JSON.stringify({
        taskId,
        progress,
      }),
    );
  }
}

🔐 安全架构

认证与授权

JWT认证流程

sequenceDiagram
    participant Client
    participant Gateway
    participant AuthService
    participant Database

    Client->>Gateway: 登录请求 (username, password)
    Gateway->>AuthService: 验证凭据
    AuthService->>Database: 查询用户信息
    Database-->>AuthService: 返回用户数据
    AuthService->>AuthService: 验证密码
    AuthService->>AuthService: 生成JWT Token
    AuthService-->>Gateway: 返回Token和用户信息
    Gateway-->>Client: 返回认证结果

    Note over Client: 后续请求携带Token
    Client->>Gateway: API请求 (Header: Authorization)
    Gateway->>AuthService: 验证Token
    AuthService-->>Gateway: 返回用户信息
    Gateway->>Gateway: 检查权限
    Gateway-->>Client: 返回API响应

权限控制模型

采用RBAC (Role-Based Access Control) 模型:

// 权限定义
interface Permission {
  id: string;
  resource: string; // 资源类型: account, message, task
  action: string; // 操作类型: create, read, update, delete
  conditions?: {
    // 条件限制
    owner?: boolean; // 只能操作自己的资源
    department?: string; // 部门限制
  };
}

// 角色定义
interface Role {
  id: string;
  name: string;
  permissions: Permission[];
  inherits?: string[]; // 继承其他角色
}

// 权限检查
class PermissionChecker {
  async checkPermission(
    userId: string,
    resource: string,
    action: string,
    resourceData?: any,
  ): Promise<boolean> {
    const userRoles = await this.getUserRoles(userId);
    const permissions = await this.flattenPermissions(userRoles);

    return permissions.some((permission) => {
      // 基础权限匹配
      if (permission.resource !== resource || permission.action !== action) {
        return false;
      }

      // 条件检查
      if (permission.conditions?.owner && resourceData?.ownerId !== userId) {
        return false;
      }

      return true;
    });
  }
}

数据安全

敏感数据加密

// 数据加密服务
class CryptoService {
  constructor() {
    this.algorithm = 'aes-256-gcm';
    this.secretKey = process.env.ENCRYPTION_KEY;
  }

  encrypt(text) {
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipher(this.algorithm, this.secretKey);
    cipher.setAAD(Buffer.from('additional-data'));

    let encrypted = cipher.update(text, 'utf8', 'hex');
    encrypted += cipher.final('hex');

    const authTag = cipher.getAuthTag();

    return {
      encrypted,
      iv: iv.toString('hex'),
      authTag: authTag.toString('hex'),
    };
  }

  decrypt(encryptedData) {
    const decipher = crypto.createDecipher(this.algorithm, this.secretKey);
    decipher.setAAD(Buffer.from('additional-data'));
    decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));

    let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');

    return decrypted;
  }
}

// 模型层数据加密
class User extends Model {
  static encrypt = ['password', 'phone', 'email'];

  static beforeSave(user) {
    this.encrypt.forEach((field) => {
      if (user[field] && user.isModified(field)) {
        user[field] = cryptoService.encrypt(user[field]);
      }
    });
  }

  static afterFind(user) {
    this.encrypt.forEach((field) => {
      if (user[field] && typeof user[field] === 'object') {
        user[field] = cryptoService.decrypt(user[field]);
      }
    });
  }
}

API安全防护

// API限流中间件
class RateLimitMiddleware {
  constructor(options = {}) {
    this.windowMs = options.windowMs || 60000; // 1分钟
    this.maxRequests = options.max || 100;
    this.skipSuccessfulRequests = options.skipSuccessfulRequests || false;
  }

  middleware() {
    return async (req, res, next) => {
      const key = `rate_limit:${req.ip}:${req.route.path}`;
      const current = await redis.get(key);

      if (current && parseInt(current) >= this.maxRequests) {
        return res.status(429).json({
          error: 'Too Many Requests',
          retryAfter: this.windowMs / 1000,
        });
      }

      await redis
        .multi()
        .incr(key)
        .expire(key, this.windowMs / 1000)
        .exec();

      next();
    };
  }
}

// XSS防护
app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        styleSrc: ["'self'", "'unsafe-inline'"],
        scriptSrc: ["'self'"],
        imgSrc: ["'self'", 'data:', 'https:'],
      },
    },
    hsts: {
      maxAge: 31536000,
      includeSubDomains: true,
      preload: true,
    },
  }),
);

// SQL注入防护 (使用参数化查询)
class DatabaseService {
  async findUser(conditions) {
    const query = 'SELECT * FROM users WHERE username = ? AND status = ?';
    return await this.connection.query(query, [
      conditions.username,
      conditions.status,
    ]);
  }
}

🚀 部署架构

容器化部署

Docker配置

# Dockerfile.frontend
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# Dockerfile.backend
FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm install --only=production

COPY . .
EXPOSE 3000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

CMD ["node", "server.js"]

Docker Compose配置

# docker-compose.yml
version: '3.8'

services:
  frontend:
    build:
      context: .
      dockerfile: Dockerfile.frontend
    ports:
      - '80:80'
    depends_on:
      - backend
    networks:
      - app-network

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.backend
    ports:
      - '3000:3000'
    environment:
      - NODE_ENV=production
      - DB_HOST=mysql
      - REDIS_HOST=redis
    depends_on:
      - mysql
      - redis
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=telegram_system
      - MYSQL_USER=app_user
      - MYSQL_PASSWORD=app_password
    volumes:
      - mysql_data:/var/lib/mysql
      - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - app-network

  nginx:
    image: nginx:alpine
    ports:
      - '443:443'
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - frontend
      - backend
    networks:
      - app-network

volumes:
  mysql_data:
  redis_data:

networks:
  app-network:
    driver: bridge

Kubernetes部署

部署清单

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: telegram-system

---
# k8s/frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: telegram-system
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: frontend
          image: telegram-system/frontend:latest
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: '128Mi'
              cpu: '100m'
            limits:
              memory: '256Mi'
              cpu: '200m'

---
# k8s/backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: telegram-system
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: telegram-system/backend:latest
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: 'production'
            - name: DB_HOST
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: host
          resources:
            requests:
              memory: '256Mi'
              cpu: '200m'
            limits:
              memory: '512Mi'
              cpu: '500m'
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5

---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  namespace: telegram-system
spec:
  selector:
    app: frontend
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

---
apiVersion: v1
kind: Service
metadata:
  name: backend-service
  namespace: telegram-system
spec:
  selector:
    app: backend
  ports:
    - port: 3000
      targetPort: 3000
  type: ClusterIP

CI/CD流水线

GitHub Actions配置

# .github/workflows/deploy.yml
name: Build and Deploy

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npm test

      - name: Run E2E tests
        run: npm run test:e2e

  build-and-push:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - uses: actions/checkout@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push frontend
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./Dockerfile.frontend
          push: true
          tags: telegram-system/frontend:${{ github.sha }},telegram-system/frontend:latest

      - name: Build and push backend
        uses: docker/build-push-action@v4
        with:
          context: ./backend
          file: ./backend/Dockerfile
          push: true
          tags: telegram-system/backend:${{ github.sha }},telegram-system/backend:latest

  deploy:
    needs: build-and-push
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Deploy to Kubernetes
        uses: azure/k8s-deploy@v1
        with:
          manifests: |
            k8s/namespace.yaml
            k8s/frontend-deployment.yaml
            k8s/backend-deployment.yaml
            k8s/service.yaml
          images: |
            telegram-system/frontend:${{ github.sha }}
            telegram-system/backend:${{ github.sha }}
          kubectl-version: 'latest'

性能优化

前端性能优化

1. 构建优化

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        // 代码分割
        manualChunks: {
          vendor: ['vue', 'vue-router', 'pinia'],
          antd: ['ant-design-vue'],
          utils: ['lodash', 'dayjs'],
        },
      },
    },
    // 压缩配置
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },
  },

  // 开发服务器优化
  server: {
    hmr: {
      overlay: false,
    },
  },

  // 依赖预构建
  optimizeDeps: {
    include: ['vue', 'vue-router', 'pinia', 'ant-design-vue'],
  },
});

2. 资源优化

// build/image-optimizer.ts
export async function optimizeImages(options: OptimizationOptions) {
  const imageFiles = await glob('**/*.{png,jpg,jpeg,gif,svg}', {
    cwd: options.inputDir,
  });

  for (const file of imageFiles) {
    const inputPath = path.join(options.inputDir, file);
    const outputPath = path.join(options.outputDir, file);

    // PNG/JPEG压缩
    if (file.match(/\.(png|jpe?g)$/)) {
      await sharp(inputPath)
        .resize(options.maxWidth, options.maxHeight, {
          fit: 'inside',
          withoutEnlargement: true,
        })
        .jpeg({ quality: options.quality })
        .png({ compressionLevel: 9 })
        .toFile(outputPath);
    }

    // 生成WebP格式
    const webpPath = outputPath.replace(/\.(png|jpe?g)$/, '.webp');
    await sharp(inputPath)
      .webp({ quality: options.webpQuality })
      .toFile(webpPath);
  }
}

3. 运行时优化

<!-- 组件懒加载 -->
<template>
  <div>
    <!-- 虚拟滚动 -->
    <VirtualList :items="largeDataset" :item-height="50" :visible-count="20">
      <template #default="{ item }">
        <ListItem :data="item" />
      </template>
    </VirtualList>

    <!-- 图片懒加载 -->
    <img v-lazy="imageUrl" :alt="description" loading="lazy" />
  </div>
</template>

<script setup lang="ts">
// 组合式函数优化
const { data, loading } = usePagination({
  api: accountApi.getList,
  pageSize: 20,
  immediate: true,
});

// 防抖搜索
const searchKeyword = ref('');
const debouncedSearch = useDebounceFn(() => {
  // 执行搜索
}, 300);

watch(searchKeyword, debouncedSearch);

// 缓存计算结果
const expensiveComputation = computed(() => {
  return heavyCalculation(data.value);
});
</script>

后端性能优化

1. 数据库优化

-- 索引优化
CREATE INDEX idx_users_status_created ON users(status, created_at);
CREATE INDEX idx_message_tasks_status_priority ON message_tasks(status, priority, created_at);
CREATE INDEX idx_telegram_accounts_managed_status ON telegram_accounts(managed_by, status);

-- 分区表(按时间分区)
CREATE TABLE message_logs (
    id BIGINT AUTO_INCREMENT,
    task_id VARCHAR(36),
    user_id VARCHAR(36),
    message TEXT,
    status ENUM('sent', 'failed'),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (TO_DAYS(created_at)) (
    PARTITION p2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
    PARTITION p2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01')),
    -- ... 更多分区
);

2. 缓存策略

// 多级缓存
class CacheManager {
  constructor() {
    this.l1Cache = new Map(); // 内存缓存
    this.l2Cache = redis; // Redis缓存
  }

  async get(key) {
    // L1缓存
    if (this.l1Cache.has(key)) {
      return this.l1Cache.get(key);
    }

    // L2缓存
    const l2Value = await this.l2Cache.get(key);
    if (l2Value) {
      const value = JSON.parse(l2Value);
      this.l1Cache.set(key, value);
      return value;
    }

    return null;
  }

  async set(key, value, ttl = 3600) {
    // 同时设置两级缓存
    this.l1Cache.set(key, value);
    await this.l2Cache.setex(key, ttl, JSON.stringify(value));
  }
}

// 查询优化
class UserService {
  async getUsers(filters, pagination) {
    const cacheKey = `users:${JSON.stringify({ filters, pagination })}`;

    // 尝试从缓存获取
    let result = await cacheManager.get(cacheKey);
    if (result) {
      return result;
    }

    // 数据库查询优化
    const query = User.find(filters)
      .populate('roles', 'name permissions') // 只选择需要的字段
      .limit(pagination.pageSize)
      .skip(pagination.offset)
      .sort({ createdAt: -1 });

    result = await query.exec();

    // 缓存结果
    await cacheManager.set(cacheKey, result, 300); // 5分钟缓存

    return result;
  }
}

3. 消息队列优化

// 批量处理消息发送
class MessageQueue {
  constructor() {
    this.queue = [];
    this.batchSize = 100;
    this.processingInterval = 1000; // 1秒

    this.startProcessing();
  }

  add(message) {
    this.queue.push(message);
  }

  startProcessing() {
    setInterval(async () => {
      if (this.queue.length === 0) return;

      const batch = this.queue.splice(0, this.batchSize);
      await this.processBatch(batch);
    }, this.processingInterval);
  }

  async processBatch(messages) {
    const promises = messages.map((message) =>
      this.sendMessage(message).catch((error) => ({
        message,
        error: error.message,
      })),
    );

    const results = await Promise.allSettled(promises);

    // 记录失败的消息,用于重试
    const failures = results
      .filter((result) => result.status === 'rejected' || result.value.error)
      .map((result) => result.value || result.reason);

    if (failures.length > 0) {
      await this.handleFailures(failures);
    }
  }
}

📊 监控体系

应用性能监控

1. 前端监控

// 性能监控 SDK
class PerformanceMonitor {
  constructor() {
    this.metrics = {
      FCP: 0, // First Contentful Paint
      LCP: 0, // Largest Contentful Paint
      FID: 0, // First Input Delay
      CLS: 0, // Cumulative Layout Shift
    };

    this.init();
  }

  init() {
    // Web Vitals监控
    import('web-vitals').then(({ getFCP, getLCP, getFID, getCLS }) => {
      getFCP(this.onFCP.bind(this));
      getLCP(this.onLCP.bind(this));
      getFID(this.onFID.bind(this));
      getCLS(this.onCLS.bind(this));
    });

    // 错误监控
    window.addEventListener('error', this.onError.bind(this));
    window.addEventListener(
      'unhandledrejection',
      this.onUnhandledRejection.bind(this),
    );
  }

  onFCP(metric) {
    this.metrics.FCP = metric.value;
    this.sendMetric('FCP', metric);
  }

  onError(event) {
    this.sendError({
      type: 'javascript',
      message: event.message,
      filename: event.filename,
      lineno: event.lineno,
      colno: event.colno,
      stack: event.error?.stack,
      userAgent: navigator.userAgent,
      url: window.location.href,
      timestamp: Date.now(),
    });
  }

  sendMetric(name, metric) {
    fetch('/api/monitoring/metrics', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name,
        value: metric.value,
        delta: metric.delta,
        id: metric.id,
        timestamp: Date.now(),
        page: window.location.pathname,
      }),
    });
  }
}

// Vue应用监控插件
const monitoringPlugin = {
  install(app) {
    // 全局错误处理
    app.config.errorHandler = (err, vm, info) => {
      console.error('Vue Error:', err, info);

      // 发送错误报告
      fetch('/api/monitoring/errors', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          type: 'vue',
          message: err.message,
          stack: err.stack,
          info,
          component: vm?.$options.name,
          timestamp: Date.now(),
        }),
      });
    };

    // 路由变化监控
    const router = app.config.globalProperties.$router;
    router.beforeEach((to, from) => {
      const startTime = performance.now();

      router.afterEach(() => {
        const endTime = performance.now();
        const navigationTime = endTime - startTime;

        // 记录路由性能
        fetch('/api/monitoring/navigation', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            from: from.path,
            to: to.path,
            duration: navigationTime,
            timestamp: Date.now(),
          }),
        });
      });
    });
  },
};

2. 后端监控

// APM (Application Performance Monitoring)
const apm = require('elastic-apm-node').start({
  serviceName: 'telegram-system-api',
  secretToken: process.env.ELASTIC_APM_SECRET_TOKEN,
  serverUrl: process.env.ELASTIC_APM_SERVER_URL,
});

// 自定义监控中间件
class MonitoringMiddleware {
  static requestTracking() {
    return (req, res, next) => {
      const startTime = Date.now();

      // 监听响应结束
      res.on('finish', () => {
        const duration = Date.now() - startTime;

        // 记录请求指标
        const metrics = {
          method: req.method,
          url: req.url,
          statusCode: res.statusCode,
          duration,
          userAgent: req.get('User-Agent'),
          ip: req.ip,
          userId: req.user?.id,
          timestamp: new Date(),
        };

        // 发送到监控系统
        this.sendMetrics(metrics);

        // 慢查询警报
        if (duration > 5000) {
          this.sendAlert('slow_request', metrics);
        }
      });

      next();
    };
  }

  static errorTracking() {
    return (err, req, res, next) => {
      // 记录错误
      const errorInfo = {
        message: err.message,
        stack: err.stack,
        url: req.url,
        method: req.method,
        userId: req.user?.id,
        timestamp: Date.now(),
      };

      // 发送错误报告
      this.sendError(errorInfo);

      next(err);
    };
  }

  static sendMetrics(metrics) {
    // 发送到 Prometheus/Grafana
    prometheus.httpRequestDuration.observe(
      { method: metrics.method, status_code: metrics.statusCode },
      metrics.duration / 1000,
    );

    prometheus.httpRequestTotal.inc({
      method: metrics.method,
      status_code: metrics.statusCode,
    });
  }
}

系统监控

1. 基础设施监控

# docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - '9090:9090'
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

  grafana:
    image: grafana/grafana:latest
    ports:
      - '3001:3000'
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./grafana/datasources:/etc/grafana/provisioning/datasources

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - '9100:9100'
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro

  alertmanager:
    image: prom/alertmanager:latest
    ports:
      - '9093:9093'
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml

volumes:
  prometheus_data:
  grafana_data:

2. 告警规则

# prometheus/rules.yml
groups:
  - name: telegram-system-alerts
    rules:
      # 系统资源告警
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: 'High CPU usage detected'
          description: 'CPU usage is above 80% for more than 5 minutes'

      - alert: HighMemoryUsage
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: 'High memory usage detected'
          description: 'Memory usage is above 90% for more than 5 minutes'

      # 应用告警
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: 'High error rate detected'
          description: 'Error rate is above 5% for more than 2 minutes'

      - alert: SlowResponse
        expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: 'Slow response time detected'
          description: '95th percentile response time is above 1 second'

      # 业务告警
      - alert: MessageSendingFailed
        expr: rate(message_send_failures_total[5m]) > 10
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: 'High message sending failure rate'
          description: 'Message sending failures are above 10 per second'

日志管理

ELK Stack配置

# docker-compose.elk.yml
version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
    environment:
      - discovery.type=single-node
      - 'ES_JAVA_OPTS=-Xms512m -Xmx512m'
    ports:
      - '9200:9200'
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:7.17.0
    volumes:
      - ./logstash/config:/usr/share/logstash/pipeline
    ports:
      - '5044:5044'
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:7.17.0
    ports:
      - '5601:5601'
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    depends_on:
      - elasticsearch

volumes:
  elasticsearch_data:
# logstash/config/pipeline.conf
input {
  beats {
    port => 5044
  }
}

filter {
  if [fields][service] == "telegram-system" {
    json {
      source => "message"
    }

    date {
      match => [ "timestamp", "ISO8601" ]
    }

    if [level] == "error" {
      mutate {
        add_tag => [ "error" ]
      }
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "telegram-system-%{+YYYY.MM.dd}"
  }
}

🔧 扩展性设计

水平扩展

1. 微服务架构

graph TB
    subgraph "API Gateway"
        A1[Kong/Istio Gateway]
    end

    subgraph "Core Services"
        B1[User Service]
        B2[Auth Service]
        B3[Message Service]
        B4[Task Service]
        B5[Analytics Service]
    end

    subgraph "Supporting Services"
        C1[Notification Service]
        C2[File Service]
        C3[Config Service]
        C4[Logging Service]
    end

    subgraph "Data Layer"
        D1[User DB]
        D2[Message DB]
        D3[Analytics DB]
        D4[Shared Cache]
    end

    A1 --> B1
    A1 --> B2
    A1 --> B3
    A1 --> B4
    A1 --> B5

    B1 --> D1
    B3 --> D2
    B5 --> D3
    B1 --> D4
    B3 --> D4

2. 数据库分片

// 数据库分片策略
class DatabaseSharding {
  constructor() {
    this.shards = [
      { id: 'shard1', host: 'db1.example.com', range: [0, 1000000] },
      { id: 'shard2', host: 'db2.example.com', range: [1000001, 2000000] },
      { id: 'shard3', host: 'db3.example.com', range: [2000001, 3000000] },
    ];
  }

  getShardByUserId(userId) {
    const numericId = parseInt(userId.replace(/\D/g, ''));
    return this.shards.find(
      (shard) => numericId >= shard.range[0] && numericId <= shard.range[1],
    );
  }

  async queryUser(userId) {
    const shard = this.getShardByUserId(userId);
    const connection = await this.getConnection(shard.host);
    return await connection.query('SELECT * FROM users WHERE id = ?', [userId]);
  }

  async queryAllShards(query, params) {
    const promises = this.shards.map((shard) => {
      const connection = this.getConnection(shard.host);
      return connection.query(query, params);
    });

    const results = await Promise.all(promises);
    return results.flat();
  }
}

插件化架构

1. 插件系统设计

// 插件接口定义
interface Plugin {
  name: string;
  version: string;
  dependencies?: string[];

  install(app: Application): void;
  uninstall?(app: Application): void;
  configure?(config: PluginConfig): void;
}

// 插件管理器
class PluginManager {
  private plugins = new Map<string, Plugin>();
  private loadOrder: string[] = [];

  async loadPlugin(pluginPath: string): Promise<void> {
    const plugin = await import(pluginPath);

    // 检查依赖
    if (plugin.dependencies) {
      for (const dep of plugin.dependencies) {
        if (!this.plugins.has(dep)) {
          throw new Error(`Plugin dependency not found: ${dep}`);
        }
      }
    }

    // 安装插件
    plugin.install(this.app);
    this.plugins.set(plugin.name, plugin);
    this.loadOrder.push(plugin.name);
  }

  unloadPlugin(name: string): void {
    const plugin = this.plugins.get(name);
    if (plugin && plugin.uninstall) {
      plugin.uninstall(this.app);
    }

    this.plugins.delete(name);
    const index = this.loadOrder.indexOf(name);
    if (index > -1) {
      this.loadOrder.splice(index, 1);
    }
  }
}

// 插件示例:短信发送插件
export class SmsPlugin implements Plugin {
  name = 'sms-plugin';
  version = '1.0.0';

  install(app: Application) {
    // 注册短信服务
    app.service('sms', new SmsService());

    // 注册API路由
    app.router.post('/api/sms/send', this.sendSms.bind(this));

    // 注册事件监听器
    app.on('user:created', this.sendWelcomeSms.bind(this));
  }

  private async sendSms(req: Request, res: Response) {
    const { phone, message } = req.body;
    const result = await app.service('sms').send(phone, message);
    res.json(result);
  }

  private async sendWelcomeSms(user: User) {
    if (user.phone) {
      await app.service('sms').send(user.phone, '欢迎使用我们的服务!');
    }
  }
}

配置管理

1. 动态配置系统

// 配置中心客户端
class ConfigCenter {
  private cache = new Map<string, any>();
  private watchers = new Map<string, Function[]>();

  constructor(private client: ConsulClient) {
    this.startWatching();
  }

  async get<T>(key: string, defaultValue?: T): Promise<T> {
    // 先从缓存获取
    if (this.cache.has(key)) {
      return this.cache.get(key);
    }

    // 从配置中心获取
    try {
      const value = await this.client.kv.get(key);
      if (value) {
        const parsed = JSON.parse(value);
        this.cache.set(key, parsed);
        return parsed;
      }
    } catch (error) {
      console.error(`Failed to get config ${key}:`, error);
    }

    return defaultValue as T;
  }

  async set(key: string, value: any): Promise<void> {
    await this.client.kv.set(key, JSON.stringify(value));
    this.cache.set(key, value);

    // 通知观察者
    const watchers = this.watchers.get(key) || [];
    watchers.forEach((callback) => callback(value));
  }

  watch(key: string, callback: (value: any) => void): void {
    if (!this.watchers.has(key)) {
      this.watchers.set(key, []);
    }
    this.watchers.get(key)!.push(callback);
  }

  private startWatching(): void {
    // 定期检查配置变更
    setInterval(async () => {
      for (const key of this.cache.keys()) {
        try {
          const newValue = await this.client.kv.get(key);
          const cached = this.cache.get(key);

          if (JSON.stringify(newValue) !== JSON.stringify(cached)) {
            this.cache.set(key, newValue);

            const watchers = this.watchers.get(key) || [];
            watchers.forEach((callback) => callback(newValue));
          }
        } catch (error) {
          console.error(`Failed to watch config ${key}:`, error);
        }
      }
    }, 5000);
  }
}

// 使用示例
const config = new ConfigCenter(consulClient);

// 监听配置变更
config.watch('telegram.api.rate_limit', (newLimit) => {
  console.log('Rate limit updated:', newLimit);
  rateLimiter.updateLimit(newLimit);
});

// 获取配置
const rateLimit = await config.get('telegram.api.rate_limit', 100);

📚 总结

本文档详细描述了Telegram管理系统的完整技术架构涵盖了

🏗️ 架构特点

  • 现代化技术栈: 采用Vue 3、TypeScript、Node.js等最新技术
  • 微服务架构: 支持水平扩展和独立部署
  • 安全性: 完整的认证授权体系和数据加密
  • 高性能: 多级缓存、数据库优化、资源压缩
  • 可观测性: 全面的监控、日志、告警体系
  • 可扩展性: 插件化架构和动态配置管理

🚀 核心优势

  1. 开发效率: 基于Vben Admin框架快速开发
  2. 用户体验: 响应式设计,实时通信
  3. 运维友好: 容器化部署,完善的监控
  4. 业务聚焦: 专注Telegram营销场景
  5. 技术先进: 采用最新的前端和后端技术

📈 未来规划

  • AI智能化: 集成机器学习提升营销效果
  • 多渠道整合: 支持更多社交媒体平台
  • 边缘计算: 降低延时,提升用户体验
  • 区块链集成: 提升数据安全和透明度

文档维护: 本文档应随系统演进持续更新,确保架构文档与实际系统保持一致。

版本管理: 重大架构变更时应更新版本号,并记录变更历史。

团队协作: 所有开发人员都应熟悉本架构文档,确保开发一致性。