Initial certificate system
This commit is contained in:
102
docs/decision-log.md
Normal file
102
docs/decision-log.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 开发决策记录
|
||||
|
||||
本文档记录开发过程中由 Codex 先行拍板的实现决定。后续如果业务方有不同意见,可以按条目调整。
|
||||
|
||||
## 已确认决策
|
||||
|
||||
### D001 PDF 生成策略
|
||||
|
||||
- 决定:PDF 由服务端生成,不在用户浏览器生成。
|
||||
- 策略:按需生成 + 30 天缓存。
|
||||
- 原因:证书属于正式凭证,服务端生成更利于统一版式、审计、作废状态控制和后续模板替换。
|
||||
|
||||
### D002 证书编号格式
|
||||
|
||||
- 决定:`EPX{YYYY}-{项目代码}-{7位短码}-{2位校验码}`。
|
||||
- 示例:`EPX2026-DBY-K7M9Q2R-83`。
|
||||
- 说明:内部数据库继续使用 `BIGINT` 主键,对外编号使用短码和校验码,降低枚举和手输错误风险。
|
||||
|
||||
### D003 公开查询方式
|
||||
|
||||
- 决定:一期公开查询支持两种方式:证书编号 + 姓名 + 图形验证码,或手机号 + 姓名 + 图形验证码。
|
||||
- 说明:手机号 + 姓名可能匹配多张证书,查询结果按列表展示。
|
||||
- 风控:继续保留图形验证码和基础频率限制,降低批量撞库风险。
|
||||
|
||||
### D004 作废证书 PDF
|
||||
|
||||
- 决定:一期作废证书不允许下载正常 PDF。
|
||||
- 展示:查询页、直达页、二维码核验页统一显示作废状态。
|
||||
|
||||
### D005 证书模板
|
||||
|
||||
- 决定:一期先使用占位模板。
|
||||
- 要求:模板文件与业务逻辑分离,后续替换 Logo、公章、排版、正式文案时不改核心业务代码。
|
||||
|
||||
### D006 更正和补发
|
||||
|
||||
- 决定:一期不实现复杂更正/补发流程。
|
||||
- 一期保留证书编辑、作废、重置链接等主链路操作。
|
||||
|
||||
## Codex 先行决定
|
||||
|
||||
### C001 项目代码维护方式
|
||||
|
||||
- 决定:后台提供项目/课程代码配置,导入 Excel 使用项目代码匹配,不允许随意生成编号中的项目代码。
|
||||
- 原因:避免同一项目出现多个拼写,确保证书编号稳定。
|
||||
|
||||
### C002 一期部署方式
|
||||
|
||||
- 决定:单机 Docker Compose 部署。
|
||||
- 组件:Nginx、前端静态资源、FastAPI 后端、MySQL。
|
||||
- 原因:符合低并发和快速上线目标,减少运维复杂度。
|
||||
|
||||
### C003 文件目录
|
||||
|
||||
- 决定:使用 `/data/certificate-system/uploads`、`error-reports`、`exports`、`pdf-cache`。
|
||||
- 原因:便于备份策略区分;PDF 缓存不进入长期备份。
|
||||
|
||||
### C004 初始化管理员
|
||||
|
||||
- 决定:通过初始化命令创建第一个系统管理员。
|
||||
- 原因:避免在公开页面暴露注册入口。
|
||||
|
||||
### C005 访问 token 一期存储
|
||||
|
||||
- 决定:一期在 `certificate_access_tokens` 中同时保存 token 哈希和 token 原值。
|
||||
- 原因:后台导出必须能生成证书对外直达链接;纯哈希无法反推出链接。
|
||||
- 风险:数据库泄露时 token 原值可被直接使用。
|
||||
- 后续优化:将 token 原值改为应用层加密存储,或仅在生成时写入导出文件并提供链接重置机制。
|
||||
|
||||
### C006 验证码和限流
|
||||
|
||||
- 决定:一期使用后端进程内存保存图形验证码和简单 IP 频率计数。
|
||||
- 原因:一期单机部署,不引入 Redis,满足快速上线和低并发目标。
|
||||
- 后续优化:访问量上来后迁移到 Redis,并把限流前移到 Nginx 或网关层。
|
||||
|
||||
### C007 后台 UI 风格
|
||||
|
||||
- 决定:后台采用浅色、清爽、偏办公工具的视觉风格。
|
||||
- 原因:这个系统是日常管理工具,用户需要快速查找和处理数据,不适合厚重的深色或营销化页面。
|
||||
|
||||
### C008 后台 PDF 下载方式
|
||||
|
||||
- 决定:后台证书 PDF 下载使用带 Authorization token 的 blob 请求。
|
||||
- 原因:受保护的后台接口不能依赖普通链接跳转,否则浏览器不会带前端保存的登录 token,容易导致下载失败。
|
||||
|
||||
### C009 Excel 导入字段
|
||||
|
||||
- 决定:导入模板只保留姓名、手机号、项目代码、发证日期。
|
||||
- 原因:证书名称、课程名称、阶段名称、发证单位属于项目配置,不应该在每一行 Excel 里重复填写。
|
||||
- 备注:导入备注字段一期移除;批量导入后的备注缺少明确展示和业务使用场景。
|
||||
|
||||
### C010 导入批次文件管理
|
||||
|
||||
- 决定:后台保留导入批次列表,并支持下载原始 Excel、下载错误报告、删除批次记录。
|
||||
- 删除范围:只删除上传文件、错误报告和批次记录,不删除已经确认导入后生成的学员和证书。
|
||||
- 原因:导入文件会占用服务器存储,但导入后的业务数据应作为正式数据继续保留。
|
||||
### C011 Certificate Rendering Template
|
||||
|
||||
- Decision: keep `certificate-template-lab` as a standalone visual tuning page.
|
||||
- Decision: production PDF rendering now uses the approved certificate image as the base layer, then renders learner/course/date/certificate number dynamically with Pillow.
|
||||
- Current limitation: the data model only has `issue_date`; until separate training start/end dates are added, the rendered course date range uses `issue_date` for both start and end.
|
||||
- Current limitation: mentor, issuer names, and QR area remain from the approved base image for visual consistency.
|
||||
56
docs/deployment-checklist.md
Normal file
56
docs/deployment-checklist.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 上线检查清单
|
||||
|
||||
## 服务器
|
||||
|
||||
- Docker 已安装。
|
||||
- Docker Compose 已安装。
|
||||
- 域名已解析到服务器。
|
||||
- HTTPS 证书已准备。
|
||||
- `/data/certificate-system` 已创建并挂载到数据盘。
|
||||
|
||||
## 环境变量
|
||||
|
||||
- `SECRET_KEY` 已改成强随机值。
|
||||
- `CERTIFICATE_NO_SECRET` 已改成强随机值。
|
||||
- `PUBLIC_BASE_URL` 已改成正式域名。
|
||||
- `DATABASE_URL` 指向生产 MySQL。
|
||||
- `DATA_ROOT` 指向生产数据目录。
|
||||
|
||||
## 数据库
|
||||
|
||||
- 已执行迁移:
|
||||
|
||||
```bash
|
||||
docker compose exec backend alembic upgrade head
|
||||
```
|
||||
|
||||
- 已初始化管理员:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -m app.cli init-db --admin-username admin --admin-password "强密码"
|
||||
```
|
||||
|
||||
## 业务配置
|
||||
|
||||
- 项目代码已维护,例如 `DBY`、`QSX`。
|
||||
- 发证单位名称已确认。
|
||||
- Excel 导入模板已下载并试填。
|
||||
- 占位证书模板已确认可临时使用。
|
||||
|
||||
## 验收动作
|
||||
|
||||
- 后台可登录。
|
||||
- 可新增学员。
|
||||
- 可新增证书并生成编号。
|
||||
- 可上传 Excel 并确认导入。
|
||||
- 可导出证书和直达链接。
|
||||
- 公开查询必须输入验证码。
|
||||
- 作废证书不能下载正常 PDF。
|
||||
- 直达链接重置后旧链接失效。
|
||||
- PDF 可生成,二维码可打开核验页。
|
||||
|
||||
## 备份
|
||||
|
||||
- MySQL 每日备份已配置。
|
||||
- `uploads`、`error-reports`、`exports` 已纳入备份策略。
|
||||
- `pdf-cache` 不纳入长期备份。
|
||||
49
docs/mvp-scope.md
Normal file
49
docs/mvp-scope.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# MVP 范围说明
|
||||
|
||||
## 一期必须完成
|
||||
|
||||
1. 后台账号登录和基础角色权限。
|
||||
2. 项目/课程代码配置。
|
||||
3. 学员管理,手机号作为主标识,支持曾用名和手机号变更记录。
|
||||
4. 证书管理,支持一个学员多张证书。
|
||||
5. Excel 批量导入,导入前校验,导入后生成证书编号和公开访问 token。
|
||||
6. 证书编号系统自动生成,格式为 `PX{YYYY}-{项目代码}-{7位短码}-{2位校验码}`。
|
||||
7. 批量导出证书数据,包含证书编号和对外直达链接。
|
||||
8. 公开查询:证书编号 + 姓名 + 图形验证码。
|
||||
9. 证书直达页:通过不可枚举 token 查看单张证书。
|
||||
10. 二维码核验页:展示真实性、状态和必要证书信息。
|
||||
11. PDF 下载:服务端按需生成,占位模板,缓存 30 天。
|
||||
12. 操作日志和导出日志。
|
||||
|
||||
## 一期不做
|
||||
|
||||
1. 手机号公开查询。
|
||||
2. 复杂更正/补发流程。
|
||||
3. 证书审批流。
|
||||
4. 可视化证书模板编辑器。
|
||||
5. 正式 Logo、公章、电子签章。
|
||||
6. Redis、Celery、RabbitMQ、Kubernetes、多实例。
|
||||
7. 对接报名系统、学习系统或 CRM。
|
||||
|
||||
## 默认业务规则
|
||||
|
||||
- 证书作废后,公开页面展示作废状态,不允许下载正常 PDF。
|
||||
- 公开页面不展示完整手机号、证件号、后台备注、导入记录。
|
||||
- 证书直达链接使用随机 token,不由证书编号推导。
|
||||
- 导出完整手机号或证件号需要高权限,并记录日志。
|
||||
|
||||
## Excel 导入模板字段
|
||||
|
||||
一期模板字段:
|
||||
|
||||
1. 姓名
|
||||
2. 手机号
|
||||
3. 项目代码
|
||||
4. 证书名称
|
||||
5. 课程名称
|
||||
6. 阶段名称
|
||||
7. 发证日期
|
||||
8. 发证单位
|
||||
9. 备注
|
||||
|
||||
证书编号不在 Excel 中填写,由系统确认导入后自动生成。
|
||||
146
docs/usage-deployment-manual.md
Normal file
146
docs/usage-deployment-manual.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# 部署与使用手册
|
||||
|
||||
本文档用于一期本地验收和正式部署交接。
|
||||
|
||||
## 本地验收版
|
||||
|
||||
适合在没有 Docker、npm 环境时先完整跑通业务流程。
|
||||
|
||||
```bat
|
||||
cd /d C:\Users\nelso\Documents\projects\certificate-system
|
||||
start-local.bat
|
||||
```
|
||||
|
||||
访问地址:
|
||||
|
||||
```text
|
||||
后台:http://127.0.0.1:8000/admin/login
|
||||
公开查询:http://127.0.0.1:8000/query
|
||||
```
|
||||
|
||||
默认账号:
|
||||
|
||||
```text
|
||||
admin / Admin123!
|
||||
```
|
||||
|
||||
本地数据保存在:
|
||||
|
||||
```text
|
||||
local_app/data/local.db
|
||||
```
|
||||
|
||||
清空本地验收数据:
|
||||
|
||||
```bat
|
||||
reset-local-data.bat
|
||||
```
|
||||
|
||||
## 后台使用流程
|
||||
|
||||
1. 登录 `/admin/login`。
|
||||
2. 进入“项目管理”,维护 `DBY`、`QSX` 等项目代码。项目支持搜索、修改、启用和停用。
|
||||
3. 进入“学员管理”,手动新增、查询、修改或删除学员。
|
||||
4. 进入“证书管理”,手动新增证书,支持单张预览、PDF 下载、作废、重置直达链接和导出。
|
||||
5. 进入“Excel 导入”,下载模板、上传 Excel、查看校验结果,确认后正式导入。模板只需要填写姓名、手机号、项目代码、发证日期;证书名称、课程名称、阶段名称、发证单位从项目配置自动带出。
|
||||
“确认导入”表示把已校验通过的临时数据正式写入学员和证书表。导入记录支持下载原文件、下载错误报告和删除;删除导入记录只删除上传文件、错误报告和批次记录,不删除已经生成的学员和证书。
|
||||
6. 进入“操作日志”,查看关键后台操作。日志动作已转成中文显示。
|
||||
|
||||
## 公开查询流程
|
||||
|
||||
1. 用户进入 `/query`。
|
||||
2. 输入证书编号 + 姓名 + 图形验证码,或手机号 + 姓名 + 图形验证码。
|
||||
3. 查询成功后展示证书状态和证书信息;手机号查询可能返回多张证书。
|
||||
4. 有效证书可下载 PDF。
|
||||
5. 作废证书只展示作废状态,不提供正常 PDF 下载。
|
||||
|
||||
## PDF 下载说明
|
||||
|
||||
PDF 由服务端按需生成,并使用 30 天缓存。这样可以保证模板、二维码、作废状态和审计逻辑统一。
|
||||
|
||||
后台 PDF 下载不能用简单的 `window.location` 直接跳转,因为后台接口需要登录态。如果直接打开下载地址,浏览器不会自动带上前端保存的 Authorization token,容易出现下载失败。当前后台已改为通过带 token 的请求下载 blob 文件,再在浏览器里保存。
|
||||
|
||||
## 正式部署准备
|
||||
|
||||
- Linux 服务器,建议 2 核 4G 起步。
|
||||
- 域名和 HTTPS 证书。
|
||||
- Docker 和 Docker Compose。
|
||||
- MySQL 8,可以使用 Compose 内置 MySQL 或云数据库。
|
||||
|
||||
默认数据目录:
|
||||
|
||||
```text
|
||||
/data/certificate-system
|
||||
```
|
||||
|
||||
建议子目录:
|
||||
|
||||
```text
|
||||
uploads
|
||||
error-reports
|
||||
exports
|
||||
pdf-cache
|
||||
```
|
||||
|
||||
`pdf-cache` 是 30 天缓存,不需要作为长期档案备份。
|
||||
|
||||
## 环境变量
|
||||
|
||||
复制 `.env.example` 为 `.env`,至少修改:
|
||||
|
||||
```text
|
||||
APP_ENV=production
|
||||
DATABASE_URL=mysql+pymysql://certificate:password@mysql:3306/certificate_system
|
||||
SECRET_KEY=change-me
|
||||
PUBLIC_BASE_URL=https://your-domain.com
|
||||
CERTIFICATE_NO_SECRET=change-me
|
||||
PDF_CACHE_DAYS=30
|
||||
DATA_ROOT=/data/certificate-system
|
||||
```
|
||||
|
||||
## Docker 部署
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
首次初始化:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -m app.cli init-db --admin-username admin --admin-password "请替换为强密码"
|
||||
```
|
||||
|
||||
单独执行数据库迁移:
|
||||
|
||||
```bash
|
||||
docker compose exec backend alembic upgrade head
|
||||
```
|
||||
|
||||
后端测试:
|
||||
|
||||
```bash
|
||||
docker compose exec backend pytest
|
||||
```
|
||||
|
||||
## 当前已实现
|
||||
|
||||
- 后台登录。
|
||||
- 后台概览统计。
|
||||
- 项目新增、搜索、修改、启用、停用。
|
||||
- 学员手动新增、查询、修改、删除。
|
||||
- 证书新增、查询、后台预览、后台下载、作废、重置直达链接。
|
||||
- Excel 模板下载、上传校验、错误报告下载、确认导入。导入模板字段为姓名、手机号、项目代码、发证日期。
|
||||
- 导入批次原文件下载和导入批次删除。
|
||||
- 导入后自动生成证书编号、直达链接 token、二维码 token。
|
||||
- 证书导出,包含证书编号和对外直达链接。
|
||||
- 公开查询:证书编号 + 姓名 + 图形验证码,或手机号 + 姓名 + 图形验证码。
|
||||
- 证书直达页和二维码核验页。
|
||||
- PDF 服务端按需生成,缓存 30 天。
|
||||
- 关键操作日志写入和中文展示。
|
||||
|
||||
## 后续上线前确认
|
||||
|
||||
- 生产域名、HTTPS 和 Nginx 限流参数。
|
||||
- PDF 正式模板、Logo、公章和证书文案。
|
||||
- 生产管理员账号和强密码。
|
||||
- 服务器部署后的联调和验收数据导入演练。
|
||||
94
docs/产品视觉设计说明.md
Normal file
94
docs/产品视觉设计说明.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# 产品视觉设计说明
|
||||
|
||||
## 设计目标
|
||||
|
||||
本系统是一套证书管理和公开查询产品,视觉上应当清爽、可信、便于长期办公使用。后台页面优先保证信息密度、扫描效率和操作稳定感;公开查询页优先保证用户能快速完成查询、预览和下载。
|
||||
|
||||
## 设计方向
|
||||
|
||||
- 不做营销式首页。
|
||||
- 不做重装饰背景。
|
||||
- 不使用沉重深色大面积背景。
|
||||
- 不使用老气的灰褐色或暗沉配色。
|
||||
- 使用浅色背景、白色工作区、克制青绿色主色。
|
||||
- 通过边框、间距、字体粗细和轻微阴影建立层级。
|
||||
|
||||
## 颜色
|
||||
|
||||
主色:
|
||||
|
||||
```text
|
||||
#16817e
|
||||
```
|
||||
|
||||
用于:
|
||||
|
||||
- 主按钮。
|
||||
- 激活导航。
|
||||
- 有效状态。
|
||||
- 链接。
|
||||
|
||||
背景:
|
||||
|
||||
```text
|
||||
#f7fafb -> #eef4f6
|
||||
```
|
||||
|
||||
用于页面底色,保持清爽但不纯白刺眼。
|
||||
|
||||
边框:
|
||||
|
||||
```text
|
||||
#dbe6ea
|
||||
#c8d7dd
|
||||
```
|
||||
|
||||
用于卡片、输入框、表格边界。
|
||||
|
||||
文字:
|
||||
|
||||
```text
|
||||
#172033 主文字
|
||||
#64748b 次级文字
|
||||
```
|
||||
|
||||
风险色:
|
||||
|
||||
```text
|
||||
#c9413a 高风险/危险操作
|
||||
#b7791f 中风险/警告
|
||||
```
|
||||
|
||||
## 后台布局
|
||||
|
||||
- 左侧导航固定 248px。
|
||||
- 工作区使用 28px 页面内边距。
|
||||
- 页面标题区采用左标题、右主操作按钮布局。
|
||||
- 表单区域和列表区域分成独立白色面板。
|
||||
- 卡片圆角控制在 10px 左右,不使用过大的圆角。
|
||||
- 分页右对齐,符合后台数据列表习惯。
|
||||
|
||||
## 公开查询页
|
||||
|
||||
- 查询卡片是第一屏核心。
|
||||
- 不放多余介绍文字。
|
||||
- 查询方式使用分段选择。
|
||||
- 查询结果使用证书卡片展示。
|
||||
- 结果卡保留证书编号、姓名、项目、课程/阶段、发证日期、发证单位。
|
||||
- 预览和下载按钮放在卡片右下方。
|
||||
|
||||
## 表格和控件
|
||||
|
||||
- 表头使用浅灰蓝背景。
|
||||
- 表格 hover 只做轻微背景变化。
|
||||
- 输入框和下拉框高度统一。
|
||||
- 下拉框箭头不得贴边。
|
||||
- 主要按钮使用青绿色,危险按钮使用红色。
|
||||
- 状态标签使用圆角胶囊,但尺寸克制。
|
||||
|
||||
## 自行决策记录
|
||||
|
||||
- 选择青绿色作为主色,因为它比蓝色更接近当前证书产品的清爽和可信气质,也不会显得像通用后台模板。
|
||||
- 没有加入大面积插画、渐变装饰或复杂动效,避免影响后台扫描效率。
|
||||
- 正式版新增全局 `design.css`,统一 Element Plus 控件和通用布局。
|
||||
- 本地验证版同步更新内联 CSS,保证本地验收看到的视觉方向与正式版一致。
|
||||
59
docs/操作日志分页需求.md
Normal file
59
docs/操作日志分页需求.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# 操作日志分页需求
|
||||
|
||||
## 背景
|
||||
|
||||
操作日志会持续增长,如果一次性展示全部日志,页面会变长,查找和点击都不方便。日志列表需要分页展示,并且页码数量较多时不能把所有页码全部铺开。
|
||||
|
||||
## 功能目标
|
||||
|
||||
1. 操作日志列表每页显示 20 条。
|
||||
2. 日志列表上方和下方都显示分页控件。
|
||||
3. 支持上一页、下一页和指定页码跳转。
|
||||
4. 页码超过 10 页时,远离当前页的页码用省略号折叠。
|
||||
5. 分页需要和现有筛选条件联动:
|
||||
- 操作类型。
|
||||
- 对象类型。
|
||||
- 风险等级。
|
||||
- 关键词。
|
||||
6. 切换筛选条件后,从第 1 页重新查询。
|
||||
7. 导出日志不受当前页限制,仍按当前筛选条件导出全部匹配日志。
|
||||
|
||||
## 页码展示规则
|
||||
|
||||
分页控件始终显示:
|
||||
|
||||
- 第 1 页。
|
||||
- 最后一页。
|
||||
- 当前页前后 2 页。
|
||||
- 中间缺失页码用 `...` 表示。
|
||||
|
||||
示例:
|
||||
|
||||
- 当前第 1 页,共 3 页:`1 2 3`
|
||||
- 当前第 6 页,共 20 页:`1 ... 4 5 6 7 8 ... 20`
|
||||
- 当前第 19 页,共 20 页:`1 ... 17 18 19 20`
|
||||
|
||||
## 接口约定
|
||||
|
||||
日志列表接口支持:
|
||||
|
||||
- `page`:页码,从 1 开始,默认 1。
|
||||
- `page_size`:每页数量,默认 20。
|
||||
|
||||
返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [],
|
||||
"total": 0,
|
||||
"page": 1,
|
||||
"page_size": 20,
|
||||
"total_pages": 1
|
||||
}
|
||||
```
|
||||
|
||||
## 自行决策记录
|
||||
|
||||
- 默认每页 20 条,兼顾浏览效率和页面密度。
|
||||
- 页码折叠规则采用“首页 + 尾页 + 当前页前后 2 页”,避免页码过多时挤压布局。
|
||||
- 上下各放一组分页控件,避免用户滚动到底部后还要回到顶部翻页。
|
||||
100
docs/操作日志强化需求.md
Normal file
100
docs/操作日志强化需求.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# 操作日志强化需求
|
||||
|
||||
## 背景
|
||||
|
||||
当前后台已经具备基础操作日志能力,可以记录部分后台动作并在页面查看。随着证书、学员、项目、导入文件等管理动作增多,日志需要更方便排查问题、追踪责任和留档审计。
|
||||
|
||||
## 一期目标
|
||||
|
||||
快速增强后台操作日志的可用性,不做复杂审计系统,但要满足日常运营排查和关键动作追踪。
|
||||
|
||||
## 功能需求
|
||||
|
||||
1. 日志列表支持筛选和搜索:
|
||||
- 按操作类型筛选。
|
||||
- 按对象类型筛选。
|
||||
- 按风险等级筛选。
|
||||
- 按关键词搜索对象 ID、摘要、详情内容。
|
||||
|
||||
2. 日志显示更易读:
|
||||
- 操作名显示中文。
|
||||
- 对象类型显示中文。
|
||||
- 增加操作摘要,例如“作废证书:PX2026-xxx”“删除导入文件:test.xlsx”。
|
||||
- 高风险动作增加醒目标记。
|
||||
|
||||
3. 日志详情弹窗:
|
||||
- 展示操作时间、操作人、操作、对象、对象 ID、风险等级。
|
||||
- 展示摘要。
|
||||
- 展示完整详情 JSON,便于排查。
|
||||
|
||||
4. 关键动作记录更多上下文:
|
||||
- 新增/修改/停用项目记录项目代码、名称、状态变化。
|
||||
- 新增/修改/删除学员记录姓名、脱敏手机号、状态变化。
|
||||
- 新增/作废/重置链接证书记录证书编号和学员信息。
|
||||
- 上传/确认/删除导入批次记录文件名、导入统计。
|
||||
|
||||
5. 日志导出:
|
||||
- 支持导出 Excel。
|
||||
- 导出内容包含时间、操作人、操作、对象、对象 ID、风险等级、摘要、详情。
|
||||
|
||||
## 风险等级规则
|
||||
|
||||
高风险:
|
||||
- 作废证书。
|
||||
- 删除导入批次/导入原文件。
|
||||
- 重置证书公开链接。
|
||||
- 停用项目。
|
||||
- 删除学员。
|
||||
|
||||
中风险:
|
||||
- 修改项目。
|
||||
- 修改学员。
|
||||
- 确认导入。
|
||||
- 新增证书。
|
||||
|
||||
低风险:
|
||||
- 新增项目。
|
||||
- 新增学员。
|
||||
- 上传导入文件。
|
||||
- 导出数据。
|
||||
|
||||
## 暂不做
|
||||
|
||||
- 日志删除功能。
|
||||
- 日志归档策略。
|
||||
- 复杂审计报表。
|
||||
- 登录失败风控和异常 IP 告警。
|
||||
|
||||
## 日志保留与清理策略
|
||||
|
||||
一期采用自动清理过期日志,不开放任意删除单条日志,避免审计证据被误删。
|
||||
|
||||
- 普通后台操作日志保留 180 天。
|
||||
- 学员公开查询、公开下载日志保留 180 天。
|
||||
- 高风险后台操作日志保留 365 天,包括作废证书、删除导入批次、重置证书公开链接、删除学员。
|
||||
- 系统启动和进入日志管理时可以触发过期清理。
|
||||
- 后台日志页提供“清理过期日志”按钮,只清理超过保留周期的日志,不删除未过期日志。
|
||||
|
||||
## 公开访问日志
|
||||
|
||||
需要记录学员/外部用户主动查询和下载电子证书的行为,用于排查“用户是否查过/下载过”的问题。
|
||||
|
||||
- 公开查询证书:
|
||||
- 记录查询方式:证书编号或手机号。
|
||||
- 记录姓名。
|
||||
- 手机号脱敏。
|
||||
- 记录匹配数量。
|
||||
- 记录失败查询,但不记录验证码。
|
||||
|
||||
- 公开下载证书:
|
||||
- 记录证书编号。
|
||||
- 记录学员姓名。
|
||||
- 记录项目代码。
|
||||
- 不记录公开 token 原文。
|
||||
|
||||
## 自行决策记录
|
||||
|
||||
- 一期优先增强后台日常可用性,不引入新的日志表结构。
|
||||
- 风险等级先由操作类型在服务端/前端映射计算,避免为当前版本增加迁移复杂度。
|
||||
- 敏感信息在摘要里脱敏,完整详情尽量不写入明文手机号或 token。
|
||||
- 公开查询/下载先进入同一张操作日志表,操作人 ID 为空,用“公开访问”对象类型区分。
|
||||
792
docs/阿里云正式部署详细操作手册.md
Normal file
792
docs/阿里云正式部署详细操作手册.md
Normal file
@@ -0,0 +1,792 @@
|
||||
# 阿里云正式部署详细操作手册
|
||||
|
||||
本文档用于把“培训结业证书管理与查询系统”部署到阿里云正式环境。当前日期:2026-06-05。
|
||||
|
||||
## 1. 先回答:数据库要不要单独买
|
||||
|
||||
可以有两种方案。
|
||||
|
||||
### 方案 A:数据库和应用都放在同一台 ECS 上
|
||||
|
||||
做法:一台阿里云 ECS 上运行 Docker Compose,里面同时跑:
|
||||
|
||||
- MySQL
|
||||
- 后端 FastAPI
|
||||
- 前端 Nginx/Vue
|
||||
|
||||
优点:
|
||||
|
||||
- 成本低。
|
||||
- 部署简单。
|
||||
- 一期快速上线足够用。
|
||||
|
||||
缺点:
|
||||
|
||||
- ECS 故障时,应用和数据库一起受影响。
|
||||
- 数据库备份、恢复、监控需要自己认真配置。
|
||||
- 后期迁移到 RDS 时需要再做一次数据库迁移。
|
||||
|
||||
适合:
|
||||
|
||||
- 一期快速上线。
|
||||
- 访问量不大。
|
||||
- 预算有限。
|
||||
- 可以接受自己维护数据库备份。
|
||||
|
||||
### 方案 B:ECS 跑应用,阿里云 RDS MySQL 跑数据库
|
||||
|
||||
做法:
|
||||
|
||||
- ECS 只跑前端和后端。
|
||||
- MySQL 使用阿里云 RDS MySQL。
|
||||
|
||||
优点:
|
||||
|
||||
- 数据库更稳定。
|
||||
- 阿里云 RDS 提供备份、恢复、监控、容灾等能力。
|
||||
- 后期维护成本低。
|
||||
- 更接近正式生产系统。
|
||||
|
||||
缺点:
|
||||
|
||||
- 成本更高。
|
||||
- 需要配置 RDS 白名单、账号、数据库连接串。
|
||||
|
||||
适合:
|
||||
|
||||
- 正式长期使用。
|
||||
- 证书数据比较重要。
|
||||
- 不希望自己维护 MySQL 备份和恢复。
|
||||
|
||||
### 我的建议
|
||||
|
||||
如果你现在要尽快上线,一期可以先用方案 A:一台 ECS + Docker Compose 自带 MySQL。
|
||||
|
||||
如果这个系统会长期对外使用,证书数据又比较重要,建议正式上线直接用方案 B:ECS + RDS MySQL。证书系统的数据价值主要在学员、证书、导入记录、操作日志,这些数据丢了很麻烦,所以 RDS 更稳。
|
||||
|
||||
阿里云官方文档里,RDS 是托管型关系型数据库服务,支持 MySQL,并提供备份、恢复、监控、容灾等能力。ECS 上也可以安装 Docker 和 Docker Compose 来统一管理多服务部署。
|
||||
|
||||
参考:
|
||||
|
||||
- 阿里云 RDS MySQL 文档:https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/product-overview/
|
||||
- 阿里云 ECS 安装 Docker 文档:https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docker/
|
||||
- Docker Compose 官方文档:https://docs.docker.com/compose/
|
||||
|
||||
## 2. 正式版和本地版的区别
|
||||
|
||||
### 本地验证版
|
||||
|
||||
路径:
|
||||
|
||||
```text
|
||||
local_app/
|
||||
```
|
||||
|
||||
启动方式:
|
||||
|
||||
```bat
|
||||
start-local.bat
|
||||
```
|
||||
|
||||
访问地址:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8000/admin/login
|
||||
```
|
||||
|
||||
用途:
|
||||
|
||||
- 本地快速验收。
|
||||
- 不依赖 MySQL、Node、Docker。
|
||||
- 用 SQLite 存测试数据。
|
||||
- 不建议正式部署使用。
|
||||
|
||||
### 正式部署版
|
||||
|
||||
路径:
|
||||
|
||||
```text
|
||||
backend/
|
||||
frontend/
|
||||
docker-compose.yml
|
||||
deploy/
|
||||
```
|
||||
|
||||
技术:
|
||||
|
||||
- 后端:FastAPI
|
||||
- 前端:Vue 3 + Element Plus
|
||||
- 数据库:MySQL 8
|
||||
- 部署:Docker Compose
|
||||
|
||||
正式部署时不要运行:
|
||||
|
||||
```text
|
||||
local_app/server.py
|
||||
```
|
||||
|
||||
正式部署要运行:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## 3. 阿里云购买建议
|
||||
|
||||
### ECS 建议
|
||||
|
||||
一期建议:
|
||||
|
||||
- 地域:选择主要用户所在地区,例如华东、华南。
|
||||
- 系统:Ubuntu 22.04 LTS 或 Alibaba Cloud Linux 3。
|
||||
- 配置:2 核 4G 起步。
|
||||
- 磁盘:系统盘 40G 起步,建议额外挂一块数据盘 50G 或以上。
|
||||
- 带宽:按量或固定 3M 起步,后面看访问量调整。
|
||||
|
||||
如果要把 MySQL 也放 ECS 上,建议:
|
||||
|
||||
- 2 核 4G 是最低可用。
|
||||
- 更稳一点用 2 核 8G。
|
||||
- 数据盘独立挂载到 `/data`。
|
||||
|
||||
### RDS 建议
|
||||
|
||||
如果买 RDS MySQL:
|
||||
|
||||
- 数据库版本:MySQL 8.0。
|
||||
- 网络:和 ECS 同地域、同 VPC。
|
||||
- 规格:小规格起步即可,后期扩容。
|
||||
- 存储:20G 起步。
|
||||
- 备份:开启自动备份。
|
||||
- 白名单:只允许 ECS 内网 IP 访问,不要开放公网访问。
|
||||
|
||||
## 4. 域名和备案
|
||||
|
||||
如果要通过正式域名访问,例如:
|
||||
|
||||
```text
|
||||
https://cert.example.com
|
||||
```
|
||||
|
||||
你需要:
|
||||
|
||||
1. 购买域名。
|
||||
2. 如果服务器在中国大陆,通常需要完成 ICP 备案。
|
||||
3. 在域名 DNS 里添加解析:
|
||||
|
||||
```text
|
||||
类型:A
|
||||
主机记录:cert
|
||||
记录值:你的 ECS 公网 IP
|
||||
```
|
||||
|
||||
如果暂时没有域名,也可以先用:
|
||||
|
||||
```text
|
||||
http://ECS公网IP:8080
|
||||
```
|
||||
|
||||
但正式对外建议使用域名和 HTTPS。
|
||||
|
||||
## 5. ECS 初始化
|
||||
|
||||
下面以 Ubuntu 22.04 为例。
|
||||
|
||||
### 5.1 登录服务器
|
||||
|
||||
在本地终端执行:
|
||||
|
||||
```bash
|
||||
ssh root@你的ECS公网IP
|
||||
```
|
||||
|
||||
### 5.2 更新系统
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt upgrade -y
|
||||
```
|
||||
|
||||
### 5.3 安装常用工具
|
||||
|
||||
```bash
|
||||
apt install -y git curl vim unzip ca-certificates gnupg lsb-release
|
||||
```
|
||||
|
||||
### 5.4 安装 Docker
|
||||
|
||||
可以按阿里云 ECS Docker 文档安装。Ubuntu 常用命令如下:
|
||||
|
||||
```bash
|
||||
apt install -y docker.io docker-compose-plugin
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
如果 `docker compose version` 能显示版本号,说明 Compose 可用。
|
||||
|
||||
### 5.5 创建数据目录
|
||||
|
||||
```bash
|
||||
mkdir -p /data/certificate-system
|
||||
mkdir -p /data/certificate-system/uploads
|
||||
mkdir -p /data/certificate-system/error-reports
|
||||
mkdir -p /data/certificate-system/exports
|
||||
mkdir -p /data/certificate-system/pdf-cache
|
||||
```
|
||||
|
||||
## 6. 上传项目代码
|
||||
|
||||
你可以用 Git,也可以用压缩包。
|
||||
|
||||
### 方式 A:Git 拉代码
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
git clone 你的代码仓库地址 certificate-system
|
||||
cd /opt/certificate-system
|
||||
```
|
||||
|
||||
### 方式 B:本地打包上传
|
||||
|
||||
在本地把项目压缩后上传到服务器:
|
||||
|
||||
```bash
|
||||
scp certificate-system.zip root@你的ECS公网IP:/opt/
|
||||
```
|
||||
|
||||
服务器上解压:
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
unzip certificate-system.zip
|
||||
cd /opt/certificate-system
|
||||
```
|
||||
|
||||
## 7. 配置环境变量
|
||||
|
||||
在服务器项目目录下:
|
||||
|
||||
```bash
|
||||
cd /opt/certificate-system
|
||||
cp .env.example .env
|
||||
vim .env
|
||||
```
|
||||
|
||||
### 7.1 自建 MySQL 方案的 `.env`
|
||||
|
||||
如果用 Docker Compose 里的 MySQL:
|
||||
|
||||
```env
|
||||
APP_ENV=production
|
||||
DATABASE_URL=mysql+pymysql://certificate:请改成强密码@mysql:3306/certificate_system
|
||||
SECRET_KEY=请改成一串很长的随机字符串
|
||||
PUBLIC_BASE_URL=https://你的域名
|
||||
CERTIFICATE_NO_SECRET=请改成另一串很长的随机字符串
|
||||
PDF_CACHE_DAYS=30
|
||||
DATA_ROOT=/data/certificate-system
|
||||
CORS_ORIGINS=https://你的域名
|
||||
```
|
||||
|
||||
同时要修改 `docker-compose.yml` 里的 MySQL 密码,保证和 `DATABASE_URL` 一致:
|
||||
|
||||
```yaml
|
||||
MYSQL_ROOT_PASSWORD: 请改成root强密码
|
||||
MYSQL_DATABASE: certificate_system
|
||||
MYSQL_USER: certificate
|
||||
MYSQL_PASSWORD: 请改成强密码
|
||||
```
|
||||
|
||||
### 7.2 RDS MySQL 方案的 `.env`
|
||||
|
||||
如果用阿里云 RDS:
|
||||
|
||||
```env
|
||||
APP_ENV=production
|
||||
DATABASE_URL=mysql+pymysql://RDS账号:RDS密码@RDS内网地址:3306/certificate_system
|
||||
SECRET_KEY=请改成一串很长的随机字符串
|
||||
PUBLIC_BASE_URL=https://你的域名
|
||||
CERTIFICATE_NO_SECRET=请改成另一串很长的随机字符串
|
||||
PDF_CACHE_DAYS=30
|
||||
DATA_ROOT=/data/certificate-system
|
||||
CORS_ORIGINS=https://你的域名
|
||||
```
|
||||
|
||||
RDS 注意事项:
|
||||
|
||||
1. ECS 和 RDS 要在同一个 VPC。
|
||||
2. RDS 白名单里加入 ECS 的内网 IP。
|
||||
3. 不建议开放 RDS 公网访问。
|
||||
4. RDS 里提前创建数据库:
|
||||
|
||||
```text
|
||||
certificate_system
|
||||
```
|
||||
|
||||
如果使用 RDS,建议把 `docker-compose.yml` 里的 `mysql` 服务去掉,或者保留但不启动。最简单的做法是先保留 compose 文件,但后端 `DATABASE_URL` 指向 RDS,实际业务不会用 compose 里的 MySQL。
|
||||
|
||||
## 8. 首次启动
|
||||
|
||||
在项目目录执行:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
查看容器状态:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
查看后端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
查看前端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f frontend
|
||||
```
|
||||
|
||||
## 9. 初始化数据库
|
||||
|
||||
首次部署需要执行:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -m app.cli init-db --admin-username admin --admin-password "请换成强密码"
|
||||
```
|
||||
|
||||
这个命令会:
|
||||
|
||||
- 执行数据库迁移。
|
||||
- 创建基础角色。
|
||||
- 创建默认管理员。
|
||||
- 初始化默认项目配置。
|
||||
|
||||
如果后续只是升级代码,一般执行:
|
||||
|
||||
```bash
|
||||
docker compose exec backend alembic upgrade head
|
||||
```
|
||||
|
||||
## 10. 访问系统
|
||||
|
||||
如果还没有配置域名,可以访问:
|
||||
|
||||
```text
|
||||
http://ECS公网IP:8080/admin/login
|
||||
```
|
||||
|
||||
如果已经配置域名和 HTTPS:
|
||||
|
||||
```text
|
||||
https://你的域名/admin/login
|
||||
```
|
||||
|
||||
公开查询页:
|
||||
|
||||
```text
|
||||
https://你的域名/query
|
||||
```
|
||||
|
||||
证书直达链接类似:
|
||||
|
||||
```text
|
||||
https://你的域名/cert/xxxx
|
||||
```
|
||||
|
||||
二维码核验链接类似:
|
||||
|
||||
```text
|
||||
https://你的域名/verify/xxxx
|
||||
```
|
||||
|
||||
## 11. 安全组设置
|
||||
|
||||
在阿里云 ECS 安全组里建议开放:
|
||||
|
||||
```text
|
||||
22 SSH,仅允许你的办公 IP 更安全
|
||||
80 HTTP
|
||||
443 HTTPS
|
||||
8080 如果临时不用 Nginx/HTTPS,可以开放;正式建议关闭
|
||||
```
|
||||
|
||||
不建议公网开放:
|
||||
|
||||
```text
|
||||
3306 MySQL
|
||||
8000 后端接口
|
||||
```
|
||||
|
||||
正式情况下,后端只让前端 Nginx 或内网访问。
|
||||
|
||||
## 12. HTTPS 和 Nginx
|
||||
|
||||
### 12.1 临时上线
|
||||
|
||||
可以先用前端容器暴露的 8080:
|
||||
|
||||
```text
|
||||
http://ECS公网IP:8080
|
||||
```
|
||||
|
||||
但这不适合长期正式使用。
|
||||
|
||||
### 12.2 正式上线
|
||||
|
||||
推荐:
|
||||
|
||||
- ECS 上安装 Nginx。
|
||||
- Nginx 监听 80/443。
|
||||
- 443 配 HTTPS 证书。
|
||||
- Nginx 反向代理到前端容器 8080。
|
||||
|
||||
项目里有参考配置:
|
||||
|
||||
```text
|
||||
deploy/nginx.prod.conf
|
||||
```
|
||||
|
||||
需要修改:
|
||||
|
||||
```nginx
|
||||
server_name example.com;
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
```
|
||||
|
||||
改成你的域名和证书路径。
|
||||
|
||||
Nginx 重新加载:
|
||||
|
||||
```bash
|
||||
nginx -t
|
||||
systemctl reload nginx
|
||||
```
|
||||
|
||||
## 13. 正式上线前检查
|
||||
|
||||
### 13.1 后台登录
|
||||
|
||||
打开:
|
||||
|
||||
```text
|
||||
https://你的域名/admin/login
|
||||
```
|
||||
|
||||
确认:
|
||||
|
||||
- 可以登录。
|
||||
- 默认密码已经改成强密码。
|
||||
|
||||
### 13.2 项目管理
|
||||
|
||||
确认:
|
||||
|
||||
- 能新增项目。
|
||||
- 能修改项目。
|
||||
- 能停用/启用项目。
|
||||
- 能搜索项目。
|
||||
|
||||
### 13.3 学员管理
|
||||
|
||||
确认:
|
||||
|
||||
- 能新增学员。
|
||||
- 能修改学员。
|
||||
- 能删除学员。
|
||||
- 手机号查询正常。
|
||||
|
||||
### 13.4 证书管理
|
||||
|
||||
确认:
|
||||
|
||||
- 能新增证书。
|
||||
- 证书编号自动生成。
|
||||
- 证书名称使用项目名称。
|
||||
- 能预览证书。
|
||||
- 能下载 PDF。
|
||||
- 证书日期、课程标题、导师、二维码显示正常。
|
||||
- 能作废证书。
|
||||
- 作废证书不能下载正常 PDF。
|
||||
|
||||
### 13.5 Excel 导入
|
||||
|
||||
确认模板字段只有:
|
||||
|
||||
```text
|
||||
姓名
|
||||
手机号
|
||||
项目代码
|
||||
发证日期
|
||||
```
|
||||
|
||||
确认:
|
||||
|
||||
- 能上传 Excel。
|
||||
- 能下载原文件。
|
||||
- 能删除导入批次。
|
||||
- 能确认导入。
|
||||
- 确认导入后状态变成已导入。
|
||||
- 不能重复确认导入。
|
||||
|
||||
### 13.6 公开查询
|
||||
|
||||
确认:
|
||||
|
||||
- 证书编号 + 姓名 + 验证码可以查。
|
||||
- 手机号 + 姓名 + 验证码可以查。
|
||||
- 查询结果可以预览和下载。
|
||||
- 公开查询和公开下载会进入操作日志。
|
||||
|
||||
### 13.7 操作日志
|
||||
|
||||
确认:
|
||||
|
||||
- 日志中文显示。
|
||||
- 风险等级显示。
|
||||
- 支持筛选。
|
||||
- 支持分页,每页 20 条。
|
||||
- 页码右对齐。
|
||||
- 上方和下方都有分页。
|
||||
- 页码多时有省略号。
|
||||
- 支持导出日志。
|
||||
- 支持清理过期日志。
|
||||
|
||||
## 14. 数据备份
|
||||
|
||||
### 14.1 如果使用 RDS
|
||||
|
||||
建议:
|
||||
|
||||
- 开启自动备份。
|
||||
- 开启日志备份。
|
||||
- 定期测试恢复。
|
||||
- RDS 白名单只允许 ECS 内网 IP。
|
||||
|
||||
### 14.2 如果使用 ECS 自建 MySQL
|
||||
|
||||
至少每天备份一次数据库。
|
||||
|
||||
创建备份目录:
|
||||
|
||||
```bash
|
||||
mkdir -p /data/backups/mysql
|
||||
```
|
||||
|
||||
手动备份:
|
||||
|
||||
```bash
|
||||
docker compose exec mysql mysqldump -ucertificate -p certificate_system > /data/backups/mysql/certificate_system_$(date +%F).sql
|
||||
```
|
||||
|
||||
注意:这个命令会提示输入 MySQL 密码。
|
||||
|
||||
也可以写定时任务:
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
加入:
|
||||
|
||||
```cron
|
||||
30 2 * * * cd /opt/certificate-system && docker compose exec -T mysql mysqldump -ucertificate -p你的密码 certificate_system > /data/backups/mysql/certificate_system_$(date +\%F).sql
|
||||
```
|
||||
|
||||
建议再加一个删除 30 天前备份的任务:
|
||||
|
||||
```cron
|
||||
10 3 * * * find /data/backups/mysql -name "certificate_system_*.sql" -mtime +30 -delete
|
||||
```
|
||||
|
||||
### 14.3 文件数据备份
|
||||
|
||||
需要备份:
|
||||
|
||||
```text
|
||||
/data/certificate-system/uploads
|
||||
/data/certificate-system/error-reports
|
||||
/data/certificate-system/exports
|
||||
```
|
||||
|
||||
不需要长期备份:
|
||||
|
||||
```text
|
||||
/data/certificate-system/pdf-cache
|
||||
```
|
||||
|
||||
PDF 可以重新生成,缓存目录不是核心数据。
|
||||
|
||||
## 15. 日志保留策略
|
||||
|
||||
当前系统建议:
|
||||
|
||||
- 普通后台操作日志保留 180 天。
|
||||
- 公开查询和公开下载日志保留 180 天。
|
||||
- 高风险后台操作日志保留 365 天。
|
||||
|
||||
后台提供“清理过期日志”,只清理超过保留周期的日志。
|
||||
|
||||
## 16. 日常运维命令
|
||||
|
||||
查看容器:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
查看后端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
查看前端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f frontend
|
||||
```
|
||||
|
||||
重启后端:
|
||||
|
||||
```bash
|
||||
docker compose restart backend
|
||||
```
|
||||
|
||||
重启全部服务:
|
||||
|
||||
```bash
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
更新代码后重新构建:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker compose exec backend alembic upgrade head
|
||||
```
|
||||
|
||||
停止服务:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
不要随便执行:
|
||||
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
`-v` 会删除 Docker volume,可能导致数据库数据丢失。
|
||||
|
||||
## 17. 常见问题
|
||||
|
||||
### 17.1 页面打不开
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f frontend
|
||||
```
|
||||
|
||||
确认安全组是否开放 8080、80 或 443。
|
||||
|
||||
### 17.2 后台接口 502
|
||||
|
||||
检查后端:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
检查数据库连接:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -m app.cli init-db --admin-username admin --admin-password "临时测试密码"
|
||||
```
|
||||
|
||||
如果数据库连不上,这个命令会报错。
|
||||
|
||||
### 17.3 PDF 中文乱码或字体不对
|
||||
|
||||
后端 Dockerfile 已安装:
|
||||
|
||||
```text
|
||||
fonts-noto-cjk
|
||||
```
|
||||
|
||||
如果换系统或自定义镜像,要确认 CJK 字体存在。
|
||||
|
||||
### 17.4 公开链接域名不对
|
||||
|
||||
检查 `.env`:
|
||||
|
||||
```env
|
||||
PUBLIC_BASE_URL=https://你的域名
|
||||
```
|
||||
|
||||
修改后重启后端:
|
||||
|
||||
```bash
|
||||
docker compose restart backend
|
||||
```
|
||||
|
||||
### 17.5 数据库密码改了但服务连不上
|
||||
|
||||
确认三处一致:
|
||||
|
||||
1. `.env` 里的 `DATABASE_URL`
|
||||
2. `docker-compose.yml` 里的 `MYSQL_PASSWORD`
|
||||
3. MySQL 实际用户密码
|
||||
|
||||
如果已经初始化过 MySQL volume,再改 `MYSQL_PASSWORD` 不一定会自动改数据库里的旧密码。需要进入 MySQL 手动改密码,或者在未上线前清空 volume 重新初始化。
|
||||
|
||||
## 18. 推荐上线顺序
|
||||
|
||||
1. 购买 ECS。
|
||||
2. 决定数据库方案:先 ECS 自建 MySQL,或直接 RDS。
|
||||
3. 配置域名解析。
|
||||
4. 安装 Docker 和 Compose。
|
||||
5. 上传项目代码。
|
||||
6. 修改 `.env`。
|
||||
7. 如果用 RDS,配置 RDS 数据库、账号、白名单。
|
||||
8. 执行 `docker compose up -d --build`。
|
||||
9. 执行 `python -m app.cli init-db`。
|
||||
10. 登录后台。
|
||||
11. 配置项目。
|
||||
12. 新增测试学员和测试证书。
|
||||
13. 验证公开查询和 PDF 下载。
|
||||
14. 配置 Nginx 和 HTTPS。
|
||||
15. 配置备份。
|
||||
16. 正式导入业务数据。
|
||||
|
||||
## 19. 一期推荐选择
|
||||
|
||||
如果你希望明天就能上线验证:
|
||||
|
||||
```text
|
||||
一台 2核4G 或 2核8G ECS
|
||||
Docker Compose 自带 MySQL
|
||||
域名 + HTTPS
|
||||
每天 mysqldump 备份
|
||||
```
|
||||
|
||||
如果你希望正式长期稳定:
|
||||
|
||||
```text
|
||||
一台 ECS 跑前后端
|
||||
阿里云 RDS MySQL 跑数据库
|
||||
RDS 自动备份
|
||||
域名 + HTTPS
|
||||
```
|
||||
|
||||
我的最终建议:如果预算允许,正式生产用 RDS;如果先快速上线,ECS 自建 MySQL 也可以,但一定要配置每日备份。
|
||||
Reference in New Issue
Block a user