ForgeFlow-ERP/docs/superpowers/plans/2026-06-03-tencent-ip-port-dev-deploy.md
2026-06-14 21:05:49 +08:00

1126 lines
19 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.

# Tencent IP Port Dev Deploy Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将当前 ForgeFlow ERP 前后端部署到腾讯云 1Panel Ubuntu 服务器,临时开启动态加载,通过 `公网 IP + 端口` 访问,数据库继续连接阿里云 MySQL。
**Architecture:** 临时测试阶段不走域名、HTTPS、Nginx/OpenResty 反代。浏览器访问 Vite dev server `http://腾讯云公网IP:5173`,前端请求 FastAPI `http://腾讯云公网IP:8000/api`,后端连接阿里云 MySQL `121.40.97.156:3306`。稳定后再切到正式生产架构前端静态构建、OpenResty 反代 `/api`、HTTPS、后端仅监听本机。
**Tech Stack:** Ubuntu 22.04/1Panel, Python 3, FastAPI/Uvicorn, Vue 3/Vite, Node.js 20, MySQL on Aliyun.
---
## Phase 0: 部署边界确认
本计划只做临时测试部署,不代表最终生产配置。
临时测试访问方式:
```text
浏览器
-> http://<腾讯云公网IP>:5173
Vite dev server支持前端热更新
前端 API 请求
-> http://<腾讯云公网IP>:8000/api
FastAPI/Uvicorn使用 --reload 支持后端动态加载
后端数据库连接
-> 121.40.97.156:3306
阿里云 MySQL
```
需要提前准备的信息:
```bash
export TENCENT_IP="<腾讯云服务器公网IP>"
export ALIYUN_MYSQL_HOST="121.40.97.156"
export ALIYUN_MYSQL_PORT="3306"
export ERP_DB_NAME="jiaheng_erp"
export ERP_DB_USER="<数据库用户名>"
export ERP_DB_PASSWORD="<数据库密码>"
```
本阶段必须接受的临时风险:
- `5173``8000` 会临时暴露在公网,只适合测试期。
- Vite dev server 和 `uvicorn --reload` 不是最终生产运行方式。
- 如果直接连现有阿里云数据库,腾讯云上的操作会真实写入同一个库。
- 数据库账号不要长期使用 `root`,至少正式前要换成 ERP 专用账号。
---
## Phase 1: 腾讯云服务器基础准备
### Task 1: 登录服务器并确认系统
- [ ] **Step 1: SSH 登录腾讯云服务器**
```bash
ssh root@<腾讯云公网IP>
```
Expected:
```text
成功进入 Ubuntu shell
```
- [ ] **Step 2: 确认系统版本和架构**
```bash
uname -a
lsb_release -a || cat /etc/os-release
```
Expected:
```text
Linux VM-0-14-ubuntu ...
Ubuntu ...
x86_64
```
### Task 2: 安装基础依赖
- [ ] **Step 1: 更新 apt 包索引**
```bash
sudo apt update
```
Expected:
```text
Reading package lists... Done
```
- [ ] **Step 2: 安装 Python、构建工具、Git、MySQL 客户端**
```bash
sudo apt install -y git curl build-essential python3 python3-venv python3-pip mysql-client tmux
```
Expected:
```text
git, curl, python3, python3-venv, mysql-client, tmux 安装完成
```
- [ ] **Step 3: 安装 Node.js 20**
如果当前没有 Node或者 `node -v` 低于 20执行
```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
```
验证:
```bash
node -v
npm -v
```
Expected:
```text
v20.x.x
10.x.x 或更高
```
---
## Phase 2: 网络和防火墙放行
### Task 3: 腾讯云安全组放行临时端口
- [ ] **Step 1: 在腾讯云控制台安全组放行 TCP 端口**
放行入站规则:
```text
TCP 5173 来源:你的办公公网 IP/32
TCP 8000 来源:你的办公公网 IP/32
TCP 22 来源:你的办公公网 IP/32
```
如果测试人员公网 IP 不固定,临时可用:
```text
TCP 5173 来源0.0.0.0/0
TCP 8000 来源0.0.0.0/0
```
但这只能用于短期测试,稳定后必须收口。
Expected:
```text
外网可以访问 5173 和 8000不再被腾讯云安全组拦截
```
### Task 4: 1Panel 或 Ubuntu 防火墙放行端口
- [ ] **Step 1: 如果使用 1Panel 防火墙,在 1Panel 面板中放行**
```text
端口5173/tcp
端口8000/tcp
```
- [ ] **Step 2: 如果服务器启用了 ufw执行放行**
```bash
sudo ufw allow 5173/tcp
sudo ufw allow 8000/tcp
sudo ufw status
```
Expected:
```text
5173/tcp ALLOW
8000/tcp ALLOW
```
### Task 5: 阿里云 MySQL 放行腾讯云公网 IP
- [ ] **Step 1: 在阿里云服务器或 RDS 安全组中放行腾讯云公网 IP**
放行规则:
```text
入站 TCP 3306 来源:<腾讯云公网IP>/32
```
- [ ] **Step 2: 在腾讯云服务器测试 MySQL 连通性**
```bash
mysql -h 121.40.97.156 -P 3306 -u <数据库用户名> -p -e "SELECT NOW() AS db_time;"
```
Expected:
```text
+---------------------+
| db_time |
+---------------------+
| 2026-... |
+---------------------+
```
如果报错:
```text
ERROR 2003 Can't connect to MySQL server
```
处理方向:
```text
优先检查阿里云安全组、MySQL bind-address、防火墙、账号 Host 权限。
```
---
## Phase 3: 部署项目代码
### Task 6: 准备项目目录
- [ ] **Step 1: 创建部署目录**
```bash
sudo mkdir -p /opt/ForgeFlow-ERP
sudo chown -R $USER:$USER /opt/ForgeFlow-ERP
```
Expected:
```text
/opt/ForgeFlow-ERP 可由当前用户读写
```
### Task 7: 上传或拉取代码
推荐方式 A服务器可以访问 Git 仓库时使用 `git clone`
- [ ] **Step 1A: 克隆项目**
```bash
cd /opt
git clone <ForgeFlow-ERP仓库地址> ForgeFlow-ERP
cd /opt/ForgeFlow-ERP
git status
```
Expected:
```text
On branch ...
working tree clean
```
推荐方式 B如果仓库暂时不方便从服务器拉取就从 Mac 同步代码。
- [ ] **Step 1B: 在 Mac 上执行 rsync 上传**
```bash
rsync -av --delete \
--exclude 'frontend/node_modules' \
--exclude 'backend/.venv' \
--exclude '.git' \
/Users/souplearn/Gitlab/py/ForgeFlow-ERP/ \
root@<腾讯云公网IP>:/opt/ForgeFlow-ERP/
```
Expected:
```text
代码同步到 /opt/ForgeFlow-ERP
```
- [ ] **Step 2: 在服务器确认目录结构**
```bash
cd /opt/ForgeFlow-ERP
ls -la
ls -la backend frontend
```
Expected:
```text
backend/
frontend/
README.md
```
---
## Phase 4: 后端动态加载部署
### Task 8: 配置后端 `.env`
- [ ] **Step 1: 创建后端环境变量文件**
```bash
cd /opt/ForgeFlow-ERP/backend
cp .env.example .env
```
- [ ] **Step 2: 编辑 `.env`**
```bash
nano /opt/ForgeFlow-ERP/backend/.env
```
推荐内容:
```env
APP_NAME=Baihua Hardware ERP API
APP_ENV=staging-dev
APP_HOST=0.0.0.0
APP_PORT=8000
MYSQL_HOST=121.40.97.156
MYSQL_PORT=3306
MYSQL_DATABASE=jiaheng_erp
MYSQL_USER=<数据库用户名>
MYSQL_PASSWORD=<数据库密码>
ALLOWED_ORIGINS=http://<腾讯云公网IP>:5173
AUTH_SECRET_KEY=<生成一串至少32位的随机字符串>
AUTH_TOKEN_EXPIRE_MINUTES=480
```
生成随机密钥:
```bash
python3 - <<'PY'
import secrets
print(secrets.token_urlsafe(48))
PY
```
Expected:
```text
输出一串随机字符串,将它填入 AUTH_SECRET_KEY
```
注意:
```text
不要把正式数据库密码、AUTH_SECRET_KEY 发到聊天或提交到 Git。
```
### Task 9: 安装后端依赖
- [ ] **Step 1: 创建虚拟环境**
```bash
cd /opt/ForgeFlow-ERP/backend
python3 -m venv .venv
```
- [ ] **Step 2: 安装依赖**
```bash
cd /opt/ForgeFlow-ERP/backend
. .venv/bin/activate
pip install -U pip
pip install -r requirements.txt
```
Expected:
```text
Successfully installed fastapi uvicorn sqlalchemy pymysql ...
```
### Task 10: 临时启动后端动态加载
- [ ] **Step 1: 用 tmux 启动后端**
```bash
tmux new -s forgeflow-backend
```
在 tmux 窗口内执行:
```bash
cd /opt/ForgeFlow-ERP/backend
. .venv/bin/activate
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
Expected:
```text
Uvicorn running on http://0.0.0.0:8000
Started reloader process
```
退出 tmux 但保留进程:
```text
按 Ctrl+B然后按 D
```
- [ ] **Step 2: 服务器本机验证后端**
```bash
curl -s http://127.0.0.1:8000/ | python3 -m json.tool
curl -s http://127.0.0.1:8000/api/system/health | python3 -m json.tool
```
Expected:
```json
{
"app": "ok",
"database": {
"connected": true
}
}
```
- [ ] **Step 3: Mac 或浏览器外网验证后端**
```bash
curl -s http://<腾讯云公网IP>:8000/api/system/health
```
Expected:
```text
能返回 app okdatabase connected true
```
---
## Phase 5: 前端动态加载部署
### Task 11: 配置前端 `.env`
- [ ] **Step 1: 创建前端环境变量文件**
```bash
cd /opt/ForgeFlow-ERP/frontend
cp .env.example .env
```
- [ ] **Step 2: 修改 API 地址**
```bash
nano /opt/ForgeFlow-ERP/frontend/.env
```
内容:
```env
VITE_API_BASE_URL=http://<腾讯云公网IP>:8000/api
```
Expected:
```text
前端所有 API 请求都会打到腾讯云后端 8000 端口
```
### Task 12: 安装前端依赖
- [ ] **Step 1: 安装 npm 依赖**
```bash
cd /opt/ForgeFlow-ERP/frontend
npm install
```
Expected:
```text
added ... packages
```
### Task 13: 临时启动前端动态加载
- [ ] **Step 1: 用 tmux 启动前端**
```bash
tmux new -s forgeflow-frontend
```
在 tmux 窗口内执行:
```bash
cd /opt/ForgeFlow-ERP/frontend
npm run dev -- --host 0.0.0.0 --port 5173
```
Expected:
```text
VITE v5.x.x ready
Local: http://localhost:5173/
Network: http://<内网IP>:5173/
```
退出 tmux 但保留进程:
```text
按 Ctrl+B然后按 D
```
- [ ] **Step 2: 服务器本机验证前端**
```bash
curl -I http://127.0.0.1:5173
```
Expected:
```text
HTTP/1.1 200 OK
```
- [ ] **Step 3: 浏览器访问**
```text
http://<腾讯云公网IP>:5173/login?redirect=/
```
Expected:
```text
出现 ERP 登录页
```
---
## Phase 6: 测试期进程守护
tmux 适合第一天快速验证。如果需要测试环境持续跑几天,建议改成 systemd 管理,但仍然保留动态加载。
### Task 14: 创建后端 dev systemd 服务
- [ ] **Step 1: 创建服务文件**
```bash
sudo nano /etc/systemd/system/forgeflow-backend-dev.service
```
内容:
```ini
[Unit]
Description=ForgeFlow ERP Backend Dev Reload
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/ForgeFlow-ERP/backend
ExecStart=/opt/ForgeFlow-ERP/backend/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
Restart=always
RestartSec=3
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
```
- [ ] **Step 2: 启动服务**
```bash
sudo systemctl daemon-reload
sudo systemctl enable forgeflow-backend-dev
sudo systemctl start forgeflow-backend-dev
sudo systemctl status forgeflow-backend-dev --no-pager
```
Expected:
```text
Active: active (running)
```
- [ ] **Step 3: 查看日志**
```bash
journalctl -u forgeflow-backend-dev -f
```
Expected:
```text
Uvicorn running on http://0.0.0.0:8000
```
### Task 15: 创建前端 dev systemd 服务
- [ ] **Step 1: 查出 npm 路径**
```bash
which npm
```
Expected:
```text
/usr/bin/npm
```
- [ ] **Step 2: 创建服务文件**
```bash
sudo nano /etc/systemd/system/forgeflow-frontend-dev.service
```
如果 `which npm` 输出 `/usr/bin/npm`,内容如下:
```ini
[Unit]
Description=ForgeFlow ERP Frontend Vite Dev Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/ForgeFlow-ERP/frontend
ExecStart=/usr/bin/npm run dev -- --host 0.0.0.0 --port 5173
Restart=always
RestartSec=3
Environment=NODE_ENV=development
[Install]
WantedBy=multi-user.target
```
- [ ] **Step 3: 启动服务**
```bash
sudo systemctl daemon-reload
sudo systemctl enable forgeflow-frontend-dev
sudo systemctl start forgeflow-frontend-dev
sudo systemctl status forgeflow-frontend-dev --no-pager
```
Expected:
```text
Active: active (running)
```
- [ ] **Step 4: 查看日志**
```bash
journalctl -u forgeflow-frontend-dev -f
```
Expected:
```text
VITE v5.x.x ready
```
---
## Phase 7: 动态加载更新流程
### Task 16: 代码更新后验证热加载
- [ ] **Step 1: 更新代码**
如果使用 Git
```bash
cd /opt/ForgeFlow-ERP
git pull
```
如果使用 rsync在 Mac 重新执行同步命令:
```bash
rsync -av --delete \
--exclude 'frontend/node_modules' \
--exclude 'backend/.venv' \
--exclude '.git' \
/Users/souplearn/Gitlab/py/ForgeFlow-ERP/ \
root@<腾讯云公网IP>:/opt/ForgeFlow-ERP/
```
- [ ] **Step 2: 如果只改后端 Python 代码**
Expected:
```text
uvicorn --reload 自动重载,无需手动重启
```
验证:
```bash
journalctl -u forgeflow-backend-dev -n 80 --no-pager
```
- [ ] **Step 3: 如果改前端 Vue/CSS/JS**
Expected:
```text
Vite dev server 自动热更新浏览器页面
```
验证:
```bash
journalctl -u forgeflow-frontend-dev -n 80 --no-pager
```
- [ ] **Step 4: 如果改了依赖**
后端依赖变更:
```bash
cd /opt/ForgeFlow-ERP/backend
. .venv/bin/activate
pip install -r requirements.txt
sudo systemctl restart forgeflow-backend-dev
```
前端依赖变更:
```bash
cd /opt/ForgeFlow-ERP/frontend
npm install
sudo systemctl restart forgeflow-frontend-dev
```
Expected:
```text
依赖安装成功,服务重启成功
```
---
## Phase 8: 功能验收清单
### Task 17: 登录和基础页面验收
- [ ] **Step 1: 打开登录页**
```text
http://<腾讯云公网IP>:5173/login?redirect=/
```
Expected:
```text
登录页正常渲染,浏览器控制台无 CORS 报错
```
- [ ] **Step 2: 登录 ERP**
Expected:
```text
登录成功,进入首页
```
- [ ] **Step 3: 打开浏览器开发者工具 Network**
Expected:
```text
API 请求地址是 http://<腾讯云公网IP>:8000/api/...
状态码不是 CORS error
```
### Task 18: 核心业务验收
- [ ] **Step 1: 基础资料页面**
验证:
```text
供应商名录、客户名录、原材料名录、产品需规清单能打开
```
- [ ] **Step 2: 订单与采购页面**
验证:
```text
销售订单列表、采购订单、到货入库、质量校验能打开
```
- [ ] **Step 3: 仓库页面**
验证:
```text
百华仓库六大库能打开,出入库弹窗能打开
```
- [ ] **Step 4: 生产执行页面**
验证:
```text
工单台账、工序报工能打开
```
- [ ] **Step 5: 发货概览页面**
验证:
```text
发货台账能打开
```
### Task 19: Excel 导入导出验收
- [ ] **Step 1: 测试导出**
验证:
```text
供应商名录、原材料名录、客户名录、仓库期初模板、盘库清单导出正常
```
- [ ] **Step 2: 测试导入**
验证:
```text
上传 Excel 时无 413、CORS、权限、临时目录报错
```
- [ ] **Step 3: 检查响应头**
Expected:
```text
浏览器能识别 Content-Disposition下载文件名正常
```
说明:
```text
后端 CORS 已 expose Content-Disposition只要 ALLOWED_ORIGINS 配对即可。
```
---
## Phase 9: 常见故障处理
### Task 20: 前端页面打不开
- [ ] **Step 1: 检查 Vite 服务**
```bash
sudo systemctl status forgeflow-frontend-dev --no-pager
journalctl -u forgeflow-frontend-dev -n 120 --no-pager
```
Expected:
```text
Active: active (running)
VITE ready
```
- [ ] **Step 2: 检查端口监听**
```bash
ss -lntp | grep 5173
```
Expected:
```text
0.0.0.0:5173
```
如果只看到 `127.0.0.1:5173`,说明没有绑定公网网卡,需要加:
```bash
npm run dev -- --host 0.0.0.0 --port 5173
```
### Task 21: 后端接口打不开
- [ ] **Step 1: 检查后端服务**
```bash
sudo systemctl status forgeflow-backend-dev --no-pager
journalctl -u forgeflow-backend-dev -n 120 --no-pager
```
- [ ] **Step 2: 检查端口监听**
```bash
ss -lntp | grep 8000
```
Expected:
```text
0.0.0.0:8000
```
- [ ] **Step 3: 本机 curl**
```bash
curl -s http://127.0.0.1:8000/api/system/health
```
Expected:
```text
本机通则进程正常;外网不通则优先查腾讯云安全组和 1Panel 防火墙。
```
### Task 22: 登录时报 CORS
- [ ] **Step 1: 确认前端访问地址**
```text
http://<腾讯云公网IP>:5173
```
- [ ] **Step 2: 确认后端 `.env`**
```bash
grep ALLOWED_ORIGINS /opt/ForgeFlow-ERP/backend/.env
```
Expected:
```env
ALLOWED_ORIGINS=http://<腾讯云公网IP>:5173
```
- [ ] **Step 3: 修改后重启后端**
```bash
sudo systemctl restart forgeflow-backend-dev
```
### Task 23: 数据库连接失败
- [ ] **Step 1: 用 mysql 客户端直连**
```bash
mysql -h 121.40.97.156 -P 3306 -u <数据库用户名> -p -e "SELECT 1;"
```
Expected:
```text
返回 1
```
- [ ] **Step 2: 如果 MySQL 客户端通,但后端 health 不通**
检查:
```bash
grep MYSQL /opt/ForgeFlow-ERP/backend/.env
journalctl -u forgeflow-backend-dev -n 120 --no-pager
```
处理方向:
```text
数据库名、账号、密码、账号 Host 权限、SQLAlchemy 连接字符串。
```
---
## Phase 10: 临时阶段转正式生产阶段
临时测试稳定后,再做以下切换。
### Task 24: 正式化前端
- [ ] **Step 1: 生产构建**
```bash
cd /opt/ForgeFlow-ERP/frontend
npm run build
```
Expected:
```text
dist/ 构建成功
```
- [ ] **Step 2: 用 1Panel OpenResty/Nginx 托管 dist**
站点根目录:
```text
/opt/ForgeFlow-ERP/frontend/dist
```
### Task 25: 正式化后端
- [ ] **Step 1: 后端改为只监听本机**
正式阶段后端不再暴露公网端口:
```text
127.0.0.1:8000
```
- [ ] **Step 2: systemd 去掉 `--reload`**
正式命令:
```bash
/opt/ForgeFlow-ERP/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000
```
### Task 26: 正式化反向代理
- [ ] **Step 1: 配置 OpenResty/Nginx**
核心规则:
```nginx
location /api/ {
proxy_pass http://127.0.0.1:8000/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
try_files $uri $uri/ /index.html;
}
```
- [ ] **Step 2: 前端正式环境 API 改为相对路径**
```env
VITE_API_BASE_URL=/api
```
### Task 27: 正式化安全策略
- [ ] **Step 1: 关闭临时公网端口**
腾讯云安全组和服务器防火墙关闭:
```text
5173/tcp
8000/tcp
```
只保留:
```text
80/tcp
443/tcp
22/tcp
```
- [ ] **Step 2: 配置域名和 HTTPS**
```text
ERP 正式访问地址https://<正式域名>
```
- [ ] **Step 3: 数据库账号最小权限**
正式账号只给 ERP 所需库权限:
```sql
CREATE USER 'forgeflow_erp'@'<腾讯云公网IP>' IDENTIFIED BY '<强密码>';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, REFERENCES
ON jiaheng_erp.* TO 'forgeflow_erp'@'<腾讯云公网IP>';
FLUSH PRIVILEGES;
```
---
## Final Verification
- [ ] 腾讯云服务器能访问阿里云 MySQL。
- [ ] `http://<腾讯云公网IP>:8000/api/system/health` 返回后端和数据库正常。
- [ ] `http://<腾讯云公网IP>:5173/login?redirect=/` 能打开登录页。
- [ ] 登录后页面 API 请求没有 CORS 报错。
- [ ] Excel 导入导出正常。
- [ ] 基础资料、订单、采购、仓库、生产、发货页面都能打开。
- [ ] 修改前端代码后 Vite 能热更新。
- [ ] 修改后端代码后 Uvicorn 能自动 reload。
- [ ] 测试期结束后有明确计划关闭公网 `5173``8000`
---
## Recommended Execution Mode
先用 `tmux` 跑通当天部署,再切 `systemd` 守护。
原因:
```text
tmux 启动最快,排错最直观;确认前后端、数据库、跨域都通后,再用 systemd 固化。
```
如果需要我来执行,建议按这个顺序:
```text
1. 先要腾讯云公网 IP、SSH 登录方式、数据库测试账号。
2. 执行 Phase 1 到 Phase 5让系统先能访问。
3. 执行 Phase 8 做业务验收。
4. 验收没问题后执行 Phase 6把进程挂 systemd。
5. 等测试稳定后,再执行 Phase 10 转正式生产配置。
```