From ea53873fa41006db670eeaa85edfabc2f349a67e Mon Sep 17 00:00:00 2001
From: zhangyuxin <15710070408@163.com>
Date: Thu, 4 Jun 2026 19:21:16 +0800
Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E9=99=8D=E4=BD=8Emaven-compiler-plu?=
=?UTF-8?q?gin=E7=89=88=E6=9C=AC=E5=88=B03.8.1=E4=BB=A5=E5=85=BC=E5=AE=B9M?=
=?UTF-8?q?aven=203.6.2=EF=BC=8C=E6=94=B9=E7=94=A8compilerArgs=E4=BC=A0?=
=?UTF-8?q?=E9=80=92-parameters?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 247e8c042..f48ca0a71 100644
--- a/pom.xml
+++ b/pom.xml
@@ -225,12 +225,14 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.13.0
+ 3.8.1
- true
${java.version}
${java.version}
${project.build.sourceEncoding}
+
+ -parameters
+
From b9dc180f86ad3e04db7b1f1febf7cb8655136a6a Mon Sep 17 00:00:00 2001
From: zhangyuxin <15710070408@163.com>
Date: Thu, 4 Jun 2026 19:49:33 +0800
Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E5=8F=91=E5=B8=83=E8=84=9A=E6=9C=AC=20(webhook=20+=20?=
=?UTF-8?q?deploy.sh=20+=20systemd)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
deploy/README.md | 123 ++++++++++++++++++++++++++++++
deploy/deploy.sh | 81 ++++++++++++++++++++
deploy/ruoyi-webhook.service | 16 ++++
deploy/webhook.py | 144 +++++++++++++++++++++++++++++++++++
4 files changed, 364 insertions(+)
create mode 100644 deploy/README.md
create mode 100644 deploy/deploy.sh
create mode 100644 deploy/ruoyi-webhook.service
create mode 100644 deploy/webhook.py
diff --git a/deploy/README.md b/deploy/README.md
new file mode 100644
index 000000000..825db6669
--- /dev/null
+++ b/deploy/README.md
@@ -0,0 +1,123 @@
+# RuoYi 自动发布配置指南
+
+## 原理
+
+```
+你 push 代码到 Gitee
+ ↓
+Gitee 发送 Webhook 到服务器 :9000/webhook
+ ↓
+webhook.py 验证签名 + 过滤 master 分支
+ ↓
+触发 deploy.sh: git pull → mvn build → 停旧 → 启新
+```
+
+## 第一步:上传文件到服务器
+
+在本地 `deploy/` 目录执行:
+
+```bash
+scp deploy.sh root@47.94.224.255:/opt/ruoyi/
+scp webhook.py root@47.94.224.255:/opt/ruoyi/
+scp ruoyi-webhook.service root@47.94.224.255:/etc/systemd/system/
+```
+
+## 第二步:SSH 登录服务器配置
+
+```bash
+ssh root@47.94.224.255
+```
+
+### 2.1 设置脚本权限
+
+```bash
+chmod +x /opt/ruoyi/deploy.sh
+chmod +x /opt/ruoyi/webhook.py
+```
+
+### 2.2 启动 Webhook 服务
+
+```bash
+systemctl daemon-reload
+systemctl enable ruoyi-webhook
+systemctl start ruoyi-webhook
+systemctl status ruoyi-webhook
+```
+
+### 2.3 验证 Webhook 运行
+
+```bash
+curl http://localhost:9000/health
+# 应返回: OK
+```
+
+### 2.4 开放防火墙端口(如有)
+
+```bash
+# 检查防火墙
+firewall-cmd --state 2>/dev/null || echo "防火墙未运行"
+
+# 如果需要开放
+firewall-cmd --add-port=9000/tcp --permanent
+firewall-cmd --reload
+```
+
+**阿里云安全组也需要放行 9000 端口**(入方向)。
+
+## 第三步:配置 Gitee Webhook
+
+1. 打开 https://gitee.com/zhangYuXinGit/system
+2. 进入 **管理 → WebHooks**
+3. 点击 "添加 WebHook"
+4. 填写:
+ - **URL**: `http://47.94.224.255:9000/webhook`
+ - **密码**: `ruoyi-deploy-2024`
+ - **事件**: 勾选 "Push"(只选 Push 就够了)
+5. 点击 "添加",然后点击 "测试" 验证连接
+
+## 第四步:测试自动发布
+
+在本地修改代码并推送:
+
+```bash
+cd E:\java\project\system
+# 修改一些代码...
+git add .
+git commit -m "test: 测试自动发布"
+git push
+```
+
+然后在服务器查看部署日志:
+
+```bash
+ssh root@47.94.224.255 "tail -f /opt/ruoyi/deploy.log"
+```
+
+## 常用运维命令
+
+```bash
+# 查看 webhook 日志
+tail -f /opt/ruoyi/webhook.log
+
+# 查看部署日志
+tail -f /opt/ruoyi/deploy.log
+
+# 查看应用日志
+tail -f /opt/ruoyi/app.log
+
+# 重启 webhook 服务
+systemctl restart ruoyi-webhook
+
+# 手动触发部署(不走 webhook)
+ssh root@47.94.224.255 "/opt/ruoyi/deploy.sh"
+
+# 停止自动发布
+systemctl stop ruoyi-webhook
+systemctl disable ruoyi-webhook
+```
+
+## 安全建议
+
+- 生产环境建议将 Webhook URL 改为 HTTPS
+- 可修改 `webhook.py` 中的 `WEBHOOK_SECRET` 更换密钥
+- 可在阿里云安全组中限制 9000 端口仅允许 Gitee 的 IP 访问
diff --git a/deploy/deploy.sh b/deploy/deploy.sh
new file mode 100644
index 000000000..23ce52990
--- /dev/null
+++ b/deploy/deploy.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+#===========================================================================
+# RuoYi 自动部署脚本
+# 触发方式: Gitee Webhook → webhook.py → deploy.sh
+#===========================================================================
+
+set -e
+
+APP_DIR=/opt/ruoyi
+JAR_FILE=$APP_DIR/ruoyi-admin/target/ruoyi-admin.jar
+LOG_FILE=$APP_DIR/app.log
+DEPLOY_LOG=$APP_DIR/deploy.log
+PROFILE=druid
+PORT=8080
+
+log() {
+ echo "$(date '+%Y-%m-%d %H:%M:%S') [DEPLOY] $1" | tee -a "$DEPLOY_LOG"
+}
+
+log "========== 开始部署 =========="
+
+# 1. 拉取最新代码
+cd "$APP_DIR"
+log "拉取最新代码..."
+git pull origin master 2>&1 | tee -a "$DEPLOY_LOG"
+
+# 2. Maven 构建
+log "开始 Maven 构建..."
+mvn clean package -DskipTests -pl ruoyi-admin -am -q 2>&1 | tee -a "$DEPLOY_LOG"
+
+if [ ! -f "$JAR_FILE" ]; then
+ log "构建失败: JAR 文件不存在"
+ exit 1
+fi
+
+log "构建成功"
+
+# 3. 停止旧进程
+OLD_PID=$(ps aux | grep ruoyi-admin.jar | grep -v grep | awk '{print $2}')
+if [ -n "$OLD_PID" ]; then
+ log "停止旧进程 PID: $OLD_PID"
+ kill "$OLD_PID"
+ sleep 3
+ if ps -p "$OLD_PID" > /dev/null 2>&1; then
+ kill -9 "$OLD_PID"
+ log "强制停止 PID: $OLD_PID"
+ fi
+fi
+
+# 4. 启动新进程
+log "启动新进程..."
+nohup java -Xms128m -Xmx384m -jar "$JAR_FILE" \
+ --spring.profiles.active="$PROFILE" \
+ --server.port="$PORT" \
+ > "$LOG_FILE" 2>&1 &
+
+NEW_PID=$!
+log "新进程 PID: $NEW_PID"
+
+# 5. 等待启动
+sleep 5
+if ps -p "$NEW_PID" > /dev/null 2>&1; then
+ log "应用启动中,等待就绪..."
+ for i in 1 2 3 4 5 6; do
+ if grep -q "Started RuoYiApplication" "$LOG_FILE" 2>/dev/null; then
+ log "部署成功! 应用已就绪"
+ break
+ fi
+ sleep 5
+ done
+else
+ log "启动失败! 查看日志: tail -50 $LOG_FILE"
+ exit 1
+fi
+
+# 6. 健康检查
+sleep 3
+HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$PORT 2>/dev/null || echo "000")
+log "健康检查 HTTP $HTTP_CODE"
+
+log "========== 部署结束 =========="
diff --git a/deploy/ruoyi-webhook.service b/deploy/ruoyi-webhook.service
new file mode 100644
index 000000000..cdde61b3b
--- /dev/null
+++ b/deploy/ruoyi-webhook.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=RuoYi Webhook Deploy Service
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/opt/ruoyi
+ExecStart=/usr/bin/python3 /opt/ruoyi/webhook.py
+Restart=always
+RestartSec=10
+StandardOutput=append:/opt/ruoyi/webhook.log
+StandardError=append:/opt/ruoyi/webhook.log
+
+[Install]
+WantedBy=multi-user.target
diff --git a/deploy/webhook.py b/deploy/webhook.py
new file mode 100644
index 000000000..86c8abbaf
--- /dev/null
+++ b/deploy/webhook.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python3
+"""
+RuoYi Gitee Webhook 接收服务
+
+接收 Gitee 推送事件,触发自动部署。
+启动: python3 webhook.py
+"""
+
+import hashlib
+import hmac
+import json
+import subprocess
+import time
+from http.server import HTTPServer, BaseHTTPRequestHandler
+from datetime import datetime
+
+# ============ 配置 ============
+LISTEN_HOST = "0.0.0.0"
+LISTEN_PORT = 9000
+
+# Gitee Webhook 密码(请在 Gitee 仓库设置中配置相同的密钥)
+WEBHOOK_SECRET = "ruoyi-deploy-2024"
+
+# 部署脚本路径
+DEPLOY_SCRIPT = "/opt/ruoyi/deploy.sh"
+
+# 部署锁文件,防止并发部署
+LOCK_FILE = "/tmp/ruoyi-deploy.lock"
+
+# ============ 日志 ============
+def log(msg):
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ line = f"[{timestamp}] [WEBHOOK] {msg}"
+ print(line, flush=True)
+
+
+class WebhookHandler(BaseHTTPRequestHandler):
+
+ def do_POST(self):
+ if self.path != "/webhook":
+ self.send_response(404)
+ self.end_headers()
+ return
+
+ # 读取请求体
+ content_length = int(self.headers.get("Content-Length", 0))
+ body = self.rfile.read(content_length)
+
+ # 验证签名
+ signature = self.headers.get("X-Gitee-Token", "")
+ if signature != WEBHOOK_SECRET:
+ log(f"签名验证失败: {signature[:20]}...")
+ self.send_response(403)
+ self.end_headers()
+ self.wfile.write(b"Forbidden")
+ return
+
+ # 解析事件
+ try:
+ data = json.loads(body)
+ except json.JSONDecodeError:
+ log("JSON 解析失败")
+ self.send_response(400)
+ self.end_headers()
+ return
+
+ event = self.headers.get("X-Gitee-Event", "unknown")
+ ref = data.get("ref", "")
+ pusher = data.get("pusher", {}).get("name", "unknown")
+
+ log(f"收到事件: {event} | 分支: {ref} | 推送者: {pusher}")
+
+ # 只处理 master 分支的 push 事件
+ if event != "push_hooks" or ref != "refs/heads/master":
+ log(f"忽略事件: {event} / {ref}")
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b"Ignored")
+ return
+
+ # 检查锁
+ if self._is_locked():
+ log("部署正在进行中,忽略重复触发")
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b"Deploy already in progress")
+ return
+
+ # 异步执行部署
+ self._lock()
+ subprocess.Popen(
+ ["/bin/bash", DEPLOY_SCRIPT],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ )
+
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b"Deploy started")
+
+ def do_GET(self):
+ """健康检查"""
+ if self.path == "/health":
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b"OK")
+ else:
+ self.send_response(404)
+ self.end_headers()
+
+ def _is_locked(self):
+ try:
+ with open(LOCK_FILE, "r") as f:
+ lock_time = float(f.read().strip())
+ # 锁超过 30 分钟自动过期
+ if time.time() - lock_time > 1800:
+ return False
+ return True
+ except FileNotFoundError:
+ return False
+
+ def _lock(self):
+ with open(LOCK_FILE, "w") as f:
+ f.write(str(time.time()))
+
+ def log_message(self, format, *args):
+ """重写默认日志,改为简洁格式"""
+ log(f"{self.client_address[0]} - {format % args}")
+
+
+def main():
+ log(f"Webhook 服务启动在 http://{LISTEN_HOST}:{LISTEN_PORT}/webhook")
+ log(f"密钥: {WEBHOOK_SECRET[:4]}****")
+
+ server = HTTPServer((LISTEN_HOST, LISTEN_PORT), WebhookHandler)
+ try:
+ server.serve_forever()
+ except KeyboardInterrupt:
+ log("服务已停止")
+ server.server_close()
+
+
+if __name__ == "__main__":
+ main()
From dfff5bc9d37d678a8fca044e056977c918e446e7 Mon Sep 17 00:00:00 2001
From: zhangyuxin <15710070408@163.com>
Date: Thu, 4 Jun 2026 20:00:55 +0800
Subject: [PATCH 3/4] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E9=A1=B9?=
=?UTF-8?q?=E7=9B=AE=E6=96=87=E6=A1=A3=E5=92=8C=E4=BF=AE=E5=A4=8D=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E5=8F=91=E5=B8=83=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
DEPLOY.md | 102 +++++++++
PROJECT_DOC.md | 431 +++++++++++++++++++++++++++++++++++
deploy/ruoyi-webhook.service | 2 +-
deploy/webhook.py | 4 +-
4 files changed, 536 insertions(+), 3 deletions(-)
create mode 100644 DEPLOY.md
create mode 100644 PROJECT_DOC.md
diff --git a/DEPLOY.md b/DEPLOY.md
new file mode 100644
index 000000000..b220c49b5
--- /dev/null
+++ b/DEPLOY.md
@@ -0,0 +1,102 @@
+# 若依系统发版指南
+
+## 服务器信息
+
+| 项目 | 值 |
+|------|-----|
+| IP | 47.94.224.255 |
+| 系统 | Alibaba Cloud Linux 3 |
+| SSH | `ssh root@47.94.224.255` |
+| 应用端口 | 8080 |
+| 访问地址 | http://47.94.224.255:8080 |
+| 默认账号 | admin / admin123 |
+
+## 服务器环境
+
+- JDK 17 (`/usr/lib/jvm/java-17-openjdk`)
+- Maven 3.6.2
+- MySQL 8.0.45 (数据库 `ry`)
+
+## 发版步骤
+
+### 1. 拉取最新代码
+
+```bash
+cd E:\java\project\system
+git pull
+```
+
+### 2. 上传到服务器
+
+```bash
+scp pom.xml root@47.94.224.255:/opt/ruoyi/pom.xml
+scp -r ruoyi-admin/src root@47.94.224.255:/opt/ruoyi/ruoyi-admin/
+scp -r ruoyi-common/src root@47.94.224.255:/opt/ruoyi/ruoyi-common/
+scp -r ruoyi-framework/src root@47.94.224.255:/opt/ruoyi/ruoyi-framework/
+scp -r ruoyi-system/src root@47.94.224.255:/opt/ruoyi/ruoyi-system/
+scp -r ruoyi-generator/src root@47.94.224.255:/opt/ruoyi/ruoyi-generator/
+scp -r ruoyi-quartz/src root@47.94.224.255:/opt/ruoyi/ruoyi-quartz/
+```
+
+### 3. SSH 登录服务器
+
+```bash
+ssh root@47.94.224.255
+```
+
+### 4. 停旧进程
+
+```bash
+kill $(ps aux | grep ruoyi-admin.jar | grep -v grep | awk '{print $2}')
+```
+
+### 5. 构建
+
+```bash
+cd /opt/ruoyi && mvn clean package -DskipTests -pl ruoyi-admin -am
+```
+
+### 6. 启动
+
+```bash
+nohup java -Xms128m -Xmx384m -jar /opt/ruoyi/ruoyi-admin/target/ruoyi-admin.jar --spring.profiles.active=druid --server.port=8080 > /opt/ruoyi/app.log 2>&1 &
+```
+
+### 7. 验证
+
+```bash
+tail -20 /opt/ruoyi/app.log
+```
+
+看到 `Started RuoYiApplication` 即成功。
+
+## 一键重启脚本(不涉及代码更新)
+
+```bash
+ssh root@47.94.224.255 "kill \$(ps aux | grep ruoyi-admin.jar | grep -v grep | awk '{print \$2}'); cd /opt/ruoyi && nohup java -Xms128m -Xmx384m -jar /opt/ruoyi/ruoyi-admin/target/ruoyi-admin.jar --spring.profiles.active=druid --server.port=8080 > /opt/ruoyi/app.log 2>&1 &"
+```
+
+## 常用运维命令
+
+```bash
+# 查看应用状态
+ps aux | grep ruoyi-admin
+
+# 查看日志
+tail -100f /opt/ruoyi/app.log
+
+# 停应用
+kill $(ps aux | grep ruoyi-admin.jar | grep -v grep | awk '{print $2}')
+
+# 查看端口
+ss -tlnp | grep 8080
+```
+
+## 注意事项
+
+- 不要升级 `maven-compiler-plugin` 版本(当前 3.8.1),服务器 Maven 3.6.2 不支持更高版本
+- 应用默认端口为 80,通过 `--server.port=8080` 覆盖
+- 如果出现 JNI 错误,检查默认 Java 版本是否为 17:
+ ```bash
+ alternatives --set java /usr/lib/jvm/java-17-openjdk-17.0.19.0.10-1.0.2.1.al8.x86_64/bin/java
+ ```
diff --git a/PROJECT_DOC.md b/PROJECT_DOC.md
new file mode 100644
index 000000000..1ba095cb1
--- /dev/null
+++ b/PROJECT_DOC.md
@@ -0,0 +1,431 @@
+# 若依管理系统 (RuoYi) 项目文档
+
+> 版本: v4.8.3 · 技术栈: Spring Boot 4.0.3 + JDK 17 + Shiro + MyBatis + Thymeleaf
+
+---
+
+## 一、项目简介
+
+若依 (RuoYi) 是一个基于 Spring Boot 的**轻量级 Java 快速开发框架**,内置完善的后台管理系统基础功能,适合中小型企业管理后台的快速搭建。
+
+### 核心能力
+
+- **权限管理**: 用户 / 角色 / 菜单 / 部门 / 岗位,支持按钮级权限控制 (RBAC)
+- **数据字典**: 动态配置下拉选项、状态值
+- **参数配置**: 系统参数在线调整
+- **操作日志**: 记录所有用户操作,支持导出
+- **登录日志**: 记录登录历史,支持异常锁定与解锁
+- **在线用户**: 查看当前在线用户,支持批量强退
+- **定时任务**: Quartz 调度,可在线添加 Cron 表达式,支持立即执行
+- **代码生成**: 根据数据库表一键生成完整 CRUD 代码(Controller/Service/Mapper/页面)
+- **服务监控**: 实时 CPU / 内存 / 磁盘 / JVM 监控
+- **缓存监控**: EhCache 缓存内容查看与清空
+- **数据监控**: Druid 连接池 SQL 监控
+- **通知公告**: 发布系统通知,已读状态追踪
+- **表单构建**: 拖拽生成表单 HTML
+- **系统接口**: 集成 Swagger/SpringDoc 接口文档
+
+---
+
+## 二、项目结构
+
+```
+system/
+├── ruoyi-admin/ Web 入口层:所有 Controller + Thymeleaf 页面模板
+├── ruoyi-common/ 通用工具:注解、枚举、字符串/文件/安全/Excel 工具类
+├── ruoyi-framework/ 框架核心:Shiro 认证、数据源、AOP、全局异常处理
+├── ruoyi-system/ 业务服务层:Service 接口/实现、Domain 实体、Mapper XML
+├── ruoyi-quartz/ 定时任务模块:Quartz 调度控制器
+├── ruoyi-generator/ 代码生成模块:Velocity 模板生成 CRUD 代码
+├── sql/
+│ ├── ry_20260319.sql 业务数据库(21张表 + 种子数据)
+│ └── quartz.sql Quartz 调度器表(11张)
+└── DEPLOY.md 发版部署指南
+```
+
+---
+
+## 三、所有账号密码
+
+| 系统 | 地址 | 用户名 | 密码 | 说明 |
+|------|------|--------|------|------|
+| 管理后台 | http://47.94.224.255:8080 | **admin** | **admin123** | 超级管理员 |
+| 管理后台 | http://47.94.224.255:8080 | **ry** | **admin123** | 普通用户(测试用) |
+| Druid 监控 | http://47.94.224.255:8080/druid | **ruoyi** | **123456** | 数据库连接池监控 |
+| Swagger 接口 | http://47.94.224.255:8080/swagger-ui/index.html | — | — | 无需登录访问 |
+| MySQL 数据库 | localhost:3306 | **root** | **password** | 数据库直接连接 |
+
+### 密码策略
+
+- 系统初始密码(新增用户时): **123456**
+- 密码加密方式: Shiro MD5(md5(password) + salt),迭代 1024 次
+- 登录错误锁定: 5 次错误后锁定 10 分钟
+- 验证码: 开启,算术验证码
+
+---
+
+## 四、管理后台功能模块与菜单
+
+### 4.1 系统管理
+
+| 菜单 | 路径 | 说明 |
+|------|------|------|
+| **用户管理** | `/system/user` | 增删改查用户,分配角色,重置密码,导入/导出 Excel |
+| **角色管理** | `/system/role` | 管理角色,分配菜单权限、数据权限(按部门) |
+| **菜单管理** | `/system/menu` | 配置菜单树,设置权限标识(按钮级控制) |
+| **部门管理** | `/system/dept` | 组织架构树(公司 → 部门 → 小组) |
+| **岗位管理** | `/system/post` | 岗位独立管理,用户可关联岗位 |
+| **字典管理** | `/system/dict` | 键值对字典(如性别、状态等),支持刷新缓存 |
+| **参数设置** | `/system/config` | 系统全局参数 key-value 在线修改 |
+| **通知公告** | `/system/notice` | 发布通知,标记已读,统计已读人数 |
+| **操作日志** | `/monitor/operlog` | 记录用户增删改操作,支持导出和清空 |
+| **登录日志** | `/monitor/logininfor` | 登录记录,支持账户解锁 |
+
+### 4.2 系统监控
+
+| 菜单 | 路径 | 说明 |
+|------|------|------|
+| **在线用户** | `/monitor/online` | 当前登录用户列表,支持批量强退 |
+| **定时任务** | `/monitor/job` | 管理 Quartz 任务,Cron 在线生成 |
+| **数据监控** | `/monitor/data` | 跳转 Druid 控制台(SQL 监控、URI 监控) |
+| **服务监控** | `/monitor/server` | 实时服务器状态:CPU、内存、磁盘、JVM |
+| **缓存监控** | `/monitor/cache` | EhCache 缓存查看、清空 |
+
+### 4.3 系统工具
+
+| 菜单 | 路径 | 说明 |
+|------|------|------|
+| **代码生成** | `/tool/gen` | 导入数据库表 → 生成 Controller/Service/Mapper/页面 |
+| **表单构建** | `/tool/build` | 拖拽式表单设计器,生成 HTML 代码 |
+| **系统接口** | `/tool/swagger` | 跳转 Swagger UI,查看所有 API 接口 |
+
+---
+
+## 五、接口文档
+
+### 5.1 认证相关
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/login` | 登录页面 |
+| `POST` | `/login` | Ajax 登录(参数: `username`, `password`, `rememberMe`) |
+| `GET` | `/captcha/captchaImage` | 获取验证码图片(参数: `type=math\|char`) |
+| `GET` | `/register` | 注册页面 |
+| `POST` | `/register` | Ajax 注册新用户 |
+| `GET` | `/logout` | 退出登录 |
+
+### 5.2 系统管理接口
+
+#### 用户管理 `/system/user`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/user/list` | 分页查询用户列表 |
+| `POST` | `/system/user/export` | 导出用户数据 Excel |
+| `POST` | `/system/user/importData` | 导入用户数据 |
+| `GET` | `/system/user/authRole/{userId}` | 查询用户角色分配 |
+| `POST` | `/system/user/authRole` | 保存用户角色分配 |
+| `POST` | `/system/user/add` | 新增用户 |
+| `GET` | `/system/user/edit/{userId}` | 编辑用户页面 |
+| `POST` | `/system/user/edit` | 保存编辑 |
+| `POST` | `/system/user/remove` | 批量删除用户 |
+| `POST` | `/system/user/resetPwd` | 重置密码为初始密码 |
+| `POST` | `/system/user/changeStatus` | 启用/停用用户 |
+| `POST` | `/system/user/checkLoginNameUnique` | 校验登录名唯一 |
+| `GET` | `/system/user/deptTreeData` | 获取部门树数据 |
+
+#### 角色管理 `/system/role`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/role/list` | 分页查询角色列表 |
+| `POST` | `/system/role/export` | 导出 |
+| `POST` | `/system/role/add` | 新增 |
+| `POST` | `/system/role/edit` | 修改 |
+| `POST` | `/system/role/remove` | 删除 |
+| `GET/POST` | `/system/role/authDataScope` | 数据权限分配 |
+| `GET` | `/system/role/authUser/allocatedList` | 已分配用户列表 |
+| `GET` | `/system/role/authUser/unallocatedList` | 未分配用户列表 |
+| `POST` | `/system/role/authUser/selectAll` | 批量分配用户 |
+| `POST` | `/system/role/authUser/cancel` | 取消单个用户授权 |
+| `POST` | `/system/role/authUser/cancelAll` | 批量取消授权 |
+
+#### 菜单管理 `/system/menu`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/menu/list` | 菜单树列表 |
+| `POST` | `/system/menu/add` | 新增菜单/按钮 |
+| `POST` | `/system/menu/edit` | 修改 |
+| `POST` | `/system/menu/remove/{menuId}` | 删除 |
+| `GET` | `/system/menu/roleMenuTreeData` | 加载角色菜单树(含权限标识) |
+| `GET` | `/system/menu/menuTreeData` | 获取所有菜单树数据 |
+| `GET` | `/system/menu/icon` | 图标列表 |
+
+#### 部门管理 `/system/dept`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/dept/list` | 部门树列表 |
+| `POST` | `/system/dept/add` | 新增部门 |
+| `POST` | `/system/dept/edit` | 修改 |
+| `GET` | `/system/dept/remove/{deptId}` | 删除 |
+| `GET` | `/system/dept/selectDeptTree/{deptId}` | 选择部门树(排除指定部门) |
+
+#### 岗位管理 `/system/post`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/post/list` | 分页查询 |
+| `POST` | `/system/post/export` | 导出 |
+| `POST` | `/system/post/add` | 新增 |
+| `POST` | `/system/post/edit` | 修改 |
+| `POST` | `/system/post/remove` | 删除 |
+
+#### 字典管理
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/dict/list` | 字典类型分页 |
+| `GET` | `/system/dict/detail/{dictId}` | 字典类型详情 |
+| `GET` | `/system/dict/treeData` | 字典树 |
+| `POST` | `/system/dict/add` | 新增字典类型 |
+| `POST` | `/system/dict/edit` | 修改 |
+| `POST` | `/system/dict/remove` | 删除 |
+| `POST` | `/system/dict/refreshCache` | 刷新字典缓存 |
+| `GET` | `/system/dict/data/list` | 字典数据分页 |
+| `POST` | `/system/dict/data/add` | 新增字典数据 |
+| `POST` | `/system/dict/data/edit` | 修改字典数据 |
+| `POST` | `/system/dict/data/remove` | 删除字典数据 |
+
+#### 参数配置 `/system/config`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/config/list` | 分页查询 |
+| `POST` | `/system/config/add` | 新增 |
+| `POST` | `/system/config/edit` | 修改 |
+| `POST` | `/system/config/remove` | 删除 |
+| `POST` | `/system/config/refreshCache` | 刷新缓存 |
+
+#### 通知公告 `/system/notice`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/notice/list` | 分页查询 |
+| `POST` | `/system/notice/add` | 新增 |
+| `POST` | `/system/notice/edit` | 修改 |
+| `POST` | `/system/notice/remove` | 删除 |
+
+#### 个人信息 `/system/user/profile`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/system/user/profile` | 个人信息页面 |
+| `POST` | `/system/user/profile/update` | 修改基本信息 |
+| `POST` | `/system/user/profile/resetPwd` | 修改密码 |
+| `POST` | `/system/user/profile/avatar` | 上传头像 |
+| `POST` | `/system/user/profile/checkPassword` | 校验密码 |
+
+### 5.3 系统监控接口
+
+#### 在线用户 `/monitor/online`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/monitor/online/list` | 在线用户列表 |
+| `POST` | `/monitor/online/batchForceLogout` | 批量强退 |
+
+#### 操作日志 `/monitor/operlog`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/monitor/operlog/list` | 分页查询 |
+| `POST` | `/monitor/operlog/export` | 导出 |
+| `POST` | `/monitor/operlog/remove` | 删除 |
+| `POST` | `/monitor/operlog/clean` | 清空所有日志 |
+
+#### 登录日志 `/monitor/logininfor`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/monitor/logininfor/list` | 分页查询 |
+| `POST` | `/monitor/logininfor/export` | 导出 |
+| `POST` | `/monitor/logininfor/remove` | 删除 |
+| `POST` | `/monitor/logininfor/clean` | 清空 |
+| `POST` | `/monitor/logininfor/unlock/{loginName}` | 账户解锁 |
+
+#### 缓存监控 `/monitor/cache`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/monitor/cache` | 缓存监控页面 |
+| `GET` | `/monitor/cache/getNames` | 获取缓存名称列表 |
+| `GET` | `/monitor/cache/getKeys/{cacheName}` | 获取缓存 key 列表 |
+| `GET` | `/monitor/cache/getValue/{cacheName}/{cacheKey}` | 获取缓存值 |
+| `POST` | `/monitor/cache/clearCacheName/{cacheName}` | 清空指定缓存名 |
+| `POST` | `/monitor/cache/clearCacheKey/{cacheKey}` | 清空指定 key |
+| `POST` | `/monitor/cache/clearAll` | 清空所有缓存 |
+
+### 5.4 定时任务 `/monitor/job`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/monitor/job/list` | 任务列表 |
+| `POST` | `/monitor/job/add` | 新增任务 |
+| `POST` | `/monitor/job/edit` | 修改任务 |
+| `POST` | `/monitor/job/remove` | 删除 |
+| `POST` | `/monitor/job/changeStatus` | 启动/暂停 |
+| `POST` | `/monitor/job/run` | 立即执行一次 |
+| `GET` | `/monitor/job/cron` | Cron 生成器页面 |
+
+#### 任务日志 `/monitor/jobLog`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/monitor/jobLog/list` | 调度日志分页 |
+| `POST` | `/monitor/jobLog/export` | 导出 |
+| `POST` | `/monitor/jobLog/remove` | 删除 |
+| `POST` | `/monitor/jobLog/clean` | 清空 |
+
+### 5.5 代码生成 `/tool/gen`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/tool/gen/list` | 已导入表列表 |
+| `GET` | `/tool/gen/db/list` | 数据库表列表(可选择导入) |
+| `GET` | `/tool/gen/column/list` | 某表字段信息 |
+| `POST` | `/tool/gen/importTable` | 导入表到代码生成器 |
+| `POST` | `/tool/gen/createTable` | 创建表 |
+| `POST` | `/tool/gen/edit` | 修改生成配置 |
+| `GET` | `/tool/gen/preview/{tableId}` | 预览生成代码 |
+| `GET` | `/tool/gen/download/{tableName}` | 下载代码 ZIP |
+| `GET` | `/tool/gen/genCode/{tableName}` | 生成代码到本地项目 |
+| `GET` | `/tool/gen/synchDb/{tableName}` | 同步数据库表结构 |
+| `POST` | `/tool/gen/batchGenCode` | 批量生成代码 |
+
+### 5.6 通用功能 `/common`
+
+| 方法 | 路径 | 说明 |
+|------|------|------|
+| `GET` | `/common/download` | 文件下载 |
+| `POST` | `/common/upload` | 单文件上传(参数: `file`) |
+| `POST` | `/common/uploads` | 多文件上传 |
+| `GET` | `/common/download/resource` | 本地资源下载 |
+
+---
+
+## 六、数据库表说明
+
+### 系统管理表 (13张)
+
+| 表名 | 说明 |
+|------|------|
+| `sys_user` | 用户表 |
+| `sys_dept` | 部门表(树形结构) |
+| `sys_post` | 岗位表 |
+| `sys_role` | 角色表 |
+| `sys_menu` | 菜单/权限表(M=目录, C=菜单, F=按钮) |
+| `sys_user_role` | 用户-角色关联 |
+| `sys_role_menu` | 角色-菜单关联 |
+| `sys_role_dept` | 角色-部门数据权限 |
+| `sys_user_post` | 用户-岗位关联 |
+| `sys_dict_type` | 字典类型 |
+| `sys_dict_data` | 字典数据 |
+| `sys_config` | 系统参数配置 |
+| `sys_oper_log` | 操作日志 |
+
+### 监控/日志表 (5张)
+
+| 表名 | 说明 |
+|------|------|
+| `sys_logininfor` | 登录日志 |
+| `sys_user_online` | 在线用户记录 |
+| `sys_notice` | 通知公告 |
+| `sys_notice_read` | 通知已读记录 |
+| `sys_job` | 定时任务配置 |
+| `sys_job_log` | 定时任务执行日志 |
+
+### 代码生成表 (2张)
+
+| 表名 | 说明 |
+|------|------|
+| `gen_table` | 代码生成表配置 |
+| `gen_table_column` | 代码生成字段配置 |
+
+---
+
+## 七、常见操作指南
+
+### 新增菜单
+
+1. 打开 **系统管理 → 菜单管理**
+2. 点击 "新增",选择类型:
+ - **目录**: 作为父级菜单分组(如"系统管理")
+ - **菜单**: 实际页面入口,填写请求地址(如 `/system/user`)
+ - **按钮**: 页面上的操作按钮(新增/修改/删除),填写权限标识(如 `system:user:add`)
+3. 保存后在 **角色管理** 中给角色分配新菜单权限
+
+### 新增用户
+
+1. 打开 **系统管理 → 用户管理**
+2. 点击 "新增",填写登录名、用户姓名、部门、角色、岗位
+3. 初始密码为 `123456`,用户首次登录可修改
+
+### 使用代码生成器
+
+1. 打开 **系统工具 → 代码生成**
+2. 点击 "导入",选择要生成代码的数据库表
+3. 点击 "编辑" 可调整字段信息、生成模板
+4. 点击 "生成代码",可预览或下载 ZIP
+5. 若选择 "生成到项目",代码会写入对应模块目录
+
+### 创建定时任务
+
+1. 先在项目中编写任务方法(实现 `Job` 接口或使用 `@Scheduled`)
+2. 打开 **系统监控 → 定时任务**
+3. 点击 "新增",填写:
+ - **调用目标字符串**: 如 `ryTask.ryNoParams`
+ - **Cron 表达式**: 可使用在线生成器
+4. 点击状态按钮启动任务
+
+### 自定义数据权限
+
+1. 打开 **系统管理 → 角色管理**
+2. 点击 "更多 → 数据权限"
+3. 选择范围:
+ - **全部数据权限**: 可看所有数据
+ - **自定数据权限**: 只能看指定部门
+ - **本部门数据权限**: 只看自己的部门
+ - **本部门及以下**: 看自己和子部门
+ - **仅本人**: 只能看自己的数据
+
+---
+
+## 八、配置参考
+
+| 配置项 | 默认值 | 说明 |
+|--------|--------|------|
+| `server.port` | 80 (生产 8080) | 服务端口 |
+| `ruoyi.name` | RuoYi | 项目名称(显示在页面标题) |
+| `ruoyi.version` | 4.8.3 | 版本号 |
+| `ruoyi.demoEnabled` | true | 演示模式(禁止修改敏感数据) |
+| `ruoyi.profile` | D:/ruoyi/uploadPath | 文件上传目录 |
+| `shiro.captchaEnabled` | true | 验证码开关 |
+| `shiro.captchaType` | math | 验证码类型 (math/char) |
+| `shiro.maxSession` | -1 | 最大会话数(-1 不限) |
+| `shiro.session.timeout` | 30min | Session 超时 |
+| `shiro.login.maxRetryCount` | 5 | 登录错误锁定次数 |
+| `shiro.login.lockTime` | 10min | 锁定时间 |
+| `sys.user.initPassword` | 123456 | 新增/重置密码时的初始密码 |
+
+---
+
+## 九、注意事项
+
+- **演示模式**: 生产部署建议关闭 `ruoyi.demoEnabled`,否则无法新增/修改/删除系统用户、角色等
+- **验证码**: 生产环境建议开启,类型可选 `math`(算术)或 `char`(字符)
+- **文件上传路径**: 默认 `D:/ruoyi/uploadPath`,Linux 服务器需改为 `/home/ruoyi/uploadPath` 等实际路径
+- **数据库密码**: 请修改 `application-druid.yml` 中的数据库密码
+- **Swagger**: 默认 `/swagger-ui/index.html`,生产环境建议关闭或加权限
+- **Druid 监控**: 默认 `/druid/*`,账号 `ruoyi/123456`,生产环境建议改密码
diff --git a/deploy/ruoyi-webhook.service b/deploy/ruoyi-webhook.service
index cdde61b3b..0c0820387 100644
--- a/deploy/ruoyi-webhook.service
+++ b/deploy/ruoyi-webhook.service
@@ -6,7 +6,7 @@ After=network.target
Type=simple
User=root
WorkingDirectory=/opt/ruoyi
-ExecStart=/usr/bin/python3 /opt/ruoyi/webhook.py
+ExecStart=/usr/bin/python3 /opt/ruoyi/deploy/webhook.py
Restart=always
RestartSec=10
StandardOutput=append:/opt/ruoyi/webhook.log
diff --git a/deploy/webhook.py b/deploy/webhook.py
index 86c8abbaf..f0b79285d 100644
--- a/deploy/webhook.py
+++ b/deploy/webhook.py
@@ -16,10 +16,10 @@ from datetime import datetime
# ============ 配置 ============
LISTEN_HOST = "0.0.0.0"
-LISTEN_PORT = 9000
+LISTEN_PORT = 9999
# Gitee Webhook 密码(请在 Gitee 仓库设置中配置相同的密钥)
-WEBHOOK_SECRET = "ruoyi-deploy-2024"
+WEBHOOK_SECRET = "ruoyi-auto-deploy"
# 部署脚本路径
DEPLOY_SCRIPT = "/opt/ruoyi/deploy.sh"
From 4e3867eee1d81cdca034fdcc27744c61bc4a7c8c Mon Sep 17 00:00:00 2001
From: zhangyuxin <15710070408@163.com>
Date: Thu, 4 Jun 2026 20:06:58 +0800
Subject: [PATCH 4/4] =?UTF-8?q?test:=20=E6=B5=8B=E8=AF=95=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E5=8F=91=E5=B8=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0efbf50a1..5997015b0 100644
--- a/README.md
+++ b/README.md
@@ -108,4 +108,4 @@ RuoYi 框架提供 Spring Boot 2.x / 3.x / 4.x 多版本分支的并行维护。
## 若依交流群
-QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc) [](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [](https://jq.qq.com/?_wv=1027&k=540WfdEr) [](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XwhV8deuZXt__yteR1clNanVSXzA-ugq&authKey=ezgwKqEZPdP%2FgC9I03OBkJb%2Biii8yvVfwrcQuu0%2FL6ILXcRdHYDBFKCXeoeBT0E6&noverify=0&group_code=180208928) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=WqsGDxpGkqOPeWGOf3I32f_rXxdhqYNr&authKey=kvdF5df7PO9bzWxmixKhZN6ShsECBiuGUmmzTZBWVr2MVOfJ8%2F4oD0Gws0rbgYfz&noverify=0&group_code=140284548) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=z9z9jkkkinfAElKZk2FXqlN4XIXlXsMi&authKey=Sm9XMTV%2FFyANBrv9rVpMfMNcX4v1lVah3795O9VclQwU4DNzQcT5BLXTmTBouIkM&noverify=0&group_code=177203794)
\ No newline at end of file
+QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc) [](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [](https://jq.qq.com/?_wv=1027&k=540WfdEr) [](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=KTVAIhggR3rR3uZWK9A8kR4yYNREQ4jo&authKey=An4DUV9e7uK8I8VgBbp949z0ypQoDrOoqvVg%2FWOr2vuNNDMZUAMPvqHor6TFMIgz&noverify=0&group_code=232896766) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XwhV8deuZXt__yteR1clNanVSXzA-ugq&authKey=ezgwKqEZPdP%2FgC9I03OBkJb%2Biii8yvVfwrcQuu0%2FL6ILXcRdHYDBFKCXeoeBT0E6&noverify=0&group_code=180208928) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=WqsGDxpGkqOPeWGOf3I32f_rXxdhqYNr&authKey=kvdF5df7PO9bzWxmixKhZN6ShsECBiuGUmmzTZBWVr2MVOfJ8%2F4oD0Gws0rbgYfz&noverify=0&group_code=140284548) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=z9z9jkkkinfAElKZk2FXqlN4XIXlXsMi&authKey=Sm9XMTV%2FFyANBrv9rVpMfMNcX4v1lVah3795O9VclQwU4DNzQcT5BLXTmTBouIkM&noverify=0&group_code=177203794)"# test auto deploy"