286 lines
14 KiB
Markdown
286 lines
14 KiB
Markdown
# 飞点健康官网 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
|
||
- 支持图片懒加载
|