banxiang/docs/技术方案-V1.0-MVP架构.md
2026-02-18 18:06:31 +00:00

25 KiB
Raw Blame History

slug
tech-v1-0-mvp-architecture

「伴享」技术方案 V1.0 — MVP架构

版本: V1.0
对应PRD: PRD-V1.0-MVP核心功能
更新日期: 2026-02-16


1. 技术架构总览

1.1 系统架构图

┌────────────────────────────────────────────────────┐
│                    客户端层                          │
│  ┌──────────────────┐  ┌───────────────────────┐  │
│  │  Flutter APP      │  │  子女端V1.2预留)    │  │
│  │  iOS + Android    │  │  微信小程序            │  │
│  └────────┬─────────┘  └───────────────────────┘  │
└───────────┼────────────────────────────────────────┘
            │ HTTPS + WebSocket
┌───────────▼────────────────────────────────────────┐
│                  API网关层Nginx                   │
│  SSL终止 │ 限流 │ 日志 │ 路由 │ CORS │ 压缩        │
└───────────┬────────────────────────────────────────┘
            │
┌───────────▼────────────────────────────────────────┐
│              业务服务层Node.js + Express          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐           │
│  │ 用户服务  │ │ 活动服务  │ │ AI管家   │           │
│  └──────────┘ └──────────┘ └──────────┘           │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐           │
│  │ 医疗服务  │ │ 支付服务  │ │ 通知服务  │           │
│  └──────────┘ └──────────┘ └──────────┘           │
└───────────┬────────────────────────────────────────┘
            │
┌───────────▼────────────────────────────────────────┐
│                   数据层                             │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐           │
│  │PostgreSQL│ │  Redis   │ │ 阿里云OSS │           │
│  └──────────┘ └──────────┘ └──────────┘           │
└────────────────────────────────────────────────────┘

1.2 技术选型

层级 技术 版本 选型理由
前端 Flutter 3.x 跨平台、性能好、适老化组件丰富
后端 Node.js + Express 22 + 4.x 生态成熟、AI集成方便
数据库 PostgreSQL 15+ JSON支持好、地理空间查询
缓存 Redis 7.x 会话管理、限流、缓存
文件存储 阿里云OSS - 图片/语音文件
AI模型 通义千问 qwen-max 国产、函数调用支持好
语音 讯飞ASR/TTS - 中文识别准确率高
地图 高德地图 - 国内POI数据全
支付 微信支付V3 - 银发群体使用率高
推送 JPush - 全平台推送
部署 Docker Compose - MVP阶段够用

2. 数据库设计

2.1 ER关系概览

users ──< activity_participants >── activities
users ──< ai_conversations
users ──< orders
users ──< appointments >── doctors >── departments >── hospitals
users ──< consultations >── doctors
users ──< family_links
users ──< notifications
users ── ai_user_preferences

2.2 完整DDL

-- ===========================
-- 伴享 V1.0 DDL
-- PostgreSQL 15+
-- ===========================

CREATE EXTENSION IF NOT EXISTS earthdistance CASCADE;
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- 1. 用户表
CREATE TABLE users (
  id BIGSERIAL PRIMARY KEY,
  phone VARCHAR(11) UNIQUE NOT NULL,
  nickname VARCHAR(50),
  avatar_url TEXT,
  birth_year INTEGER,
  birth_month INTEGER,
  gender VARCHAR(10) CHECK (gender IN ('male', 'female', 'other')),
  city VARCHAR(50) DEFAULT '成都',
  district VARCHAR(50),
  interests TEXT[] DEFAULT '{}',
  real_name VARCHAR(50),
  id_card_hash VARCHAR(64),
  id_card_encrypted TEXT,
  verified BOOLEAN DEFAULT FALSE,
  emergency_contact_name VARCHAR(50),
  emergency_contact_phone VARCHAR(11),
  font_size VARCHAR(10) DEFAULT 'medium',
  speech_speed VARCHAR(10) DEFAULT 'normal',
  auto_voice BOOLEAN DEFAULT TRUE,
  last_login_at TIMESTAMP,
  login_count INTEGER DEFAULT 0,
  status VARCHAR(20) DEFAULT 'active',
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_users_phone ON users(phone);
CREATE INDEX idx_users_city ON users(city);
CREATE INDEX idx_users_interests ON users USING GIN(interests);

-- 2. 短信验证码
CREATE TABLE sms_codes (
  id BIGSERIAL PRIMARY KEY,
  phone VARCHAR(11) NOT NULL,
  code VARCHAR(6) NOT NULL,
  purpose VARCHAR(20) DEFAULT 'login',
  used BOOLEAN DEFAULT FALSE,
  expires_at TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

-- 3. 家庭关联
CREATE TABLE family_links (
  id BIGSERIAL PRIMARY KEY,
  parent_user_id BIGINT REFERENCES users(id),
  child_user_id BIGINT,
  invite_code VARCHAR(6),
  status VARCHAR(20) DEFAULT 'active',
  linked_at TIMESTAMP DEFAULT NOW(),
  UNIQUE(parent_user_id, child_user_id)
);

CREATE TABLE invite_codes (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT REFERENCES users(id),
  code VARCHAR(6) UNIQUE NOT NULL,
  used BOOLEAN DEFAULT FALSE,
  expires_at TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

-- 4. 活动表
CREATE TABLE activities (
  id BIGSERIAL PRIMARY KEY,
  creator_id BIGINT REFERENCES users(id) NOT NULL,
  title VARCHAR(100) NOT NULL,
  category VARCHAR(50) NOT NULL,
  description TEXT,
  cover_image_url TEXT,
  location_lat DECIMAL(10,7) NOT NULL,
  location_lng DECIMAL(10,7) NOT NULL,
  location_address TEXT NOT NULL,
  location_name VARCHAR(100),
  start_time TIMESTAMP NOT NULL,
  end_time TIMESTAMP,
  max_participants INTEGER DEFAULT 10 CHECK (max_participants BETWEEN 5 AND 15),
  current_participants INTEGER DEFAULT 0,
  status VARCHAR(20) DEFAULT 'upcoming',
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_activities_status_time ON activities(status, start_time);
CREATE INDEX idx_activities_category ON activities(category);

-- 5. 活动报名
CREATE TABLE activity_participants (
  id BIGSERIAL PRIMARY KEY,
  activity_id BIGINT REFERENCES activities(id),
  user_id BIGINT REFERENCES users(id),
  status VARCHAR(20) DEFAULT 'registered',
  signed_in_at TIMESTAMP,
  signed_in_lat DECIMAL(10,7),
  signed_in_lng DECIMAL(10,7),
  rating INTEGER CHECK (rating BETWEEN 1 AND 5),
  review TEXT,
  joined_at TIMESTAMP DEFAULT NOW(),
  cancelled_at TIMESTAMP,
  UNIQUE(activity_id, user_id)
);

-- 6. AI对话
CREATE TABLE ai_conversations (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT REFERENCES users(id),
  session_id VARCHAR(36) NOT NULL,
  role VARCHAR(20) NOT NULL,
  content TEXT NOT NULL,
  content_type VARCHAR(20) DEFAULT 'text',
  voice_url TEXT,
  intent VARCHAR(50),
  metadata JSONB,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_ai_conv_user ON ai_conversations(user_id, session_id);

CREATE TABLE ai_user_preferences (
  user_id BIGINT PRIMARY KEY REFERENCES users(id),
  preferred_hospital VARCHAR(100),
  preferred_doctor VARCHAR(100),
  home_address TEXT,
  common_destinations JSONB,
  dietary_restrictions TEXT[],
  updated_at TIMESTAMP DEFAULT NOW()
);

-- 7. 医院/科室/医生/排班
CREATE TABLE hospitals (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  address TEXT,
  lat DECIMAL(10,7),
  lng DECIMAL(10,7),
  phone VARCHAR(20),
  logo_url TEXT,
  level VARCHAR(20),
  status VARCHAR(20) DEFAULT 'active',
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE departments (
  id BIGSERIAL PRIMARY KEY,
  hospital_id BIGINT REFERENCES hospitals(id),
  name VARCHAR(50) NOT NULL,
  description TEXT,
  sort_order INTEGER DEFAULT 0
);

CREATE TABLE doctors (
  id BIGSERIAL PRIMARY KEY,
  hospital_id BIGINT REFERENCES hospitals(id),
  department_id BIGINT REFERENCES departments(id),
  name VARCHAR(50) NOT NULL,
  title VARCHAR(50),
  avatar_url TEXT,
  specialty TEXT,
  rating DECIMAL(2,1) DEFAULT 5.0,
  rating_count INTEGER DEFAULT 0,
  status VARCHAR(20) DEFAULT 'active'
);

CREATE TABLE doctor_schedules (
  id BIGSERIAL PRIMARY KEY,
  doctor_id BIGINT REFERENCES doctors(id),
  schedule_date DATE NOT NULL,
  start_time TIME NOT NULL,
  end_time TIME NOT NULL,
  max_patients INTEGER DEFAULT 30,
  current_patients INTEGER DEFAULT 0,
  fee DECIMAL(10,2),
  status VARCHAR(20) DEFAULT 'available'
);

-- 8. 预约/问诊
CREATE TABLE appointments (
  id BIGSERIAL PRIMARY KEY,
  order_no VARCHAR(20) UNIQUE NOT NULL,
  user_id BIGINT REFERENCES users(id),
  hospital_id BIGINT REFERENCES hospitals(id),
  department_id BIGINT REFERENCES departments(id),
  doctor_id BIGINT REFERENCES doctors(id),
  schedule_id BIGINT REFERENCES doctor_schedules(id),
  patient_name VARCHAR(50),
  patient_phone VARCHAR(11),
  appointment_date DATE,
  appointment_time TIME,
  fee DECIMAL(10,2),
  status VARCHAR(20) DEFAULT 'pending',
  paid_at TIMESTAMP,
  cancelled_at TIMESTAMP,
  cancel_reason TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE consultations (
  id BIGSERIAL PRIMARY KEY,
  order_no VARCHAR(20) UNIQUE NOT NULL,
  user_id BIGINT REFERENCES users(id),
  doctor_id BIGINT REFERENCES doctors(id),
  symptom_description TEXT,
  images TEXT[],
  doctor_reply TEXT,
  fee DECIMAL(10,2) DEFAULT 19.90,
  status VARCHAR(20) DEFAULT 'pending',
  replied_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT NOW()
);

-- 9. 订单
CREATE TABLE orders (
  id BIGSERIAL PRIMARY KEY,
  order_no VARCHAR(20) UNIQUE NOT NULL,
  user_id BIGINT REFERENCES users(id),
  order_type VARCHAR(50) NOT NULL,
  amount DECIMAL(10,2) NOT NULL,
  status VARCHAR(20) DEFAULT 'pending',
  detail JSONB,
  wx_transaction_id VARCHAR(50),
  paid_at TIMESTAMP,
  completed_at TIMESTAMP,
  cancelled_at TIMESTAMP,
  refund_amount DECIMAL(10,2),
  refund_at TIMESTAMP,
  refund_reason TEXT,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_orders_user ON orders(user_id, created_at DESC);

-- 10. 通知
CREATE TABLE notifications (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT REFERENCES users(id),
  type VARCHAR(50) NOT NULL,
  title VARCHAR(100),
  content TEXT,
  data JSONB,
  is_read BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_notif_user ON notifications(user_id, is_read, created_at DESC);

-- 11. 审计日志
CREATE TABLE audit_logs (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT,
  action VARCHAR(50),
  resource_type VARCHAR(50),
  resource_id BIGINT,
  detail JSONB,
  ip_address INET,
  created_at TIMESTAMP DEFAULT NOW()
);

3. API文档

3.1 规范

  • Base URL: https://api.banxiang.com/api/v1
  • 认证: Authorization: Bearer <JWT>
  • 响应格式: { "success": true, "data": {...} } / { "success": false, "error": {"code":"...", "message":"..."} }

3.2 完整接口清单

模块 方法 路径 描述
认证 POST /auth/send-code 发送验证码
认证 POST /auth/login 登录/注册
认证 POST /auth/refresh 刷新Token
用户 GET /users/me 获取当前用户
用户 PUT /users/profile 更新资料
用户 POST /users/verify 实名认证
用户 PUT /users/emergency-contact 紧急联系人
用户 PUT /users/settings 更新设置
家庭 POST /family/generate-code 生成邀请码
家庭 POST /family/link 绑定子女
家庭 GET /family/members 家人列表
活动 GET /activities 活动列表
活动 GET /activities/:id 活动详情
活动 POST /activities 创建活动
活动 PUT /activities/:id 修改活动
活动 DELETE /activities/:id 取消活动
活动 POST /activities/:id/join 报名
活动 POST /activities/:id/cancel 取消报名
活动 POST /activities/:id/sign-in 签到
活动 POST /activities/:id/review 评价
活动 GET /users/me/activities 我的活动
AI POST /ai/chat 文字对话(SSE)
AI POST /ai/voice 语音对话
AI GET /ai/history 对话历史
医疗 GET /medical/hospitals 医院列表
医疗 GET /medical/hospitals/:id/departments 科室
医疗 GET /medical/doctors 医生列表
医疗 GET /medical/doctors/:id/schedules 排班
医疗 POST /medical/appointments 创建预约
医疗 POST /medical/appointments/:id/cancel 取消
医疗 POST /medical/consultations 创建问诊
订单 POST /orders/create 创建订单
订单 GET /orders 订单列表
订单 GET /orders/:orderNo 订单详情
订单 POST /orders/:orderNo/refund 退款
通知 GET /notifications 通知列表
通知 PUT /notifications/:id/read 标记已读
上传 POST /upload/image 上传图片
上传 POST /upload/voice 上传语音

4. Flutter组件架构

4.1 项目结构

banxiang_app/
├── lib/
│   ├── main.dart
│   ├── app.dart
│   ├── config/
│   │   ├── theme.dart          # 适老化主题
│   │   ├── routes.dart
│   │   └── constants.dart
│   ├── core/
│   │   ├── api/
│   │   │   ├── api_client.dart # Dio封装
│   │   │   └── endpoints.dart
│   │   ├── models/             # 数据模型
│   │   ├── providers/          # Riverpod状态管理
│   │   ├── services/           # 业务服务
│   │   └── utils/
│   ├── features/
│   │   ├── auth/
│   │   ├── home/
│   │   ├── activity/
│   │   ├── ai_butler/
│   │   ├── medical/
│   │   ├── profile/
│   │   └── notification/
│   └── shared/
│       ├── widgets/            # BX适老化组件库
│       └── layouts/
├── assets/
│   ├── images/
│   ├── fonts/
│   └── animations/
├── test/
└── pubspec.yaml

4.2 适老化组件库BX Design System

/// BX适老化按钮
class BxButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;
  final BxButtonStyle style; // primary / secondary / danger
  final bool loading;
  
  // 最小高度48dp字号18sp圆角12dp
  // 点击区域≥48x48dp
  // loading状态显示转圈+文字
}

/// BX适老化输入框
class BxInput extends StatelessWidget {
  final String label;
  final String hint;
  final TextInputType keyboardType;
  final bool voiceEnabled; // 右侧语音输入按钮
  
  // 高度56dp字号18sp
  // label在输入框上方
  // 错误提示在下方红色16sp
}

/// BX确认弹窗防误操作
class BxConfirmDialog extends StatelessWidget {
  final String title;
  final String message;
  final String confirmText;
  final String cancelText;
  
  // 标题22sp正文18sp
  // 按钮大且间隔远
  // 危险操作confirmText用红色
}

/// BX活动卡片
class BxActivityCard extends StatelessWidget {
  final Activity activity;
  final double distance;
  
  // 大标题18sp时间地点16sp
  // 报名按钮在右侧
  // 已满员显示灰色
}

4.3 核心代码示例

API客户端

// core/api/api_client.dart
class ApiClient {
  late final Dio _dio;
  
  ApiClient() {
    _dio = Dio(BaseOptions(
      baseUrl: 'https://api.banxiang.com/api/v1',
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 30),
    ));
    
    _dio.interceptors.addAll([
      AuthInterceptor(),   // 自动附加JWT
      LogInterceptor(),
      ErrorInterceptor(),  // 统一错误处理
    ]);
  }
  
  Future<T> get<T>(String path, {Map<String, dynamic>? params}) async {
    final response = await _dio.get(path, queryParameters: params);
    return response.data['data'] as T;
  }
  
  Future<T> post<T>(String path, {dynamic data}) async {
    final response = await _dio.post(path, data: data);
    return response.data['data'] as T;
  }
}

AI管家对话页面

// features/ai_butler/chat_page.dart
class AiChatPage extends ConsumerStatefulWidget {
  @override
  ConsumerState<AiChatPage> createState() => _AiChatPageState();
}

class _AiChatPageState extends ConsumerState<AiChatPage> {
  final _controller = TextEditingController();
  bool _isRecording = false;
  
  @override
  Widget build(BuildContext context) {
    final messages = ref.watch(aiChatProvider);
    
    return Scaffold(
      appBar: AppBar(title: Text('🤖 小伴 · AI管家')),
      body: Column(
        children: [
          // 消息列表
          Expanded(
            child: ListView.builder(
              reverse: true,
              itemCount: messages.length,
              itemBuilder: (ctx, i) => ChatBubble(
                message: messages[i],
                fontSize: ref.watch(fontSizeProvider),
              ),
            ),
          ),
          // 快捷指令栏
          QuickActions(
            actions: ['附近活动', '挂号', '买菜', '天气'],
            onTap: (action) => _sendMessage(action),
          ),
          // 输入栏
          ChatInputBar(
            controller: _controller,
            onSend: () => _sendMessage(_controller.text),
            onVoiceStart: _startRecording,
            onVoiceEnd: _stopRecording,
            isRecording: _isRecording,
          ),
        ],
      ),
    );
  }
  
  void _sendMessage(String text) {
    ref.read(aiChatProvider.notifier).sendMessage(text);
    _controller.clear();
  }
}

活动推荐算法

// core/services/recommendation_service.dart
double calculateRecommendScore(User user, Activity activity, double distanceKm) {
  // 兴趣匹配度 (0-1)
  final commonInterests = user.interests
      .where((i) => i == activity.category)
      .length;
  final interestScore = commonInterests > 0 ? 1.0 : 0.0;
  
  // 距离分 (0-1), 10km内线性衰减
  final distanceScore = 1 - (distanceKm / 10).clamp(0, 1);
  
  // 时间分 (0-1), 168小时(一周)内线性衰减
  final hoursDiff = activity.startTime.difference(DateTime.now()).inHours;
  final timeScore = 1 - (hoursDiff / 168).clamp(0, 1);
  
  // 热度分 (0-1)
  final hotScore = activity.currentParticipants / activity.maxParticipants;
  
  return interestScore * 0.4 + distanceScore * 0.3 + timeScore * 0.2 + hotScore * 0.1;
}

5. AI管家技术方案

5.1 架构

用户输入(文字/语音)
     ↓
┌─────────────┐
│  语音处理   │  ← 讯飞ASR语音→文字
└──────┬──────┘
       ↓
┌─────────────┐
│  意图识别   │  ← 通义千问 Function Calling
└──────┬──────┘
       ↓
┌─────────────────────────────┐
│        任务路由              │
│  ├── 活动查询 → 调用活动API  │
│  ├── 挂号预约 → 调用医疗API  │
│  ├── 生鲜购买 → 调用商品API  │
│  └── 闲聊/咨询 → 直接对话    │
└──────┬──────────────────────┘
       ↓
┌─────────────┐
│  响应生成   │  ← 通义千问生成回复
└──────┬──────┘
       ↓
┌─────────────┐
│  语音合成   │  ← 讯飞TTS文字→语音
└──────┬──────┘
       ↓
  返回用户(文字+语音+操作按钮)

5.2 Function Calling定义

// AI工具定义
const tools = [
  {
    type: 'function',
    function: {
      name: 'search_activities',
      description: '搜索附近的活动',
      parameters: {
        type: 'object',
        properties: {
          category: { type: 'string', description: '活动类型' },
          timeRange: { type: 'string', enum: ['today', 'tomorrow', 'week'] },
          lat: { type: 'number' },
          lng: { type: 'number' }
        }
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'book_appointment',
      description: '预约挂号',
      parameters: {
        type: 'object',
        properties: {
          hospitalName: { type: 'string' },
          departmentName: { type: 'string' },
          doctorName: { type: 'string' },
          date: { type: 'string' },
          time: { type: 'string' }
        }
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'order_grocery',
      description: '生鲜配送下单',
      parameters: {
        type: 'object',
        properties: {
          items: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                name: { type: 'string' },
                quantity: { type: 'number' }
              }
            }
          },
          deliveryAddress: { type: 'string' }
        }
      }
    }
  }
];

5.3 System Prompt

你是「小伴」「伴享」APP的AI智能管家。你服务的是50-70岁的银发群体。

规则:
1. 说话简洁、亲切、温暖,像家人一样
2. 每次回复不超过100字
3. 称呼用户为"X阿姨"或"X叔叔"(根据性别和姓氏)
4. 不使用网络用语、不说英文
5. 涉及医疗健康的建议必须加"仅供参考,建议咨询医生"
6. 涉及支付前必须明确告知金额并确认
7. 不确定的信息不要编造,说"我帮您查查"
8. 提供操作选项时,用简短的按钮文字

用户信息:
- 姓名:{userName}
- 城市:{city}
- 兴趣:{interests}
- 常去医院:{preferredHospital}
- 家庭住址:{homeAddress}

6. 部署方案

6.1 服务器配置MVP阶段

服务 配置 月费用
应用服务器 阿里云ECS 2核4G ¥200/月
数据库 阿里云RDS PostgreSQL 2核4G ¥300/月
Redis 阿里云Redis 1G ¥100/月
OSS 按量计费 ¥50/月
CDN 按量计费 ¥50/月
合计 ¥700/月

6.2 Docker Compose

version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://banxiang:xxx@db:5432/banxiang
      - REDIS_URL=redis://redis:6379
      - QWEN_API_KEY=${QWEN_API_KEY}
      - XUNFEI_APP_ID=${XUNFEI_APP_ID}
      - WX_PAY_MCH_ID=${WX_PAY_MCH_ID}
    depends_on:
      - db
      - redis
    restart: always

  db:
    image: postgres:15
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      - POSTGRES_DB=banxiang
      - POSTGRES_USER=banxiang
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    restart: always

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data
    restart: always

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - app
    restart: always

volumes:
  pgdata:
  redisdata:

6.3 CI/CD流程

代码推送 → GitHub Actions
  ├── 运行测试
  ├── 构建Docker镜像
  ├── 推送到阿里云容器镜像
  └── SSH到服务器执行 docker compose pull && docker compose up -d

6.4 监控方案

维度 工具 说明
应用监控 PM2 + 阿里云ARMS 错误率、响应时间
服务器监控 阿里云云监控 CPU/内存/磁盘
日志 Winston + 阿里云SLS 结构化日志
报警 钉钉/飞书Webhook 异常自动通知

7. 安全方案

7.1 数据安全

层面 措施
传输 HTTPS + TLS 1.3
存储 敏感字段AES-256加密
身份证 哈希索引 + 加密存储,不存明文
JWT HS256签名7天有效期
密钥管理 环境变量,不入代码库

7.2 接口安全

措施 配置
全局限流 100次/分钟/IP
登录限流 5次/分钟/手机号
验证码限流 3次/5分钟/手机号
SQL注入防护 参数化查询
XSS防护 输出转义 + CSP头
CORS 白名单域名

文档结束