Files
YaoXiang/docs/architecture.md
T
2026-06-15 14:50:15 +08:00

27 KiB
Raw Blame History

系统架构设计文档

1. 系统概述

家庭药品与应急物资管理系统(YaoXiang)是一个基于 Web 的家庭药品库存管理系统,支持 AI 自动录入、智能搜索、到期提醒等功能。系统采用前后端分离架构,支持 Docker 单容器部署。

2. 技术栈

前端

  • 框架: React 18+
  • 语言: TypeScript
  • 构建工具: Vite
  • UI 库: Ant Design Mobile 5.x(移动端优化)
  • 状态管理: Zustand
  • 路由: React Router 6
  • HTTP 客户端: Axios
  • PWA: vite-plugin-pwa

后端

  • 框架: FastAPI
  • 语言: Python 3.11+
  • ORM: SQLAlchemy 2.0
  • 数据库迁移: Alembic
  • 文件存储: 本地文件系统
  • 任务队列: 无(采用异步任务)

数据库

  • 主数据库: SQLite(可升级 PostgreSQL
  • 缓存: 无(可选 Redis

AI Provider

  • 多模态模型: OpenAI GPT-4o / Gemini / Claude
  • 文本模型: DeepSeek / Ollama
  • 抽象层: 统一 Provider 接口

部署

  • 容器化: Docker
  • 编排: Docker Compose
  • 反向代理: Nginx(前端静态文件)

3. 系统架构图

┌─────────────────────────────────────────────────────────────┐
│                      客户端层                                │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  手机浏览器  │  │   平板浏览器 │  │   PC 浏览器  │         │
│  │   (PWA)     │  │   (大屏模式) │  │             │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      前端应用层                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  React App  │  │   PWA 配置   │  │  状态管理    │         │
│  │  (Vite)     │  │  Service Worker │  │  (Zustand)  │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  页面组件    │  │   业务组件   │  │  API 调用层  │         │
│  │  (Router)   │  │  (Ant Design)│  │  (Axios)    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      API 通信层                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │                 RESTful API                         │   │
│  │  POST /api/auth/login                               │   │
│  │  GET  /api/medicines                                │   │
│  │  POST /api/medicines                                │   │
│  │  POST /api/medicines/recognize                      │   │
│  │  ...                                                │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      后端应用层                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  FastAPI    │  │  路由层      │  │  中间件      │         │
│  │  (Router)   │  │  (APIRouter)│  │  (Auth)     │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  服务层      │  │  数据访问层   │  │  模型层      │         │
│  │  (Service)  │  │  (Repository)│  │  (Model)    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  AI Provider│  │  通知系统    │  │  文件存储    │         │
│  │  (Abstract) │  │  (Provider) │  │  (Local)    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      数据存储层                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  SQLite     │  │  文件系统    │  │  缓存       │         │
│  │  (Database) │  │  (Uploads)  │  │  (可选)     │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘

4. 模块划分

4.1 前端模块

frontend/
├── src/
│   ├── api/                    # API 调用层
│   │   ├── client.ts          # Axios 实例配置
│   │   ├── auth.ts            # 认证相关 API
│   │   ├── medicines.ts       # 药品管理 API
│   │   ├── categories.ts      # 分类管理 API
│   │   ├── batches.ts         # 批次管理 API
│   │   └── notifications.ts   # 通知相关 API
│   ├── components/             # 业务组件
│   │   ├── MedicineCard/      # 药品卡片
│   │   ├── BatchForm/         # 批次表单
│   │   ├── CategoryTree/      # 分类树
│   │   └── SearchBar/         # 搜索栏
│   ├── pages/                  # 页面组件
│   │   ├── Home/              # 首页(库存概览)
│   │   ├── MedicineList/      # 药品列表
│   │   ├── MedicineDetail/    # 药品详情
│   │   ├── AddMedicine/       # 添加药品
│   │   ├── QuickDispense/     # 快速取药(大屏模式)
│   │   ├── Scanner/           # AI 识别
│   │   ├── Search/            # 搜索页面
│   │   ├── Notifications/     # 通知中心
│   │   ├── Settings/          # 设置页面
│   │   └── Login/             # 登录页面
│   ├── stores/                 # 状态管理
│   │   ├── authStore.ts       # 认证状态
│   │   ├── medicineStore.ts   # 药品状态
│   │   └── uiStore.ts         # UI 状态
│   ├── hooks/                  # 自定义 Hooks
│   │   ├── useAuth.ts         # 认证 Hook
│   │   ├── useMedicine.ts     # 药品 Hook
│   │   └── useCamera.ts       # 摄像头 Hook
│   ├── utils/                  # 工具函数
│   │   ├── date.ts            # 日期处理
│   │   ├── storage.ts         # 本地存储
│   │   └── validators.ts      # 表单验证
│   ├── types/                  # TypeScript 类型
│   │   ├── medicine.ts        # 药品类型
│   │   ├── batch.ts           # 批次类型
│   │   ├── user.ts            # 用户类型
│   │   └── api.ts             # API 响应类型
│   ├── styles/                 # 样式文件
│   │   ├── global.css         # 全局样式
│   │   └── variables.css      # CSS 变量
│   ├── App.tsx                 # 根组件
│   ├── main.tsx                # 入口文件
│   └── router.tsx              # 路由配置
├── public/                     # 静态资源
├── index.html                  # HTML 模板
├── vite.config.ts              # Vite 配置
├── tsconfig.json               # TypeScript 配置
└── package.json                # 依赖配置

4.2 后端模块

backend/
├── app/
│   ├── api/                    # 路由层
│   │   ├── v1/                # API 版本
│   │   │   ├── auth.py        # 认证路由
│   │   │   ├── medicines.py   # 药品路由
│   │   │   ├── batches.py     # 批次路由
│   │   │   ├── categories.py  # 分类路由
│   │   │   ├── search.py      # 搜索路由
│   │   │   ├── notifications.py # 通知路由
│   │   │   ├── ai.py          # AI 识别路由
│   │   │   └── users.py       # 用户管理路由
│   │   └── router.py          # 路由汇总
│   ├── core/                   # 核心配置
│   │   ├── config.py          # 配置管理
│   │   ├── security.py        # 安全工具
│   │   └── deps.py            # 依赖注入
│   ├── models/                 # 数据模型
│   │   ├── medicine.py        # 药品模型
│   │   ├── batch.py           # 批次模型
│   │   ├── category.py        # 分类模型
│   │   ├── user.py            # 用户模型
│   │   ├── notification.py    # 通知模型
│   │   └── audit.py           # 审计日志模型
│   ├── schemas/                # Pydantic 模型
│   │   ├── medicine.py        # 药品 Schema
│   │   ├── batch.py           # 批次 Schema
│   │   ├── category.py        # 分类 Schema
│   │   ├── user.py            # 用户 Schema
│   │   └── auth.py            # 认证 Schema
│   ├── services/               # 服务层
│   │   ├── medicine.py        # 药品服务
│   │   ├── batch.py           # 批次服务
│   │   ├── category.py        # 分类服务
│   │   ├── user.py            # 用户服务
│   │   ├── auth.py            # 认证服务
│   │   ├── notification.py    # 通知服务
│   │   └── search.py          # 搜索服务
│   ├── repositories/           # 数据访问层
│   │   ├── medicine.py        # 药品仓库
│   │   ├── batch.py           # 批次仓库
│   │   ├── category.py        # 分类仓库
│   │   └── user.py            # 用户仓库
│   ├── ai/                     # AI Provider
│   │   ├── provider.py        # 抽象基类
│   │   ├── openai.py          # OpenAI 实现
│   │   ├── gemini.py          # Gemini 实现
│   │   ├── claude.py          # Claude 实现
│   │   ├── deepseek.py        # DeepSeek 实现
│   │   ├── ollama.py          # Ollama 实现
│   │   └── manager.py         # Provider 管理器
│   ├── notifications/          # 通知系统
│   │   ├── provider.py        # 抽象基类
│   │   ├── serverchan.py      # Server酱
│   │   ├── pushplus.py        # PushPlus
│   │   ├── bark.py            # Bark
│   │   ├── wechat.py          # 企业微信
│   │   ├── telegram.py        # Telegram
│   │   ├── email.py           # 邮件
│   │   └── manager.py         # 通知管理器
│   ├── storage/                # 文件存储
│   │   ├── local.py           # 本地存储
│   │   └── manager.py         # 存储管理器
│   ├── tasks/                  # 异步任务
│   │   ├── expiry_check.py    # 到期检查任务
│   │   └── stock_check.py     # 库存检查任务
│   ├── database.py             # 数据库连接
│   └── main.py                 # 应用入口
├── alembic/                    # 数据库迁移
│   ├── versions/
│   └── env.py
├── tests/                      # 测试文件
├── requirements.txt            # 依赖配置
├── alembic.ini                 # Alembic 配置
├── Dockerfile                  # Docker 配置
└── .env.example                # 环境变量示例

5. 数据流设计

5.1 AI 自动录入流程

用户上传图片
    │
    ▼
┌─────────────────┐
│  图片预处理      │
│  (压缩/格式化)   │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  调用 Vision    │
│  Provider       │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  返回识别结果    │
│  (JSON)         │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  用户确认/编辑   │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  保存到数据库    │
│  + 保存图片      │
└─────────────────┘

5.2 快速取药流程

用户选择药品
    │
    ▼
┌─────────────────┐
│  显示药品详情    │
│  (可用批次列表)  │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  用户选择批次    │
│  输入取药数量    │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  扣减库存        │
│  记录审计日志    │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  检查库存阈值    │
│  触发通知(可选)  │
└─────────────────┘

5.3 到期提醒流程

定时任务触发
    │
    ▼
┌─────────────────┐
│  查询即将过期    │
│  批次 (90/30/7天)│
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  生成提醒内容    │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  调用通知系统    │
│  发送提醒        │
└─────────────────┘

6. AI Provider 抽象层设计

6.1 抽象接口

from abc import ABC, abstractmethod
from typing import Optional
from pydantic import BaseModel

class VisionResult(BaseModel):
    """视觉识别结果"""
    generic_name: str
    brand_name: Optional[str]
    manufacturer: Optional[str]
    specification: Optional[str]

class DateResult(BaseModel):
    """日期识别结果"""
    production_date: Optional[str]
    expiry_date: Optional[str]

class LeafletResult(BaseModel):
    """说明书识别结果"""
    indications: str
    adult_dose: str
    child_dose: Optional[str]
    contraindications: str
    notes: Optional[str]

class VisionProvider(ABC):
    """视觉模型提供者抽象基类"""
    
    @abstractmethod
    async def recognize_medicine(self, image_bytes: bytes) -> VisionResult:
        """识别药盒信息"""
        pass
    
    @abstractmethod
    async def recognize_dates(self, image_bytes: bytes) -> DateResult:
        """识别日期信息"""
        pass

class TextProvider(ABC):
    """文本模型提供者抽象基类"""
    
    @abstractmethod
    async def summarize_leaflet(self, text: str) -> LeafletResult:
        """总结说明书内容"""
        pass
    
    @abstractmethod
    async def natural_language_search(self, query: str, medicines: list) -> list:
        """自然语言搜索"""
        pass

6.2 Provider 管理器

class AIManager:
    """AI Provider 管理器"""
    
    def __init__(self):
        self.vision_providers: dict[str, VisionProvider] = {}
        self.text_providers: dict[str, TextProvider] = {}
    
    def register_vision_provider(self, name: str, provider: VisionProvider):
        """注册视觉模型提供者"""
        self.vision_providers[name] = provider
    
    def register_text_provider(self, name: str, provider: TextProvider):
        """注册文本模型提供者"""
        self.text_providers[name] = provider
    
    def get_vision_provider(self, name: str) -> VisionProvider:
        """获取视觉模型提供者"""
        return self.vision_providers.get(name)
    
    def get_text_provider(self, name: str) -> TextProvider:
        """获取文本模型提供者"""
        return self.text_providers.get(name)

7. 通知系统设计

7.1 通知 Provider 抽象

from abc import ABC, abstractmethod

class NotificationProvider(ABC):
    """通知提供者抽象基类"""
    
    @abstractmethod
    async def send(self, title: str, content: str) -> bool:
        """发送通知"""
        pass
    
    @abstractmethod
    def validate_config(self) -> bool:
        """验证配置"""
        pass

7.2 通知管理器

class NotificationManager:
    """通知管理器"""
    
    def __init__(self):
        self.providers: list[NotificationProvider] = []
    
    def add_provider(self, provider: NotificationProvider):
        """添加通知提供者"""
        self.providers.append(provider)
    
    async def send_notification(self, title: str, content: str):
        """发送通知到所有提供者"""
        for provider in self.providers:
            try:
                await provider.send(title, content)
            except Exception as e:
                # 记录错误但不中断
                pass

8. 认证授权设计

8.1 用户角色

  • admin: 管理员,拥有所有权限
  • user: 普通用户,可查看、添加库存、取药
  • readonly: 只读用户,仅可查看

8.2 权限矩阵

功能 admin user readonly
查看药品
添加药品
修改药品
删除药品
取药
用户管理
系统设置
通知管理

8.3 JWT 认证流程

用户登录
    │
    ▼
┌─────────────────┐
│  验证用户名密码  │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  生成 JWT Token  │
│  (Access Token)  │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  返回 Token      │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  前端存储 Token  │
│  (localStorage)  │
└─────────────────┘
    │
    ▼
┌─────────────────┐
│  后续请求携带    │
│  Authorization   │
│  Header          │
└─────────────────┘

9. 插件系统设计

9.1 插件接口

from abc import ABC, abstractmethod

class Plugin(ABC):
    """插件抽象基类"""
    
    @abstractmethod
    def get_name(self) -> str:
        """获取插件名称"""
        pass
    
    @abstractmethod
    def get_description(self) -> str:
        """获取插件描述"""
        pass
    
    @abstractmethod
    def initialize(self, app):
        """初始化插件"""
        pass

9.2 插件管理器

class PluginManager:
    """插件管理器"""
    
    def __init__(self):
        self.plugins: dict[str, Plugin] = {}
    
    def register_plugin(self, plugin: Plugin):
        """注册插件"""
        name = plugin.get_name()
        self.plugins[name] = plugin
    
    def get_plugin(self, name: str) -> Plugin:
        """获取插件"""
        return self.plugins.get(name)
    
    def list_plugins(self) -> list[str]:
        """列出所有插件"""
        return list(self.plugins.keys())

10. MCP 协议支持

10.1 MCP 工具定义

from mcp import Tool

# 查询库存工具
query_inventory_tool = Tool(
    name="query_inventory",
    description="查询家庭药品库存",
    inputSchema={
        "type": "object",
        "properties": {
            "medicine_name": {
                "type": "string",
                "description": "药品名称"
            }
        }
    }
)

# 取药工具
dispense_medicine_tool = Tool(
    name="dispense_medicine",
    description="取药操作",
    inputSchema={
        "type": "object",
        "properties": {
            "medicine_id": {
                "type": "integer",
                "description": "药品ID"
            },
            "quantity": {
                "type": "integer",
                "description": "取药数量"
            }
        },
        "required": ["medicine_id", "quantity"]
    }
)

11. 部署架构

┌─────────────────────────────────────────┐
│              Docker 容器                 │
├─────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐       │
│  │   Nginx     │  │   FastAPI   │       │
│  │   (静态文件) │  │   (后端)    │       │
│  │   :80       │  │   :8000     │       │
│  └─────────────┘  └─────────────┘       │
│  ┌─────────────┐  ┌─────────────┐       │
│  │   SQLite    │  │   文件存储   │       │
│  │   (数据库)   │  │   (图片)    │       │
│  └─────────────┘  └─────────────┘       │
└─────────────────────────────────────────┘

12. 环境变量配置

# 数据库配置
DATABASE_URL=sqlite:///./data/yaoxiang.db

# AI Provider 配置
AI_PROVIDER=openai
OPENAI_API_KEY=sk-xxx
OPENAI_MODEL=gpt-4o

# 通知配置
NOTIFICATION_PROVIDERS=serverchan,pushplus
SERVERCHAN_KEY=xxx
PUSHPLUS_TOKEN=xxx

# 安全配置
JWT_SECRET_KEY=xxx
JWT_ALGORITHM=HS256
JWT_EXPIRATION_HOURS=24

# 文件存储配置
UPLOAD_DIR=./data/uploads
MAX_UPLOAD_SIZE=10485760  # 10MB

# 应用配置
APP_NAME=药箱
APP_VERSION=1.0.0
DEBUG=false

13. 开发规范

13.1 代码风格

  • Python: 遵循 PEP 8,使用 Black 格式化
  • TypeScript: 遵循 ESLint 规则,使用 Prettier 格式化
  • Git: 使用 Conventional Commits 规范

13.2 分支管理

  • main: 生产分支
  • develop: 开发分支
  • feature/*: 功能分支
  • bugfix/*: 修复分支
  • release/*: 发布分支

13.3 提交规范

feat: 新功能
fix: 修复 bug
docs: 文档更新
style: 代码格式调整
refactor: 重构
test: 测试相关
chore: 构建/工具相关

14. 性能优化

14.1 前端优化

  • 路由懒加载
  • 图片懒加载
  • 虚拟列表(长列表优化)
  • Service Worker 缓存

14.2 后端优化

  • 数据库连接池
  • 查询优化(索引、分页)
  • 异步处理耗时任务
  • 响应缓存

15. 安全设计

15.1 认证安全

  • 密码使用 bcrypt 加密存储
  • JWT Token 定期轮换
  • 登录失败次数限制

15.2 数据安全

  • 敏感配置使用环境变量
  • 文件上传类型验证
  • SQL 注入防护(ORM
  • XSS 防护(前端)

15.3 传输安全

  • 支持 HTTPS
  • CORS 配置
  • 请求限流