首次提交by MimoCode

This commit is contained in:
tang1219
2026-06-15 14:50:15 +08:00
parent 584b31da50
commit ead13f863c
166 changed files with 14908 additions and 1 deletions
+728
View File
@@ -0,0 +1,728 @@
# 系统架构设计文档
## 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 配置
- 请求限流