# 药箱前端开发文档 ## 1. 项目概述 药箱(YaoXiang)是一个家庭药品与应急物资管理系统,前端采用 React + TypeScript + Vite 技术栈,支持 PWA 和大屏模式。 ## 2. 技术栈 | 技术 | 版本 | 说明 | |------|------|------| | React | 18.2.0 | UI 框架 | | TypeScript | 5.2.2 | 类型系统 | | Vite | 5.0.0 | 构建工具 | | React Router | 6.20.0 | 路由管理 | | Zustand | 4.4.7 | 状态管理 | | Ant Design Mobile | 5.34.0 | UI 组件库 | | Axios | 1.6.2 | HTTP 客户端 | | Day.js | 1.11.10 | 日期处理 | ## 3. 项目结构 ``` frontend/ ├── public/ # 静态资源 │ ├── favicon.svg # 网站图标 │ ├── manifest.json # PWA 配置 │ └── icons/ # 应用图标 │ ├── src/ │ ├── api/ # API 调用层 │ │ ├── client.ts # Axios 实例配置 │ │ ├── auth.ts # 认证相关 API │ │ ├── medicines.ts # 药品管理 API │ │ ├── batches.ts # 批次管理 API │ │ ├── categories.ts # 分类管理 API │ │ ├── search.ts # 搜索 API │ │ ├── notifications.ts # 通知 API │ │ ├── users.ts # 用户管理 API │ │ └── index.ts # 导出汇总 │ │ │ ├── components/ # 公共组件 │ │ ├── Layout/ # 布局组件(含 TabBar) │ │ ├── MedicineCard/ # 药品卡片 │ │ ├── QuantitySelector/ # 数量选择器 │ │ ├── SearchBar/ # 搜索栏 │ │ ├── CameraCapture/ # 摄像头捕获 │ │ ├── CategoryTree/ # 分类树 │ │ └── index.ts # 导出汇总 │ │ │ ├── pages/ # 页面组件 │ │ ├── Home/ # 首页(库存概览) │ │ ├── Login/ # 登录页 │ │ ├── MedicineList/ # 药品列表 │ │ ├── MedicineDetail/ # 药品详情 │ │ ├── AddMedicine/ # 添加/编辑药品 │ │ ├── QuickDispense/ # 快速取药(大屏模式) │ │ ├── Search/ # 搜索页 │ │ ├── Notifications/ # 通知中心 │ │ ├── Settings/ # 设置页 │ │ └── index.ts # 导出汇总 │ │ │ ├── stores/ # 状态管理 │ │ ├── authStore.ts # 认证状态 │ │ ├── medicineStore.ts # 药品状态 │ │ ├── categoryStore.ts # 分类状态 │ │ ├── notificationStore.ts # 通知状态 │ │ ├── uiStore.ts # UI 状态 │ │ └── index.ts # 导出汇总 │ │ │ ├── hooks/ # 自定义 Hooks │ │ ├── useAuth.ts # 认证 Hook │ │ ├── useMedicine.ts # 药品 Hook │ │ ├── useCamera.ts # 摄像头 Hook │ │ ├── useNotification.ts # 通知 Hook │ │ └── index.ts # 导出汇总 │ │ │ ├── types/ # TypeScript 类型定义 │ │ ├── user.ts # 用户类型 │ │ ├── medicine.ts # 药品类型 │ │ ├── batch.ts # 批次类型 │ │ ├── category.ts # 分类类型 │ │ ├── notification.ts # 通知类型 │ │ ├── api.ts # API 响应类型 │ │ └── index.ts # 导出汇总 │ │ │ ├── utils/ # 工具函数 │ │ ├── date.ts # 日期处理 │ │ ├── storage.ts # 本地存储 │ │ ├── validators.ts # 表单验证 │ │ ├── constants.ts # 常量定义 │ │ └── index.ts # 导出汇总 │ │ │ ├── styles/ # 样式文件 │ │ ├── global.css # 全局样式 │ │ ├── variables.css # CSS 变量 │ │ ├── mixins.css # CSS 混入 │ │ └── index.css # 导入汇总 │ │ │ ├── App.tsx # 根组件 │ ├── main.tsx # 入口文件 │ └── router.tsx # 路由配置 │ ├── index.html # HTML 模板 ├── package.json # 依赖配置 ├── vite.config.ts # Vite 配置 ├── tsconfig.json # TypeScript 配置 ├── tsconfig.node.json # Node TypeScript 配置 ├── .env.example # 环境变量示例 └── .gitignore # Git 忽略文件 ``` ## 4. 快速开始 ### 4.1 环境准备 ```bash # 进入前端目录 cd frontend # 安装依赖 npm install ``` ### 4.2 配置环境变量 ```bash # 复制环境变量示例文件 cp .env.example .env # 编辑 .env 文件 VITE_API_BASE_URL=/api ``` ### 4.3 启动开发服务器 ```bash npm run dev ``` 访问 http://localhost:5173 ### 4.4 构建生产版本 ```bash npm run build ``` 构建产物位于 `dist/` 目录。 ### 4.5 预览生产版本 ```bash npm run preview ``` ## 5. 路由配置 ### 5.1 路由表 | 路径 | 页面 | 说明 | 权限 | |------|------|------|------| | `/login` | Login | 登录页 | 公开 | | `/` | Home | 首页 | 登录用户 | | `/medicines` | MedicineList | 药品列表 | 登录用户 | | `/medicines/add` | AddMedicine | 添加药品 | admin/user | | `/medicines/:id` | MedicineDetail | 药品详情 | 登录用户 | | `/medicines/edit/:id` | AddMedicine | 编辑药品 | admin/user | | `/quick-dispense` | QuickDispense | 快速取药 | 登录用户 | | `/search` | Search | 搜索页 | 登录用户 | | `/notifications` | Notifications | 通知中心 | 登录用户 | | `/settings` | Settings | 设置页 | 登录用户 | ### 5.2 路由守卫 路由守卫通过 `useAuth` Hook 实现: ```tsx import { useAuth } from '../hooks'; const ProtectedRoute = ({ children }) => { const { isAuthenticated } = useAuth(); if (!isAuthenticated) { return ; } return children; }; ``` ## 6. 状态管理 ### 6.1 Store 结构 | Store | 说明 | 主要状态 | |-------|------|----------| | authStore | 认证状态 | user, token, isAuthenticated | | medicineStore | 药品状态 | medicines, currentMedicine, loading | | categoryStore | 分类状态 | categories, loading | | notificationStore | 通知状态 | notifications, unreadCount | | uiStore | UI 状态 | isLargeScreen, isDarkMode | ### 6.2 使用示例 ```tsx import { useMedicineStore } from '../stores'; const MyComponent = () => { const { medicines, loading, fetchMedicines } = useMedicineStore(); useEffect(() => { fetchMedicines(); }, []); return (
{loading ? '加载中...' : medicines.map(m =>
{m.name}
)}
); }; ``` ## 7. API 调用 ### 7.1 API 客户端配置 ```typescript // api/client.ts import axios from 'axios'; import { useAuthStore } from '../stores/authStore'; const client = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 30000, }); // 请求拦截器 - 添加 Token client.interceptors.request.use((config) => { const token = useAuthStore.getState().token; if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // 响应拦截器 - 处理 401 client.interceptors.response.use( (response) => response.data, (error) => { if (error.response?.status === 401) { useAuthStore.getState().logout(); window.location.href = '/login'; } return Promise.reject(error); } ); ``` ### 7.2 API 调用示例 ```typescript import { medicineApi } from '../api'; // 获取药品列表 const { data, total } = await medicineApi.list({ page: 1, pageSize: 20 }); // 创建药品 const medicine = await medicineApi.create({ name: '布洛芬', specification: '0.3g' }); // AI 识别药盒 const result = await medicineApi.recognize(imageFile); ``` ## 8. 组件开发 ### 8.1 添加新组件 1. 在 `src/components/` 目录下创建组件文件夹 2. 创建 `index.tsx` 和 `index.css` 3. 在 `src/components/index.ts` 中导出 ```tsx // components/MyComponent/index.tsx import React from 'react'; import './index.css'; interface MyComponentProps { title: string; } const MyComponent: React.FC = ({ title }) => { return
{title}
; }; export default MyComponent; ``` ### 8.2 添加新页面 1. 在 `src/pages/` 目录下创建页面文件夹 2. 创建 `index.tsx` 和 `index.css` 3. 在 `src/pages/index.ts` 中导出 4. 在 `src/router.tsx` 中添加路由 ```tsx // pages/MyPage/index.tsx import React from 'react'; import './index.css'; const MyPage: React.FC = () => { return
My Page
; }; export default MyPage; ``` ### 8.3 添加新 Hook 1. 在 `src/hooks/` 目录下创建 Hook 文件 2. 在 `src/hooks/index.ts` 中导出 ```tsx // hooks/useMyHook.ts import { useState, useCallback } from 'react'; export const useMyHook = () => { const [data, setData] = useState(null); const fetchData = useCallback(async () => { // 实现逻辑 }, []); return { data, fetchData }; }; ``` ## 9. 样式开发 ### 9.1 CSS 变量 项目使用 CSS 变量管理主题: ```css :root { --adm-color-primary: #1677ff; --adm-color-success: #52c41a; --adm-color-warning: #faad14; --adm-color-danger: #ff4d4f; } ``` ### 9.2 大屏模式适配 ```css /* 基础样式 */ .quantity-btn { width: 48px; height: 48px; } /* 大屏模式 */ @media (min-width: 768px) { .quantity-btn { width: 80px; height: 80px; } } ``` ### 9.3 使用 Ant Design Mobile 样式 ```tsx import { Button } from 'antd-mobile'; // 使用组件自带样式 // 使用自定义样式
``` ## 10. 类型定义 ### 10.1 添加新类型 1. 在 `src/types/` 目录下创建类型文件 2. 在 `src/types/index.ts` 中导出 ```typescript // types/myType.ts export interface MyType { id: number; name: string; createdAt: string; } export interface MyTypeCreate { name: string; } ``` ### 10.2 使用类型 ```typescript import { MyType, MyTypeCreate } from '../types'; const myFunction = (data: MyTypeCreate): MyType => { return { id: 1, ...data, createdAt: new Date().toISOString() }; }; ``` ## 11. 开发规范 ### 11.1 代码风格 - 使用 TypeScript 严格模式 - 遵循 ESLint 规则 - 使用 Prettier 格式化 ### 11.2 命名规范 | 类型 | 规范 | 示例 | |------|------|------| | 组件 | PascalCase | MedicineCard | | Hook | use + PascalCase | useAuth | | 函数 | camelCase | fetchMedicines | | 变量 | camelCase | medicineList | | 常量 | UPPER_SNAKE_CASE | API_BASE_URL | | 文件 | PascalCase (组件) / camelCase (其他) | MedicineCard/index.tsx | | CSS 类 | kebab-case | medicine-card | ### 11.3 文件组织 - 每个组件/页面单独一个文件夹 - 包含 `index.tsx` 和 `index.css` - 通过 `index.ts` 导出 ### 11.4 提交规范 ``` feat: 新功能 fix: 修复 bug docs: 文档更新 style: 代码格式调整 refactor: 重构 test: 测试相关 chore: 构建/工具相关 ``` ## 12. 构建与部署 ### 12.1 开发环境 ```bash npm run dev ``` ### 12.2 生产构建 ```bash npm run build ``` ### 12.3 部署到 Nginx ```nginx server { listen 80; server_name your-domain.com; root /path/to/dist; index index.html; location / { try_files $uri $uri/ /index.html; } location /api { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` ## 13. 常见问题 ### 13.1 开发服务器启动失败 检查端口是否被占用: ```bash # Windows netstat -ano | findstr :5173 # Mac/Linux lsof -i :5173 ``` ### 13.2 API 请求失败 1. 检查后端服务是否启动 2. 检查 `.env` 中的 `VITE_API_BASE_URL` 配置 3. 检查浏览器控制台错误 ### 13.3 类型错误 确保所有组件和函数都有正确的类型注解: ```typescript // 错误 const handleClick = (e) => { ... } // 正确 const handleClick = (e: React.MouseEvent) => { ... } ``` ### 13.4 样式不生效 1. 检查 CSS 文件是否正确导入 2. 检查选择器是否正确 3. 使用浏览器开发者工具检查样式 ## 14. 扩展开发 ### 14.1 添加新的 AI 识别功能 1. 在 `src/api/medicines.ts` 中添加 API 调用 2. 在页面中使用摄像头组件捕获图片 3. 调用 AI 接口识别 ### 14.2 添加新的通知渠道 1. 在后端添加通知 Provider 2. 在前端通知页面展示 ### 14.3 添加新的页面 1. 创建页面组件 2. 添加路由配置 3. 添加导航入口