# 药箱后端开发文档 ## 1. 项目概述 药箱(YaoXiang)是一个家庭药品与应急物资管理系统,后端采用 FastAPI 框架,提供 RESTful API 服务。 ## 2. 技术栈 | 技术 | 版本 | 说明 | |------|------|------| | Python | 3.11+ | 运行环境 | | FastAPI | 0.104.1 | Web 框架 | | SQLAlchemy | 2.0.23 | ORM 框架 | | Alembic | 1.13.0 | 数据库迁移 | | SQLite | - | 数据库 | | Pydantic | 2.5.2 | 数据验证 | | python-jose | 3.3.0 | JWT 认证 | | passlib | 1.7.4 | 密码加密 | | OpenAI | 1.6.1 | AI 服务 | ## 3. 项目结构 ``` backend/ ├── app/ # 主应用目录 │ ├── __init__.py │ ├── main.py # FastAPI 应用入口 │ ├── config.py # 配置管理 │ ├── database.py # 数据库连接 │ │ │ ├── api/ # API 路由层 │ │ ├── router.py # 路由汇总 │ │ └── v1/ # API 版本 1 │ │ ├── auth.py # 认证接口 │ │ ├── medicines.py # 药品管理接口 │ │ ├── batches.py # 批次管理接口 │ │ ├── categories.py # 分类管理接口 │ │ ├── search.py # 搜索接口 │ │ ├── notifications.py # 通知接口 │ │ ├── ai.py # AI 识别接口 │ │ ├── users.py # 用户管理接口 │ │ └── settings.py # 系统设置接口 │ │ │ ├── models/ # SQLAlchemy 数据模型 │ │ ├── user.py # 用户模型 │ │ ├── medicine.py # 药品模型 │ │ ├── batch.py # 批次模型 │ │ ├── category.py # 分类模型 │ │ ├── audit_log.py # 审计日志模型 │ │ ├── notification.py # 通知模型 │ │ └── setting.py # 设置模型 │ │ │ ├── schemas/ # Pydantic 数据模式 │ │ ├── user.py │ │ ├── medicine.py │ │ ├── batch.py │ │ ├── category.py │ │ └── auth.py │ │ │ ├── services/ # 业务服务层 │ │ ├── auth.py # 认证服务 │ │ ├── user.py # 用户服务 │ │ ├── medicine.py # 药品服务 │ │ ├── batch.py # 批次服务 │ │ ├── category.py # 分类服务 │ │ ├── audit.py # 审计日志服务 │ │ └── notification.py # 通知服务 │ │ │ ├── repositories/ # 数据访问层 │ │ ├── user.py │ │ ├── medicine.py │ │ ├── batch.py │ │ ├── category.py │ │ ├── audit_log.py │ │ └── notification.py │ │ │ ├── ai/ # AI Provider 模块 │ │ ├── base.py # 抽象基类 │ │ ├── openai_provider.py # OpenAI 实现 │ │ └── manager.py # Provider 管理器 │ │ │ ├── notifications/ # 通知系统 │ │ ├── base.py # 抽象基类 │ │ ├── serverchan.py # Server酱 │ │ ├── pushplus.py # PushPlus │ │ └── manager.py # 通知管理器 │ │ │ ├── storage/ # 文件存储 │ │ ├── base.py # 抽象基类 │ │ ├── local.py # 本地存储 │ │ └── manager.py # 存储管理器 │ │ │ ├── core/ # 核心功能 │ │ ├── security.py # 安全工具 (JWT, 密码) │ │ ├── deps.py # 依赖注入 │ │ └── exceptions.py # 异常处理 │ │ │ └── tasks/ # 异步任务 │ └── expiry_check.py # 到期检查任务 │ ├── tests/ # 测试目录 ├── data/ # 数据目录 ├── requirements.txt # Python 依赖 ├── .env.example # 环境变量示例 └── .env # 环境变量配置 ``` ## 4. 快速开始 ### 4.1 环境准备 ```bash # 进入后端目录 cd backend # 创建虚拟环境 (可选) python -m venv venv venv\Scripts\activate # Windows # source venv/bin/activate # Linux/Mac # 安装依赖 pip install -r requirements.txt ``` ### 4.2 配置环境变量 ```bash # 复制环境变量示例文件 cp .env.example .env # 编辑 .env 文件,配置必要的参数 ``` ### 4.3 启动服务 ```bash # 开发模式启动 uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 # 生产模式启动 uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4 ``` ### 4.4 访问 API 文档 - Swagger UI: http://localhost:8000/docs - ReDoc: http://localhost:8000/redoc - 健康检查: http://localhost:8000/health ## 5. 配置说明 ### 5.1 环境变量配置 | 变量名 | 默认值 | 说明 | |--------|--------|------| | DATABASE_URL | sqlite+aiosqlite:///./data/yaoxiang.db | 数据库连接字符串 | | JWT_SECRET_KEY | your-secret-key-change-in-production | JWT 密钥 | | JWT_ALGORITHM | HS256 | JWT 算法 | | JWT_EXPIRATION_HOURS | 24 | JWT 过期时间(小时) | | AI_PROVIDER | openai | AI 服务提供者 | | OPENAI_API_KEY | - | OpenAI API Key | | OPENAI_MODEL | gpt-4o | OpenAI 模型 | | UPLOAD_DIR | ./data/uploads | 文件上传目录 | | CORS_ORIGINS | http://localhost:5173 | CORS 允许的源 | ### 5.2 AI Provider 配置 支持的 AI Provider: - **openai**: OpenAI GPT-4o - **gemini**: Google Gemini - **claude**: Anthropic Claude - **deepseek**: DeepSeek - **ollama**: 本地 Ollama ## 6. 数据库设计 ### 6.1 数据表 | 表名 | 说明 | |------|------| | users | 用户表 | | categories | 分类表 | | medicines | 药品表 | | batches | 批次表 | | audit_logs | 审计日志表 | | notifications | 通知表 | | settings | 系统设置表 | ### 6.2 核心表结构 #### users 表 ```sql CREATE TABLE users ( id INTEGER PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, role VARCHAR(20) DEFAULT 'user', display_name VARCHAR(100), email VARCHAR(100), notification_level VARCHAR(20) DEFAULT 'normal', is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP, updated_at TIMESTAMP ); ``` #### medicines 表 ```sql CREATE TABLE medicines ( id INTEGER PRIMARY KEY, name VARCHAR(200) NOT NULL, generic_name VARCHAR(200), brand_name VARCHAR(200), manufacturer VARCHAR(200), specification VARCHAR(200), category_id INTEGER REFERENCES categories(id), indications TEXT, adult_dose TEXT, child_dose TEXT, contraindications TEXT, notes TEXT, image_front_path VARCHAR(500), image_expiry_path VARCHAR(500), image_leaflet_paths JSON, expiry_grace_days INTEGER DEFAULT 0, created_by INTEGER REFERENCES users(id), created_at TIMESTAMP, updated_at TIMESTAMP ); ``` #### batches 表 ```sql CREATE TABLE batches ( id INTEGER PRIMARY KEY, medicine_id INTEGER REFERENCES medicines(id), batch_no VARCHAR(100), production_date DATE, expiry_date DATE NOT NULL, quantity INTEGER DEFAULT 0, location VARCHAR(200), is_expired BOOLEAN DEFAULT FALSE, created_at TIMESTAMP, updated_at TIMESTAMP ); ``` ## 7. API 接口 ### 7.1 认证接口 | 方法 | 路径 | 说明 | |------|------|------| | POST | /api/v1/auth/login | 用户登录 | | GET | /api/v1/auth/me | 获取当前用户信息 | | PUT | /api/v1/auth/password | 修改密码 | ### 7.2 药品管理接口 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | GET | /api/v1/medicines | 获取药品列表 | 登录用户 | | GET | /api/v1/medicines/{id} | 获取药品详情 | 登录用户 | | POST | /api/v1/medicines | 创建药品 | admin/user | | PUT | /api/v1/medicines/{id} | 更新药品 | admin/user | | DELETE | /api/v1/medicines/{id} | 删除药品 | admin | ### 7.3 批次管理接口 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | GET | /api/v1/batches/medicine/{medicine_id} | 获取药品的所有批次 | 登录用户 | | GET | /api/v1/batches/{id} | 获取批次详情 | 登录用户 | | POST | /api/v1/batches/medicine/{medicine_id} | 创建批次 | admin/user | | PUT | /api/v1/batches/{id} | 更新批次 | admin/user | | DELETE | /api/v1/batches/{id} | 删除批次 | admin | | POST | /api/v1/batches/{id}/dispense | 取药 | admin/user | | POST | /api/v1/batches/{id}/add-stock | 入库 | admin/user | ### 7.4 分类管理接口 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | GET | /api/v1/categories | 获取分类列表 | 登录用户 | | GET | /api/v1/categories/tree | 获取分类树 | 登录用户 | | GET | /api/v1/categories/{id} | 获取分类详情 | 登录用户 | | POST | /api/v1/categories | 创建分类 | admin | | PUT | /api/v1/categories/{id} | 更新分类 | admin | | DELETE | /api/v1/categories/{id} | 删除分类 | admin | ### 7.5 搜索接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | /api/v1/search?q=关键词 | 关键词搜索 | | POST | /api/v1/search/natural | 自然语言搜索 | ### 7.6 AI 识别接口 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | POST | /api/v1/ai/recognize-medicine | 识别药盒 | admin/user | | POST | /api/v1/ai/recognize-dates | 识别日期 | admin/user | | POST | /api/v1/ai/recognize-leaflet | 识别说明书 | admin/user | ### 7.7 用户管理接口 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | GET | /api/v1/users | 获取用户列表 | admin | | GET | /api/v1/users/{id} | 获取用户详情 | admin | | POST | /api/v1/users | 创建用户 | admin | | PUT | /api/v1/users/{id} | 更新用户 | admin | | DELETE | /api/v1/users/{id} | 删除用户 | admin | | POST | /api/v1/users/{id}/reset-password | 重置密码 | admin | ### 7.8 通知接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | /api/v1/notifications | 获取通知列表 | | PUT | /api/v1/notifications/{id}/read | 标记为已读 | | PUT | /api/v1/notifications/read-all | 全部标记为已读 | | DELETE | /api/v1/notifications/{id} | 删除通知 | ### 7.9 系统设置接口 | 方法 | 路径 | 说明 | 权限 | |------|------|------|------| | GET | /api/v1/settings | 获取所有设置 | admin | | GET | /api/v1/settings/{key} | 获取单个设置 | admin | | PUT | /api/v1/settings/{key} | 更新设置 | admin | ## 8. 开发指南 ### 8.1 添加新的 API 接口 1. 在 `app/api/v1/` 目录下创建或修改路由文件 2. 定义请求和响应的 Pydantic 模式 3. 实现业务逻辑(服务层) 4. 在 `app/api/router.py` 中注册路由 示例: ```python # app/api/v1/example.py from fastapi import APIRouter, Depends from app.core.deps import get_current_user router = APIRouter() @router.get("/") async def list_examples(current_user = Depends(get_current_user)): return {"message": "success"} ``` ### 8.2 添加新的数据模型 1. 在 `app/models/` 目录下创建模型文件 2. 继承 `Base` 类 3. 定义表名和字段 4. 在 `app/models/__init__.py` 中导入 ```python # app/models/example.py from sqlalchemy import Column, Integer, String from app.database import Base class Example(Base): __tablename__ = "examples" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), nullable=False) ``` ### 8.3 添加新的服务 1. 在 `app/services/` 目录下创建服务文件 2. 实现业务逻辑 3. 使用 Repository 进行数据访问 ```python # app/services/example.py from sqlalchemy.ext.asyncio import AsyncSession from app.repositories.example import ExampleRepository class ExampleService: def __init__(self, db: AsyncSession): self.db = db self.repo = ExampleRepository(db) async def get_example(self, example_id: int): return await self.repo.get_by_id(example_id) ``` ### 8.4 添加新的 AI Provider 1. 在 `app/ai/` 目录下创建 Provider 文件 2. 继承 `VisionProvider` 或 `TextProvider` 3. 实现抽象方法 4. 在 `app/ai/manager.py` 中注册 ```python # app/ai/custom_provider.py from app.ai.base import VisionProvider, VisionResult class CustomVisionProvider(VisionProvider): async def recognize_medicine(self, image_bytes: bytes) -> VisionResult: # 实现识别逻辑 return VisionResult(generic_name="药品名称") async def recognize_dates(self, image_bytes: bytes): # 实现日期识别 pass ``` ### 8.5 添加新的通知 Provider 1. 在 `app/notifications/` 目录下创建 Provider 文件 2. 继承 `NotificationProvider` 3. 实现 `send` 和 `validate_config` 方法 ```python # app/notifications/custom.py from app.notifications.base import NotificationProvider class CustomNotificationProvider(NotificationProvider): def __init__(self): self.config = "your-config" def validate_config(self) -> bool: return bool(self.config) async def send(self, title: str, content: str) -> bool: # 实现发送逻辑 return True ``` ## 9. 测试 ### 9.1 运行测试 ```bash # 运行所有测试 pytest # 运行特定测试 pytest tests/test_auth.py # 运行带详细输出的测试 pytest -v ``` ### 9.2 编写测试 ```python # tests/test_example.py import pytest from httpx import AsyncClient @pytest.mark.asyncio async def test_health_check(client: AsyncClient): response = await client.get("/health") assert response.status_code == 200 assert response.json()["status"] == "healthy" ``` ## 10. 部署 ### 10.1 Docker 部署 ```dockerfile # Dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` ### 10.2 生产环境配置 ```bash # 设置环境变量 export DATABASE_URL=sqlite+aiosqlite:///./data/yaoxiang.db export JWT_SECRET_KEY=your-production-secret-key export DEBUG=false # 启动服务 uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4 ``` ## 11. 常见问题 ### 11.1 数据库初始化失败 检查 `data/` 目录是否存在,确保有写入权限。 ### 11.2 AI 服务连接失败 检查 `.env` 文件中的 API Key 配置是否正确。 ### 11.3 文件上传失败 检查 `UPLOAD_DIR` 配置的目录是否存在,确保有写入权限。 ## 12. 扩展开发 ### 12.1 添加新的通知渠道 参考 `app/notifications/serverchan.py` 实现新的通知 Provider。 ### 12.2 添加新的 AI 能力 1. 扩展 `app/ai/base.py` 中的抽象基类 2. 实现新的 Provider 3. 在 `app/ai/manager.py` 中注册 ### 12.3 添加新的定时任务 使用 APScheduler 添加定时任务: ```python from apscheduler.schedulers.asyncio import AsyncIOScheduler scheduler = AsyncIOScheduler() async def my_task(): # 任务逻辑 pass scheduler.add_job(my_task, 'cron', hour=9, minute=0) scheduler.start() ```