# 知识管理平台自动化工具 - Docker部署版

这是一个基于 Docker 的知识管理平台自动化工具，支持多用户、定时任务、代理IP、VIP管理、金山文档集成等功能。

---

## 近期更新（2026-02）

- Socket.IO 运行模式已切换为 `eventlet`（生产优先）。
- 管理端前端增加请求缓存/去重，降低报表页重复请求压力。
- 默认 Docker 端口映射更新为 `51232 -> 51233`。
- 已清理仓库中的历史清理报告与明显冗余文件。

---

## 项目简介

本项目是一个 **Docker 容器化应用**，使用 Flask + Vue 3 + Requests + wkhtmltoimage + SQLite 构建，提供：

### 核心功能
- 多用户注册登录系统（支持邮箱绑定与验证）
- 自动化浏览任务（纯 HTTP API 模拟，速度快）
- 智能截图系统（wkhtmltoimage，支持线程池）
- 用户自定义定时任务（支持随机延迟）
- VIP 用户管理（账号数量限制、优先队列）

### 集成功能
- **金山文档集成** - 自动上传截图到在线表格，支持姓名搜索匹配
- **邮件通知** - 任务完成通知、密码重置、邮箱验证
- **代理IP支持** - 动态代理API集成

### 安全功能
- 威胁检测引擎（JNDI/SQL注入/XSS/命令注入检测）
- IP/用户风险评分系统
- 自动黑名单机制
- 登录设备指纹追踪

### 管理功能
- 现代化 Vue 3 SPA 后台管理界面
- 公告系统（支持图片）
- Bug 反馈系统
- 任务日志与统计

---

## 技术栈

- **后端**: Python 3.10+, Flask, Flask-SocketIO
- **前端**: Vue 3 + Vite + Element Plus (SPA)
- **数据库**: SQLite + 连接池
- **自动化**: Requests + BeautifulSoup (浏览)
- **截图**: wkhtmltoimage
- **金山文档**: Playwright (表格操作/上传)
- **容器化**: Docker + Docker Compose
- **实时通信**: Socket.IO (WebSocket)

---

## 项目结构

```
zsglpt/
├── app.py                          # 启动/装配入口
├── routes/                         # 路由层（Blueprint）
│   ├── api_*.py                    # API 路由
│   ├── admin_api/                  # 管理后台 API
│   └── pages.py                    # 页面路由
├── services/                       # 业务服务层
│   ├── tasks.py                    # 任务调度器
│   ├── screenshots.py              # 截图服务
│   ├── kdocs_uploader.py           # 金山文档上传服务
│   └── schedule_*.py               # 定时任务相关
├── security/                       # 安全防护模块
│   ├── threat_detector.py          # 威胁检测引擎
│   ├── risk_scorer.py              # 风险评分
│   ├── blacklist.py                # 黑名单管理
│   └── middleware.py               # 安全中间件
├── realtime/                       # SocketIO 事件与推送
├── database.py                     # 数据库稳定门面（对外 API）
├── db/                             # DB 分域实现 + schema/migrations
├── db_pool.py                      # 数据库连接池
├── api_browser.py                  # Requests 自动化（主浏览流程）
├── browser_pool_worker.py          # wkhtmltoimage 截图线程池
├── app_config.py                   # 配置管理
├── app_logger.py                   # 日志系统
├── app_security.py                 # 安全工具函数
├── password_utils.py               # 密码哈希工具
├── crypto_utils.py                 # 加解密工具
├── email_service.py                # 邮件服务（SMTP）
├── requirements.txt                # Python依赖
├── requirements-dev.txt            # 开发依赖（不进生产镜像）
├── pyproject.toml                  # ruff/pytest 配置
├── Dockerfile                      # Docker镜像构建文件
├── docker-compose.yml              # Docker编排文件
├── templates/                      # HTML模板（SPA 入口）
│   ├── app.html                    # 用户端 SPA 入口
│   ├── admin.html                  # 管理端 SPA 入口
│   └── email/                      # 邮件模板
├── app-frontend/                   # 用户端 Vue 源码
├── admin-frontend/                 # 管理端 Vue 源码
├── static/                         # 前端构建产物
│   ├── app/                        # 用户端 SPA 资源
│   └── admin/                      # 管理端 SPA 资源
└── scripts/                       # 维护脚本（例如健康监控）
```

---

## 部署前准备

### 1. 环境要求

- **服务器**: Linux (Ubuntu 20.04+ / CentOS 7+)
- **Docker**: 20.10+
- **Docker Compose**: 1.29+
- **内存**: 4GB+ (推荐8GB)
- **磁盘**: 20GB+

### 2. SSH连接

**注意**: 本文档假设你已经有服务器的SSH访问权限。

你需要准备：
- 服务器IP地址
- SSH用户名和密码（或SSH密钥）
- SSH端口（默认22）

**SSH连接示例**:
```bash
ssh root@your-server-ip
# 或使用密钥
ssh -i /path/to/key root@your-server-ip
```

---

### 3. 配置加密密钥（重要！）

系统使用 Fernet 对称加密保护用户账号密码。**首次部署或迁移时必须正确配置加密密钥！**

#### 方式一：使用 .env 文件（推荐）

在项目根目录创建 `.env` 文件：

```bash
cd /www/wwwroot/zsglpt

# 生成随机密钥
python3 -c "from cryptography.fernet import Fernet; print(f'ENCRYPTION_KEY_RAW={Fernet.generate_key().decode()}')" > .env

# 设置权限（仅 root 可读）
chmod 600 .env
```

#### 方式二：已有密钥迁移

如果从其他服务器迁移，需要复制原有的密钥：

```bash
# 从旧服务器复制 .env 文件
scp root@old-server:/www/wwwroot/zsglpt/.env /www/wwwroot/zsglpt/
```

#### ⚠️ 重要警告

- **密钥丢失 = 所有加密密码无法解密**，必须重新录入所有账号密码
- `.env` 文件已在 `.gitignore` 中，不会被提交到 Git
- 建议将密钥备份到安全的地方（如密码管理器）
- 系统启动时会检测密钥，如果密钥丢失但存在加密数据，将拒绝启动并报错

---

## 快速部署

### 步骤1: 上传项目文件

将整个 `zsglpt` 文件夹上传到服务器的 `/www/wwwroot/` 目录：

```bash
# 在本地执行（Windows PowerShell 或 Git Bash）
scp -r C:\Users\Administrator\Desktop\zsglpt root@your-server-ip:/www/wwwroot/

# 或者使用 FileZilla、WinSCP 等工具上传
```

上传后，服务器上的路径应该是：`/www/wwwroot/zsglpt/`

### 步骤2: SSH登录服务器

```bash
ssh root@your-server-ip
```

### 步骤3: 进入项目目录

```bash
cd /www/wwwroot/zsglpt
```

### 步骤4: 创建必要的目录

```bash
mkdir -p data logs 截图
chown -R 1000:1000 data logs 截图
chmod 750 data logs 截图
```

> 说明：避免使用 `chmod 777`。如容器内运行用户不是 `1000:1000`，请改为实际 UID/GID。

### 步骤5: 构建并启动Docker容器

```bash
# 构建镜像
docker build -t knowledge-automation .

# 启动容器
docker compose up -d

# 查看容器状态
docker ps | grep knowledge-automation
```

### 步骤6: 检查容器日志

```bash
docker logs -f knowledge-automation-multiuser
```

如果看到以下信息，说明启动成功：
```
服务器启动中...
用户访问地址: http://0.0.0.0:51233
后台管理地址: http://0.0.0.0:51233/yuyx
```

---

## 配置Nginx反向代理（可选但推荐）

如果你想通过域名访问，需要配置Nginx反向代理。

### 1. 安装Nginx

```bash
# Ubuntu/Debian
apt update && apt install nginx -y

# CentOS/RHEL
yum install nginx -y
```

### 2. 创建Nginx配置文件

创建文件 `/etc/nginx/conf.d/zsgpt.conf`:

```nginx
server {
    listen 80;
    server_name your-domain.com;  # 替换为你的域名

    # 日志
    access_log /var/log/nginx/zsgpt_access.log;
    error_log /var/log/nginx/zsgpt_error.log;

    # 反向代理
    location / {
        proxy_pass http://127.0.0.1:51232;
        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;
        client_max_body_size 50M;

        # WebSocket支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }
}
```

### 3. 重启Nginx

```bash
nginx -t           # 测试配置
nginx -s reload    # 重新加载配置
```

### 4. 配置SSL（推荐）

```bash
# 安装certbot
apt install certbot python3-certbot-nginx -y

# 申请证书
certbot --nginx -d your-domain.com

# 自动续期
certbot renew --dry-run
```

---

## 访问系统

### 用户端

- **HTTP**: `http://your-server-ip:51232`
- **域名**: `http://your-domain.com` (配置Nginx后)
- **HTTPS**: `https://your-domain.com` (配置SSL后)

### 后台管理

- **后台地址**: `/yuyx`
- **管理员账号**: 以数据库现有账号为准（首次运行默认创建 `admin`）
- **管理员密码**: 首次运行随机生成，请查看容器启动日志

**首次登录后请立即修改密码！**

---

## 系统配置

登录后台后，在"系统配置"页面可以设置：

### 1. 并发控制
- **全局最大并发**: 2 (根据服务器配置调整)
- **单用户并发**: 1

### 2. 定时任务
- **启用定时浏览**: 是/否
- **执行时间**: 02:00 (CST时间)
- **浏览类型**: 应读/注册前未读
- **执行日期**: 周一到周日

### 3. 代理配置
- **启用代理**: 是/否
- **API地址**: http://your-proxy-api.com
- **IP有效期**: 3分钟

---

## Docker常用命令

### 容器管理

```bash
# 启动容器
docker start knowledge-automation-multiuser

# 停止容器
docker stop knowledge-automation-multiuser

# 重启容器
docker restart knowledge-automation-multiuser

# 删除容器
docker rm -f knowledge-automation-multiuser

# 查看容器状态
docker ps -a | grep knowledge-automation
```

### 日志查看

```bash
# 查看实时日志
docker logs -f knowledge-automation-multiuser

# 查看最近100行日志
docker logs --tail 100 knowledge-automation-multiuser

# 查看应用日志文件
tail -f /www/wwwroot/zsglpt/logs/app.log
```

### 进入容器

```bash
# 进入容器Shell
docker exec -it knowledge-automation-multiuser bash

# 在容器内执行命令
docker exec knowledge-automation-multiuser python -c "print('Hello')"
```

### 重新构建

如果修改了代码，需要重新构建：

```bash
cd /www/wwwroot/zsglpt

# 停止并删除旧容器
docker compose down

# 重新构建并启动
docker compose build
docker compose up -d
```

---

## 数据备份与恢复

### 1. 备份数据

```bash
cd /www/wwwroot

# 备份整个项目
tar -czf zsglpt_backup_$(date +%Y%m%d).tar.gz zsglpt/

# 仅备份数据库
cp /www/wwwroot/zsglpt/data/app_data.db /backup/app_data_$(date +%Y%m%d).db

# 备份截图
tar -czf screenshots_$(date +%Y%m%d).tar.gz /www/wwwroot/zsglpt/截图/
```

### 2. 恢复数据

```bash
# 停止容器
docker stop knowledge-automation-multiuser

# 恢复整个项目
cd /www/wwwroot
tar -xzf zsglpt_backup_20251027.tar.gz

# 恢复数据库
cp /backup/app_data_20251027.db /www/wwwroot/zsglpt/data/app_data.db

# 重启容器
docker start knowledge-automation-multiuser
```

### 3. 定时备份

添加cron任务自动备份：

```bash
crontab -e
```

添加以下内容：

```bash
# 每天凌晨3点备份
0 3 * * * tar -czf /backup/zsglpt_$(date +\%Y\%m\%d).tar.gz /www/wwwroot/zsglpt/data
```

---

## 常见问题

### 1. 容器启动失败

**问题**: `docker compose up -d` 失败

**解决方案**:
```bash
# 查看详细错误
docker compose logs

# 检查端口占用
netstat -tlnp | grep 51232

# 重新构建
docker compose build --no-cache
docker compose up -d
```

### 2. 502 Bad Gateway

**问题**: Nginx返回502错误

**解决方案**:
```bash
# 检查容器是否运行
docker ps | grep knowledge-automation

# 检查端口是否监听
netstat -tlnp | grep 51232

# 测试直接访问
curl http://127.0.0.1:51232

# 检查Nginx配置
nginx -t
```

### 3. 数据库锁定

**问题**: "database is locked"

**解决方案**:
```bash
# 重启容器
docker restart knowledge-automation-multiuser

# 如果问题持续,优化数据库
cd /www/wwwroot/zsglpt
cp data/app_data.db data/app_data.db.backup
sqlite3 data/app_data.db "VACUUM;"
```

### 4. 内存不足

**问题**: 容器OOM (Out of Memory)

**解决方案**:

修改 `docker-compose.yml`：

```yaml
services:
  knowledge-automation:
    mem_limit: 2g
    memswap_limit: 2g
```

然后重启：

```bash
docker compose down
docker compose up -d
```

### 5. 截图工具未安装

**问题**: wkhtmltoimage 命令不存在

**解决方案**:
```bash
# 进入容器手动安装
docker exec -it knowledge-automation-multiuser bash
apt-get update
apt-get install -y wkhtmltopdf

# 验证安装
wkhtmltoimage --version
```

---

## 性能优化

### 1. 调整并发参数

根据服务器配置调整：
- **2核4GB**: 全局并发=1, 单用户并发=1
- **4核8GB**: 全局并发=2, 单用户并发=1
- **8核16GB**: 全局并发=4, 单用户并发=2

### 2. 启用代理IP

避免IP被封，提高成功率：
- 选择稳定的代理服务商
- 设置合适的IP有效期（3-5分钟）
- 启用自动重试机制

### 3. 定期清理数据

系统会自动清理7天前的数据，也可以手动清理：

```bash
# 清理7天前的截图
find /www/wwwroot/zsglpt/截图 -name "*.jpg" -mtime +7 -delete

# 清理旧日志
find /www/wwwroot/zsglpt/logs -name "*.log" -mtime +30 -delete

# 优化数据库
sqlite3 /www/wwwroot/zsglpt/data/app_data.db "VACUUM;"
```

---

## 安全建议

### 1. 修改默认密码

首次登录后立即修改：
- 管理员密码
- 用户密码

### 2. 配置防火墙

```bash
# 只开放必要端口
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --reload

# 禁止直接访问51232端口（仅Nginx可访问）
iptables -A INPUT -p tcp --dport 51232 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 51232 -j DROP
```

### 3. 启用HTTPS

强烈建议使用HTTPS加密传输：

```bash
certbot --nginx -d your-domain.com
```

### 4. 限制SSH访问

```bash
# 修改SSH端口（可选）
vi /etc/ssh/sshd_config
# Port 22222

# 禁止root密码登录（使用密钥）
PermitRootLogin prohibit-password
PasswordAuthentication no

# 重启SSH服务
systemctl restart sshd
```

---

## 监控与维护

### 1. 系统监控

推荐使用以下工具：
- **Docker Stats**: `docker stats knowledge-automation-multiuser`
- **Grafana + Prometheus**: 可视化监控
- **Uptime Kuma**: 服务可用性监控

### 2. 日志分析

```bash
# 统计今日任务数
grep "浏览完成" /www/wwwroot/zsglpt/logs/app.log | grep $(date +%Y-%m-%d) | wc -l

# 查看错误日志
grep "ERROR" /www/wwwroot/zsglpt/logs/app.log | tail -20

# 查看最近的登录
grep "登录成功" /www/wwwroot/zsglpt/logs/app.log | tail -10
```

### 3. 数据库维护

```bash
# 定期优化数据库（每月一次）
docker exec knowledge-automation-multiuser python3 << 'EOF'
import sqlite3
conn = sqlite3.connect('/app/data/app_data.db')
conn.execute('VACUUM')
conn.close()
print("数据库优化完成")
EOF
```

---

## 更新升级

### 1. 更新代码

```bash
# 停止容器
docker compose down

# 备份数据
cp -r data data.backup
cp -r 截图 截图.backup

# 上传新代码（覆盖旧文件）
# 使用 scp 或 FTP 工具上传

# 重新构建并启动
docker compose build
docker compose up -d
```

### 2. 数据库迁移

如果数据库结构有变化，应用会自动迁移。

查看迁移日志：

```bash
docker logs knowledge-automation-multiuser | grep "数据库"
```

---

## 端口说明

| 端口 | 说明 | 映射 |
|------|------|------|
| 51233 | 容器内应用端口 | - |
| 51232 | 主机映射端口 | 容器51233 → 主机51232 |
| 80 | HTTP端口 | Nginx |
| 443 | HTTPS端口 | Nginx |

---

## 环境变量

可以在 `docker-compose.yml` 中设置的环境变量：

| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| ENCRYPTION_KEY_RAW | 加密密钥（Fernet格式，优先级最高） | 从 .env 文件读取 |
| ENCRYPTION_KEY | 加密密钥（会通过PBKDF2派生） | - |
| TZ | 时区 | Asia/Shanghai |
| PYTHONUNBUFFERED | Python输出缓冲 | 1 |
| WKHTMLTOIMAGE_PATH | wkhtmltoimage 可执行文件路径 | 自动探测 |
| WKHTMLTOIMAGE_JS_DELAY_MS | JS 等待时间（毫秒） | 3000 |
| WKHTMLTOIMAGE_WIDTH | 截图宽度 | 1920 |
| WKHTMLTOIMAGE_HEIGHT | 截图高度（视口高度） | 1080 |
| WKHTMLTOIMAGE_FULL_PAGE | 是否输出全页截图（忽略视口高度/裁剪） | 0 |
| WKHTMLTOIMAGE_ZOOM | 渲染缩放比例 | 1.0 |
| WKHTMLTOIMAGE_CROP_WIDTH | 裁剪宽度（0 表示不裁剪） | 默认跟随截图宽度 |
| WKHTMLTOIMAGE_CROP_HEIGHT | 裁剪高度（0 表示不裁剪） | 默认跟随截图高度 |
| WKHTMLTOIMAGE_CROP_X | 裁剪起点 X | 0 |
| WKHTMLTOIMAGE_CROP_Y | 裁剪起点 Y | 0 |
| WKHTMLTOIMAGE_QUALITY | JPG截图质量 | 95 |
| WKHTMLTOIMAGE_TIMEOUT_SECONDS | 截图超时时间（秒） | 60 |
| WKHTMLTOIMAGE_USER_AGENT | 截图使用的 UA | Chrome 120 |

---

## 技术支持

### 项目信息

- **项目名称**: 知识管理平台自动化工具
- **版本**: Docker 多用户版
- **技术栈**: Python + Flask + Requests + wkhtmltopdf + SQLite + Docker

### 常用文档链接

- [Docker 官方文档](https://docs.docker.com/)
- [Flask 官方文档](https://flask.palletsprojects.com/)
- [wkhtmltopdf 官方文档](https://wkhtmltopdf.org/)

### 故障排查

遇到问题时，请按以下顺序检查：

1. **容器日志**: `docker logs knowledge-automation-multiuser`
2. **应用日志**: `cat /www/wwwroot/zsglpt/logs/app.log`
3. **Nginx日志**: `cat /var/log/nginx/zsgpt_error.log`
4. **系统资源**: `docker stats`, `htop`, `df -h`

---

## 许可证

本项目仅供学习和研究使用。

---

**文档版本**: v2.1
**更新日期**: 2026-02-07
**适用版本**: Docker多用户版 + Vue SPA

---

## 快速上手命令清单

```bash
# 1. 上传文件
scp -r zsglpt root@your-ip:/www/wwwroot/

# 2. SSH登录
ssh root@your-ip

# 3. 进入目录并创建必要目录
cd /www/wwwroot/zsglpt
mkdir -p data logs 截图
chmod 777 data logs 截图

# 4. 启动容器
docker compose up -d

# 5. 查看日志
docker logs -f knowledge-automation-multiuser

# 6. 访问系统
# 浏览器打开: http://your-ip:51232
# 后台管理: http://your-ip:51232/yuyx
# 首次管理员密码会写入 data/default_admin_credentials.txt（权限600）
# 登录后请立即修改密码并删除该文件
```

完成！🎉

---

## 更新日志

### v2.0 (2026-01-08)

#### 新功能
- **金山文档集成**: 自动上传截图到金山文档表格
  - 支持姓名搜索匹配单元格
  - 支持配置有效行范围
  - 支持覆盖已有图片
  - 离线状态监控与邮件通知
- **Vue 3 SPA 前端**: 用户端和管理端全面升级为现代化单页应用
  - Element Plus UI 组件库
  - 实时任务状态更新
  - 响应式设计
- **用户自定义定时任务**: 用户可创建自己的定时任务
  - 支持多时间段配置
  - 支持随机延迟
  - 支持选择指定账号
- **安全防护系统**:
  - 威胁检测引擎（JNDI/SQL注入/XSS/命令注入）
  - IP/用户风险评分
  - 自动黑名单机制
- **邮件通知系统**:
  - 任务完成通知
  - 密码重置邮件
  - 邮箱验证
- **公告系统**: 支持图片的系统公告
- **Bug反馈系统**: 用户可提交问题反馈

#### 优化
- **截图线程池**: wkhtmltoimage 截图支持多线程并发
  - 线程池管理，按需启动
  - 空闲自动释放资源
- **二次登录机制**: 刷新"上次登录时间"显示
- **API 预热**: 启动时预热连接，减少首次请求延迟
- **数据库连接池**: 提高并发性能

### v1.0 (2025-10-29)
- 初始版本
- 多用户系统
- 基础自动化任务
- 定时任务调度
- 代理IP支持
