# 系统架构设计文档 ## 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 抽象接口 ```python 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 管理器 ```python 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 抽象 ```python 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 通知管理器 ```python 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 插件接口 ```python 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 插件管理器 ```python 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 工具定义 ```python 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. 环境变量配置 ```bash # 数据库配置 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 配置 - 请求限流