# 飞点健康官网 CMS 系统 - 架构设计文档 ## 1. 项目概述 基于 fumamxCRM 技术栈重写飞点健康(尿大夫/吾大夫/吴试纸)企业官网,采用模块化首页设计,支持后台可视化配置。 ## 2. 技术栈 ### 前端 | 技术 | 版本 | 用途 | |------|------|------| | React | 19.2.4 | UI 框架 | | Vite | 8.0.4 | 构建工具 | | TailwindCSS | 4.2.2 | 样式框架 | | React Router | 7.14.1 | 路由管理 | | @uiw/react-md-editor | ^4.1.0 | Markdown 编辑器 | | Lucide React | ^1.8.0 | 图标库 | ### 后端 | 技术 | 版本 | 用途 | |------|------|------| | Python | 3.12 | 运行环境 | | FastAPI | ^0.115 | Web 框架 | | SQLAlchemy | ^2.0 | ORM | | Pydantic | ^2.0 | 数据验证 | | JWT | ^2.8 | 认证 | | Uvicorn | ^0.32 | ASGI 服务器 | ### 数据库 - SQLite - 轻量级数据库,适合 CMS 场景 ## 3. 系统架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 客户端 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ PC 浏览器 │ │ 平板浏览器 │ │ 手机浏览器 │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Nginx 反向代理 │ │ (端口: 10002 前端 / 10003 API) │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ ▼ ▼ ┌───────────────────────┐ ┌───────────────────────────┐ │ 前端 (React + Vite) │ │ 后端 (FastAPI) │ │ 端口: 10002 │ │ 端口: 10003 │ │ serve 静态部署 │ │ Uvicorn 运行 │ │ │ │ │ │ ┌─────────────────┐ │ │ ┌─────────────────────┐ │ │ │ 前台用户端 │ │ │ │ API 路由层 │ │ │ │ - 首页 │ │◄─────►│ │ - /api/* │ │ │ │ - 产品页 │ │ │ └─────────────────────┘ │ │ │ - 新闻页 │ │ │ │ │ │ └─────────────────┘ │ │ ▼ │ │ ┌─────────────────┐ │ │ ┌─────────────────────┐ │ │ │ 后台管理端 │ │◄─────►│ │ 服务层 (Services) │ │ │ │ - 首页模块管理 │ │ │ │ - 首页模块服务 │ │ │ │ - 导航管理 │ │ │ │ - 内容管理服务 │ │ │ │ - 内容管理 │ │ │ │ - 认证服务 │ │ │ └─────────────────┘ │ │ └─────────────────────┘ │ │ │ │ │ │ └────────────────────────┘ │ ▼ │ │ ┌─────────────────────┐ │ │ │ 数据访问层 (ORM) │ │ │ │ SQLAlchemy Models │ │ │ └─────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────┐ │ │ │ SQLite 数据库 │ │ │ │ cms.db │ │ │ └─────────────────────┘ │ │ │ └────────────────────────────┘ ``` ## 4. 目录结构 ``` website-new/ ├── docs/ # 设计文档 │ ├── ARCHITECTURE.md # 架构设计 │ ├── DATABASE.md # 数据库设计 │ ├── API.md # API 接口文档 │ ├── FRONTEND.md # 前端组件设计 │ ├── NEWS_MODULE_DESIGN.md # 新闻模块设计 │ └── ROADMAP.md # 实现路线图 │ ├── backend/ # 后端项目 │ ├── app/ │ │ ├── __init__.py │ │ ├── main.py # FastAPI 入口 │ │ ├── config.py # 配置(含 UPLOAD_DIR 等) │ │ ├── database.py # 数据库连接 │ │ ├── auth.py # JWT 认证 │ │ ├── models/ # SQLAlchemy 模型 │ │ │ ├── __init__.py │ │ │ ├── admin.py # 管理员 │ │ │ ├── home_module.py # 首页模块 │ │ │ ├── image.py # 图片资源 │ │ │ ├── nav_menu.py # 导航菜单 │ │ │ ├── news_category.py # 新闻栏目 │ │ │ ├── news_post.py # 新闻资讯 │ │ │ └── setting.py # 系统设置 │ │ ├── routers/ # API 路由 │ │ │ ├── __init__.py │ │ │ ├── auth.py # 认证接口 │ │ │ ├── crawl.py # 文章采集 │ │ │ ├── home_modules.py # 首页模块接口 │ │ │ ├── images.py # 图片资源管理 │ │ │ ├── nav_menus.py # 导航菜单接口 │ │ │ ├── news.py # 新闻资讯接口 │ │ │ ├── settings.py # 系统设置接口 │ │ │ └── upload.py # 通用文件上传 │ │ └── utils/ │ │ └── file_utils.py # 文件工具(含缩略图清理) │ ├── requirements.txt │ └── cms.db # SQLite 数据库 │ ├── frontend/ # 前端项目 │ ├── src/ │ │ ├── main.jsx # React 入口 │ │ ├── App.jsx # 根组件 │ │ ├── api/ # API 请求封装 │ │ │ └── index.js # 自定义 ApiClient │ │ ├── components/ # 公共组件 │ │ │ ├── admin/ # 后台通用组件 │ │ │ │ ├── Badge.jsx │ │ │ │ ├── Button.jsx │ │ │ │ ├── Card.jsx │ │ │ │ ├── Input.jsx │ │ │ │ ├── Modal.jsx │ │ │ │ ├── Stats.jsx │ │ │ │ └── Table.jsx │ │ │ ├── AdminLayout.jsx # 后台布局 │ │ │ ├── HelpModal.jsx │ │ │ └── Layout.jsx # 前台布局 │ │ ├── contexts/ │ │ │ └── AuthContext.jsx # 认证上下文 │ │ ├── pages/ # 页面组件 │ │ │ ├── admin/ # 后台管理页 │ │ │ │ ├── images/ │ │ │ │ │ └── ImageManager.jsx # 图片管理 │ │ │ │ ├── news/ │ │ │ │ │ ├── CategoryList.jsx # 栏目管理 │ │ │ │ │ ├── CrawlNews.jsx # 采集新闻 │ │ │ │ │ ├── PostEdit.jsx # 添加/编辑资讯 │ │ │ │ │ └── PostList.jsx # 资讯列表 │ │ │ │ ├── BannerManage.jsx │ │ │ │ ├── FeaturesManage.jsx │ │ │ │ └── HomeManage.jsx │ │ │ ├── AdminHome.jsx │ │ │ ├── Login.jsx │ │ │ ├── Modules.jsx │ │ │ ├── NavMenus.jsx │ │ │ ├── NewsDetail.jsx │ │ │ ├── NewsList.jsx │ │ │ ├── PublicHome.jsx │ │ │ └── Settings.jsx │ │ ├── App.css │ │ └── index.css │ ├── index.html │ ├── package.json │ └── vite.config.js │ ├── storage/ # 文件存储目录 │ ├── admin/ │ │ └── images/ # 管理员上传图片 │ │ ├── thumbnails/ # 自动生成的缩略图 │ │ ├── banners/ # 轮播图(手动维护) │ │ ├── features/ # 特色展示图(手动维护) │ │ └── 202604/ # 按月分组的旧文件 │ └── public/ # 公开文件(预留) │ └── scripts/ # 启动脚本 ├── start-backend.sh └── start-frontend.sh ``` ## 5. 部署架构 | 服务 | 端口 | 命令 | 说明 | |------|------|------|------| | 前端开发 | 10002 | `npm run dev` | Vite 开发服务器(含代理) | | 前端生产 | 10002 | `serve -s dist -l 10002` | 静态文件服务 | | 后端 | 10003 | `uvicorn app.main:app --host 0.0.0.0 --port 10003` | API 服务 | ### Vite 代理配置(开发环境) ```js // vite.config.js proxy: { '/api': { target: 'http://localhost:10003', changeOrigin: true }, '/uploads': { target: 'http://localhost:10003', changeOrigin: true }, '/storage': { target: 'http://localhost:10003', changeOrigin: true }, } ``` ### 静态文件挂载(后端) ```python # main.py app.mount("/uploads", StaticFiles(directory="storage/admin/images"), name="uploads") app.mount("/storage/admin", StaticFiles(directory="storage/admin"), name="storage_admin") app.mount("/storage/public", StaticFiles(directory="storage/public"), name="storage_public") ``` ## 6. 设计风格:新粗野主义 (Neobrutalism) 参考 personal-blog 和 RetroUI 项目: | 元素 | 规范 | |------|------| | 主背景 | `#FEF9E7` 奶油色 | | 边框 | 2px 纯黑硬边框 | | 阴影 | 4px 硬阴影偏移 | | 圆角 | 无(直角) | | 强调色 | 粉红 `#FF6B9D`、青色 `#00D9FF`、黄色 `#FFDE59` | | 交互 | 点击位移 + 阴影消失 | ## 7. 图片存储架构 ### 7.1 存储路径规则 | 配置项 | 值 | 说明 | |--------|-----|------| | `UPLOAD_DIR` | `../storage/admin/images` | 相对于 `backend/` 目录 | | 实际物理路径 | `{project_root}/storage/admin/images` | 项目根目录下的 storage | | 缩略图目录 | `{UPLOAD_DIR}/thumbnails` | 自动生成 | **重要:** `UPLOAD_DIR` 配置值是基于后端启动目录(`backend/`)的相对路径。从 `backend/` 到 `storage/admin/images` 只需 `../storage/admin/images`(上一级到项目根目录)。 ### 7.2 图片生命周期管理 **上传流程:** 1. 接收上传文件 → 校验格式和大小 2. 生成唯一文件名:`YYYYMMDD_HHMMSS_xxxxxxxx.ext` 3. 保存原图到 `storage/admin/images/` 4. 自动创建缩略图到 `storage/admin/images/thumbnails/` 5. 写入数据库(记录路径为 `/storage/admin/images/...`) **缩略图规则:** - 最大尺寸:300x300 像素,等比缩放 - 格式:统一为 JPEG,质量 85% - 命名:与原图同名,扩展名统一为 `.jpg` - 失败处理:缩略图创建失败时,`thumb_path` 为 `null` **删除规则:** - 单条删除:`DELETE /api/images/{id}` → 删除数据库记录 + 物理文件(原图 + 缩略图) - 批量删除:`POST /api/images/batch-delete` → 同上,循环处理 - 资讯删除:删除资讯时同步删除封面图及其缩略图 - 外部 URL:删除时跳过物理文件(仅删除数据库记录) **清理工具:** `app/utils/file_utils.py` - `cleanup_file()`: 根据路径删除文件及缩略图 - `cleanup_file_by_path()`: 包装函数,支持 `/storage/admin/images/` 格式路径 ### 7.3 图片访问路径 | 类型 | URL 格式 | 物理路径 | |------|----------|----------| | 原图 | `/storage/admin/images/{filename}` | `storage/admin/images/{filename}` | | 缩略图 | `/storage/admin/images/thumbnails/{filename}.jpg` | `storage/admin/images/thumbnails/{filename}.jpg` | | 兼容旧路径 | `/uploads/{filename}` | 与 `/storage/admin/images/` 指向同一目录 | ## 8. 安全策略 1. **认证**: JWT + Bearer Token 2. **密码**: bcrypt 加密存储 3. **CORS**: 允许前端域名访问 4. **上传**: 限制文件类型(jpg, png, gif, webp, bmp)和大小(10MB) 5. **SQL**: 使用 ORM 防止注入 6. **文件访问**: 防止目录遍历攻击(`file_path.resolve().relative_to()` 检查) ## 9. 性能目标 - API 响应时间 < 300ms - 首页加载时间 < 2s - 支持图片懒加载