Files
huangjingfen/docs/deploy.md
apple ae8b866319 feat(fsgx): 管理后台与部署相关更新
- admin: 路由守卫修复空白页、addRoute、devServer 端口与代理
- admin: package.json 生产构建去掉 NODE_OPTIONS openssl
- ajcaptcha: 滑块验证码改用 file 缓存避免 Redis NOAUTH
- nginx-crmeb: 增加 81 端口站点
- docs: deploy 补充 NOAUTH/Redis 说明,新增 H5 部署脚本与 nginx 示例
- 其他: database、start-api、swoole ini、uniapp 资源等

Made-with: Cursor
2026-03-21 02:33:14 +08:00

467 lines
14 KiB
Markdown
Raw Permalink 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.
# CRMEB Pro v3.5 简化发布部署方案
> 云端 `.env`、数据库、Nginx、Swoole 等已配置完成。本方案将**服务器 API**、**管理后台前端**、**H5 前端**拆分为三个子项目,可**独立执行**对应的发布部署。
---
## 一、部署信息
| 项目 | 值 |
|------|-----|
| 服务器 | `root@182.92.142.158`,密码 `A@123456` |
| 部署根目录 | `/www/wwwroot/hjf.suzhouyuqi.com` |
| 域名 | `hjf.suzhouyuqi.com` |
| 本地项目路径 | `/Users/apple/scott2026/huangjingfen/pro_v3.5.1` |
| 子项目 | 本地路径 | 服务器目标路径 |
|--------|----------|----------------|
| 服务器 API | `pro_v3.5.1/`(排除 view、public/admin | `/www/wwwroot/hjf.suzhouyuqi.com/` |
| 管理后台前端 | `pro_v3.5.1/view/admin/dist/` | `/www/wwwroot/hjf.suzhouyuqi.com/public/admin/` |
| H5 前端 | `pro_v3.5.1/view/uniapp/unpackage/dist/build/web/``.../h5/` | `/www/wwwroot/hjf.suzhouyuqi.com/public/` |
### 云服务器 Nginx 配置要求H5 根路径访问必备)
域名根路径 `https://hjf.suzhouyuqi.com/` 需正确返回 H5 页面。若出现 `Unexpected token '<'`(请求 JS 时返回 HTML通常是 Nginx 未正确提供静态文件。
**必须满足:**
1. **站点 root 指向 public**`root /www/wwwroot/hjf.suzhouyuqi.com/public;`
2. **index 顺序**`index index.html index.php;`(优先 index.html
3. **静态文件优先**:对 `/static/``/assets/``/pages/` 等路径Nginx 应先尝试本地文件,**仅当文件不存在**时才转发到 PHP/Swoole。
**推荐配置示例**(宝塔/ LNMP 站点):
```nginx
server {
listen 80;
listen 443 ssl http2;
server_name hjf.suzhouyuqi.com;
root /www/wwwroot/hjf.suzhouyuqi.com/public;
index index.html index.php;
# 静态资源:直接由 Nginx 提供,不转发到 PHP
location ~ ^/(static|assets|pages)/ {
try_files $uri =404;
expires 7d;
}
# PHP 请求
location ~ \.php$ {
# 转发到 Swoole 或 php-fpm按现有配置
}
# 其余请求:先找静态文件,再走 PHP
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
```
若使用 `if (!-e $request_filename) { proxy_pass ... }`,需确保**文件存在时不会进入 proxy**,否则 `/static/js/xxx.js` 会被错误地返回 HTML。
完整示例见 `docs/nginx-hjf-cloud.conf.example`
---
## 二、子项目一:服务器 API
仅部署后端 PHP 代码app、crmeb、config、route、vendor、public 等),不覆盖管理后台和 H5 前端。
### 方式一:全量同步(先整站备份,再覆盖)
#### 2.1.1 备份(服务器)
```bash
ssh root@182.92.142.158
mkdir -p /www/backup
tar -czvf /www/backup/hjf_api_$(date +%Y%m%d_%H%M%S).tar.gz \
-C /www/wwwroot hjf.suzhouyuqi.com
```
#### 2.1.2 上传(本地)
```bash
cd /Users/apple/scott2026/huangjingfen
rsync -avz --delete \
--exclude='.env' \
--exclude='.git' \
--exclude='node_modules' \
--exclude='view' \
--exclude='public/admin' \
--exclude='public/uploads' \
--exclude='runtime/cache' \
--exclude='runtime/log' \
--exclude='.cursor' \
--exclude='.cursor-cli' \
pro_v3.5.1/ \
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/
```
---
### 方式二:按 Git 版本增量部署(仅上传 git 中有变更的文件)
对比 `origin/main` 与本地工作区,先列出将要上传的文件,再通过 SSH 执行「先备份再上传覆盖」。
#### 2.2.1 步骤一:列出将要上传的文件
```bash
cd /Users/apple/scott2026/huangjingfen
git fetch origin
git diff --name-only origin/main -- pro_v3.5.1/ \
| sed 's|^pro_v3.5.1/||' \
| grep -v '^view' \
| grep -v '^public/admin' \
| grep -v '^public/uploads' \
| grep -v '^runtime/cache' \
| grep -v '^runtime/log' \
| grep -v '\.env$' \
| grep -v '/\.' \
| tee /tmp/hjf_api_changed.txt
```
确认列表无误后,执行步骤二。
#### 2.2.2 步骤二:通过 SSH 发布部署
```bash
cd /Users/apple/scott2026/huangjingfen
# 若无变更则退出
if [ ! -s /tmp/hjf_api_changed.txt ]; then
echo "无 API 相关文件变更,跳过部署"
exit 0
fi
# 创建备份目录SSH 执行)
BACKUP_SUFFIX=$(date +%Y%m%d_%H%M%S)
ssh root@182.92.142.158 "mkdir -p /www/backup/hjf_api_git_${BACKUP_SUFFIX}"
# 通过 rsync over SSH 上传变更文件(覆盖前自动备份到 backup-dir
rsync -avz --backup --backup-dir=/www/backup/hjf_api_git_${BACKUP_SUFFIX} \
--files-from=/tmp/hjf_api_changed.txt \
pro_v3.5.1/ \
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/
```
说明:
- 步骤一用 `tee` 同时输出到屏幕和 `/tmp/hjf_api_changed.txt`,步骤二复用该文件。
-`origin/main` 为基准;可改为 `origin/其他分支``标签名`
- `--backup --backup-dir=...`:覆盖前将服务器上的旧文件移动到备份目录。
- 增量备份目录示例:`/www/backup/hjf_api_git_20260117_143022/`
---
### 2.3 上传后(服务器)
```bash
ssh root@182.92.142.158
supervisorctl restart hjfshop-swoole
cd /www/wwwroot/hjf.suzhouyuqi.com && php think clear
```
---
## 三、子项目二:管理后台前端
仅部署管理后台 Vue 构建产物到 `public/admin/`
### 3.1 本地构建
```bash
cd /Users/apple/scott2026/huangjingfen/pro_v3.5.1/view/admin
npm install # 依赖有变更时执行
npm run build
```
构建产物在 `view/admin/dist/`
### 3.2 备份(服务器)
```bash
ssh root@182.92.142.158
mkdir -p /www/backup
tar -czvf /www/backup/hjf_admin_$(date +%Y%m%d_%H%M%S).tar.gz \
-C /www/wwwroot/hjf.suzhouyuqi.com/public admin
```
### 3.3 上传(本地)
**方式 Arsync**(服务器需已安装 rsync
```bash
cd /Users/apple/scott2026/huangjingfen
rsync -avz --delete \
pro_v3.5.1/view/admin/dist/ \
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/public/admin/
```
**方式 Btar + ssh**(服务器无 rsync 时使用)
```bash
cd /Users/apple/scott2026/huangjingfen
tar czf - -C pro_v3.5.1/view/admin/dist . | \
ssh root@182.92.142.158 "cd /www/wwwroot/hjf.suzhouyuqi.com/public && rm -rf admin && mkdir -p admin && tar xzf - -C admin"
```
### 3.4 上传后修改权限(服务器)
```bash
ssh root@182.92.142.158
chown -R www:www /www/wwwroot/hjf.suzhouyuqi.com/public/admin
chmod -R 775 /www/wwwroot/hjf.suzhouyuqi.com/public/admin
```
### 3.5 验证
浏览器访问 `http://hjf.suzhouyuqi.com/admin/login`,确认页面正常。
### 3.6 本地环境部署
将管理后台前端打包并部署到本机,配合 `nginx-crmeb.conf` 与 Swoole 使用。
**前置条件:**
- Nginx 已加载 `pro_v3.5.1/nginx-crmeb.conf``root` 指向 `pro_v3.5.1/public`80 反代到 20199
- Swoole API 已启动:`./help/start-api.sh``php -d memory_limit=300M think swoole`
**步骤:**
```bash
# 1. 本地构建(同 3.1
cd /Users/apple/scott2026/huangjingfen/pro_v3.5.1/view/admin
npm install # 依赖有变更时执行
npm run build
# 2. 将构建产物复制到 public/admin覆盖旧文件
cd /Users/apple/scott2026/huangjingfen
rm -rf pro_v3.5.1/public/admin
cp -r pro_v3.5.1/view/admin/dist pro_v3.5.1/public/admin
```
或使用 rsync保留权限、便于增量更新
```bash
cd /Users/apple/scott2026/huangjingfen
rsync -av --delete pro_v3.5.1/view/admin/dist/ pro_v3.5.1/public/admin/
```
**验证:**
浏览器访问 `http://127.0.0.1/admin/``http://127.0.0.1/admin/login`,确认管理后台页面正常。
---
## 四、子项目三H5 前端
仅部署 H5 构建产物到 `public/`(站点根目录)。部署时仅覆盖 H5 相关文件,不删除 `admin/``index.php` 等。
### 4.1 本地打包HBuilder 或 npm
**方式 AHBuilder 打包(推荐)**
1. 用 HBuilderX 打开 `pro_v3.5.1/view/uniapp` 项目
2. 确认 `config/app.js``BASE_HOST` 已设为云服务器域名(如 `hjf.suzhouyuqi.com`
3. 菜单:发行 → 网站-H5 手机版(或 Web → 填写网站标题 → 发行
4. 构建产物在 `view/uniapp/unpackage/dist/build/web/``.../build/h5/`
**方式 B命令行构建**
```bash
cd /Users/apple/scott2026/huangjingfen/pro_v3.5.1/view/uniapp
npm install # 依赖有变更时执行
npm run build:h5
```
构建产物在 `view/uniapp/unpackage/dist/build/h5/`
### 4.2 备份(服务器,上传前执行)
上传前在服务器备份 `public` 目录,便于回滚:
```bash
ssh root@182.92.142.158
mkdir -p /www/wwwroot/backup
tar -czvf /www/wwwroot/backup/hjf_public_$(date +%Y%m%d_%H%M%S).tar.gz \
-C /www/wwwroot/hjf.suzhouyuqi.com public
```
> 一键部署脚本 `deploy-h5.sh` 会自动执行此备份后再上传。
### 4.3 上传(本地)
**方式 Arsync**(服务器需已安装 rsync
```bash
cd /Users/apple/scott2026/huangjingfen
rsync -avz \
pro_v3.5.1/view/uniapp/unpackage/dist/build/h5/ \
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/public/
```
> 不使用 `--delete`,避免覆盖或删除 `admin/`、`index.php` 等文件。
**方式 Btar + ssh**(服务器无 rsync 时使用)
```bash
cd /Users/apple/scott2026/huangjingfen
tar czf - -C pro_v3.5.1/view/uniapp/unpackage/dist/build/h5 . | \
ssh root@182.92.142.158 "cd /www/wwwroot/hjf.suzhouyuqi.com/public && tar xzf -"
```
> 仅解压覆盖 H5 文件index.html、static/ 等),不删除 `admin/`。
**方式 Cscp**
```bash
cd /Users/apple/scott2026/huangjingfen
scp -r pro_v3.5.1/view/uniapp/unpackage/dist/build/h5/* \
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/public/
```
### 4.4 上传后修改权限(服务器)
```bash
ssh root@182.92.142.158
chown -R www:www /www/wwwroot/hjf.suzhouyuqi.com/public
chmod -R 755 /www/wwwroot/hjf.suzhouyuqi.com/public
```
> 若仅更新 H5 根目录下的 index.html、static 等,可只对相关路径执行:
> `chown -R www:www /www/wwwroot/hjf.suzhouyuqi.com/public/index.html /www/wwwroot/hjf.suzhouyuqi.com/public/static`
### 4.5 一键部署脚本(本地执行)
脚本 `docs/deploy-h5.sh` 会依次执行:**备份上一版本 → 上传 → 修改权限**。执行前确保已打包好 H5`unpackage/dist/build/web/``h5/` 存在):
```bash
#!/usr/bin/env bash
# H5 前端一键部署到云服务器(需 sshpass或已配置 SSH 免密)
# 支持 HBuilder 导出 web 或 h5 路径
set -e
cd "$(dirname "$0")/.."
REMOTE="root@182.92.142.158"
REMOTE_PUBLIC="/www/wwwroot/hjf.suzhouyuqi.com/public"
BACKUP_DIR="/www/wwwroot/backup"
# 优先使用 web其次 h5
if [ -d "pro_v3.5.1/view/uniapp/unpackage/dist/build/web" ]; then
H5_SRC="pro_v3.5.1/view/uniapp/unpackage/dist/build/web"
elif [ -d "pro_v3.5.1/view/uniapp/unpackage/dist/build/h5" ]; then
H5_SRC="pro_v3.5.1/view/uniapp/unpackage/dist/build/h5"
else
echo "错误:未找到 H5 构建产物,请先用 HBuilder 或 npm run build:h5 打包"
exit 1
fi
echo "备份云服务器 public 目录(上一版本)..."
ssh "$REMOTE" "mkdir -p $BACKUP_DIR && tar -czf $BACKUP_DIR/hjf_public_\$(date +%Y%m%d_%H%M%S).tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com public && echo '备份完成'"
echo "上传 H5 到 $REMOTE:$REMOTE_PUBLIC ..."
tar czf - -C "$H5_SRC" . | ssh "$REMOTE" "cd $REMOTE_PUBLIC && tar xzf -"
echo "修改权限 ..."
ssh "$REMOTE" "chown -R www:www $REMOTE_PUBLIC && chmod -R 755 $REMOTE_PUBLIC"
echo "部署完成,请访问 https://hjf.suzhouyuqi.com/ 验证"
```
用法:
```bash
cd /Users/apple/scott2026/huangjingfen
chmod +x docs/deploy-h5.sh
./docs/deploy-h5.sh
```
若需密码,可安装 `sshpass` 后使用:`SSHPASS='A@123456' sshpass -e ./docs/deploy-h5.sh`
### 4.6 验证
浏览器访问 `http://hjf.suzhouyuqi.com/``https://hjf.suzhouyuqi.com/`,确认 H5 页面正常。
### 4.7 H5 报错 `Unexpected token '<'` 排查
**现象**:访问根路径时控制台报 `index.xxx.js:1 Uncaught SyntaxError: Unexpected token '<'`
**原因**:请求 JS 时服务器返回了 HTML404 页或 index.php 输出)。常见情况:
- **index.html 引用 `/h5/static/...`**:旧版 index 与当前部署路径不一致,`/h5/static/js/xxx.js` 返回 404 → HTML
- **Nginx 未正确提供静态文件**root 未指向 `.../public` 或缺少 `location ~ ^/(static|assets|pages)/`
**排查步骤**
1. **检查 index.html 引用路径**
```bash
curl -s "https://hjf.suzhouyuqi.com/" | grep -oE 'src=[^>]+\.js'
```
若出现 `/h5/static/`,说明服务器 index.html 为旧版,需重新部署。
2. **重新构建并部署**(部署脚本会先清理旧 index.html、static 等):
```bash
# 本地HBuilder 发行 H5 或 npm run build:h5
./docs/deploy-h5.sh
```
3. **确认 Nginx root**:站点 root 必须为 `.../public`,见上文「云服务器 Nginx 配置要求」。
4. **清除浏览器缓存**强制刷新Ctrl+Shift+R或无痕模式访问。
---
## 四(补充)、管理后台登录滑块:`NOAUTH Authentication required`
若访问 `/adminapi/ajcaptcha` 或 `/adminapi/is_captcha` 返回 `{"msg":"NOAUTH Authentication required."}`,说明 **Redis 需要密码但 `.env` 中 `[REDIS]` 的 `PASSWORD` 与服务器 Redis 不一致**(或 Redis 开启了 `requirepass` 而 `.env` 为空)。
**处理:**
1. 在服务器上核对 Redis`redis-cli -h <主机> -p 6379 -a '<实际密码>' ping`,将正确密码写入站点根目录 `.env` 的 `PASSWORD = ...`。
2. 重启 Swoole / PHP 进程使配置生效。
3. 项目已把 **滑块验证码ajcaptcha缓存改为本地 file**,不依赖 Redis 认证;部署后请同步更新 `config/ajcaptcha.php`。登录次数统计等仍走 Redis**长期仍须修正 Redis 配置**。
---
## 五、发布检查汇总
| 子项目 | 检查项 |
|--------|--------|
| API | `supervisorctl status hjfshop-swoole` 为 RUNNING`curl http://hjf.suzhouyuqi.com/adminapi/login/info` 返回 JSON |
| 管理后台 | `http://hjf.suzhouyuqi.com/admin/login` 可打开;登录后无「暂未授权」提示 |
| H5 | `http://hjf.suzhouyuqi.com/` 可打开 |
---
## 六、回滚
按备份文件名中的时间戳选择对应子项目备份恢复:
```bash
ssh root@182.92.142.158
# 回滚 API整站
cd /www/wwwroot
rm -rf hjf.suzhouyuqi.com
tar -xzvf /www/backup/hjf_api_YYYYMMDD_HHMMSS.tar.gz
supervisorctl restart hjfshop-swoole
# 回滚管理后台(仅 public/admin
rm -rf /www/wwwroot/hjf.suzhouyuqi.com/public/admin
tar -xzvf /www/backup/hjf_admin_YYYYMMDD_HHMMSS.tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com/public
# 回滚 H5恢复 public/ 目录)
rm -rf /www/wwwroot/hjf.suzhouyuqi.com/public
tar -xzvf /www/wwwroot/backup/hjf_public_YYYYMMDD_HHMMSS.tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com
```