Files
nanocode/new-media-platform/website-new/docs/ARCHITECTURE.md
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

286 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 飞点健康官网 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
- 支持图片懒加载