chore: initial baseline with P0-safety .gitignore
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
# 企微IT智能服务台 — 服务器部署指南
|
||||
|
||||
> 目标服务器:`10.90.5.110`(Linux)
|
||||
> 域名:`itsupport.servyou.com.cn`
|
||||
> 更新日期:2026-06-12
|
||||
|
||||
---
|
||||
|
||||
## 一、前置条件
|
||||
|
||||
- [x] 服务器可访问内网(火绒 `huorong.oa.servyou-it.com`、Dify `yw-dify.dc.servyou-it.com`)
|
||||
- [ ] 服务器已安装 Docker + Docker Compose
|
||||
- [ ] 域名 `itsupport.servyou.com.cn` DNS 已解析到 `10.90.5.110`(或先用 IP 访问)
|
||||
|
||||
---
|
||||
|
||||
## 二、安装 Docker(如已安装跳过)
|
||||
|
||||
### 2.1 检查是否已安装
|
||||
|
||||
```bash
|
||||
docker --version # 应显示 Docker version 24.x+
|
||||
docker compose version # 应显示 Docker Compose version v2.x+
|
||||
```
|
||||
|
||||
如果已安装,跳到第三步。
|
||||
|
||||
### 2.2 安装 Docker(CentOS/RHEL)
|
||||
|
||||
```bash
|
||||
# 1. 卸载旧版本(如有)
|
||||
sudo yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
|
||||
|
||||
# 2. 安装 yum 工具
|
||||
sudo yum install -y yum-utils
|
||||
|
||||
# 3. 添加 Docker 官方仓库(国内用阿里云镜像加速)
|
||||
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
||||
|
||||
# 4. 安装 Docker Engine + Compose 插件
|
||||
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# 5. 启动 Docker 并设置开机自启
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# 6. 验证安装
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### 2.3 安装 Docker(Ubuntu/Debian)
|
||||
|
||||
```bash
|
||||
# 1. 卸载旧版本
|
||||
sudo apt-get remove -y docker docker-engine docker.io containerd runc
|
||||
|
||||
# 2. 安装依赖
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates curl gnupg
|
||||
|
||||
# 3. 添加 Docker GPG 密钥
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# 4. 添加仓库
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# 5. 安装
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# 6. 启动
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# 7. 验证
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### 2.4(可选)非 root 用户使用 Docker
|
||||
|
||||
```bash
|
||||
# 将当前用户加入 docker 组,避免每次 sudo
|
||||
sudo usermod -aG docker $USER
|
||||
# 重新登录生效
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、上传部署包
|
||||
|
||||
### 3.1 在服务器创建目录
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/wecom-it-desk
|
||||
sudo chown $USER:$USER /opt/wecom-it-desk
|
||||
```
|
||||
|
||||
### 3.2 上传文件
|
||||
|
||||
在本地 Windows 用 SCP/SFTP 上传部署包:
|
||||
|
||||
```powershell
|
||||
# 方法1:用 scp 命令(Git Bash 或 PowerShell)
|
||||
scp it-smart-desk-server-deploy.zip user@10.90.5.110:/opt/wecom-it-desk/
|
||||
|
||||
# 方法2:用 WinSCP / FileZilla 图形化工具上传
|
||||
```
|
||||
|
||||
### 3.3 解压
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
unzip it-smart-desk-server-deploy.zip
|
||||
# 解压后目录结构:
|
||||
# /opt/wecom-it-desk/
|
||||
# ├── docker-compose.yml
|
||||
# ├── .env
|
||||
# ├── nginx/
|
||||
# │ └── nginx.conf
|
||||
# ├── backend/
|
||||
# │ ├── Dockerfile
|
||||
# │ ├── app/
|
||||
# │ ├── alembic/
|
||||
# │ ├── alembic.ini
|
||||
# │ └── requirements.txt
|
||||
# ├── frontend-h5/dist/
|
||||
# ├── frontend-agent/dist/
|
||||
# └── frontend-admin/dist/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、修改配置
|
||||
|
||||
### 4.1 编辑环境变量
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
vim .env
|
||||
```
|
||||
|
||||
**必须确认的配置项:**
|
||||
|
||||
| 配置项 | 当前值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `WECOM_CORP_ID` | `wwa8c87970b2011f41` | 企微企业ID |
|
||||
| `WECOM_AGENT_ID` | `1000133` | 企微应用AgentId |
|
||||
| `WECOM_SECRET` | `EOtQsl...` | 企微应用Secret |
|
||||
| `MOCK_LOGIN_ENABLED` | `true` | 测试阶段用 true,正式上线改为 false |
|
||||
| `DIFY_API_KEY` | `http://...` | Dify AI 服务 Key |
|
||||
| `POSTGRES_PASSWORD` | `wecom_secret_2026` | 数据库密码(首次初始化后不可改) |
|
||||
|
||||
### 4.2 确认域名解析
|
||||
|
||||
```bash
|
||||
# 测试域名是否指向本机
|
||||
ping itsupport.servyou.com.cn
|
||||
# 如果还没配 DNS,可以先在 .env 中把 CORS_ORIGINS 改为:
|
||||
# CORS_ORIGINS=http://10.90.5.110
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、启动服务
|
||||
|
||||
### 5.1 首次启动
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 构建后端镜像 + 启动所有容器
|
||||
docker compose up -d --build
|
||||
|
||||
# 首次启动需要 2-3 分钟(下载镜像 + 构建后端 + 数据库迁移)
|
||||
```
|
||||
|
||||
### 5.2 查看启动状态
|
||||
|
||||
```bash
|
||||
# 查看所有容器状态(应全部 healthy/running)
|
||||
docker compose ps
|
||||
|
||||
# 查看实时日志(Ctrl+C 退出)
|
||||
docker compose logs -f
|
||||
|
||||
# 只看后端日志
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
**预期输出(`docker compose ps`):**
|
||||
|
||||
```
|
||||
NAME STATUS PORTS
|
||||
wecom_it_postgres Up (healthy) 5432/tcp
|
||||
wecom_it_redis Up (healthy) 6379/tcp
|
||||
wecom_it_backend Up (healthy) 8000/tcp
|
||||
wecom_it_nginx Up (healthy) 0.0.0.0:80->80/tcp
|
||||
```
|
||||
|
||||
### 5.3 验证服务
|
||||
|
||||
```bash
|
||||
# 1. 健康检查
|
||||
curl http://localhost/itdesk/health
|
||||
# 预期:healthy
|
||||
|
||||
# 2. 后端 API
|
||||
curl http://localhost/api/health
|
||||
# 预期:{"status":"ok"}
|
||||
|
||||
# 3. 浏览器访问
|
||||
# H5 员工端:http://itsupport.servyou.com.cn/itdesk/
|
||||
# 坐席工作台:http://itsupport.servyou.com.cn/itagent/
|
||||
# 管理后台:http://itsupport.servyou.com.cn/itadmin/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、常用运维命令
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 重启所有服务
|
||||
docker compose restart
|
||||
|
||||
# 只重启后端(代码更新后)
|
||||
docker compose restart backend
|
||||
|
||||
# 查看某个容器的日志
|
||||
docker compose logs -f --tail=100 backend
|
||||
|
||||
# 进入后端容器调试
|
||||
docker compose exec backend /bin/sh
|
||||
|
||||
# 停止所有服务
|
||||
docker compose down
|
||||
|
||||
# 停止并删除数据卷(⚠️ 会清空数据库!)
|
||||
docker compose down -v
|
||||
|
||||
# 查看磁盘使用
|
||||
docker system df
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、代码更新流程
|
||||
|
||||
当有新代码需要部署时:
|
||||
|
||||
```bash
|
||||
# 1. 上传新的部署包,覆盖旧文件
|
||||
# 2. 重新构建并启动
|
||||
cd /opt/wecom-it-desk
|
||||
docker compose up -d --build
|
||||
|
||||
# 如果只有前端更新,不需要重建后端镜像:
|
||||
docker compose up -d --no-deps --build nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、故障排查
|
||||
|
||||
| 问题 | 排查命令 | 常见原因 |
|
||||
|------|----------|----------|
|
||||
| 容器反复重启 | `docker compose logs backend` | 数据库连接失败、环境变量缺失 |
|
||||
| 页面空白 | `docker compose logs nginx` | 前端 dist 目录为空或路径错误 |
|
||||
| API 404 | `curl http://localhost:8000/health` | 后端未启动或 nginx proxy 配置错误 |
|
||||
| 数据库连接失败 | `docker compose logs postgres` | POSTGRES_PASSWORD 与 DATABASE_URL 不一致 |
|
||||
| 端口被占用 | `sudo lsof -i :80` | 其他服务占用 80 端口 |
|
||||
|
||||
---
|
||||
|
||||
## 九、安全建议(后续)
|
||||
|
||||
- [ ] 配置 HTTPS(Nginx 反代 + 证书,或使用反向代理)
|
||||
- [ ] 修改默认数据库密码
|
||||
- [ ] 关闭 Mock 登录(`MOCK_LOGIN_ENABLED=false`)
|
||||
- [ ] 限制 80 端口访问来源(防火墙规则)
|
||||
@@ -0,0 +1,452 @@
|
||||
# IT智能服务台 — 新服务器部署手册
|
||||
|
||||
> **目标服务器**:`10.80.0.136`(公司内网)
|
||||
> **域名**:`itsupport.servyou.com.cn`
|
||||
> **访问方式**:通过堡垒机 `10.212.189.210:2222`(用户 `sxn`,OTP 动态口令认证)
|
||||
> **Docker**:已安装
|
||||
> **部署方式**:Docker Compose(4容器:nginx + backend + postgres + redis)
|
||||
|
||||
---
|
||||
|
||||
## 一、前置条件检查清单
|
||||
|
||||
| 条件 | 状态 | 验证命令 |
|
||||
|------|------|---------|
|
||||
| Linux 服务器 10.80.0.136 | ✅ 已确认 | — |
|
||||
| Docker 已安装 | ✅ 已确认 | `docker --version` |
|
||||
| Docker Compose V2 | 待确认 | `docker compose version` |
|
||||
| 端口 80 未被占用 | 待确认 | `ss -tlnp \| grep :80` |
|
||||
| DNS 解析 | 待配置 | `nslookup itsupport.servyou.com.cn` |
|
||||
| 堡垒机可访问 | 待确认 | `ssh -p 2222 user@10.212.189.210` |
|
||||
|
||||
---
|
||||
|
||||
## 二、SSH 通过堡垒机连接
|
||||
|
||||
### 2.1 什么是堡垒机?
|
||||
|
||||
堡垒机(跳板机)是公司内网的安全访问入口。你不能直接 SSH 到目标服务器,必须先登录堡垒机,再从堡垒机跳转到目标服务器。OTP(One-Time Password)是指每次登录需要输入动态验证码(通常来自手机令牌 App)。
|
||||
|
||||
### 2.2 连接方式
|
||||
|
||||
```bash
|
||||
# 方式一:ssh -J 一步跳转(推荐)
|
||||
# -J 指定跳板机,ssh 会自动帮你跳转
|
||||
# 堡垒机端口 2222,需要输入 OTP 动态口令
|
||||
ssh -J sxn@10.212.189.210:2222 sxn@10.80.0.136
|
||||
|
||||
# 方式二:先登录堡垒机,再手动跳转
|
||||
ssh -p 2222 sxn@10.212.189.210
|
||||
# 输入 OTP 动态口令
|
||||
# 登录成功后:
|
||||
ssh sxn@10.80.0.136
|
||||
```
|
||||
|
||||
### 2.3 配置 SSH 快捷方式(推荐)
|
||||
|
||||
在开发机上编辑 `~/.ssh/config`,添加以下内容,以后只需要 `ssh itdesk` 即可:
|
||||
|
||||
```
|
||||
# 堡垒机
|
||||
Host bastion
|
||||
HostName 10.212.189.210
|
||||
Port 2222
|
||||
User sxn
|
||||
|
||||
# IT智能服务台服务器
|
||||
Host itdesk
|
||||
HostName 10.80.0.136
|
||||
User sxn
|
||||
ProxyJump bastion
|
||||
```
|
||||
|
||||
> **堡垒机用户名为 `sxn`,已填入下方命令中**
|
||||
|
||||
之后只需:
|
||||
```bash
|
||||
ssh itdesk # 自动通过堡垒机跳转
|
||||
scp file itdesk:/opt/ # 文件传输也会自动走堡垒机
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、文件传输(通过堡垒机)
|
||||
|
||||
### 3.1 SCP 传输(推荐小文件/单次传输)
|
||||
|
||||
```bash
|
||||
# 上传单个文件
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
it-smart-desk-server-deploy.zip \
|
||||
sxn@10.80.0.136:/opt/
|
||||
|
||||
# 如果已配置 ~/.ssh/config:
|
||||
scp it-smart-desk-server-deploy.zip itdesk:/opt/
|
||||
```
|
||||
|
||||
### 3.2 大文件传输优化
|
||||
|
||||
部署包可能较大(含后端源码 + 前端产物),如果 SCP 速度慢,可以先传到堡垒机再转:
|
||||
|
||||
```bash
|
||||
# 步骤1:传到堡垒机
|
||||
scp -P 2222 it-smart-desk-server-deploy.zip sxn@10.212.189.210:/tmp/
|
||||
|
||||
# 步骤2:SSH 到堡垒机
|
||||
ssh -p 2222 sxn@10.212.189.210
|
||||
|
||||
# 步骤3:从堡垒机传到目标服务器
|
||||
scp /tmp/it-smart-desk-server-deploy.zip sxn@10.80.0.136:/opt/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、部署步骤(完整流程)
|
||||
|
||||
### 步骤 1:在开发机上构建前端并打包
|
||||
|
||||
```bash
|
||||
# 在开发机(Windows)上,进入项目根目录
|
||||
cd D:\资料\03-项目开发\wecom_it_smart_desk
|
||||
|
||||
# 方法A:使用打包脚本(自动构建前端 + 组装 + 打包)
|
||||
bash deploy-server/package.sh
|
||||
|
||||
# 方法B:手动构建
|
||||
# H5 员工端
|
||||
cd frontend-h5
|
||||
npm install && npm run build
|
||||
|
||||
# 坐席工作台
|
||||
cd ../frontend-agent
|
||||
npm install && npm run build
|
||||
|
||||
# 手动打包(如果不用 package.sh)
|
||||
# 需要把 frontend-h5/dist/、frontend-agent/dist/、backend/、deploy-server/ 下的配置文件一起打包
|
||||
```
|
||||
|
||||
打包完成后,项目根目录下会生成 `it-smart-desk-server-deploy.zip`。
|
||||
|
||||
### 步骤 2:上传部署包到服务器
|
||||
|
||||
```bash
|
||||
# 在开发机上执行
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
it-smart-desk-server-deploy.zip \
|
||||
sxn@10.80.0.136:/tmp/
|
||||
```
|
||||
|
||||
> 上传到 `/tmp/` 而非 `/opt/`,因为普通用户对 `/opt/` 没有写权限
|
||||
|
||||
### 步骤 3:SSH 登录服务器并解压
|
||||
|
||||
```bash
|
||||
# 登录目标服务器
|
||||
ssh -J sxn@10.212.189.210:2222 sxn@10.80.0.136
|
||||
|
||||
# 切换 root(普通用户对 /opt 无写权限)
|
||||
sudo -i
|
||||
|
||||
# 移动并解压部署包
|
||||
mv /tmp/it-smart-desk-server-deploy.zip /opt/
|
||||
cd /opt
|
||||
unzip it-smart-desk-server-deploy.zip
|
||||
|
||||
# 重命名目录为更简短的名称
|
||||
mv it-smart-desk-server-deploy wecom-it-desk
|
||||
cd wecom-it-desk
|
||||
```
|
||||
|
||||
### 步骤 4:配置环境变量
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 从模板创建 .env
|
||||
cp .env.example .env
|
||||
|
||||
# 编辑 .env
|
||||
vi .env
|
||||
```
|
||||
|
||||
**阶段一(Mock 模式)最小配置** — 只需确认以下默认值:
|
||||
|
||||
```ini
|
||||
# 数据库密码(默认即可,首次初始化后不可更改)
|
||||
POSTGRES_PASSWORD=wecom_secret_2024
|
||||
|
||||
# 企微配置(阶段一 Mock 模式可以留空)
|
||||
WECOM_CORP_ID=
|
||||
WECOM_AGENT_ID=1000002
|
||||
WECOM_SECRET=
|
||||
WECOM_TOKEN=
|
||||
WECOM_ENCODING_AES_KEY=
|
||||
|
||||
# Mock 登录(阶段一设为 true)
|
||||
MOCK_LOGIN_ENABLED=true
|
||||
|
||||
# Dify AI(暂时可以留空)
|
||||
DIFY_API_URL=http://yw-dify.dc.servyou-it.com/dify2openai/v1/chat/completions
|
||||
DIFY_API_KEY=
|
||||
```
|
||||
|
||||
> **重要**:`POSTGRES_PASSWORD` 首次启动时写入数据库,之后修改 `.env` 不会生效。如需修改密码,必须删除数据卷重建。
|
||||
|
||||
### 步骤 5:部署
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 添加执行权限
|
||||
chmod +x deploy.sh
|
||||
|
||||
# 执行部署
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
1. ✅ 检查 Docker 环境
|
||||
2. ✅ 检查 .env 配置
|
||||
3. ✅ 检查前端文件
|
||||
4. ✅ 构建后端 Docker 镜像
|
||||
5. ✅ 启动 4 个容器
|
||||
6. ✅ 等待服务就绪
|
||||
7. ✅ 验证部署
|
||||
|
||||
### 步骤 6:验证部署
|
||||
|
||||
```bash
|
||||
# 在服务器上验证
|
||||
curl http://localhost/api/health
|
||||
# 应返回 {"status":"healthy"}
|
||||
|
||||
curl http://localhost/itdesk/
|
||||
# 应返回 H5 前端 HTML
|
||||
|
||||
# 查看所有容器状态
|
||||
docker compose ps
|
||||
# 应显示 4 个容器都是 Up 状态
|
||||
|
||||
# 如果有容器未启动,查看日志
|
||||
docker compose logs --tail 50 backend
|
||||
docker compose logs --tail 50 postgres
|
||||
```
|
||||
|
||||
### 步骤 7:配置 DNS
|
||||
|
||||
需要联系公司 IT 运维,在公司 DNS 上添加 A 记录:
|
||||
|
||||
```
|
||||
itsupport.servyou.com.cn A 10.80.0.136
|
||||
```
|
||||
|
||||
**DNS 未生效前**,可以通过本地 hosts 文件测试:
|
||||
|
||||
```
|
||||
# Windows: C:\Windows\System32\drivers\etc\hosts
|
||||
# macOS/Linux: /etc/hosts
|
||||
# 添加一行:
|
||||
10.80.0.136 itsupport.servyou.com.cn
|
||||
```
|
||||
|
||||
> 注意:修改 hosts 文件后,浏览器可能有 DNS 缓存。Chrome 可访问 `chrome://net-internals/#dns` 清除缓存,或用无痕窗口测试。
|
||||
|
||||
### 步骤 8:浏览器验证
|
||||
|
||||
DNS 生效后(或配置了本地 hosts),在浏览器中访问:
|
||||
|
||||
| 页面 | URL | 预期结果 |
|
||||
|------|-----|---------|
|
||||
| H5 员工端 | `http://itsupport.servyou.com.cn/itdesk/` | 看到登录页面 |
|
||||
| 坐席工作台 | `http://itsupport.servyou.com.cn/itagent/` | 看到坐席工作台 |
|
||||
| API 健康检查 | `http://itsupport.servyou.com.cn/api/health` | `{"status":"healthy"}` |
|
||||
|
||||
**Mock 登录测试**:
|
||||
1. 访问 `http://itsupport.servyou.com.cn/itdesk/login`
|
||||
2. 输入任意工号和姓名(如 `test001` / `测试用户`)
|
||||
3. 应成功登录并进入聊天页面
|
||||
|
||||
---
|
||||
|
||||
## 五、部署文件结构
|
||||
|
||||
```
|
||||
/opt/wecom-it-desk/
|
||||
├── docker-compose.yml # Docker Compose 配置(4容器)
|
||||
├── .env # 环境变量(已配置)
|
||||
├── .env.example # 环境变量模板
|
||||
├── deploy.sh # 一键部署脚本
|
||||
├── README.md # 本手册
|
||||
├── nginx/
|
||||
│ └── nginx.conf # Nginx 配置(反代 + 静态文件)
|
||||
├── backend/
|
||||
│ ├── Dockerfile # 后端镜像构建文件
|
||||
│ ├── requirements.txt # Python 依赖
|
||||
│ └── app/ # 后端源代码
|
||||
├── frontend-h5/
|
||||
│ └── dist/ # H5 员工端构建产物
|
||||
└── frontend-agent/
|
||||
└── dist/ # 坐席工作台构建产物
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、常用运维命令
|
||||
|
||||
在服务器上 `/opt/wecom-it-desk` 目录下执行:
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 查看服务状态 | `./deploy.sh status` |
|
||||
| 查看后端日志 | `./deploy.sh logs` |
|
||||
| 停止所有服务 | `./deploy.sh stop` |
|
||||
| 重新构建后端 | `./deploy.sh rebuild` |
|
||||
| 重置数据库 | `./deploy.sh reset-db` |
|
||||
| 手动启动 | `docker compose up -d` |
|
||||
| 手动停止 | `docker compose down` |
|
||||
| 只重启后端 | `docker compose restart backend` |
|
||||
| 查看数据库 | `docker exec -it wecom_it_postgres psql -U wecom -d wecom_it_desk` |
|
||||
| 查看 Redis | `docker exec -it wecom_it_redis redis-cli` |
|
||||
| 重载 Nginx | `docker exec wecom_it_nginx nginx -s reload` |
|
||||
| 查看容器日志 | `docker compose logs --tail 50 <容器名>` |
|
||||
|
||||
---
|
||||
|
||||
## 七、升级前端
|
||||
|
||||
当有新的前端版本需要部署时:
|
||||
|
||||
```bash
|
||||
# 1. 在开发机上构建新版本
|
||||
cd frontend-h5 && npm run build
|
||||
cd frontend-agent && npm run build
|
||||
|
||||
# 2. 上传到服务器(通过堡垒机)
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r frontend-h5/dist/ \
|
||||
sxn@10.80.0.136:/opt/wecom-it-desk/frontend-h5/dist/
|
||||
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r frontend-agent/dist/ \
|
||||
sxn@10.80.0.136:/opt/wecom-it-desk/frontend-agent/dist/
|
||||
|
||||
# 3. 重载 Nginx(不需要重启整个服务)
|
||||
ssh itdesk # 如果已配置 SSH 快捷方式
|
||||
cd /opt/wecom-it-desk
|
||||
docker exec wecom_it_nginx nginx -s reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、升级后端
|
||||
|
||||
```bash
|
||||
# 1. 上传新代码到服务器
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r backend/ \
|
||||
sxn@10.80.0.136:/opt/wecom-it-desk/backend/
|
||||
|
||||
# 2. 重新构建并启动
|
||||
ssh itdesk
|
||||
cd /opt/wecom-it-desk
|
||||
./deploy.sh rebuild
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、故障排查
|
||||
|
||||
### 后端容器一直重启
|
||||
|
||||
```bash
|
||||
# 1. 查看容器状态
|
||||
docker compose ps
|
||||
|
||||
# 2. 查看后端日志(最常见原因:数据库连接失败)
|
||||
docker compose logs --tail 100 backend
|
||||
|
||||
# 3. 检查 PostgreSQL 是否健康
|
||||
docker exec wecom_it_postgres pg_isready -U wecom -d wecom_it_desk
|
||||
|
||||
# 4. 检查 Redis 是否健康
|
||||
docker exec wecom_it_redis redis-cli ping
|
||||
```
|
||||
|
||||
### PostgreSQL 密码错误
|
||||
|
||||
```bash
|
||||
# ⚠️ 这会清空所有数据!只有首次部署密码错误时才需要
|
||||
docker compose down
|
||||
docker volume rm wecom-it-desk_postgres_data
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### H5/坐席端白屏
|
||||
|
||||
```bash
|
||||
# 检查前端文件是否存在
|
||||
docker exec wecom_it_nginx ls /usr/share/nginx/html/itdesk/
|
||||
docker exec wecom_it_nginx ls /usr/share/nginx/html/itagent/
|
||||
|
||||
# 检查 index.html 中的 base 路径是否正确
|
||||
docker exec wecom_it_nginx cat /usr/share/nginx/html/itdesk/index.html | grep /itdesk/
|
||||
docker exec wecom_it_nginx cat /usr/share/nginx/html/itagent/index.html | grep /itagent/
|
||||
```
|
||||
|
||||
### DNS 未生效
|
||||
|
||||
```bash
|
||||
# 在服务器上验证
|
||||
nslookup itsupport.servyou.com.cn
|
||||
|
||||
# 如果 DNS 未配置,临时用 IP 直接访问
|
||||
curl http://10.80.0.136/itdesk/
|
||||
curl http://10.80.0.136/api/health
|
||||
```
|
||||
|
||||
### Mock 登录返回 401
|
||||
|
||||
```bash
|
||||
# 1. 确认 .env 中 MOCK_LOGIN_ENABLED=true
|
||||
cat /opt/wecom-it-desk/.env | grep MOCK
|
||||
|
||||
# 2. 检查后端日志
|
||||
docker compose logs --tail 50 backend | grep mock
|
||||
|
||||
# 3. 直接测试 mock-login 接口
|
||||
curl -X POST http://localhost/api/h5/mock-login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"employee_id":"test001","employee_name":"测试用户"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、HTTPS 配置(可选)
|
||||
|
||||
如果公司要求 HTTPS,有两种方式:
|
||||
|
||||
### 方式一:公司统一 SSL 终端(推荐)
|
||||
|
||||
```
|
||||
客户端 → HTTPS → 公司SSL终端(F5/网关) → HTTP → 10.80.0.136:80
|
||||
```
|
||||
|
||||
不需要在本服务器上配置证书。联系运维配置 SSL 终端即可。
|
||||
|
||||
### 方式二:本机 SSL
|
||||
|
||||
编辑 `nginx/nginx.conf`,取消 HTTPS server 块注释,配置证书路径。
|
||||
|
||||
---
|
||||
|
||||
## 十一、与 NAS 部署的差异
|
||||
|
||||
| 维度 | NAS 部署(10.80.0.136 旧) | 新服务器部署(10.80.0.136 新) |
|
||||
|------|---------------------------|-------------------------------|
|
||||
| 容器数量 | 5个(含 cloudflared) | 4个(无 cloudflared) |
|
||||
| 外网访问 | Cloudflare Tunnel | 公司 DNS 直连 |
|
||||
| 域名 | itdesk.amanzac.com | itsupport.servyou.com.cn |
|
||||
| SSL | Cloudflare 自动 | 无(内网 HTTP)或公司统一 SSL |
|
||||
| 数据平台反代 | 需要(共用域名) | 不需要(独立域名) |
|
||||
| 部署目录 | `/volume1/docker/wecom-it-desk` | `/opt/wecom-it-desk` |
|
||||
| 文件传输 | File Station / 7z | SCP 通过堡垒机 |
|
||||
@@ -0,0 +1,277 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 打包 + 构建后端镜像 + 部署脚本
|
||||
# =============================================================================
|
||||
# 功能:
|
||||
# 1. 打包前端构建产物 + nginx配置 + docker-compose.yml + .env
|
||||
# 2. 构建后端 Docker 镜像(修复 AIHandler 后)
|
||||
# 3. 导出镜像为 tar 文件
|
||||
# 4. 一键部署到服务器(可选)
|
||||
# 用法:
|
||||
# .\build-and-deploy.ps1 -Mode local # 仅本地打包
|
||||
# .\build-and-deploy.ps1 -Mode deploy # 打包 + 部署到服务器
|
||||
# =============================================================================
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[ValidateSet("local", "deploy")]
|
||||
[string]$Mode = "local",
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$ServerHost = "10.90.5.110"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$projectRoot = "D:\资料\03-项目开发\wecom_it_smart_desk"
|
||||
$deployDir = "$projectRoot\deploy-server"
|
||||
$packageDir = "$deployDir\_package"
|
||||
$zipFile = "$deployDir\it-smart-desk-server-deploy.zip"
|
||||
$backendTar = "$deployDir\deploy-backend.tar"
|
||||
|
||||
# 彩色输出函数
|
||||
function Write-Step {
|
||||
param([string]$Text)
|
||||
Write-Host "[STEP] $Text" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function Write-Success {
|
||||
param([string]$Text)
|
||||
Write-Host "[OK] $Text" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Write-Warn {
|
||||
param([string]$Text)
|
||||
Write-Host "[WARN] $Text" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
function Write-Error {
|
||||
param([string]$Text)
|
||||
Write-Host "[ERROR] $Text" -ForegroundColor Red
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " 企微IT智能服务台 — 打包部署自动化" -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " 模式:$Mode" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 1: 清理旧打包目录
|
||||
# =============================================================================
|
||||
Write-Step "清理旧打包目录..."
|
||||
if (Test-Path $packageDir) {
|
||||
Remove-Item $packageDir -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Path $packageDir -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path "$packageDir\nginx" -Force | Out-Null
|
||||
Write-Success "清理完成"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 2: 复制 docker-compose.yml
|
||||
# =============================================================================
|
||||
Write-Step "复制 docker-compose.yml..."
|
||||
Copy-Item "$deployDir\docker-compose.yml" "$packageDir\docker-compose.yml"
|
||||
Write-Success "已复制"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 3: 复制 .env(含真实配置)
|
||||
# =============================================================================
|
||||
Write-Step "复制 .env..."
|
||||
if (Test-Path "$deployDir\.env") {
|
||||
Copy-Item "$deployDir\.env" "$packageDir\.env"
|
||||
Write-Success "已复制"
|
||||
} else {
|
||||
Write-Warn ".env 文件不存在,跳过"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 4: 复制 nginx 配置
|
||||
# =============================================================================
|
||||
Write-Step "复制 nginx 配置..."
|
||||
Copy-Item "$deployDir\nginx.conf" "$packageDir\nginx\nginx.conf"
|
||||
Write-Success "已复制"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 5: 复制后端代码(排除 __pycache__、.pyc)
|
||||
# =============================================================================
|
||||
Write-Step "复制后端代码..."
|
||||
$backendSrc = "$projectRoot\backend"
|
||||
$backendDst = "$packageDir\backend"
|
||||
New-Item -ItemType Directory -Path $backendDst -Force | Out-Null
|
||||
|
||||
$backendFiles = @("Dockerfile", "requirements.txt", "alembic.ini", "alembic", "app")
|
||||
foreach ($item in $backendFiles) {
|
||||
$src = "$backendSrc\$item"
|
||||
if (Test-Path $src) {
|
||||
if ((Get-Item $src).PSIsContainer) {
|
||||
robocopy $src "$backendDst\$item" /E /XD __pycache__ /XF *.pyc *.db /NFL /NDL /NJH /NJS /NC /NS /NP | Out-Null
|
||||
} else {
|
||||
Copy-Item $src "$backendDst\$item"
|
||||
}
|
||||
}
|
||||
}
|
||||
$backendFileCount = (Get-ChildItem $backendDst -Recurse -File).Count
|
||||
Write-Success "已复制 $backendFileCount 个文件"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 6: 复制前端构建产物
|
||||
# =============================================================================
|
||||
Write-Step "复制前端构建产物..."
|
||||
@("frontend-h5", "frontend-agent", "frontend-admin", "frontend-portal") | ForEach-Object {
|
||||
$src = "$projectRoot\$_\dist"
|
||||
$dst = "$packageDir\$_\dist"
|
||||
if (Test-Path $src) {
|
||||
New-Item -ItemType Directory -Path $dst -Force | Out-Null
|
||||
robocopy $src $dst /E /NFL /NDL /NJH /NJS /NC /NS /NP | Out-Null
|
||||
$count = (Get-ChildItem $dst -Recurse -File).Count
|
||||
Write-Host " $_ : $count files" -ForegroundColor Gray
|
||||
} else {
|
||||
Write-Host " $_ : dist not found, skipping" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
Write-Success "前端构建产物复制完成"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 7: 打包成 zip
|
||||
# =============================================================================
|
||||
Write-Step "打包成 zip..."
|
||||
if (Test-Path $zipFile) {
|
||||
Remove-Item $zipFile -Force
|
||||
}
|
||||
Compress-Archive -Path "$packageDir\*" -DestinationPath $zipFile -CompressionLevel Optimal
|
||||
$zipSize = [math]::Round((Get-Item $zipFile).Length / 1MB, 2)
|
||||
Write-Success "zip 打包完成: $zipSize MB"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 8: 构建后端 Docker 镜像
|
||||
# =============================================================================
|
||||
Write-Step "构建后端 Docker 镜像..."
|
||||
Write-Host " 镜像名: wecom-it-desk-backend:latest" -ForegroundColor Gray
|
||||
|
||||
# 先检查 Docker 是否运行
|
||||
$docker ps > $null 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Docker 未运行,请先启动 Docker Desktop"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 构建镜像
|
||||
$buildStart = Get-Date
|
||||
docker build -t wecom-it-desk-backend:latest "$packageDir\backend" 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Docker 镜像构建失败"
|
||||
exit 1
|
||||
}
|
||||
$buildTime = ((Get-Date) - $buildStart).TotalSeconds
|
||||
Write-Success "镜像构建完成 (耗时: $([math]::Round($buildTime, 1))s)"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 9: 导出镜像为 tar
|
||||
# =============================================================================
|
||||
Write-Step "导出镜像为 tar..."
|
||||
if (Test-Path $backendTar) {
|
||||
Remove-Item $backendTar -Force
|
||||
}
|
||||
docker save -o $backendTar wecom-it-desk-backend:latest
|
||||
$tarSize = [math]::Round((Get-Item $backendTar).Length / 1MB, 2)
|
||||
Write-Success "tar 导出完成: $tarSize MB"
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 10: 清理临时目录
|
||||
# =============================================================================
|
||||
Write-Step "清理临时文件..."
|
||||
Remove-Item $packageDir -Recurse -Force
|
||||
Write-Success "清理完成"
|
||||
|
||||
# =============================================================================
|
||||
# 输出结果汇总
|
||||
# =============================================================================
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host " 本地打包完成!" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "生成文件:" -ForegroundColor White
|
||||
Write-Host " 1. $zipFile (${zipSize} MB)" -ForegroundColor Cyan
|
||||
Write-Host " 2. $backendTar (${tarSize} MB)" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# =============================================================================
|
||||
# 步骤 11: 部署到服务器(如果指定了 -Mode deploy)
|
||||
# =============================================================================
|
||||
if ($Mode -eq "deploy") {
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " 开始部署到服务器 $ServerHost..." -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# 步骤 11.1: 上传 zip 和 tar 到服务器
|
||||
Write-Step "上传部署文件到服务器..."
|
||||
# 使用 SCP 上传(需要配置 SSH 密钥或输入密码)
|
||||
scp -o StrictHostKeyChecking=no "$zipFile" "root@${ServerHost}:/tmp/it-smart-desk-server-deploy.zip"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warn "SCP 上传失败,请手动上传: $zipFile"
|
||||
} else {
|
||||
Write-Success "zip 已上传"
|
||||
}
|
||||
|
||||
scp -o StrictHostKeyChecking=no "$backendTar" "root@${ServerHost}:/tmp/deploy-backend.tar"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warn "SCP 上传失败,请手动上传: $backendTar"
|
||||
} else {
|
||||
Write-Success "tar 已上传"
|
||||
}
|
||||
|
||||
# 步骤 11.2: SSH 到服务器执行部署
|
||||
Write-Step "执行服务器部署..."
|
||||
|
||||
$deployCommands = @'
|
||||
# 进入部署目录
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 停止服务
|
||||
docker compose down
|
||||
|
||||
# 备份旧镜像
|
||||
docker images | grep wecom-it-desk-backend | awk '{print $1":"$2}' | xargs -I {} docker tag {} wecom-it-desk-backend:backup-$(date +%Y%m%d%H%M%S) 2>/dev/null || true
|
||||
|
||||
# 导入新镜像
|
||||
docker load -i /tmp/deploy-backend.tar
|
||||
|
||||
# 解压部署包
|
||||
unzip -o /tmp/it-smart-desk-server-deploy.zip -d . 2>/dev/null || unzip -o /tmp/it-smart-desk-server-deploy.zip
|
||||
|
||||
# 启动服务(重新构建并启动)
|
||||
docker compose up -d --build
|
||||
|
||||
# 等待服务启动
|
||||
echo "等待服务启动..."
|
||||
sleep 10
|
||||
|
||||
# 检查容器状态
|
||||
docker compose ps
|
||||
|
||||
# 检查后端日志
|
||||
docker logs --tail 20 wecom_it_backend
|
||||
'@
|
||||
|
||||
# 执行远程部署命令
|
||||
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=30 "root@${ServerHost}" $deployCommands
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Success "部署完成!"
|
||||
Write-Host ""
|
||||
Write-Host "验证地址:" -ForegroundColor White
|
||||
Write-Host " - H5: https://itsupport.servyou.com.cn/itdesk/" -ForegroundColor Cyan
|
||||
Write-Host " - 坐席: https://itsupport.servyou.com.cn/itagent/" -ForegroundColor Cyan
|
||||
Write-Host " - 管理: https://itsupport.servyou.com.cn/itadmin/" -ForegroundColor Cyan
|
||||
} else {
|
||||
Write-Error "部署命令执行失败,请检查服务器日志"
|
||||
}
|
||||
} else {
|
||||
Write-Host "提示:使用 -Mode deploy 参数可一键部署到服务器" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
@@ -0,0 +1,111 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 打包部署脚本
|
||||
# =============================================================================
|
||||
# 功能:将所有部署所需文件打包成一个 zip 文件
|
||||
# 用法:在 PowerShell 中运行此脚本
|
||||
# 输出:it-smart-desk-server-deploy.zip
|
||||
# =============================================================================
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# 获取项目根目录(脚本所在目录的父目录的父目录)
|
||||
$projectRoot = $PSScriptRoot
|
||||
# 如果在 deploy-server 子目录运行,向上一级
|
||||
if ($projectRoot -match "deploy-server") {
|
||||
$projectRoot = Split-Path -Parent $projectRoot
|
||||
}
|
||||
$deployDir = "$projectRoot\deploy-server"
|
||||
$packageDir = "$deployDir\_package"
|
||||
$zipFile = "$deployDir\it-smart-desk-server-deploy.zip"
|
||||
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " 企微IT智能服务台 — 打包部署文件" -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# 清理旧的打包目录
|
||||
if (Test-Path $packageDir) {
|
||||
Remove-Item $packageDir -Recurse -Force
|
||||
Write-Host "[1/7] 清理旧打包目录... done" -ForegroundColor Gray
|
||||
} else {
|
||||
Write-Host "[1/7] 创建打包目录..." -ForegroundColor Gray
|
||||
}
|
||||
New-Item -ItemType Directory -Path $packageDir -Force | Out-Null
|
||||
|
||||
# 复制 docker-compose.yml
|
||||
Write-Host "[2/7] 复制 docker-compose.yml..." -ForegroundColor Yellow
|
||||
Copy-Item "$deployDir\docker-compose.yml" "$packageDir\docker-compose.yml"
|
||||
|
||||
# 复制 .env(含真实配置)
|
||||
Write-Host "[3/7] 复制 .env(含真实配置)..." -ForegroundColor Yellow
|
||||
Copy-Item "$deployDir\.env" "$packageDir\.env"
|
||||
|
||||
# 复制 nginx 配置
|
||||
Write-Host "[4/7] 复制 nginx 配置..." -ForegroundColor Yellow
|
||||
New-Item -ItemType Directory -Path "$packageDir\nginx" -Force | Out-Null
|
||||
Copy-Item "$deployDir\nginx.conf" "$packageDir\nginx\nginx.conf"
|
||||
|
||||
# 复制后端代码
|
||||
Write-Host "[5/7] 复制后端代码(含 Dockerfile)..." -ForegroundColor Yellow
|
||||
$backendSrc = "$projectRoot\backend"
|
||||
$backendDst = "$packageDir\backend"
|
||||
New-Item -ItemType Directory -Path $backendDst -Force | Out-Null
|
||||
|
||||
# 复制后端核心文件(排除 __pycache__、.pyc、.db 等)
|
||||
$backendFiles = @(
|
||||
"Dockerfile",
|
||||
"requirements.txt",
|
||||
"alembic.ini",
|
||||
"alembic",
|
||||
"app"
|
||||
)
|
||||
foreach ($item in $backendFiles) {
|
||||
$src = "$backendSrc\$item"
|
||||
if (Test-Path $src) {
|
||||
if ((Get-Item $src).PSIsContainer) {
|
||||
# 复制目录,排除 __pycache__ 和 .pyc
|
||||
robocopy $src "$backendDst\$item" /E /XD __pycache__ /XF *.pyc *.db /NFL /NDL /NJH /NJS /NC /NS /NP | Out-Null
|
||||
} else {
|
||||
Copy-Item $src "$backendDst\$item"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 复制前端构建产物
|
||||
Write-Host "[6/7] 复制前端构建产物..." -ForegroundColor Yellow
|
||||
@("frontend-h5", "frontend-agent", "frontend-admin") | ForEach-Object {
|
||||
$src = "$projectRoot\$_\dist"
|
||||
$dst = "$packageDir\$_\dist"
|
||||
if (Test-Path $src) {
|
||||
robocopy $src $dst /E /NFL /NDL /NJH /NJS /NC /NS /NP | Out-Null
|
||||
$count = (Get-ChildItem $dst -Recurse -File).Count
|
||||
Write-Host " $_ : $count files" -ForegroundColor Gray
|
||||
} else {
|
||||
Write-Host " $_ : WARNING - dist not found!" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
# 打包成 zip
|
||||
Write-Host "[7/7] 打包成 zip..." -ForegroundColor Yellow
|
||||
if (Test-Path $zipFile) {
|
||||
Remove-Item $zipFile -Force
|
||||
}
|
||||
Compress-Archive -Path "$packageDir\*" -DestinationPath $zipFile -CompressionLevel Optimal
|
||||
|
||||
# 清理临时目录
|
||||
Remove-Item $packageDir -Recurse -Force
|
||||
|
||||
# 输出结果
|
||||
$zipSize = [math]::Round((Get-Item $zipFile).Length / 1MB, 2)
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host " 打包完成!" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host " 文件:$zipFile" -ForegroundColor White
|
||||
Write-Host " 大小:${zipSize} MB" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "下一步:" -ForegroundColor Cyan
|
||||
Write-Host " 1. 上传 zip 到服务器 /opt/wecom-it-desk/" -ForegroundColor White
|
||||
Write-Host " 2. 解压:unzip it-smart-desk-server-deploy.zip" -ForegroundColor White
|
||||
Write-Host " 3. 启动:docker compose up -d --build" -ForegroundColor White
|
||||
Write-Host " 4. 参考 DEPLOY-GUIDE.md 查看详细步骤" -ForegroundColor White
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# IT智能服务台 — RAGFlow 集成部署脚本
|
||||
# 目标服务器:10.90.5.110
|
||||
# 部署路径:/opt/wecom-it-desk
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
DEPLOY_DIR="/opt/wecom-it-desk"
|
||||
BACKUP_DIR="/opt/wecom-it-desk-backup-$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
echo "=========================================="
|
||||
echo "IT智能服务台 — RAGFlow 集成部署"
|
||||
echo "时间: $(date)"
|
||||
echo "=========================================="
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 1. 备份当前版本
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤1: 备份当前版本..."
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
cp -r "$DEPLOY_DIR/frontend-admin/dist" "$BACKUP_DIR/frontend-admin-dist" 2>/dev/null || true
|
||||
cp -r "$DEPLOY_DIR/backend" "$BACKUP_DIR/backend" 2>/dev/null || true
|
||||
echo "备份完成: $BACKUP_DIR"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 2. 解压管理后台前端
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤2: 解压管理后台前端..."
|
||||
cd "$DEPLOY_DIR"
|
||||
rm -rf frontend-admin/dist
|
||||
tar -xf /tmp/deploy-admin.tar -C frontend-admin/
|
||||
echo "管理后台前端已更新"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 3. 更新后端代码
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤3: 更新后端代码..."
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# 备份后端 .env(生产配置,不能覆盖)
|
||||
cp backend/.env /tmp/backend-env-backup 2>/dev/null || true
|
||||
|
||||
# 解压后端代码(覆盖旧文件)
|
||||
tar -xf /tmp/deploy-backend.tar -C ./
|
||||
|
||||
# 恢复后端 .env
|
||||
cp /tmp/backend-env-backup backend/.env 2>/dev/null || true
|
||||
echo "后端代码已更新"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 4. 重建后端 Docker 镜像
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤4: 重建后端 Docker 镜像..."
|
||||
cd "$DEPLOY_DIR"
|
||||
docker compose build --no-cache backend
|
||||
echo "后端镜像重建完成"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 5. 重启所有容器
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤5: 重启所有容器..."
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
echo "容器重启完成"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 6. 等待服务就绪
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤6: 等待服务就绪..."
|
||||
sleep 10
|
||||
|
||||
# 检查容器状态
|
||||
echo ""
|
||||
echo "容器状态:"
|
||||
docker compose ps
|
||||
|
||||
# 检查后端健康
|
||||
echo ""
|
||||
echo "后端健康检查:"
|
||||
curl -s http://localhost:8000/health || echo "后端未就绪,请稍后重试"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "部署完成!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "下一步:配置 RAGFlow API Key"
|
||||
echo " 1. 登录管理后台: https://itsupport.servyou.com.cn/itadmin/"
|
||||
echo " 2. 进入 集成管理 → RAGFlow"
|
||||
echo " 3. 填入 API 地址: http://10.80.0.85:9380"
|
||||
echo " 4. 填入 API Key: sk-654e************f7b91ea2b"
|
||||
echo " 5. 点击 测试连接"
|
||||
echo ""
|
||||
echo "如需回滚,执行:"
|
||||
echo " cp -r $BACKUP_DIR/frontend-admin-dist $DEPLOY_DIR/frontend-admin/dist"
|
||||
echo " cp -r $BACKUP_DIR/backend $DEPLOY_DIR/backend"
|
||||
echo " docker compose restart"
|
||||
@@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# IT智能服务台 — 生产部署脚本
|
||||
# 目标服务器:10.90.5.110
|
||||
# 部署路径:/opt/wecom-it-desk
|
||||
# =============================================================================
|
||||
|
||||
set -e # 遇到错误立即停止
|
||||
|
||||
DEPLOY_DIR="/opt/wecom-it-desk"
|
||||
BACKUP_DIR="/opt/wecom-it-desk-backup-$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
echo "=========================================="
|
||||
echo "IT智能服务台 生产部署"
|
||||
echo "时间: $(date)"
|
||||
echo "=========================================="
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 1. 备份当前版本
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤1: 备份当前版本..."
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
cp -r "$DEPLOY_DIR/frontend-h5/dist" "$BACKUP_DIR/frontend-h5-dist" 2>/dev/null || true
|
||||
cp -r "$DEPLOY_DIR/frontend-agent/dist" "$BACKUP_DIR/frontend-agent-dist" 2>/dev/null || true
|
||||
cp -r "$DEPLOY_DIR/frontend-admin/dist" "$BACKUP_DIR/frontend-admin-dist" 2>/dev/null || true
|
||||
cp -r "$DEPLOY_DIR/frontend-portal/dist" "$BACKUP_DIR/frontend-portal-dist" 2>/dev/null || true
|
||||
cp -r "$DEPLOY_DIR/backend" "$BACKUP_DIR/backend" 2>/dev/null || true
|
||||
echo "备份完成: $BACKUP_DIR"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 2. 解压前端文件
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤2: 解压前端文件..."
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# H5 前端
|
||||
rm -rf frontend-h5/dist
|
||||
tar -xf /tmp/deploy-h5.tar -C frontend-h5/
|
||||
echo "H5 前端已更新"
|
||||
|
||||
# 坐席前端
|
||||
rm -rf frontend-agent/dist
|
||||
tar -xf /tmp/deploy-agent.tar -C frontend-agent/
|
||||
echo "坐席前端已更新"
|
||||
|
||||
# 管理后台
|
||||
rm -rf frontend-admin/dist
|
||||
tar -xf /tmp/deploy-admin.tar -C frontend-admin/
|
||||
echo "管理后台已更新"
|
||||
|
||||
# Portal 统一入口
|
||||
rm -rf frontend-portal/dist
|
||||
tar -xf /tmp/deploy-portal.tar -C frontend-portal/ 2>/dev/null || echo "Portal 包未找到,跳过"
|
||||
echo "Portal 已更新"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 3. 更新后端代码
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤3: 更新后端代码..."
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
# 备份后端 .env(生产配置,不能覆盖)
|
||||
cp backend/.env /tmp/backend-env-backup 2>/dev/null || true
|
||||
|
||||
# 解压后端代码(覆盖旧文件)
|
||||
tar -xf /tmp/deploy-backend.tar -C ./
|
||||
|
||||
# 恢复后端 .env
|
||||
cp /tmp/backend-env-backup backend/.env 2>/dev/null || true
|
||||
echo "后端代码已更新"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 4. 数据库迁移(角色系统)
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤4: 执行数据库迁移..."
|
||||
cd "$DEPLOY_DIR/backend"
|
||||
alembic upgrade head
|
||||
echo "数据库迁移完成"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 5. 关闭 Mock 登录(如果还开着)
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤5: 检查 Mock 登录配置..."
|
||||
if grep -q "MOCK_LOGIN_ENABLED=true" "$DEPLOY_DIR/backend/.env" 2>/dev/null || \
|
||||
grep -q "MOCK_LOGIN_ENABLED=true" "$DEPLOY_DIR/.env" 2>/dev/null; then
|
||||
echo "发现 MOCK_LOGIN_ENABLED=true,正在关闭..."
|
||||
sed -i 's/MOCK_LOGIN_ENABLED=true/MOCK_LOGIN_ENABLED=false/g' "$DEPLOY_DIR/backend/.env" 2>/dev/null || true
|
||||
sed -i 's/MOCK_LOGIN_ENABLED=true/MOCK_LOGIN_ENABLED=false/g' "$DEPLOY_DIR/.env" 2>/dev/null || true
|
||||
echo "Mock 登录已关闭"
|
||||
else
|
||||
echo "Mock 登录已关闭,无需修改"
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 6. 重建后端 Docker 镜像
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤6: 重建后端 Docker 镜像..."
|
||||
cd "$DEPLOY_DIR"
|
||||
docker compose build --no-cache backend
|
||||
echo "后端镜像重建完成"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 7. 重启所有容器
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤7: 重启所有容器..."
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
echo "容器重启完成"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 8. 等待服务就绪
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo ">>> 步骤8: 等待服务就绪..."
|
||||
sleep 10
|
||||
|
||||
# 检查容器状态
|
||||
echo ""
|
||||
echo "容器状态:"
|
||||
docker compose ps
|
||||
|
||||
# 检查后端健康
|
||||
echo ""
|
||||
echo "后端健康检查:"
|
||||
curl -s http://localhost:8000/health || echo "后端未就绪,请稍后重试"
|
||||
|
||||
# 检查前端
|
||||
echo ""
|
||||
echo "前端健康检查:"
|
||||
curl -s http://localhost:80/itdesk/health || echo "前端未就绪,请稍后重试"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "部署完成!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "访问地址:"
|
||||
echo " 统一入口: https://itsupport.servyou.com.cn/itportal/"
|
||||
echo " H5 用户端: https://itsupport.servyou.com.cn/itdesk/"
|
||||
echo " 坐席工作台: https://itsupport.servyou.com.cn/itagent/"
|
||||
echo " 管理后台: https://itsupport.servyou.com.cn/itadmin/"
|
||||
echo ""
|
||||
echo "如需回滚,执行:"
|
||||
echo " cp -r $BACKUP_DIR/frontend-h5-dist $DEPLOY_DIR/frontend-h5/dist"
|
||||
echo " cp -r $BACKUP_DIR/frontend-agent-dist $DEPLOY_DIR/frontend-agent/dist"
|
||||
echo " cp -r $BACKUP_DIR/frontend-admin-dist $DEPLOY_DIR/frontend-admin/dist"
|
||||
echo " cp -r $BACKUP_DIR/backend $DEPLOY_DIR/backend"
|
||||
echo " docker compose restart"
|
||||
@@ -0,0 +1,175 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — Docker Compose(公司内网服务器版)
|
||||
# =============================================================================
|
||||
# 目标服务器:10.90.5.110
|
||||
# 域名:itsupport.servyou.com.cn
|
||||
#
|
||||
# 用法:
|
||||
# 1. 上传部署包到服务器
|
||||
# 2. cp .env.example .env && vim .env # 填入真实配置
|
||||
# 3. docker compose up -d # 启动所有服务
|
||||
# 4. docker compose logs -f # 查看日志
|
||||
#
|
||||
# 架构:
|
||||
# 客户端浏览器 → Nginx:80 → { /itdesk/, /itagent/, /itadmin/, /api/, /ws/ }
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
# --------------------------------------------------------------------------
|
||||
# PostgreSQL 16 — 持久化数据库
|
||||
# --------------------------------------------------------------------------
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: wecom_it_postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-wecom}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-wecom_secret}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-wecom_it_desk}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-wecom}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- it-desk-internal
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Redis 7 — 缓存服务(token、会话、员工信息)
|
||||
# --------------------------------------------------------------------------
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: wecom_it_redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes --save 900 1 --save 300 10 --requirepass ${REDIS_PASSWORD:-R3d!s@2026#Secure}
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-R3d!s@2026#Secure}", "ping"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- it-desk-internal
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# FastAPI 后端 — 核心业务服务
|
||||
# --------------------------------------------------------------------------
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
image: wecom-it-desk-backend:latest
|
||||
container_name: wecom_it_backend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# 企微凭证
|
||||
- WECOM_CORP_ID=${WECOM_CORP_ID}
|
||||
- WECOM_AGENT_ID=${WECOM_AGENT_ID}
|
||||
- WECOM_SECRET=${WECOM_SECRET}
|
||||
- WECOM_TOKEN=${WECOM_TOKEN}
|
||||
- WECOM_ENCODING_AES_KEY=${WECOM_ENCODING_AES_KEY}
|
||||
# 数据库(Docker 内部网络,用容器名通信)
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis(Docker 内部网络,带密码认证)
|
||||
- REDIS_URL=redis://:${REDIS_PASSWORD:-R3d!s@2026#Secure}@redis:6379/0
|
||||
# CORS
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
|
||||
# AI 服务(Dify)
|
||||
- DIFY_API_URL=${DIFY_API_URL}
|
||||
- DIFY_API_KEY=${DIFY_API_KEY}
|
||||
- DIFY_TIMEOUT=${DIFY_TIMEOUT:-30}
|
||||
# AI Wingman(留空禁用)
|
||||
- DIFY_WINGMAN_API_URL=${DIFY_WINGMAN_API_URL:-}
|
||||
- DIFY_WINGMAN_API_KEY=${DIFY_WINGMAN_API_KEY:-}
|
||||
- DIFY_WINGMAN_TIMEOUT=${DIFY_WINGMAN_TIMEOUT:-30}
|
||||
# Mock 登录(生产环境默认关闭,如需临时调试请在 .env 中显式设置为 true)
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8000
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
command: >
|
||||
/bin/sh -c "
|
||||
echo '>>> 执行数据库迁移...' &&
|
||||
cd /app && PYTHONPATH=/app alembic upgrade head &&
|
||||
echo '>>> 启动 API 服务...' &&
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2
|
||||
"
|
||||
networks:
|
||||
- it-desk-internal
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "20m"
|
||||
max-file: "5"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Nginx — 反向代理 + 静态文件服务
|
||||
# --------------------------------------------------------------------------
|
||||
nginx:
|
||||
image: nginx:1.27-alpine
|
||||
container_name: wecom_it_nginx
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./nginx/ssl:/etc/nginx/ssl:ro
|
||||
- ./frontend-h5/dist:/usr/share/nginx/html/itdesk:ro
|
||||
- ./frontend-agent/dist:/usr/share/nginx/html/itagent:ro
|
||||
- ./frontend-admin/dist:/usr/share/nginx/html/itadmin:ro
|
||||
- ./frontend-portal/dist:/usr/share/nginx/html/itportal:ro
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- it-desk-internal
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:80/itdesk/health || exit 1"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# =============================================================================
|
||||
# 网络
|
||||
# =============================================================================
|
||||
networks:
|
||||
it-desk-internal:
|
||||
driver: bridge
|
||||
|
||||
# =============================================================================
|
||||
# 数据卷 — 持久化存储
|
||||
# =============================================================================
|
||||
volumes:
|
||||
postgres_data:
|
||||
name: wecom_it_postgres_data
|
||||
redis_data:
|
||||
name: wecom_it_redis_data
|
||||
@@ -0,0 +1,191 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — Nginx 配置(公司内网服务器版 + HTTPS)
|
||||
# =============================================================================
|
||||
# 目标服务器:10.90.5.110
|
||||
# 域名:itsupport.servyou.com.cn
|
||||
#
|
||||
# 路由规则:
|
||||
# HTTP → 自动重定向到 HTTPS
|
||||
# HTTPS → { /itdesk/, /itagent/, /itadmin/, /api/, /ws/ }
|
||||
# =============================================================================
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 日志格式
|
||||
# ------------------------------------------------------------------
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 基础配置
|
||||
# ------------------------------------------------------------------
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
client_max_body_size 50m; # 支持文件上传(企微媒体文件)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Gzip 压缩(前端静态资源)
|
||||
# ------------------------------------------------------------------
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript
|
||||
application/javascript application/xml+rss
|
||||
application/json application/ld+json;
|
||||
|
||||
# =================================================================
|
||||
# 上游服务定义(Docker 内部网络)
|
||||
# =================================================================
|
||||
upstream backend_api {
|
||||
server backend:8000;
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTP → HTTPS 重定向
|
||||
# =================================================================
|
||||
server {
|
||||
listen 80;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# 企微域名验证文件(HTTP 也需要,企微验证可能走 HTTP)
|
||||
location /WW_verify_lxWC7WJDjTQuutBE.txt {
|
||||
alias /usr/share/nginx/html/itdesk/WW_verify_lxWC7WJDjTQuutBE.txt;
|
||||
}
|
||||
|
||||
# 其余全部重定向到 HTTPS
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTPS 主服务
|
||||
# =================================================================
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# SSL 证书配置
|
||||
# ------------------------------------------------------------------
|
||||
ssl_certificate /etc/nginx/ssl/servyou.com.cn.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/servyou.com.cn.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 安全头
|
||||
# ------------------------------------------------------------------
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 健康检查端点(用于 Docker healthcheck)
|
||||
# ------------------------------------------------------------------
|
||||
location = /itdesk/health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# H5 员工端 — /itdesk/
|
||||
# ------------------------------------------------------------------
|
||||
location /itdesk/ {
|
||||
alias /usr/share/nginx/html/itdesk/;
|
||||
index index.html;
|
||||
try_files $uri /itdesk/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 坐席工作台 — /itagent/
|
||||
# ------------------------------------------------------------------
|
||||
location /itagent/ {
|
||||
alias /usr/share/nginx/html/itagent/;
|
||||
index index.html;
|
||||
try_files $uri /itagent/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 统一入口 Portal — /itportal/
|
||||
# ------------------------------------------------------------------
|
||||
location /itportal/ {
|
||||
alias /usr/share/nginx/html/itportal/;
|
||||
index index.html;
|
||||
try_files $uri /itportal/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 管理后台 — /itadmin/
|
||||
# ------------------------------------------------------------------
|
||||
location /itadmin/ {
|
||||
alias /usr/share/nginx/html/itadmin/;
|
||||
index index.html;
|
||||
try_files $uri /itadmin/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 后端 API — /api/
|
||||
# ------------------------------------------------------------------
|
||||
location /api/ {
|
||||
proxy_pass http://backend_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 https;
|
||||
|
||||
# 超时设置(AI 回复可能较慢)
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# WebSocket — /ws/(坐席端实时通信)
|
||||
# ------------------------------------------------------------------
|
||||
location /ws/ {
|
||||
proxy_pass http://backend_api;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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 https;
|
||||
proxy_read_timeout 86400s; # WebSocket 长连接
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 企微域名验证文件
|
||||
# ------------------------------------------------------------------
|
||||
location /WW_verify_lxWC7WJDjTQuutBE.txt {
|
||||
alias /usr/share/nginx/html/itdesk/WW_verify_lxWC7WJDjTQuutBE.txt;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 默认路径 — 重定向到统一入口 Portal
|
||||
# ------------------------------------------------------------------
|
||||
location = / {
|
||||
return 302 /itportal/;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — Nginx 配置(公司内网服务器版)
|
||||
# =============================================================================
|
||||
# 适用场景:独立域名 itsupport.servyou.com.cn,公司内网 DNS 解析
|
||||
# 与 NAS 版的区别:
|
||||
# 1. 移除 Cloudflare 相关头(X-Forwarded-Proto https 等)
|
||||
# 2. server_name 改为正式域名
|
||||
# 3. 真实 IP 直接从 $remote_addr 获取(无 CF 代理层)
|
||||
# 4. 预留 HTTPS 配置注释(如公司有统一 SSL 终端)
|
||||
# =============================================================================
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 日志格式
|
||||
# ------------------------------------------------------------------
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 基础配置
|
||||
# ------------------------------------------------------------------
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
client_max_body_size 50m; # 支持文件上传(企微媒体文件)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Gzip 压缩(前端静态资源)
|
||||
# ------------------------------------------------------------------
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript
|
||||
application/javascript application/xml+rss
|
||||
application/json application/ld+json;
|
||||
|
||||
# =================================================================
|
||||
# 上游服务定义(Docker 内部网络)
|
||||
# =================================================================
|
||||
upstream backend_api {
|
||||
server backend:8000;
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTP 服务(监听 80 端口)
|
||||
# =================================================================
|
||||
# 如果公司有统一 SSL 终端(如 F5/Nginx 反代),此服务器只需监听 80
|
||||
# 如果需要本机 HTTPS,取消下方 server 块注释,并配置证书路径
|
||||
# =================================================================
|
||||
server {
|
||||
listen 80;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 安全头
|
||||
# ------------------------------------------------------------------
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 健康检查端点
|
||||
# ------------------------------------------------------------------
|
||||
location = /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# H5 员工端 — /itdesk/
|
||||
# ------------------------------------------------------------------
|
||||
location /itdesk/ {
|
||||
alias /usr/share/nginx/html/itdesk/;
|
||||
index index.html;
|
||||
try_files $uri /itdesk/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 坐席工作台 — /itagent/
|
||||
# ------------------------------------------------------------------
|
||||
location /itagent/ {
|
||||
alias /usr/share/nginx/html/itagent/;
|
||||
index index.html;
|
||||
try_files $uri /itagent/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 管理后台 — /itadmin/(仅限内网/VPN 访问)
|
||||
# ------------------------------------------------------------------
|
||||
location /itadmin/ {
|
||||
# IP 白名单:仅允许内网网段
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 192.168.0.0/16;
|
||||
allow 10.212.0.0/16; # VPN 网段
|
||||
deny all;
|
||||
|
||||
alias /usr/share/nginx/html/itadmin/;
|
||||
index index.html;
|
||||
try_files $uri /itadmin/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 统一入口 Portal — /itportal/
|
||||
# ------------------------------------------------------------------
|
||||
location /itportal/ {
|
||||
alias /usr/share/nginx/html/itportal/;
|
||||
index index.html;
|
||||
try_files $uri /itportal/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 后端 API — /api/(管理端 API 仅限内网/VPN)
|
||||
# ------------------------------------------------------------------
|
||||
location /api/ {
|
||||
# 管理端 API 路径需要 IP 白名单
|
||||
location ~ ^/api/admin/ {
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 192.168.0.0/16;
|
||||
allow 10.212.0.0/16;
|
||||
deny all;
|
||||
|
||||
proxy_pass http://backend_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;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# 其他 API 路径
|
||||
proxy_pass http://backend_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;
|
||||
|
||||
# 超时设置(AI 回复可能较慢)
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# WebSocket — /ws/(坐席端实时通信)
|
||||
# ------------------------------------------------------------------
|
||||
location /ws/ {
|
||||
proxy_pass http://backend_api;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
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_read_timeout 86400s; # WebSocket 长连接
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 企微回调 — /api/wecom/callback(接收企微消息推送)
|
||||
# ------------------------------------------------------------------
|
||||
# 企微验证回调 URL 时使用 GET,后续消息推送使用 POST
|
||||
# 此路径已包含在 /api/ 的代理规则中,无需单独配置
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 默认路径 — 重定向到 H5 员工端
|
||||
# ------------------------------------------------------------------
|
||||
location = / {
|
||||
return 302 /itdesk/;
|
||||
}
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTPS 配置(按需启用)
|
||||
# =================================================================
|
||||
# 如果需要本机直接提供 HTTPS(不走公司统一 SSL 终端),
|
||||
# 取消下方注释并配置 SSL 证书路径
|
||||
#
|
||||
# server {
|
||||
# listen 443 ssl;
|
||||
# server_name itsupport.servyou.com.cn;
|
||||
#
|
||||
# ssl_certificate /etc/nginx/ssl/itsupport.servyou.com.cn.crt;
|
||||
# ssl_certificate_key /etc/nginx/ssl/itsupport.servyou.com.cn.key;
|
||||
# ssl_protocols TLSv1.2 TLSv1.3;
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
#
|
||||
# # 其余 location 配置与上方 HTTP server 相同
|
||||
# ...
|
||||
# }
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
@echo off
|
||||
REM =============================================================================
|
||||
REM IT智能服务台 — 打包部署脚本(Windows)
|
||||
REM 目标:生成部署包,通过堡垒机上传到服务器
|
||||
REM =============================================================================
|
||||
|
||||
echo ==========================================
|
||||
echo IT智能服务台 部署包打包
|
||||
echo 时间: %date% %time%
|
||||
echo ==========================================
|
||||
|
||||
REM 切换到项目根目录
|
||||
cd /d "D:\资料\03-项目开发\wecom_it_smart_desk"
|
||||
|
||||
REM --------------------------------------------------------------------------
|
||||
REM 1. 打包后端代码
|
||||
REM --------------------------------------------------------------------------
|
||||
echo.
|
||||
echo ">>> 步骤1: 打包后端代码..."
|
||||
|
||||
REM 创建临时目录
|
||||
if not exist "deploy-temp" mkdir deploy-temp
|
||||
|
||||
REM 打包后端(排除 .env、__pycache__、.git 等)
|
||||
cd backend
|
||||
tar -cf "../deploy-temp/deploy-backend.tar" ^
|
||||
--exclude="__pycache__" ^
|
||||
--exclude="*.pyc" ^
|
||||
--exclude=".env" ^
|
||||
--exclude="it_smart_desk.db" ^
|
||||
--exclude=".venv" ^
|
||||
app/
|
||||
alembic/
|
||||
requirements.txt
|
||||
Dockerfile
|
||||
cd ..
|
||||
|
||||
echo "后端代码已打包"
|
||||
|
||||
REM --------------------------------------------------------------------------
|
||||
REM 2. 打包前端代码(如果已构建)
|
||||
REM --------------------------------------------------------------------------
|
||||
echo.
|
||||
echo ">>> 步骤2: 打包前端代码..."
|
||||
|
||||
REM H5 前端
|
||||
if exist "frontend-h5\dist" (
|
||||
cd frontend-h5
|
||||
tar -cf "../deploy-temp/deploy-h5.tar" dist/
|
||||
cd ..
|
||||
echo "H5 前端已打包"
|
||||
) else (
|
||||
echo "H5 前端未构建,跳过"
|
||||
)
|
||||
|
||||
REM 坐席前端
|
||||
if exist "frontend-agent\dist" (
|
||||
cd frontend-agent
|
||||
tar -cf "../deploy-temp/deploy-agent.tar" dist/
|
||||
cd ..
|
||||
echo "坐席前端已打包"
|
||||
) else (
|
||||
echo "坐席前端未构建,跳过"
|
||||
)
|
||||
|
||||
REM 管理后台
|
||||
if exist "frontend-admin\dist" (
|
||||
cd frontend-admin
|
||||
tar -cf "../deploy-temp/deploy-admin.tar" dist/
|
||||
cd ..
|
||||
echo "管理后台已打包"
|
||||
) else (
|
||||
echo "管理后台未构建,跳过"
|
||||
)
|
||||
|
||||
REM Portal 统一入口
|
||||
if exist "frontend-portal\dist" (
|
||||
cd frontend-portal
|
||||
tar -cf "../deploy-temp/deploy-portal.tar" dist/
|
||||
cd ..
|
||||
echo "Portal 已打包"
|
||||
) else (
|
||||
echo "Portal 未构建,跳过"
|
||||
)
|
||||
|
||||
REM --------------------------------------------------------------------------
|
||||
REM 3. 打包部署脚本
|
||||
REM --------------------------------------------------------------------------
|
||||
echo.
|
||||
echo ">>> 步骤3: 打包部署脚本..."
|
||||
copy deploy-server\deploy.sh deploy-temp\
|
||||
echo "部署脚本已复制"
|
||||
|
||||
REM --------------------------------------------------------------------------
|
||||
REM 4. 完成
|
||||
REM --------------------------------------------------------------------------
|
||||
echo.
|
||||
echo ==========================================
|
||||
echo 打包完成!
|
||||
echo ==========================================
|
||||
echo.
|
||||
echo 部署包位置: deploy-temp\
|
||||
echo.
|
||||
echo 下一步:
|
||||
echo 1. 通过堡垒机上传 deploy-temp\ 目录下的所有文件到服务器 /tmp/
|
||||
echo 2. 在服务器执行: bash /tmp/deploy.sh
|
||||
echo.
|
||||
echo 堡垒机信息:
|
||||
echo 地址: 10.212.189.210:2222
|
||||
echo 用户: sxn
|
||||
echo 认证: OTP
|
||||
echo.
|
||||
@@ -0,0 +1,213 @@
|
||||
"""
|
||||
企微IT智能服务台 — 部署包生成脚本(Windows 兼容版)
|
||||
=======================================================
|
||||
功能:
|
||||
1. 构建前端(H5 + 坐席端)
|
||||
2. 将前端产物 + 后端源码 + 配置文件打包为 zip
|
||||
3. 输出 zip 文件,可上传到服务器直接解压部署
|
||||
|
||||
用法:
|
||||
cd 项目根目录
|
||||
python deploy-server/package.py
|
||||
|
||||
说明:
|
||||
- 使用 Python 而非 bash,确保 Windows 上可直接运行
|
||||
- 打包前会自动执行 npm run build 构建前端
|
||||
- 如不想重新构建,传 --skip-build 参数跳过
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
# ─── 配置 ───────────────────────────────────────────────────────
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent # 项目根目录
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent # deploy-server 目录
|
||||
PACKAGE_NAME = "it-smart-desk-server-deploy"
|
||||
ZIP_FILENAME = f"{PACKAGE_NAME}.zip"
|
||||
|
||||
# 需要打包的目录和文件映射
|
||||
# key: 源路径(相对于 PROJECT_ROOT),value: 目标路径(在 zip 中的相对路径,含顶层目录)
|
||||
PACKAGE_PREFIX = PACKAGE_NAME # zip 内顶层目录名
|
||||
INCLUDE_MAP = {
|
||||
"deploy-server/docker-compose.yml": f"{PACKAGE_PREFIX}/docker-compose.yml",
|
||||
"deploy-server/.env.example": f"{PACKAGE_PREFIX}/.env.example",
|
||||
"deploy-server/deploy.sh": f"{PACKAGE_PREFIX}/deploy.sh",
|
||||
"deploy-server/README.md": f"{PACKAGE_PREFIX}/README.md",
|
||||
"deploy-server/nginx/nginx.conf": f"{PACKAGE_PREFIX}/nginx/nginx.conf",
|
||||
"frontend-h5/dist": f"{PACKAGE_PREFIX}/frontend-h5/dist",
|
||||
"frontend-agent/dist": f"{PACKAGE_PREFIX}/frontend-agent/dist",
|
||||
"backend": f"{PACKAGE_PREFIX}/backend",
|
||||
}
|
||||
|
||||
# 后端目录中需要排除的文件/文件夹
|
||||
BACKEND_EXCLUDE = {
|
||||
"__pycache__", ".pytest_cache", ".venv", "venv",
|
||||
"*.pyc", ".git", ".env", "*.egg-info",
|
||||
}
|
||||
|
||||
# ─── 辅助函数 ───────────────────────────────────────────────────
|
||||
|
||||
def run_cmd(cmd: str, cwd: Path | None = None) -> bool:
|
||||
"""执行命令,返回是否成功"""
|
||||
print(f" 执行: {cmd}")
|
||||
result = subprocess.run(
|
||||
cmd, shell=True, cwd=cwd,
|
||||
capture_output=True,
|
||||
encoding='utf-8', errors='replace' # Windows 下 npm 输出 UTF-8,忽略解码错误
|
||||
)
|
||||
if result.returncode != 0:
|
||||
stderr = result.stderr.strip() if result.stderr else ""
|
||||
# npm build 偶尔有非致命警告,只在实际失败时报错
|
||||
if "error" in stderr.lower() or result.returncode != 0:
|
||||
print(f" ⚠ 命令返回码: {result.returncode}")
|
||||
if stderr:
|
||||
# 只打印最后几行,避免刷屏
|
||||
lines = stderr.strip().split('\n')
|
||||
for line in lines[-3:]:
|
||||
print(f" {line}")
|
||||
return result.returncode == 0
|
||||
return True
|
||||
|
||||
|
||||
def should_exclude(path: Path) -> bool:
|
||||
"""判断文件/目录是否应排除"""
|
||||
name = path.name
|
||||
if name in {"__pycache__", ".pytest_cache", ".venv", "venv", ".git", ".env", "node_modules"}:
|
||||
return True
|
||||
if name.endswith(".pyc") or name.endswith(".egg-info"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def add_dir_to_zip(zipf: zipfile.ZipFile, src_dir: Path, arc_prefix: str):
|
||||
"""递归添加目录到 zip"""
|
||||
for item in src_dir.rglob("*"):
|
||||
if should_exclude(item):
|
||||
continue
|
||||
if item.is_file():
|
||||
# 计算在 zip 中的相对路径
|
||||
rel = item.relative_to(src_dir)
|
||||
arc = f"{arc_prefix}/{rel}".replace("\\", "/")
|
||||
zipf.write(item, arc)
|
||||
|
||||
|
||||
# ─── 主流程 ─────────────────────────────────────────────────────
|
||||
|
||||
def build_frontends():
|
||||
"""构建前端"""
|
||||
print("\n--- [1/2] 构建前端 ---")
|
||||
|
||||
# H5 员工端
|
||||
h5_dir = PROJECT_ROOT / "frontend-h5"
|
||||
print("构建 H5 员工端...")
|
||||
if not run_cmd("npm install --quiet", cwd=h5_dir):
|
||||
print(" ⚠ npm install 失败,尝试继续...")
|
||||
if not run_cmd("npm run build", cwd=h5_dir):
|
||||
print(" ❌ H5 构建失败!")
|
||||
sys.exit(1)
|
||||
print(" ✅ H5 员工端构建完成")
|
||||
|
||||
# 坐席工作台
|
||||
agent_dir = PROJECT_ROOT / "frontend-agent"
|
||||
print("构建坐席工作台...")
|
||||
if not run_cmd("npm install --quiet", cwd=agent_dir):
|
||||
print(" ⚠ npm install 失败,尝试继续...")
|
||||
if not run_cmd("npm run build", cwd=agent_dir):
|
||||
print(" ❌ 坐席端构建失败!")
|
||||
sys.exit(1)
|
||||
print(" ✅ 坐席工作台构建完成")
|
||||
|
||||
|
||||
def create_package():
|
||||
"""创建部署包 zip"""
|
||||
print("\n--- [2/2] 创建部署包 ---")
|
||||
|
||||
zip_path = PROJECT_ROOT / ZIP_FILENAME
|
||||
|
||||
# 检查必要文件是否存在
|
||||
checks = [
|
||||
(PROJECT_ROOT / "frontend-h5" / "dist" / "index.html", "H5 前端产物"),
|
||||
(PROJECT_ROOT / "frontend-agent" / "dist" / "index.html", "坐席端前端产物"),
|
||||
(PROJECT_ROOT / "backend" / "Dockerfile", "后端 Dockerfile"),
|
||||
(SCRIPT_DIR / "docker-compose.yml", "docker-compose.yml"),
|
||||
(SCRIPT_DIR / "nginx" / "nginx.conf", "nginx.conf"),
|
||||
]
|
||||
for path, desc in checks:
|
||||
if not path.exists():
|
||||
print(f" ❌ 缺少: {desc} ({path})")
|
||||
sys.exit(1)
|
||||
|
||||
print(f" 正在打包到 {zip_path}...")
|
||||
|
||||
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf:
|
||||
for src_rel, dst_rel in INCLUDE_MAP.items():
|
||||
src = PROJECT_ROOT / src_rel
|
||||
if not src.exists():
|
||||
print(f" ⚠ 跳过不存在的路径: {src_rel}")
|
||||
continue
|
||||
|
||||
if src.is_file():
|
||||
zf.write(src, dst_rel)
|
||||
elif src.is_dir():
|
||||
add_dir_to_zip(zf, src, dst_rel)
|
||||
|
||||
# 显示结果
|
||||
size_mb = zip_path.stat().st_size / (1024 * 1024)
|
||||
print(f" ✅ 部署包已生成: {zip_path}")
|
||||
print(f" 大小: {size_mb:.1f} MB")
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 50)
|
||||
print(" IT智能服务台 — 部署包生成")
|
||||
print("=" * 50)
|
||||
|
||||
# 检查是否跳过构建
|
||||
skip_build = "--skip-build" in sys.argv
|
||||
|
||||
if skip_build:
|
||||
print("\n ⏭ 跳过前端构建(使用现有 dist 目录)")
|
||||
else:
|
||||
build_frontends()
|
||||
|
||||
create_package()
|
||||
|
||||
# 输出后续步骤
|
||||
print("\n" + "=" * 50)
|
||||
print(" 后续步骤:")
|
||||
print("=" * 50)
|
||||
print(f"""
|
||||
1. 上传部署包到服务器(通过堡垒机):
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \\
|
||||
{ZIP_FILENAME} \\
|
||||
sxn@10.80.0.136:/tmp/
|
||||
|
||||
2. SSH 登录服务器(通过堡垒机):
|
||||
ssh -J sxn@10.212.189.210:2222 sxn@10.80.0.136
|
||||
|
||||
3. 在服务器上执行:
|
||||
sudo cp /tmp/{ZIP_FILENAME} /opt/
|
||||
cd /opt
|
||||
unzip {ZIP_FILENAME}
|
||||
mv {PACKAGE_NAME} wecom-it-desk
|
||||
cd wecom-it-desk
|
||||
cp .env.example .env
|
||||
vi .env # 编辑配置(阶段一 Mock 模式默认即可)
|
||||
chmod +x deploy.sh
|
||||
./deploy.sh
|
||||
|
||||
4. 配置 DNS(联系 IT 运维):
|
||||
itsupport.servyou.com.cn → 10.80.0.136
|
||||
|
||||
5. 浏览器验证:
|
||||
http://itsupport.servyou.com.cn/itdesk/
|
||||
http://itsupport.servyou.com.cn/itagent/
|
||||
""")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 部署包生成脚本(在开发机上运行)
|
||||
# =============================================================================
|
||||
# 功能:
|
||||
# 1. 构建前端(H5 + 坐席端)
|
||||
# 2. 将前端产物 + 后端源码 + 配置文件打包为部署包
|
||||
# 3. 输出 zip 文件,可上传到服务器直接解压部署
|
||||
#
|
||||
# 用法:
|
||||
# cd 项目根目录
|
||||
# bash deploy-server/package.sh
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 项目根目录(脚本在 deploy-server/ 下,需要回到上一级)
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
PACKAGE_NAME="it-smart-desk-server-deploy"
|
||||
BUILD_DIR="/tmp/$PACKAGE_NAME"
|
||||
|
||||
echo -e "${GREEN}============================================${NC}"
|
||||
echo -e "${GREEN} IT智能服务台 — 部署包生成${NC}"
|
||||
echo -e "${GREEN}============================================${NC}"
|
||||
|
||||
# --- 1. 构建前端 ---
|
||||
echo ""
|
||||
echo "--- [1/3] 构建前端 ---"
|
||||
|
||||
# H5 员工端
|
||||
echo "构建 H5 员工端..."
|
||||
cd "$PROJECT_ROOT/frontend-h5"
|
||||
npm install --quiet
|
||||
npm run build
|
||||
echo -e "${GREEN}✓ H5 员工端构建完成${NC}"
|
||||
|
||||
# 坐席工作台
|
||||
echo "构建坐席工作台..."
|
||||
cd "$PROJECT_ROOT/frontend-agent"
|
||||
npm install --quiet
|
||||
npm run build
|
||||
echo -e "${GREEN}✓ 坐席工作台构建完成${NC}"
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# --- 2. 组装部署包 ---
|
||||
echo ""
|
||||
echo "--- [2/3] 组装部署包 ---"
|
||||
|
||||
# 清理旧目录
|
||||
rm -rf "$BUILD_DIR"
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
# 复制 Docker Compose 配置
|
||||
cp -r "$SCRIPT_DIR/docker-compose.yml" "$BUILD_DIR/"
|
||||
cp -r "$SCRIPT_DIR/.env.example" "$BUILD_DIR/"
|
||||
cp -r "$SCRIPT_DIR/deploy.sh" "$BUILD_DIR/"
|
||||
cp -r "$SCRIPT_DIR/README.md" "$BUILD_DIR/"
|
||||
|
||||
# 复制 Nginx 配置
|
||||
mkdir -p "$BUILD_DIR/nginx"
|
||||
cp "$SCRIPT_DIR/nginx/nginx.conf" "$BUILD_DIR/nginx/"
|
||||
|
||||
# 复制前端构建产物
|
||||
mkdir -p "$BUILD_DIR/frontend-h5/dist"
|
||||
cp -r "$PROJECT_ROOT/frontend-h5/dist/"* "$BUILD_DIR/frontend-h5/dist/"
|
||||
|
||||
mkdir -p "$BUILD_DIR/frontend-agent/dist"
|
||||
cp -r "$PROJECT_ROOT/frontend-agent/dist/"* "$BUILD_DIR/frontend-agent/dist/"
|
||||
|
||||
# 复制后端源码
|
||||
mkdir -p "$BUILD_DIR/backend"
|
||||
cp -r "$PROJECT_ROOT/backend/"* "$BUILD_DIR/backend/"
|
||||
|
||||
# 清理后端中的缓存和临时文件
|
||||
rm -rf "$BUILD_DIR/backend/__pycache__"
|
||||
rm -rf "$BUILD_DIR/backend/app/__pycache__"
|
||||
find "$BUILD_DIR/backend" -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find "$BUILD_DIR/backend" -name "*.pyc" -delete 2>/dev/null || true
|
||||
|
||||
echo -e "${GREEN}✓ 部署包组装完成${NC}"
|
||||
|
||||
# --- 3. 打包 ---
|
||||
echo ""
|
||||
echo "--- [3/3] 打包 ---"
|
||||
|
||||
cd /tmp
|
||||
zip -r "$PROJECT_ROOT/${PACKAGE_NAME}.zip" "$PACKAGE_NAME" -q
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# 清理临时目录
|
||||
rm -rf "$BUILD_DIR"
|
||||
|
||||
# 输出信息
|
||||
ZIP_SIZE=$(du -h "${PACKAGE_NAME}.zip" | cut -f1)
|
||||
echo ""
|
||||
echo -e "${GREEN}============================================${NC}"
|
||||
echo -e "${GREEN} 部署包生成完成!${NC}"
|
||||
echo -e "${GREEN}============================================${NC}"
|
||||
echo ""
|
||||
echo "文件:${PACKAGE_NAME}.zip (${ZIP_SIZE})"
|
||||
echo ""
|
||||
echo "部署步骤:"
|
||||
echo " 1. 上传到服务器: scp ${PACKAGE_NAME}.zip user@服务器IP:/opt/"
|
||||
echo " 2. 解压: cd /opt && unzip ${PACKAGE_NAME}.zip && mv ${PACKAGE_NAME} wecom-it-desk"
|
||||
echo " 3. 配置: cp .env.example .env && vi .env"
|
||||
echo " 4. 部署: chmod +x deploy.sh && ./deploy.sh"
|
||||
@@ -0,0 +1,65 @@
|
||||
@echo off
|
||||
REM =============================================================================
|
||||
REM 企微IT智能服务台 — 打包部署一键执行
|
||||
REM =============================================================================
|
||||
REM 功能:
|
||||
REM 1. 打包前端构建产物 + nginx配置 + docker-compose.yml + .env
|
||||
REM 2. 构建后端 Docker 镜像(包含最新代码)
|
||||
REM 3. 导出镜像为 tar 文件
|
||||
REM 4. 自动上传到服务器并部署
|
||||
REM
|
||||
REM 用法:
|
||||
REM 打包部署.bat 仅本地打包
|
||||
REM 打包部署.bat deploy 打包 + 部署到服务器
|
||||
REM =============================================================================
|
||||
|
||||
setlocal
|
||||
|
||||
set MODE=%1
|
||||
if "%MODE%"=="" set MODE=local
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 企微IT智能服务台 — 打包部署
|
||||
echo ========================================
|
||||
echo 模式: %MODE%
|
||||
echo.
|
||||
|
||||
cd /d "%~dp0"
|
||||
|
||||
if "%MODE%"=="deploy" (
|
||||
powershell -ExecutionPolicy Bypass -File ".\build-and-deploy.ps1" -Mode deploy
|
||||
) else (
|
||||
powershell -ExecutionPolicy Bypass -File ".\build-and-deploy.ps1" -Mode local
|
||||
)
|
||||
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo [ERROR] 执行失败,请检查错误信息
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 执行完成
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
if "%MODE%"=="deploy" (
|
||||
echo 部署完成!验证地址:
|
||||
echo - H5: https://itsupport.servyou.com.cn/itdesk/
|
||||
echo - 坐席: https://itsupport.servyou.com.cn/itagent/
|
||||
echo - 管理: https://itsupport.servyou.com.cn/itadmin/
|
||||
) else (
|
||||
echo 本地打包完成!
|
||||
echo 生成文件:
|
||||
echo - it-smart-desk-server-deploy.zip
|
||||
echo - deploy-backend.tar
|
||||
echo.
|
||||
echo 请手动上传到服务器部署目录 /opt/wecom-it-desk/
|
||||
echo 然后执行部署命令
|
||||
)
|
||||
|
||||
echo.
|
||||
pause
|
||||
Reference in New Issue
Block a user