chore: initial baseline with P0-safety .gitignore

This commit is contained in:
Simon
2026-06-14 16:49:18 +08:00
commit 63262292d7
510 changed files with 146008 additions and 0 deletions
+286
View File
@@ -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 安装 DockerCentOS/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 安装 DockerUbuntu/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 端口访问来源(防火墙规则)
+452
View File
@@ -0,0 +1,452 @@
# IT智能服务台 — 新服务器部署手册
> **目标服务器**`10.80.0.136`(公司内网)
> **域名**`itsupport.servyou.com.cn`
> **访问方式**:通过堡垒机 `10.212.189.210:2222`(用户 `sxn`OTP 动态口令认证)
> **Docker**:已安装
> **部署方式**Docker Compose4容器: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/
# 步骤2SSH 到堡垒机
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 通过堡垒机 |
+277
View File
@@ -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 ""
+111
View File
@@ -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
+105
View File
@@ -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"
+155
View File
@@ -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"
+175
View File
@@ -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
+191
View File
@@ -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/;
}
}
}
+210
View File
@@ -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 相同
# ...
# }
}
+112
View File
@@ -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.
+213
View File
@@ -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()
+115
View File
@@ -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"
+65
View File
@@ -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