Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13800dc389 | ||
|
|
619d9b1e84 | ||
|
|
556cc93f14 | ||
|
|
a50375616e | ||
|
|
e33447d023 | ||
|
|
7be277b3e6 | ||
|
|
5fa385e90b | ||
|
|
0a78966737 | ||
|
|
0eb7f00867 | ||
|
|
00ce7f2d98 | ||
|
|
003c066361 | ||
|
|
a5e7c59fd4 | ||
|
|
accac603cf | ||
|
|
7c96c730e6 | ||
|
|
a2dbdb30ff | ||
|
|
772e4af9bf | ||
|
|
e601eb6db5 | ||
|
|
84dbc2cfbf | ||
|
|
f160ec714b | ||
|
|
6c4c661516 | ||
|
|
b85c17a126 | ||
|
|
0690156362 | ||
|
|
dc1e84bc52 | ||
|
|
4977df0ba8 | ||
|
|
27211b67f9 | ||
|
|
1600ab384e | ||
|
|
418805a1ef | ||
|
|
4c4b52bca7 | ||
|
|
7245259bc4 | ||
|
|
6690c8204c | ||
|
|
d8fc597f85 | ||
|
|
7f1146ecae | ||
|
|
0130028952 | ||
|
|
5a716da5a6 | ||
|
|
2470ec7573 | ||
|
|
e3fb25fba6 | ||
|
|
2aa7e0f4f1 | ||
|
|
b2d2fb34b8 | ||
|
|
c1e2a03178 | ||
|
|
fd38d2030e | ||
|
|
a42f881b67 | ||
|
|
20d531c0db | ||
|
|
1e6046cf52 | ||
|
|
495f2de6ef | ||
|
|
e97bd4e201 | ||
|
|
70e5e393ef | ||
|
|
8954f59cd7 | ||
|
|
c78b1a14a9 | ||
|
|
e768c4b356 | ||
|
|
d059f50ba6 | ||
|
|
26bcfbba8a | ||
|
|
d6e4a50d6e | ||
|
|
0a115f289e | ||
|
|
31e8df8bc0 | ||
|
|
ee477213e0 | ||
|
|
1e6e236d3c | ||
|
|
593a0d0049 | ||
|
|
d4f8f91893 | ||
|
|
f25ebdf9ec | ||
|
|
32b8144b56 | ||
|
|
b40805cb57 | ||
|
|
008f64617f | ||
|
|
3539e222d2 | ||
|
|
c4d1ea974d | ||
|
|
ace7e961a4 | ||
|
|
5dc21653c0 | ||
|
|
d0d4b2229f | ||
|
|
07c9727345 | ||
|
|
689adf079d | ||
|
|
1d1b72c6e2 | ||
|
|
d9bdce1d8a | ||
|
|
885d46a4aa | ||
|
|
420e05ecf3 | ||
|
|
afa3c78180 | ||
|
|
91a44e1ba8 | ||
|
|
4a36aaa780 | ||
|
|
c78b456dbf | ||
|
|
e8c187125f | ||
|
|
7b8cfe02a1 |
32
.editorconfig
Normal file
@@ -0,0 +1,32 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
# 所有文件 ([*]):
|
||||
# 使用空格缩进,每级 4 个空格
|
||||
# UTF-8 编码
|
||||
# Unix 风格换行符 (LF)
|
||||
# 自动删除行尾空格
|
||||
# 文件末尾自动添加空行
|
||||
# JSON/YAML 文件:
|
||||
# 缩进改为 2 个空格
|
||||
# Markdown 文件:
|
||||
# 不在末尾添加空行
|
||||
# 保留行尾空格(Markdown 语法需要)
|
||||
# 作用:
|
||||
# 支持此标准的编辑器(VS Code、IDEA、Sublime 等)会自动读取并应用这些规则,确保不同开发者使用不同编辑器时,代码格式保持一致。
|
||||
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{json,yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
||||
57
.github/ISSUE_TEMPLATE/enterprise-collaboration.md
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
name: 企业AI应用合作登记
|
||||
about: 登记企业信息与合作意向,获取免费技术支持
|
||||
title: '[合作登记] 企业AI应用需求登记'
|
||||
labels: '合作登记'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 登记说明
|
||||
|
||||
感谢您关注 RuoYi AI!我们团队今年的重点是帮助企业落地AI应用,如果贵公司符合要求,我们可以提供**免费的技术支持**。
|
||||
|
||||
请在下方评论中填写登记信息,格式如下:
|
||||
|
||||
---
|
||||
|
||||
## 登记格式预览
|
||||
|
||||
| 字段 | 内容 |
|
||||
|:---|:---|
|
||||
| 公司名称 | (必填) |
|
||||
| 公司Logo地址 | (可选) |
|
||||
| 所属行业 | (必填) |
|
||||
| 公司所在地 | (必填) |
|
||||
| 项目名称 | (必填) |
|
||||
| 项目Logo地址 | (可选) |
|
||||
| 项目简介 | (必填) |
|
||||
| 当前AI应用状态 | □ 尚未开始 □ 规划中 □ 已有初步应用 □ 已有成熟应用 |
|
||||
| 计划落地时间 | □ 1个月内 □ 1-3个月 □ 3-6个月 □ 6个月以上 |
|
||||
| 当前痛点或挑战 | (可选) |
|
||||
| 公司简介 | (可选) |
|
||||
|
||||
---
|
||||
|
||||
## 可复制格式
|
||||
|
||||
复制下方内容并在评论中填写:
|
||||
|
||||
```
|
||||
| 字段 | 内容 |
|
||||
|:---|:---|
|
||||
| 公司名称 | |
|
||||
| 公司Logo地址 | |
|
||||
| 所属行业 | |
|
||||
| 公司所在地 | |
|
||||
| 项目名称 | |
|
||||
| 项目Logo地址 | |
|
||||
| 项目简介 | |
|
||||
| 当前AI应用状态 | |
|
||||
| 计划落地时间 | |
|
||||
| 当前痛点或挑战 | |
|
||||
| 公司简介 | |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **温馨提示**:提交的信息仅用于合作沟通,不会对外公开。
|
||||
BIN
.gitignore
vendored
36
Dockerfile.backend
Normal file
@@ -0,0 +1,36 @@
|
||||
# RuoYi-AI 后端 Dockerfile
|
||||
# 基于 Maven + OpenJDK 17
|
||||
|
||||
FROM maven:3.9-eclipse-temurin-17 AS builder
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /build
|
||||
|
||||
# 复制 pom.xml 和源码
|
||||
COPY pom.xml .
|
||||
COPY ruoyi-admin ./ruoyi-admin
|
||||
COPY ruoyi-common ./ruoyi-common
|
||||
COPY ruoyi-modules ./ruoyi-modules
|
||||
COPY ruoyi-extend ./ruoyi-extend
|
||||
|
||||
|
||||
# 构建项目 (使用 prod profile)
|
||||
RUN mvn clean package -Pprod -DskipTests
|
||||
|
||||
# 最终运行镜像
|
||||
FROM eclipse-temurin:17-jre-alpine
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 从构建阶段复制 jar 包
|
||||
COPY --from=builder /build/ruoyi-admin/target/ruoyi-admin.jar ./ruoyi-admin.jar
|
||||
|
||||
# 创建日志目录
|
||||
RUN mkdir -p /ruoyi/server/logs
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 6039
|
||||
|
||||
# 启动命令
|
||||
ENTRYPOINT ["java", "-jar", "ruoyi-admin.jar", "--spring.profiles.active=prod"]
|
||||
21
Dockerfile.mysql
Normal file
@@ -0,0 +1,21 @@
|
||||
# 基于官方MySQL 8.0镜像构建自定义镜像
|
||||
# 构建命令: docker build -t registry.cn-hangzhou.aliyuncs.com/ruoyi-ai/mysql:v3 -f Dockerfile.mysql .
|
||||
FROM mysql:8.0.33
|
||||
|
||||
# 设置时区
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
# 复制初始化脚本和SQL文件到镜像中
|
||||
COPY docs/script/docker/mysql/init/init-db.sh /docker-entrypoint-initdb.d/init-db.sh
|
||||
COPY docs/script/sql/ruoyi-ai-v3_mysql8.sql /docker-entrypoint-initdb.d/ruoyi-ai-v3_mysql8.sql
|
||||
|
||||
# 设置脚本可执行权限
|
||||
RUN chmod +x /docker-entrypoint-initdb.d/init-db.sh
|
||||
|
||||
# MySQL启动参数
|
||||
CMD ["--default-authentication-plugin=mysql_native_password", \
|
||||
"--character-set-server=utf8mb4", \
|
||||
"--collation-server=utf8mb4_general_ci", \
|
||||
"--explicit_defaults_for_timestamp=true", \
|
||||
"--lower_case_table_names=1", \
|
||||
"--skip-ssl"]
|
||||
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 ruoyi-ai
|
||||
Copyright (c) 2026 ruoyi-ai
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
234
README.md
@@ -15,62 +15,38 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
<img src="image/00.png" alt="RuoYi AI Logo" width="120" height="120">
|
||||
<img src="docs/image/logo.png" alt="RuoYi AI Logo" width="120" height="120">
|
||||
|
||||
### 企业级AI助手平台
|
||||
|
||||
*开箱即用的智能AI平台,深度集成 FastGPT、扣子(Coze)、DIFY 等主流AI平台,提供先进的RAG技术、知识图谱、数字人和AI流程编排能力*
|
||||
*开箱即用的全栈AI平台,支持多智能体协同、Supervisor模式编排、多种决策模型,提供先进的RAG技术和可视化流程编排能力*
|
||||
|
||||
**[🇺🇸 English](README_EN.md)** | **[📖 使用文档](https://doc.pandarobot.chat)** | *
|
||||
*[🚀 在线体验](https://web.pandarobot.chat)** | **[🐛 问题反馈](https://github.com/ageerle/ruoyi-ai/issues)** | *
|
||||
*[💡 功能建议](https://github.com/ageerle/ruoyi-ai/issues)**
|
||||
**[English](README_EN.md)** | **[📖 使用文档](https://doc.pandarobot.chat)** |
|
||||
**[🚀 在线体验](https://web.pandarobot.chat)** | **[🐛 问题反馈](https://github.com/ageerle/ruoyi-ai/issues)** | **[💡 功能建议](https://github.com/ageerle/ruoyi-ai/issues)**
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
## ✨ 核心亮点
|
||||
|
||||
### 智能AI引擎
|
||||
|
||||
- **多模型接入**:支持 OpenAI GPT-4、Azure、ChatGLM、通义千问、智谱AI 等主流模型
|
||||
- **AI平台集成**:深度集成 **FastGPT**、**扣子(Coze)**、**DIFY** 等主流AI应用平台
|
||||
- **Spring AI MCP 集成**:基于模型上下文协议,打造可扩展的AI工具生态系统
|
||||
- **实时流式对话**:采用 SSE/WebSocket 技术,提供丝滑的对话体验
|
||||
- **AI 编程助手**:内置智能代码分析和项目脚手架生成能力
|
||||
|
||||
### AI平台生态集成
|
||||
|
||||
- **FastGPT 深度集成**:原生支持 FastGPT API,包括知识库检索、工作流编排和上下文管理
|
||||
- **扣子(Coze) 官方SDK**:集成字节跳动扣子平台官方SDK,支持Bot对话和流式响应
|
||||
- **DIFY 完整兼容**:使用 DIFY Java Client,支持应用编排、工作流和知识库管理
|
||||
- **统一聊天接口**:提供统一的聊天服务接口,支持多平台无缝切换和负载均衡
|
||||
|
||||
### 本地化RAG方案
|
||||
|
||||
- **私有知识库**:基于 Langchain4j 框架 + BGE-large-zh-v1.5 中文向量模型
|
||||
- **多种向量库**:支持 Milvus、Weaviate、Qdrant 等主流向量数据库
|
||||
- **数据安全可控**:支持完全本地部署,保护企业数据隐私
|
||||
- **灵活模型部署**:兼容 Ollama、vLLM 等本地推理框架
|
||||
|
||||
### AI创作工具
|
||||
|
||||
- **AI 绘画创作**:深度集成 DALL·E-3、MidJourney、Stable Diffusion
|
||||
- **智能PPT生成**:一键将文本内容转换为精美演示文稿
|
||||
- **多模态理解**:支持文本、图片、文档等多种格式的智能处理
|
||||
|
||||
### 知识图谱与智能编排
|
||||
|
||||
- **知识图谱构建**:自动从文档和对话中提取实体关系,构建可视化知识网络
|
||||
- **AI 流程编排**:可视化工作流设计器,支持复杂AI任务的编排和自动化执行
|
||||
- **数字人交互**:集成数字人形象,提供更自然的人机交互体验
|
||||
- **智能推理引擎**:基于知识图谱的智能推理和问答能力
|
||||
| 模块 | 现有能力 | 扩展方向 |
|
||||
|:----------:|---|------------------------|
|
||||
| **模型管理** | 多模型接入(OpenAI/DeepSeek/通义/智谱)、多模态理解、Coze/DIFY/FastGPT平台集成 | 自动模式、容错机制、计费管理 |
|
||||
| **知识管理** | 本地RAG + 向量库(Milvus/Weaviate) + 文档解析 | 多模态、知识出处、知识图谱、重排序 |
|
||||
| **工具管理** | Mcp协议集成、Skills能力 + 可扩展工具生态 | 工具插件市场、 |
|
||||
| **流程编排** | 可视化工作流设计器、节点拖拽编排、SSE流式执行,目前已经支持模型调用,邮件发送,人工审核等节点 | 更多节点类型 |
|
||||
| **多智能体** | 基于Langchain4j的Agent框架、Supervisor模式编排,支持多种决策模型 | 智能体可配置 |
|
||||
|
||||
## 🚀 快速体验
|
||||
|
||||
### 在线演示
|
||||
|
||||
- **用户端体验**:[web.pandarobot.chat](https://web.pandarobot.chat) (账号:admin 密码:admin123)
|
||||
- **管理后台**:[admin.pandarobot.chat](https://admin.pandarobot.chat) (账号:admin 密码:admin123)
|
||||
| 平台 | 地址 | 账号 |
|
||||
|:------:|---|---|
|
||||
| 用户端 | [web.pandarobot.chat](https://web.pandarobot.chat) | admin / admin123 |
|
||||
| 管理后台 | [admin.pandarobot.chat](https://admin.pandarobot.chat) | admin / admin123 |
|
||||
|
||||
### 项目源码
|
||||
|
||||
@@ -81,25 +57,129 @@
|
||||
| 🛠️ 管理后台 | [ruoyi-admin](https://github.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitee.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitcode.com/ageerle/ruoyi-admin) |
|
||||
|
||||
### 合作项目
|
||||
|
||||
| 项目介绍 | GitHub 仓库 | Gitee 仓库 |
|
||||
|:-----:|:----------------------------------------------------------------------:|:----------------------------------------------------------------:|
|
||||
| 前端简化版 | [ruoyi-element-ai](https://github.com/element-plus-x/ruoyi-element-ai) | [ruoyi-element-ai](https://gitee.com/he-jiayue/ruoyi-element-ai) |
|
||||
| 项目名称 | GitHub 仓库 | Gitee 仓库
|
||||
|----------------|-------------------------------------------------------|------------------------------------------------------|
|
||||
| element-plus-x | [element-plus-x](https://github.com/element-plus-x/Element-Plus-X) | [element-plus-x](https://gitee.com/he-jiayue/element-plus-x) |
|
||||
|
||||
## 🛠️ 技术架构
|
||||
|
||||
### 核心框架
|
||||
|
||||
- **后端架构**:Spring Boot 3.4 + Spring AI + Langchain4j
|
||||
- **数据存储**:MySQL 8.0 + Redis + 向量数据库(Milvus/Weaviate/Qdrant)
|
||||
- **前端技术**:Vue 3 + Vben Admin + Naive UI
|
||||
- **后端架构**:Spring Boot 4.0 + Spring ai 2.0 + Langchain4j
|
||||
- **数据存储**:MySQL 8.0 + Redis + 向量数据库(Milvus/Weaviate)
|
||||
- **前端技术**:Vue 3 + Vben Admin + element-plus-x
|
||||
- **安全认证**:Sa-Token + JWT 双重保障
|
||||
|
||||
### 系统组件
|
||||
|
||||
- **文档处理**:PDF、Word、Excel 解析,图像智能分析
|
||||
- **实时通信**:WebSocket 实时通信,SSE 流式响应
|
||||
- **系统监控**:完善的日志体系、性能监控、服务健康检查
|
||||
## 🐳 Docker 部署
|
||||
|
||||
本项目提供两种 Docker 部署方式:
|
||||
|
||||
### 方式一:一键启动所有服务(推荐)
|
||||
|
||||
使用 `docker-compose-all.yaml` 可以一键启动所有服务(包括后端、管理端、用户端及依赖服务):
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone https://github.com/ageerle/ruoyi-ai.git
|
||||
cd ruoyi-ai
|
||||
|
||||
# 启动所有服务(从镜像仓库拉取预构建镜像)
|
||||
docker-compose -f docker-compose-all.yaml up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose -f docker-compose-all.yaml ps
|
||||
|
||||
# 访问服务
|
||||
# 管理端: http://localhost:25666 (admin / admin123)
|
||||
# 用户端: http://localhost:25137
|
||||
# 后端API: http://localhost:26039
|
||||
```
|
||||
|
||||
### 方式二:分步部署(源码编译)
|
||||
|
||||
如果您需要从源码构建后端服务,请按照以下步骤操作:
|
||||
|
||||
#### 第一步:部署后端服务
|
||||
|
||||
```bash
|
||||
# 进入后端项目目录
|
||||
cd ruoyi-ai
|
||||
|
||||
# 启动后端服务(源码编译构建)
|
||||
docker-compose up -d --build
|
||||
|
||||
# 等待后端服务启动完成
|
||||
docker-compose logs -f backend
|
||||
```
|
||||
|
||||
#### 第二步:部署管理端
|
||||
|
||||
```bash
|
||||
# 进入管理端项目目录
|
||||
cd ruoyi-admin
|
||||
|
||||
# 构建并启动管理端
|
||||
docker-compose up -d --build
|
||||
|
||||
# 访问管理端
|
||||
# 地址: http://localhost:5666
|
||||
```
|
||||
|
||||
#### 第三步:部署用户端(可选)
|
||||
|
||||
```bash
|
||||
# 进入用户端项目目录
|
||||
cd ruoyi-web
|
||||
|
||||
# 构建并启动用户端
|
||||
docker-compose up -d --build
|
||||
|
||||
# 访问用户端
|
||||
# 地址: http://localhost:5137
|
||||
```
|
||||
|
||||
### 服务端口说明
|
||||
|
||||
| 服务 | 一键启动端口 | 分步部署端口 | 说明 |
|
||||
|------|-------------|-------------|------|
|
||||
| 管理端 | 25666 | 5666 | 管理后台访问地址 |
|
||||
| 用户端 | 25137 | 5137 | 用户前端访问地址 |
|
||||
| 后端服务 | 26039 | 6039 | 后端 API 服务 |
|
||||
| MySQL | 23306 | 23306 | 数据库服务 |
|
||||
| Redis | 26379 | 6379 | 缓存服务 |
|
||||
| Weaviate | 28080 | 28080 | 向量数据库 |
|
||||
| MinIO API | 29000 | 9000 | 对象存储 API |
|
||||
| MinIO Console | 29090 | 9090 | 对象存储控制台 |
|
||||
|
||||
### 镜像仓库
|
||||
|
||||
所有镜像托管在阿里云容器镜像服务:
|
||||
|
||||
```
|
||||
crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai
|
||||
```
|
||||
|
||||
可用镜像:
|
||||
- `mysql:v3` - MySQL 数据库(包含初始化 SQL)
|
||||
- `redis:6.2` - Redis 缓存
|
||||
- `weaviate:1.30.0` - 向量数据库
|
||||
- `minio:latest` - 对象存储
|
||||
- `ruoyi-ai-backend:latest` - 后端服务
|
||||
- `ruoyi-ai-admin:latest` - 管理端前端
|
||||
- `ruoyi-ai-web:latest` - 用户端前端
|
||||
|
||||
### 常用命令
|
||||
|
||||
```bash
|
||||
# 停止所有服务
|
||||
docker-compose -f docker-compose-all.yaml down
|
||||
|
||||
# 查看服务日志
|
||||
docker-compose -f docker-compose-all.yaml logs -f [服务名]
|
||||
|
||||
# 重启某个服务
|
||||
docker-compose -f docker-compose-all.yaml restart [服务名]
|
||||
```
|
||||
|
||||
## 📚 使用文档
|
||||
|
||||
@@ -107,12 +187,6 @@
|
||||
|
||||
**👉 [完整使用文档](https://doc.pandarobot.chat)**
|
||||
|
||||
遇到知识库或 RAG 回答异常问题?
|
||||
|
||||
**👉 [RAG 回答异常排查手册](docs/troubleshooting/rag-failures.md)**
|
||||
|
||||
---
|
||||
|
||||
## 🤝 参与贡献
|
||||
|
||||
我们热烈欢迎社区贡献!无论您是资深开发者还是初学者,都可以为项目贡献力量 💪
|
||||
@@ -134,21 +208,20 @@
|
||||
## 🙏 特别鸣谢
|
||||
|
||||
感谢以下优秀的开源项目为本项目提供支持:
|
||||
|
||||
- [Spring AI Alibaba Copilot](https://github.com/springaialibaba/spring-ai-alibaba-copilot) - 基于spring-ai-alibaba
|
||||
- [Spring AI Alibaba Copilot](https://github.com/spring-ai-alibaba/copilot) - 基于spring-ai-alibaba
|
||||
的智能编码助手
|
||||
- [Spring AI](https://spring.io/projects/spring-ai) - Spring 官方 AI 集成框架
|
||||
- [Langchain4j](https://github.com/langchain4j/langchain4j) - 强大的 Java LLM 开发框架
|
||||
- [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus) - 成熟的企业级快速开发框架
|
||||
- [Vben Admin](https://github.com/vbenjs/vue-vben-admin) - 现代化的 Vue 后台管理模板
|
||||
- [chatgpt-java](https://github.com/Grt1228/chatgpt-java) - 优秀的 ChatGPT Java SDK
|
||||
|
||||
## 🌐 生态伙伴
|
||||
|
||||
- [PPIO 派欧云](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - 提供高性价比的 GPU
|
||||
算力和模型 API 服务
|
||||
- [优云智算](https://www.compshare.cn/?ytag=GPU_YY-gh_ruoyi) - 万卡RTX40系GPU+海内外主流模型API服务,秒级响应,按量计费,新客免费用。
|
||||
- [胜算云](https://www.shengsuanyun.com/?from=CH_3WG71ZOS) - AI模型算力聚合超市云服务。
|
||||
|
||||
## 优秀开源项目及社区推荐
|
||||
- [imaiwork](https://gitee.com/tsinghua-open/imaiwork) - AI手机开源版,AI获客手机项目,基于无障碍模式,RPA,比豆包AI手机更强大。
|
||||
|
||||
## 💬 社区交流
|
||||
|
||||
@@ -157,12 +230,12 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="image/wx.png" alt="微信二维码" width="200" height="200"><br>
|
||||
<img src="docs/image/wx.png" alt="微信二维码" width="200" height="200"><br>
|
||||
<strong>扫码添加作者微信</strong><br>
|
||||
<em>邀请进群学习</em>
|
||||
</td>
|
||||
<td align="center">
|
||||
<img src="image/qq.png" alt="QQ群二维码" width="200" height="200"><br>
|
||||
<img src="docs/image/qq.png" alt="QQ群二维码" width="200" height="200"><br>
|
||||
<strong>QQ技术交流群</strong><br>
|
||||
<em>技术讨论</em>
|
||||
</td>
|
||||
@@ -174,11 +247,32 @@
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 📺 视频教程
|
||||
|
||||
<div align="center">
|
||||
|
||||
**[⭐ 点个Star支持一下](https://github.com/ageerle/ruoyi-ai)** • *
|
||||
*[🍴 Fork 开始贡献](https://github.com/ageerle/ruoyi-ai/fork)** • **[📚 English](README_EN.md)** • *
|
||||
*[📖 查看完整文档](https://doc.pandarobot.chat)**
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="docs/image/dy.png" alt="微信二维码" width="200" height="200"><br>
|
||||
<strong>打开抖音扫一扫</strong><br>
|
||||
<em>获取免费视频教程</em>
|
||||
</td>
|
||||
<td align="center">
|
||||
<img src="docs/image/bibi.png" alt="QQ群二维码" width="200" height="200"><br>
|
||||
<strong>打开B站扫一扫</strong><br>
|
||||
<em>获取免费视频教程</em>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
|
||||
**[⭐ 点个Star支持一下](https://github.com/ageerle/ruoyi-ai)** • **[ Fork 开始贡献](https://github.com/ageerle/ruoyi-ai/fork)** • **[📚 English](README_EN.md)** • **[📖 查看完整文档](https://doc.pandarobot.chat)**
|
||||
|
||||
*用 ❤️ 打造,由 RuoYi AI 开源社区维护*
|
||||
|
||||
|
||||
175
README_EN.md
@@ -1,3 +1,4 @@
|
||||
|
||||
# RuoYi AI
|
||||
|
||||
<div align="center">
|
||||
@@ -8,157 +9,114 @@
|
||||
[![Issues][issues-shield]][issues-url]
|
||||
[![MIT License][license-shield]][license-url]
|
||||
|
||||
<img src="image/00.png" alt="RuoYi AI Logo" width="120" height="120">
|
||||
|
||||
<p align="center">
|
||||
<a href="https://trendshift.io/repositories/13209">
|
||||
<img src="https://trendshift.io/api/badge/repositories/13209" alt="GitHub Trending">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<img src="docs/image/logo.png" alt="RuoYi AI Logo" width="120" height="120">
|
||||
|
||||
### Enterprise-Grade AI Assistant Platform
|
||||
|
||||
*Production-ready AI platform with deep integration of FastGPT, Coze, DIFY, featuring advanced RAG technology, knowledge
|
||||
graphs, digital humans, and AI workflow orchestration*
|
||||
*An out-of-the-box full-stack AI platform supporting multi-agent collaboration, Supervisor mode orchestration, and multiple decision models, with advanced RAG technology and visual workflow orchestration capabilities*
|
||||
|
||||
**[📖 中文文档](README.md)** | **[📚 Documentation](https://doc.pandarobot.chat)** | *
|
||||
*[🚀 Live Demo](https://web.pandarobot.chat)** | **[🐛 Report Bug](https://github.com/ageerle/ruoyi-ai/issues)** | *
|
||||
*[💡 Request Feature](https://github.com/ageerle/ruoyi-ai/issues)**
|
||||
**[中文](README.md)** | **[📖 Documentation](https://doc.pandarobot.chat)** |
|
||||
**[🚀 Live Demo](https://web.pandarobot.chat)** | **[🐛 Report Issues](https://github.com/ageerle/ruoyi-ai/issues)** | **[💡 Feature Requests](https://github.com/ageerle/ruoyi-ai/issues)**
|
||||
|
||||
</div>
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
### 🤖 Advanced AI Engine
|
||||
|
||||
- **Multi-Model Support**: OpenAI GPT-4, Azure, ChatGLM, Qwen, ZhipuAI
|
||||
- **AI Platform Integration**: Deep integration with **FastGPT**, **Coze**, **DIFY** and other leading AI platforms
|
||||
- **Spring AI MCP Integration**: Extensible tool ecosystem with Model Context Protocol
|
||||
- **Streaming Chat**: Real-time SSE/WebSocket communication
|
||||
- **AI Copilot**: Intelligent code analysis and project scaffolding
|
||||
|
||||
### 🌟 AI Platform Ecosystem
|
||||
## ✨ Core Features
|
||||
|
||||
- **FastGPT Deep Integration**: Native FastGPT API support with knowledge base retrieval, workflow orchestration and
|
||||
context management
|
||||
- **Coze Official SDK**: Integration with ByteDance Coze platform official SDK, supporting Bot conversations and
|
||||
streaming responses
|
||||
- **DIFY Full Compatibility**: Using DIFY Java Client for app orchestration, workflows and knowledge base management
|
||||
- **Unified Chat Interface**: Standardized chat service interface supporting seamless platform switching and load
|
||||
balancing
|
||||
|
||||
### 🧠 Enterprise RAG Solution
|
||||
|
||||
- **Local Knowledge Base**: Langchain4j + BGE-large-zh-v1.5 embeddings
|
||||
- **Vector Database Support**: Milvus, Weaviate, Qdrant
|
||||
- **Privacy-First**: On-premise deployment with local LLM support
|
||||
- **Ollama & vLLM Compatible**: Flexible model deployment options
|
||||
|
||||
### 🎨 Creative AI Tools
|
||||
|
||||
- **AI Art Generation**: DALL·E-3, MidJourney, Stable Diffusion integration
|
||||
- **PPT Creation**: Automated slide generation from text input
|
||||
- **Multi-Modal Processing**: Text, image, and document understanding
|
||||
|
||||
### 🧩 Knowledge Graph & Intelligent Orchestration
|
||||
|
||||
- **Knowledge Graph Construction**: Automatically extract entities and relationships from documents and conversations to
|
||||
build visual knowledge networks
|
||||
- **AI Workflow Orchestration**: Visual workflow designer supporting complex AI task orchestration and automated
|
||||
execution
|
||||
- **Digital Human Interaction**: Integrated digital human avatars for more natural human-computer interaction
|
||||
- **Intelligent Reasoning Engine**: Knowledge graph-based intelligent reasoning and Q&A capabilities
|
||||
| Module | Current Capabilities | Extension Direction |
|
||||
|:---:|---|---|
|
||||
| **Model Management** | Multi-model integration (OpenAI/DeepSeek/Tongyi/Zhipu), multi-modal understanding, Coze/DIFY/FastGPT platform integration | Auto mode, fault tolerance |
|
||||
| **Knowledge Base** | Local RAG + Vector DB (Milvus/Weaviate) + Knowledge Graph + Document parsing + Reranking | Audio/video parsing, knowledge source |
|
||||
| **Tool Management** | MCP protocol integration, Skills capability + Extensible tool ecosystem | Tool plugin marketplace, toolAgent auto-loading |
|
||||
| **Workflow Orchestration** | Visual workflow designer, drag-and-drop node orchestration, SSE streaming execution, currently supports model (with RAG) calls, email sending, manual review nodes | More node types |
|
||||
| **Multi-Agent** | Agent framework based on Langchain4j, Supervisor mode orchestration, supports multiple decision models | Configurable agents |
|
||||
| **AI Coding** | Intelligent code analysis, project scaffolding generation, Copilot assistant | Code generation optimization |
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Live Demo
|
||||
|
||||
- **User Portal**: [web.pandarobot.chat](https://web.pandarobot.chat) (demo/demo123)
|
||||
- **Admin Panel**: [admin.pandarobot.chat](https://admin.pandarobot.chat) (admin/admin123)
|
||||
| Platform | URL | Account |
|
||||
|:------:|---|---|
|
||||
| User Frontend | [web.pandarobot.chat](https://web.pandarobot.chat) | admin / admin123 |
|
||||
| Admin Panel | [admin.pandarobot.chat](https://admin.pandarobot.chat) | admin / admin123 |
|
||||
|
||||
### Source Code
|
||||
### Project Repositories
|
||||
|
||||
| Component | GitHub | Gitee | GitCode |
|
||||
|----------------|-------------------------------------------------------|------------------------------------------------------|--------------------------------------------------------|
|
||||
| Backend API | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
|
||||
| User Frontend | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
|
||||
| Admin Frontend | [ruoyi-admin](https://github.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitee.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitcode.com/ageerle/ruoyi-admin) |
|
||||
| Module | GitHub Repository | Gitee Repository | GitCode Repository |
|
||||
|----------|-------------------------------------------------------|------------------------------------------------------|--------------------------------------------------------|
|
||||
| 🔧 Backend | [ruoyi-ai](https://github.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitee.com/ageerle/ruoyi-ai) | [ruoyi-ai](https://gitcode.com/ageerle/ruoyi-ai) |
|
||||
| 🎨 User Frontend | [ruoyi-web](https://github.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitee.com/ageerle/ruoyi-web) | [ruoyi-web](https://gitcode.com/ageerle/ruoyi-web) |
|
||||
| 🛠️ Admin Panel | [ruoyi-admin](https://github.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitee.com/ageerle/ruoyi-admin) | [ruoyi-admin](https://gitcode.com/ageerle/ruoyi-admin) |
|
||||
|
||||
### Collaborative Projects
|
||||
### Partner Projects
|
||||
| Project Name | GitHub Repository | Gitee Repository
|
||||
|----------------|-------------------------------------------------------|------------------------------------------------------|
|
||||
| element-plus-x | [element-plus-x](https://github.com/element-plus-x/Element-Plus-X) | [element-plus-x](https://gitee.com/he-jiayue/element-plus-x) |
|
||||
|
||||
| Project Description | GitHub Repository | Gitee Repository |
|
||||
|:-------------------:|:----------------------------------------------------------------------:|:----------------------------------------------------------------:|
|
||||
| Simplified Frontend | [ruoyi-element-ai](https://github.com/element-plus-x/ruoyi-element-ai) | [ruoyi-element-ai](https://gitee.com/he-jiayue/ruoyi-element-ai) |
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
## 🛠️ Technical Architecture
|
||||
|
||||
### Core Framework
|
||||
- **Backend**: Spring Boot 4.0 + Spring AI 2.0 + Langchain4j
|
||||
- **Data Storage**: MySQL 8.0 + Redis + Vector Databases (Milvus/Weaviate)
|
||||
- **Frontend**: Vue 3 + Vben Admin + element-plus-x
|
||||
- **Security**: Sa-Token + JWT dual-layer security
|
||||
|
||||
- **Backend**: Spring Boot 3.4, Spring AI, Langchain4j
|
||||
- **Database**: MySQL 8.0, Redis, Vector Databases (Milvus/Weaviate/Qdrant)
|
||||
- **Frontend**: Vue 3, Vben Admin, Naive UI
|
||||
- **Authentication**: Sa-Token, JWT
|
||||
|
||||
### System Components
|
||||
|
||||
- **File Processing**: PDF, Word, Excel parsing, intelligent image analysis
|
||||
- **Real-time Communication**: WebSocket real-time communication, SSE streaming
|
||||
- **System Monitoring**: Comprehensive logging, performance monitoring, health checks
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
For detailed setup, configuration, and development guides, visit our comprehensive documentation:
|
||||
Want to learn more about installation, deployment, configuration, and secondary development?
|
||||
|
||||
**[📖 Official Documentation](https://doc.pandarobot.chat)**
|
||||
**👉 [Complete Documentation](https://doc.pandarobot.chat)**
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We welcome contributions from developers of all skill levels! Whether you're fixing bugs, adding features, or improving
|
||||
documentation, your help is appreciated.
|
||||
We warmly welcome community contributions! Whether you are a seasoned developer or just getting started, you can contribute to the project 💪
|
||||
|
||||
### How to Contribute
|
||||
|
||||
1. Fork the repository
|
||||
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
||||
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
||||
4. Push to the branch (`git push origin feature/amazing-feature`)
|
||||
5. Open a Pull Request
|
||||
1. **Fork** the project to your account
|
||||
2. **Create a branch** (`git checkout -b feature/new-feature-name`)
|
||||
3. **Commit your changes** (`git commit -m 'Add new feature'`)
|
||||
4. **Push to the branch** (`git push origin feature/new-feature-name`)
|
||||
5. **Create a Pull Request**
|
||||
|
||||
*Please submit PRs to GitHub - they will be synchronized to other platforms automatically.*
|
||||
> 💡 **Tip**: We recommend submitting PRs to GitHub, we will automatically sync to other code hosting platforms
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Special thanks to these amazing open source projects:
|
||||
|
||||
- [Spring AI Alibaba Copilot](https://github.com/springaialibaba/spring-ai-alibaba-copilot) - Intelligent coding
|
||||
assistant based on spring-ai-alibaba with MCP protocol integration for project analysis and code generation
|
||||
- [Spring AI](https://spring.io/projects/spring-ai) - Spring's AI integration framework
|
||||
- [Langchain4j](https://github.com/langchain4j/langchain4j) - Java LLM framework
|
||||
- [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus) - Enterprise development framework
|
||||
- [Vben Admin](https://github.com/vbenjs/vue-vben-admin) - Vue admin template
|
||||
- [chatgpt-java](https://github.com/Grt1228/chatgpt-java) - ChatGPT Java SDK
|
||||
Thanks to the following excellent open-source projects for their support:
|
||||
- [Spring AI Alibaba Copilot](https://github.com/spring-ai-alibaba/copilot) - Intelligent coding assistant based on spring-ai-alibaba
|
||||
- [Langchain4j](https://github.com/langchain4j/langchain4j) - Powerful Java LLM development framework
|
||||
- [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus) - Mature enterprise-level rapid development framework
|
||||
- [Vben Admin](https://github.com/vbenjs/vue-vben-admin) - Modern Vue admin template
|
||||
|
||||
## 🌐 Ecosystem Partners
|
||||
|
||||
- [PPIO Cloud](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - Cost-effective GPU
|
||||
containers and model APIs
|
||||
- [PPIO Cloud](https://ppinfra.com/user/register?invited_by=P8QTUY&utm_source=github_ruoyi-ai) - Provides cost-effective GPU computing and model API services
|
||||
- [Youyun Intelligent Computing](https://www.compshare.cn/?ytag=GPU_YY-gh_ruoyi) - Thousands of RTX40 series GPUs + mainstream models API services, second-level response, pay-per-use, free for new customers.
|
||||
|
||||
## 💬 Community
|
||||
## Outstanding Open-Source Projects and Community Recommendations
|
||||
- [imaiwork](https://gitee.com/tsinghua-open/imaiwork) - Open-source AI phone, AI customer acquisition phone project, based on accessibility mode and RPA, more powerful than Doubao AI phone.
|
||||
|
||||
## 💬 Community Chat
|
||||
|
||||
<div align="center">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="image/wx.png" alt="WeChat" width="200" height="200"><br>
|
||||
<strong>Add Author WeChat</strong><br>
|
||||
<em>Scan to join learning group</em>
|
||||
</td>
|
||||
<td align="center">
|
||||
<img src="image/qq.png" alt="QQ Group" width="200" height="200"><br>
|
||||
<strong>QQ Group</strong><br>
|
||||
<em>Technical discussion</em>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
**[📱 Join Telegram Group](https://t.me/+LqooQAc5HxRmYmE1)**
|
||||
|
||||
</div>
|
||||
|
||||
@@ -166,10 +124,9 @@ Special thanks to these amazing open source projects:
|
||||
|
||||
<div align="center">
|
||||
|
||||
**[⭐ Star this repo](https://github.com/ageerle/ruoyi-ai)** • **[🍴 Fork it](https://github.com/ageerle/ruoyi-ai/fork)
|
||||
** • **[📖 中文文档](README.md)** • **[📚 Documentation](https://doc.pandarobot.chat)**
|
||||
**[⭐ Star to Support](https://github.com/ageerle/ruoyi-ai)** • **[Fork to Contribute](https://github.com/ageerle/ruoyi-ai/fork)** • **[📚 中文](README.md)** • **[📖 Complete Documentation](https://doc.pandarobot.chat)**
|
||||
|
||||
*Built with ❤️ by the RuoYi AI community*
|
||||
*Built with ❤️, maintained by the RuoYi AI open-source community*
|
||||
|
||||
</div>
|
||||
|
||||
@@ -194,7 +151,3 @@ Special thanks to these amazing open source projects:
|
||||
[license-shield]: https://img.shields.io/github/license/ageerle/ruoyi-ai.svg?style=flat-square
|
||||
|
||||
[license-url]: https://github.com/ageerle/ruoyi-ai/blob/main/LICENSE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
180
docker-compose-all.yaml
Normal file
@@ -0,0 +1,180 @@
|
||||
# RuoYi-AI 一键启动全部服务
|
||||
# 使用方式: docker-compose up -d
|
||||
#
|
||||
# 包含服务:
|
||||
# - MySQL 8.0 (数据库,包含初始化SQL)
|
||||
# - Redis 6.2 (缓存)
|
||||
# - Weaviate (向量数据库)
|
||||
# - MinIO (对象存储)
|
||||
# - RuoYi-Backend (后端服务)
|
||||
# - RuoYi-Admin (管理端前端)
|
||||
# - RuoYi-Web (用户端前端)
|
||||
#
|
||||
# 镜像仓库地址: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# ==================== MySQL 数据库 ====================
|
||||
mysql:
|
||||
# 阿里云镜像地址(包含初始化SQL)
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/mysql:v3
|
||||
container_name: ruoyi-ai-mysql
|
||||
restart: always
|
||||
ports:
|
||||
- "23306:3306"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: ruoyi-ai-agent
|
||||
TZ: Asia/Shanghai
|
||||
volumes:
|
||||
- mysql-data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 60s
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== Redis 缓存 ====================
|
||||
redis:
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/redis:6.2
|
||||
container_name: ruoyi-ai-redis
|
||||
restart: always
|
||||
ports:
|
||||
- "26379:6379"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
command: redis-server --appendonly yes
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== Weaviate 向量数据库 ====================
|
||||
weaviate:
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/weaviate:1.30.0
|
||||
container_name: ruoyi-ai-weaviate
|
||||
restart: always
|
||||
ports:
|
||||
- "28080:8080"
|
||||
environment:
|
||||
QUERY_DEFAULTS_LIMIT: 25
|
||||
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: true
|
||||
PERSISTENCE_DATA_PATH: /var/lib/weaviate
|
||||
DEFAULT_VECTORIZER_MODULE: none
|
||||
ENABLE_MODULES: text2vec-cohere,text2vec-huggingface,text2vec-palm,text2vec-openai,generative-openai,generative-cohere,generative-palm,ref2vec-centroid,reranker-cohere,qna-openai
|
||||
CLUSTER_HOSTNAME: node1
|
||||
volumes:
|
||||
- weaviate-data:/var/lib/weaviate
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== MinIO 对象存储 ====================
|
||||
minio:
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/minio:latest
|
||||
container_name: ruoyi-ai-minio
|
||||
restart: always
|
||||
ports:
|
||||
- "29000:9000"
|
||||
- "29090:9090"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ruoyi
|
||||
MINIO_ROOT_PASSWORD: ruoyi123
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
command: server /data --console-address ":9090"
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== RuoYi-AI 后端服务 ====================
|
||||
backend:
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/ruoyi-ai-backend:latest
|
||||
container_name: ruoyi-ai-backend
|
||||
restart: always
|
||||
ports:
|
||||
- "26039:6039"
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
# MySQL 配置
|
||||
SPRING_DATASOURCE_DYNAMIC_PRIMARY: master
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_DRIVERCLASSNAME: com.mysql.cj.jdbc.Driver
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_URL: jdbc:mysql://mysql:3306/ruoyi-ai-agent?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_USERNAME: root
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_PASSWORD: root
|
||||
# Redis 配置
|
||||
SPRING_DATA_REDIS_HOST: redis
|
||||
SPRING_DATA_REDIS_PORT: 6379
|
||||
SPRING_DATA_REDIS_DATABASE: 0
|
||||
# 日志配置
|
||||
LOGGING_LEVEL_ORG_RUOYI: info
|
||||
LOGGING_LEVEL_ORG_SPRINGFRAMEWORK: warn
|
||||
SYS_UPLOAD_PATH: /ruoyi/upload
|
||||
volumes:
|
||||
- logs-data:/ruoyi/server/logs
|
||||
- upload-data:/ruoyi/upload
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== RuoYi-AI 管理端前端 ====================
|
||||
admin-frontend:
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/ruoyi-ai-admin:latest
|
||||
container_name: ruoyi-ai-admin
|
||||
restart: always
|
||||
ports:
|
||||
- "25666:5666"
|
||||
environment:
|
||||
# 后端 API 地址 - 运行时动态配置(无需重新构建镜像)
|
||||
# nginx upstream 配置不需要 http:// 前缀,直接使用 host:port
|
||||
UPSTREAM_HOST: backend:6039
|
||||
# 资源限制 - 防止 CPU 和内存耗尽
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 3G
|
||||
reservations:
|
||||
cpus: '1'
|
||||
memory: 1G
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== RuoYi-AI 用户端前端 ====================
|
||||
web-frontend:
|
||||
image: crpi-31mraxd99y2gqdgr.cn-beijing.personal.cr.aliyuncs.com/ruoyi_ai/ruoyi-ai-web:latest
|
||||
container_name: ruoyi-ai-web
|
||||
restart: always
|
||||
ports:
|
||||
- "25137:5137"
|
||||
environment:
|
||||
UPSTREAM_URL: http://backend:6039
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# ==================== 网络配置 ====================
|
||||
networks:
|
||||
ruoyi-net:
|
||||
driver: bridge
|
||||
|
||||
# ==================== 数据卷配置 ====================
|
||||
volumes:
|
||||
mysql-data:
|
||||
redis-data:
|
||||
weaviate-data:
|
||||
minio-data:
|
||||
logs-data:
|
||||
upload-data:
|
||||
144
docker-compose.yaml
Normal file
@@ -0,0 +1,144 @@
|
||||
# RuoYi-AI 一键启动后端服务
|
||||
# 使用方式: docker-compose up -d --build
|
||||
#
|
||||
# 包含服务:
|
||||
# - MySQL 8.0 (数据库)
|
||||
# - Redis 6.2 (缓存)
|
||||
# - Weaviate (向量数据库)
|
||||
# - MinIO (对象存储)
|
||||
# - RuoYi-Backend (后端服务,源码编译)
|
||||
|
||||
services:
|
||||
# MySQL 数据库
|
||||
mysql:
|
||||
image: mysql:8.0.33
|
||||
container_name: ruoyi-ai-mysql
|
||||
restart: always
|
||||
ports:
|
||||
- "23306:3306"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: ruoyi-ai-agent
|
||||
TZ: Asia/Shanghai
|
||||
volumes:
|
||||
- ./docs/script/docker/mysql/init/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh:ro
|
||||
- ./docs/script/sql/ruoyi-ai-v3_mysql8.sql:/docker-entrypoint-initdb.d/ruoyi-ai-v3_mysql8.sql:ro
|
||||
- mysql-data:/var/lib/mysql
|
||||
command:
|
||||
--default-authentication-plugin=mysql_native_password
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_general_ci
|
||||
--explicit_defaults_for_timestamp=true
|
||||
--lower_case_table_names=1
|
||||
--skip-ssl
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 60s
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# Redis 缓存
|
||||
redis:
|
||||
image: redis:6.2
|
||||
container_name: ruoyi-ai-redis
|
||||
restart: always
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
command: redis-server --appendonly yes
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# Weaviate 向量数据库
|
||||
weaviate:
|
||||
image: semitechnologies/weaviate:1.30.0
|
||||
container_name: ruoyi-ai-weaviate
|
||||
restart: always
|
||||
ports:
|
||||
- "28080:8080"
|
||||
environment:
|
||||
QUERY_DEFAULTS_LIMIT: 25
|
||||
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: true
|
||||
PERSISTENCE_DATA_PATH: /var/lib/weaviate
|
||||
DEFAULT_VECTORIZER_MODULE: none
|
||||
ENABLE_MODULES: text2vec-cohere,text2vec-huggingface,text2vec-palm,text2vec-openai,generative-openai,generative-cohere,generative-palm,ref2vec-centroid,reranker-cohere,qna-openai
|
||||
CLUSTER_HOSTNAME: node1
|
||||
volumes:
|
||||
- weaviate-data:/var/lib/weaviate
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# MinIO 对象存储
|
||||
minio:
|
||||
image: minio/minio
|
||||
container_name: ruoyi-ai-minio
|
||||
restart: always
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9090:9090"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ruoyi
|
||||
MINIO_ROOT_PASSWORD: ruoyi123
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
command: server /data --console-address ":9090"
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
# RuoYi-AI 后端服务 (源码编译)
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.backend
|
||||
container_name: ruoyi-ai-backend
|
||||
restart: always
|
||||
ports:
|
||||
- "26039:6039"
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
# MySQL 配置
|
||||
SPRING_DATASOURCE_DYNAMIC_PRIMARY: master
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_DRIVERCLASSNAME: com.mysql.cj.jdbc.Driver
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_URL: jdbc:mysql://mysql:3306/ruoyi-ai-agent?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_USERNAME: root
|
||||
SPRING_DATASOURCE_DYNAMIC_DATASOURCE_MASTER_PASSWORD: root
|
||||
# Redis 配置
|
||||
SPRING_DATA_REDIS_HOST: redis
|
||||
SPRING_DATA_REDIS_PORT: 6379
|
||||
SPRING_DATA_REDIS_DATABASE: 0
|
||||
# 日志配置
|
||||
LOGGING_LEVEL_ORG_RUOYI: info
|
||||
LOGGING_LEVEL_ORG_SPRINGFRAMEWORK: warn
|
||||
SYS_UPLOAD_PATH: /ruoyi/upload # 新增:对应 sys.upload.path
|
||||
volumes:
|
||||
- logs-data:/ruoyi/server/logs
|
||||
- upload-data:/ruoyi/upload
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
networks:
|
||||
- ruoyi-net
|
||||
|
||||
networks:
|
||||
ruoyi-net:
|
||||
driver: bridge
|
||||
|
||||
# 数据卷 支持手动指定 空为默认值
|
||||
volumes:
|
||||
mysql-data:
|
||||
redis-data:
|
||||
weaviate-data:
|
||||
minio-data:
|
||||
logs-data:
|
||||
upload-data:
|
||||
@@ -1,222 +0,0 @@
|
||||
## RuoYi-AI 后端部署教程(Docker 部署版)
|
||||
|
||||
### 一、前置条件
|
||||
|
||||
在部署前,请确保系统已满足以下条件:
|
||||
|
||||
#### ✅ 系统环境要求
|
||||
|
||||
- 操作系统:Linux / MacOS(推荐 Linux 服务器)
|
||||
- CPU:4 核以上
|
||||
- 内存:≥ 4GB
|
||||
- 磁盘空间:≥ 10GB(建议 20GB+)
|
||||
|
||||
#### ✅ 已安装软件
|
||||
|
||||
- **Docker**
|
||||
- **Docker Compose**
|
||||
|
||||
验证命令是否可用:
|
||||
|
||||
```
|
||||
docker -v
|
||||
docker compose version
|
||||
```
|
||||
|
||||
若无输出或提示“command not found”,请先安装 Docker 及 Compose。
|
||||
|
||||
------
|
||||
|
||||
### 二、目录结构配置
|
||||
|
||||
#### 1️⃣ 创建部署目录
|
||||
|
||||
在目标服务器执行以下命令:
|
||||
|
||||
```
|
||||
# 第一级目录
|
||||
mkdir /ruoyi-ai
|
||||
cd /ruoyi-ai
|
||||
|
||||
# 第二级目录
|
||||
mkdir deploy
|
||||
cd deploy
|
||||
|
||||
# 第三级目录
|
||||
mkdir data mysql-init
|
||||
|
||||
# 第四级目录
|
||||
mkdir logs minio minio-config mysql redis weaviate
|
||||
```
|
||||
|
||||
> 💡 `data` 目录用于挂载容器运行期间生成的数据文件。
|
||||
|
||||
最终目录结构示例:
|
||||
|
||||
```
|
||||
/ruoyi-ai
|
||||
└── deploy
|
||||
├── data/
|
||||
├── mysql-init/
|
||||
├── logs/
|
||||
├── minio/
|
||||
├── minio-config/
|
||||
├── mysql/
|
||||
├── redis/
|
||||
├── weaviate/
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
### 三、上传配置文件
|
||||
|
||||
将以下配置文件上传到 `/ruoyi-ai/deploy` 目录:
|
||||
|
||||
- `docker-compose.yaml`
|
||||
- `.env`
|
||||
- `ruoyi-ai.sql`
|
||||
- `Dockerfile`
|
||||
|
||||
> 📂 这些文件在项目目录 `/script/deploy/deploy` 下。
|
||||
> 上传后请检查文件路径是否与上方目录结构一致。
|
||||
|
||||
------
|
||||
|
||||
### 四、构建 Jar 包
|
||||
|
||||
1. 打开 IDEA 或其他构建工具
|
||||
2. 选择 **Maven 构建配置**,勾选 `prod` 环境,取消 `dev` 环境
|
||||
3. 点击 `package` 进行打包
|
||||
4. **注意:** 在构建前请将 `application-prod.yml` 拖入
|
||||
`ruoyi-admin/src/main/resources` 目录中
|
||||
|
||||
构建完成后会在:
|
||||
|
||||
```
|
||||
ruoyi-admin/target/ruoyi-admin.jar
|
||||
```
|
||||
|
||||
生成打包文件。
|
||||
|
||||
------
|
||||
|
||||
### 五、上传 Jar 包至服务器
|
||||
|
||||
将生成的 `ruoyi-admin.jar` 上传到服务器 `/ruoyi-ai/deploy` 目录下。
|
||||
确保与 `Dockerfile` 同目录。
|
||||
|
||||
------
|
||||
|
||||
### 六、构建 Docker 镜像
|
||||
|
||||
`Dockerfile` 内容如下:
|
||||
|
||||
```
|
||||
FROM openjdk:17-jdk
|
||||
|
||||
RUN mkdir -p /ruoyi/server/logs \
|
||||
/ruoyi/server/temp
|
||||
|
||||
WORKDIR /ruoyi/server
|
||||
COPY ruoyi-admin.jar ruoyi-admin.jar
|
||||
|
||||
ENTRYPOINT ["java","-jar","ruoyi-admin.jar"]
|
||||
```
|
||||
|
||||
在 `/ruoyi-ai/deploy` 目录执行以下命令:
|
||||
|
||||
```
|
||||
# 构建镜像
|
||||
docker build -t ruoyi-ai-backend:v20251013 .
|
||||
|
||||
# 查看镜像是否构建成功
|
||||
docker image ls
|
||||
```
|
||||
|
||||
然后在 `docker-compose.yaml` 文件中,将对应服务的镜像名修改为:
|
||||
|
||||
```
|
||||
image: ruoyi-ai-backend:v20251013
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
### 七、启动容器服务
|
||||
|
||||
在启动前请确认:
|
||||
|
||||
- `.env` 中端口号、数据库密码、环境变量已正确配置
|
||||
- `docker-compose.yaml` 中 MySQL 的端口已开放(用于导入数据)
|
||||
|
||||
如示例:
|
||||
|
||||
```
|
||||
ports:
|
||||
- "3306:3306"
|
||||
```
|
||||
|
||||
#### 启动命令:
|
||||
|
||||
```
|
||||
cd /ruoyi-ai/deploy
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
#### 查看运行状态:
|
||||
|
||||
```
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
#### 查看日志:
|
||||
|
||||
```
|
||||
docker logs -f <容器名称>
|
||||
```
|
||||
|
||||
> ⚠️ 初次启动时可仅运行 `ruoyi-admin`(后端)模块,将前端 `ruoyi-web` 服务暂时注释,确认后端服务正常后再启用前端容器。
|
||||
|
||||
------
|
||||
|
||||
### 八、数据库初始化
|
||||
|
||||
启动 MySQL 容器后,执行以下操作:
|
||||
|
||||
```
|
||||
docker exec -it <mysql_container_name> bash
|
||||
mysql -uroot -p
|
||||
source /docker-entrypoint-initdb.d/ruoyi-ai.sql;
|
||||
```
|
||||
|
||||
或手动在客户端中导入 `/ruoyi-ai/deploy/ruoyi-ai.sql` 文件。
|
||||
|
||||
------
|
||||
|
||||
### 九、常用 Docker 命令
|
||||
|
||||
| 功能 | 命令 |
|
||||
|-----------|-----------------------------------|
|
||||
| 查看容器状态 | `docker ps -a` |
|
||||
| 查看日志 | `docker logs -f <容器名>` |
|
||||
| 停止服务 | `docker compose down` |
|
||||
| 重启服务 | `docker compose restart` |
|
||||
| 重新构建镜像 | `docker compose build --no-cache` |
|
||||
| 清理无用镜像/容器 | `docker system prune -a` |
|
||||
|
||||
------
|
||||
|
||||
### 🔍 十、部署验证
|
||||
|
||||
1. 检查容器是否全部启动成功:
|
||||
|
||||
```
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
2. 访问后端接口:
|
||||
|
||||
```
|
||||
http://<服务器IP>:<后端端口>
|
||||
```
|
||||
|
||||
3. 检查日志输出无异常。
|
||||
75
docs/docker/milvus/docker-compose.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
etcd:
|
||||
container_name: milvus-etcd
|
||||
image: quay.io/coreos/etcd:v3.5.18
|
||||
environment:
|
||||
- ETCD_AUTO_COMPACTION_MODE=revision
|
||||
- ETCD_AUTO_COMPACTION_RETENTION=1000
|
||||
- ETCD_QUOTA_BACKEND_BYTES=4294967296
|
||||
- ETCD_SNAPSHOT_COUNT=50000
|
||||
volumes:
|
||||
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
|
||||
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
|
||||
healthcheck:
|
||||
test: ["CMD", "etcdctl", "endpoint", "health"]
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
minio:
|
||||
container_name: milvus-minio
|
||||
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
|
||||
environment:
|
||||
MINIO_ACCESS_KEY: minioadmin
|
||||
MINIO_SECRET_KEY: minioadmin
|
||||
ports:
|
||||
- "9001:9001"
|
||||
- "9000:9000"
|
||||
volumes:
|
||||
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
|
||||
command: minio server /minio_data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
standalone:
|
||||
container_name: milvus-standalone
|
||||
image: milvusdb/milvus:v2.5.7
|
||||
command: ["milvus", "run", "standalone"]
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
environment:
|
||||
ETCD_ENDPOINTS: etcd:2379
|
||||
MINIO_ADDRESS: minio:9000
|
||||
volumes:
|
||||
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
|
||||
interval: 30s
|
||||
start_period: 90s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
ports:
|
||||
- "19530:19530"
|
||||
- "9091:9091"
|
||||
depends_on:
|
||||
- "etcd"
|
||||
- "minio"
|
||||
|
||||
attu:
|
||||
container_name: attu
|
||||
image: zilliz/attu:v2.5.7
|
||||
environment:
|
||||
MILVUS_URL: milvus-standalone:19530
|
||||
ports:
|
||||
- "19500:3000" # 外部端口19500可以自定义
|
||||
depends_on:
|
||||
- "standalone"
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: milvus
|
||||
BIN
docs/image/bibi.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/image/dy.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
docs/image/logo.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/image/qq.png
Normal file
|
After Width: | Height: | Size: 193 KiB |
BIN
docs/image/wx.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
10
docs/script/docker/mysql/init/init-db.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# 数据库初始化脚本
|
||||
# 使用 --force 参数确保即使出错也继续执行
|
||||
|
||||
echo "开始初始化数据库..."
|
||||
|
||||
# 使用 --force 参数忽略错误继续执行
|
||||
mysql -uroot -proot ruoyi-ai-agent --force < /docker-entrypoint-initdb.d/ruoyi-ai-v3_mysql8.sql
|
||||
|
||||
echo "数据库初始化完成"
|
||||
129
docs/script/leave/leave1.json
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"nodeList": [
|
||||
{
|
||||
"nodeType": "0",
|
||||
"nodeCode": "d5ee3ddf-3968-4379-a86f-9ceabde5faac",
|
||||
"nodeName": "开始",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "200,200|200,200",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "d5ee3ddf-3968-4379-a86f-9ceabde5faac",
|
||||
"nextNodeCode": "dd515cdd-59f6-446f-94ca-25ca062afb42",
|
||||
"coordinate": "220,200;310,200"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "dd515cdd-59f6-446f-94ca-25ca062afb42",
|
||||
"nodeName": "申请人",
|
||||
"permissionFlag": "",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,copy\"}]",
|
||||
"coordinate": "360,200|360,200",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "dd515cdd-59f6-446f-94ca-25ca062afb42",
|
||||
"nextNodeCode": "78fa8e5b-e809-44ed-978a-41092409ebcf",
|
||||
"coordinate": "410,200;490,200"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "78fa8e5b-e809-44ed-978a-41092409ebcf",
|
||||
"nodeName": "组长",
|
||||
"permissionFlag": "role:1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,copy,transfer,trust,file\"}]",
|
||||
"coordinate": "540,200|540,200",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "78fa8e5b-e809-44ed-978a-41092409ebcf",
|
||||
"nextNodeCode": "a8abf15f-b83e-428a-86cc-033555ea9bbe",
|
||||
"coordinate": "590,200;670,200"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "a8abf15f-b83e-428a-86cc-033555ea9bbe",
|
||||
"nodeName": "部门主管",
|
||||
"permissionFlag": "role:3@@role:4",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,copy,transfer,trust,file\"}]",
|
||||
"coordinate": "720,200|720,200",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "a8abf15f-b83e-428a-86cc-033555ea9bbe",
|
||||
"nextNodeCode": "8b82b7d7-8660-455e-b880-d6d22ea3eb6d",
|
||||
"coordinate": "770,200;880,200"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "2",
|
||||
"nodeCode": "8b82b7d7-8660-455e-b880-d6d22ea3eb6d",
|
||||
"nodeName": "结束",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "900,200|900,200",
|
||||
"version": "1",
|
||||
"skipList": []
|
||||
}
|
||||
],
|
||||
"flowCode": "leave1",
|
||||
"flowName": "请假申请-普通",
|
||||
"modelValue": "CLASSICS",
|
||||
"category": "103",
|
||||
"version": "1",
|
||||
"formCustom": "N",
|
||||
"formPath": "/workflow/leaveEdit/index",
|
||||
"listenerType": null,
|
||||
"listenerPath": null
|
||||
}
|
||||
187
docs/script/leave/leave2.json
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"nodeList": [
|
||||
{
|
||||
"nodeType": "0",
|
||||
"nodeCode": "cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a",
|
||||
"nodeName": "开始",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "300,240|300,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a",
|
||||
"nextNodeCode": "fdcae93b-b69c-498a-b231-09255e74bcbd",
|
||||
"coordinate": "320,240;390,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "fdcae93b-b69c-498a-b231-09255e74bcbd",
|
||||
"nodeName": "申请人",
|
||||
"permissionFlag": "",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file\"}]",
|
||||
"coordinate": "440,240|440,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "fdcae93b-b69c-498a-b231-09255e74bcbd",
|
||||
"nextNodeCode": "7b8c7ead-7dc8-4951-a7f3-f0c41995909e",
|
||||
"coordinate": "490,240;535,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "3",
|
||||
"nodeCode": "7b8c7ead-7dc8-4951-a7f3-f0c41995909e",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "560,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": "le@@leaveDays|2",
|
||||
"skipName": null,
|
||||
"nowNodeCode": "7b8c7ead-7dc8-4951-a7f3-f0c41995909e",
|
||||
"nextNodeCode": "b3528155-dcb7-4445-bbdf-3d00e3499e86",
|
||||
"coordinate": "560,265;560,320;670,320"
|
||||
},
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": "gt@@leaveDays|2",
|
||||
"skipName": "大于两天",
|
||||
"nowNodeCode": "7b8c7ead-7dc8-4951-a7f3-f0c41995909e",
|
||||
"nextNodeCode": "5ed2362b-fc0c-4d52-831f-95208b830605",
|
||||
"coordinate": "560,215;560,160;670,160|560,187"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "b3528155-dcb7-4445-bbdf-3d00e3499e86",
|
||||
"nodeName": "组长",
|
||||
"permissionFlag": "3@@4",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "720,320|720,320",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "b3528155-dcb7-4445-bbdf-3d00e3499e86",
|
||||
"nextNodeCode": "c9fa6d7d-2a74-4e78-b947-0cad8a6af869",
|
||||
"coordinate": "770,320;860,320;860,280"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "c9fa6d7d-2a74-4e78-b947-0cad8a6af869",
|
||||
"nodeName": "总经理",
|
||||
"permissionFlag": "role:1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "860,240|860,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "c9fa6d7d-2a74-4e78-b947-0cad8a6af869",
|
||||
"nextNodeCode": "40aa65fd-0712-4d23-b6f7-d0432b920fd1",
|
||||
"coordinate": "910,240;980,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "2",
|
||||
"nodeCode": "40aa65fd-0712-4d23-b6f7-d0432b920fd1",
|
||||
"nodeName": "结束",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1000,240|1000,240",
|
||||
"version": "1",
|
||||
"skipList": []
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "5ed2362b-fc0c-4d52-831f-95208b830605",
|
||||
"nodeName": "部门领导",
|
||||
"permissionFlag": "role:1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "720,160|720,160",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "5ed2362b-fc0c-4d52-831f-95208b830605",
|
||||
"nextNodeCode": "c9fa6d7d-2a74-4e78-b947-0cad8a6af869",
|
||||
"nextNodeType": "1",
|
||||
"coordinate": "770,160;860,160;860,200"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"flowCode": "leave2",
|
||||
"flowName": "请假申请-排他网关",
|
||||
"modelValue": "CLASSICS",
|
||||
"category": "103",
|
||||
"version": "1",
|
||||
"formCustom": "N",
|
||||
"formPath": "/workflow/leaveEdit/index",
|
||||
"listenerType": null,
|
||||
"listenerPath": null
|
||||
}
|
||||
211
docs/script/leave/leave3.json
Normal file
@@ -0,0 +1,211 @@
|
||||
{
|
||||
"nodeList": [
|
||||
{
|
||||
"nodeType": "0",
|
||||
"nodeCode": "a80ecf9f-f465-4ae5-a429-e30ec5d0f957",
|
||||
"nodeName": "开始",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "380,220|380,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "a80ecf9f-f465-4ae5-a429-e30ec5d0f957",
|
||||
"nextNodeCode": "b7bbb571-06de-455c-8083-f83c07bf0b99",
|
||||
"coordinate": "400,220;470,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "b7bbb571-06de-455c-8083-f83c07bf0b99",
|
||||
"nodeName": "申请人",
|
||||
"permissionFlag": "",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file\"}]",
|
||||
"coordinate": "520,220|520,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "b7bbb571-06de-455c-8083-f83c07bf0b99",
|
||||
"nextNodeCode": "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a",
|
||||
"coordinate": "570,220;655,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "4",
|
||||
"nodeCode": "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "680,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a",
|
||||
"nextNodeCode": "4b7743cd-940c-431b-926f-e7b614fbf1fe",
|
||||
"coordinate": "680,195;680,140;750,140"
|
||||
},
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a",
|
||||
"nextNodeCode": "762cb975-37d8-4276-b6db-79a4c3606394",
|
||||
"coordinate": "680,245;680,300;750,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "4b7743cd-940c-431b-926f-e7b614fbf1fe",
|
||||
"nodeName": "市场部",
|
||||
"permissionFlag": "role:1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "800,140|800,140",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "4b7743cd-940c-431b-926f-e7b614fbf1fe",
|
||||
"nextNodeCode": "b66b6563-f9fe-41cc-a782-f7837bb6f3d2",
|
||||
"coordinate": "850,140;920,140;920,195"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "4",
|
||||
"nodeCode": "b66b6563-f9fe-41cc-a782-f7837bb6f3d2",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "920,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "b66b6563-f9fe-41cc-a782-f7837bb6f3d2",
|
||||
"nextNodeCode": "23e7429e-2b47-4431-b93e-40db7c431ce6",
|
||||
"coordinate": "945,220;975,220;975,220;960,220;960,220;990,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "23e7429e-2b47-4431-b93e-40db7c431ce6",
|
||||
"nodeName": "CEO",
|
||||
"permissionFlag": "1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "1040,220|1040,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "23e7429e-2b47-4431-b93e-40db7c431ce6",
|
||||
"nextNodeCode": "f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1",
|
||||
"coordinate": "1090,220;1140,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "2",
|
||||
"nodeCode": "f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1",
|
||||
"nodeName": "结束",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1160,220|1160,220",
|
||||
"version": "1",
|
||||
"skipList": []
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "762cb975-37d8-4276-b6db-79a4c3606394",
|
||||
"nodeName": "综合部",
|
||||
"permissionFlag": "role:3@@role:4",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "800,300|800,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "762cb975-37d8-4276-b6db-79a4c3606394",
|
||||
"nextNodeCode": "b66b6563-f9fe-41cc-a782-f7837bb6f3d2",
|
||||
"nextNodeType": "4",
|
||||
"coordinate": "850,300;920,300;920,245"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"flowCode": "leave3",
|
||||
"flowName": "请假申请-并行网关",
|
||||
"modelValue": "CLASSICS",
|
||||
"category": "103",
|
||||
"version": "1",
|
||||
"formCustom": "N",
|
||||
"formPath": "/workflow/leaveEdit/index",
|
||||
"listenerType": null,
|
||||
"listenerPath": null
|
||||
}
|
||||
154
docs/script/leave/leave4.json
Normal file
@@ -0,0 +1,154 @@
|
||||
{
|
||||
"nodeList": [
|
||||
{
|
||||
"nodeType": "0",
|
||||
"nodeCode": "9ce8bf00-f25b-4fc6-91b8-827082fc4876",
|
||||
"nodeName": "开始",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "320,240|320,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "9ce8bf00-f25b-4fc6-91b8-827082fc4876",
|
||||
"nextNodeCode": "e90b98ef-35b4-410c-a663-bae8b7624b9f",
|
||||
"coordinate": "340,240;410,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "e90b98ef-35b4-410c-a663-bae8b7624b9f",
|
||||
"nodeName": "申请人",
|
||||
"permissionFlag": "",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file\"}]",
|
||||
"coordinate": "460,240|460,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "e90b98ef-35b4-410c-a663-bae8b7624b9f",
|
||||
"nextNodeCode": "768b5b1a-6726-4d67-8853-4cc70d5b1045",
|
||||
"coordinate": "510,240;590,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "768b5b1a-6726-4d67-8853-4cc70d5b1045",
|
||||
"nodeName": "百分之60通过",
|
||||
"permissionFlag": "${userList}",
|
||||
"nodeRatio": "60.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,addSign,subSign\"}]",
|
||||
"coordinate": "640,240|640,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "768b5b1a-6726-4d67-8853-4cc70d5b1045",
|
||||
"nextNodeCode": "2f9f2e21-9bcf-42a3-a07c-13037aad22d1",
|
||||
"coordinate": "690,240;770,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "2f9f2e21-9bcf-42a3-a07c-13037aad22d1",
|
||||
"nodeName": "全部审批通过",
|
||||
"permissionFlag": "role:1@@role:3",
|
||||
"nodeRatio": "100.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,addSign,subSign\"}]",
|
||||
"coordinate": "820,240|820,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "2f9f2e21-9bcf-42a3-a07c-13037aad22d1",
|
||||
"nextNodeCode": "27461e01-3d9f-4530-8fe3-bd5ec7f9571f",
|
||||
"coordinate": "870,240;950,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "27461e01-3d9f-4530-8fe3-bd5ec7f9571f",
|
||||
"nodeName": "CEO",
|
||||
"permissionFlag": "1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "1000,240|1000,240",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "27461e01-3d9f-4530-8fe3-bd5ec7f9571f",
|
||||
"nextNodeCode": "b62b88c3-8d8d-4969-911e-2aaea219e7fc",
|
||||
"coordinate": "1050,240;1080,240;1080,240;1070,240;1070,240;1100,240"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "2",
|
||||
"nodeCode": "b62b88c3-8d8d-4969-911e-2aaea219e7fc",
|
||||
"nodeName": "结束",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1120,240|1120,240",
|
||||
"version": "1",
|
||||
"skipList": []
|
||||
}
|
||||
],
|
||||
"flowCode": "leave4",
|
||||
"flowName": "请假申请-会签",
|
||||
"modelValue": "CLASSICS",
|
||||
"category": "103",
|
||||
"version": "1",
|
||||
"formCustom": "N",
|
||||
"formPath": "/workflow/leaveEdit/index",
|
||||
"listenerType": null,
|
||||
"listenerPath": null
|
||||
}
|
||||
211
docs/script/leave/leave5.json
Normal file
@@ -0,0 +1,211 @@
|
||||
{
|
||||
"nodeList": [
|
||||
{
|
||||
"nodeType": "0",
|
||||
"nodeCode": "ebebaf26-9cb6-497e-8119-4c9fed4c597c",
|
||||
"nodeName": "开始",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "300,220|300,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "ebebaf26-9cb6-497e-8119-4c9fed4c597c",
|
||||
"nextNodeCode": "e1b04e96-dc81-4858-a309-2fe945d2f374",
|
||||
"coordinate": "320,220;350,220;350,220;340,220;340,220;370,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "e1b04e96-dc81-4858-a309-2fe945d2f374",
|
||||
"nodeName": "申请人",
|
||||
"permissionFlag": "",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file\"}]",
|
||||
"coordinate": "420,220|420,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "e1b04e96-dc81-4858-a309-2fe945d2f374",
|
||||
"nextNodeCode": "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9",
|
||||
"coordinate": "470,220;535,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "4",
|
||||
"nodeCode": "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "560,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9",
|
||||
"nextNodeCode": "c80f273e-1f17-4bd8-9ad1-04a4a94ea862",
|
||||
"coordinate": "560,245;560,320;650,320"
|
||||
},
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9",
|
||||
"nextNodeCode": "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4",
|
||||
"coordinate": "560,195;560,120;650,120"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "c80f273e-1f17-4bd8-9ad1-04a4a94ea862",
|
||||
"nodeName": "会签",
|
||||
"permissionFlag": "role:1@@role:3",
|
||||
"nodeRatio": "100.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,addSign,subSign\"}]",
|
||||
"coordinate": "700,320|700,320",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "c80f273e-1f17-4bd8-9ad1-04a4a94ea862",
|
||||
"nextNodeCode": "1a20169e-3d82-4926-a151-e2daad28de1b",
|
||||
"coordinate": "750,320;860,320;860,245"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "4",
|
||||
"nodeCode": "1a20169e-3d82-4926-a151-e2daad28de1b",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "860,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "1a20169e-3d82-4926-a151-e2daad28de1b",
|
||||
"nextNodeCode": "7a8f0473-e409-442e-a843-5c2b813d00e9",
|
||||
"coordinate": "885,220;950,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "7a8f0473-e409-442e-a843-5c2b813d00e9",
|
||||
"nodeName": "CEO",
|
||||
"permissionFlag": "1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,transfer,trust,copy\"}]",
|
||||
"coordinate": "1000,220|1000,220",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "7a8f0473-e409-442e-a843-5c2b813d00e9",
|
||||
"nextNodeCode": "03c4d2bc-58b5-4408-a2e4-65afb046f169",
|
||||
"coordinate": "1050,220;1120,220"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "2",
|
||||
"nodeCode": "03c4d2bc-58b5-4408-a2e4-65afb046f169",
|
||||
"nodeName": "结束",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1140,220|1140,220",
|
||||
"version": "1",
|
||||
"skipList": []
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4",
|
||||
"nodeName": "百分之60票签",
|
||||
"permissionFlag": "${userList}",
|
||||
"nodeRatio": "60.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file,addSign,subSign\"}]",
|
||||
"coordinate": "700,120|700,120",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4",
|
||||
"nextNodeCode": "1a20169e-3d82-4926-a151-e2daad28de1b",
|
||||
"nextNodeType": "4",
|
||||
"coordinate": "750,120;860,120;860,195"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"flowCode": "leave5",
|
||||
"flowName": "请假申请-并行会签网关",
|
||||
"modelValue": "CLASSICS",
|
||||
"category": "103",
|
||||
"version": "1",
|
||||
"formCustom": "N",
|
||||
"formPath": "/workflow/leaveEdit/index",
|
||||
"listenerType": null,
|
||||
"listenerPath": null
|
||||
}
|
||||
368
docs/script/leave/leave6.json
Normal file
@@ -0,0 +1,368 @@
|
||||
{
|
||||
"nodeList": [
|
||||
{
|
||||
"nodeType": "0",
|
||||
"nodeCode": "122b89a5-7c6f-40a3-aa09-7a263f902054",
|
||||
"nodeName": "开始",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "240,300|240,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "122b89a5-7c6f-40a3-aa09-7a263f902054",
|
||||
"nextNodeCode": "c25a0e86-fdd1-4f03-8e22-14db70389dbd",
|
||||
"coordinate": "260,300;350,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "c25a0e86-fdd1-4f03-8e22-14db70389dbd",
|
||||
"nodeName": "申请人",
|
||||
"permissionFlag": "",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,file\"}]",
|
||||
"coordinate": "400,300|400,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "c25a0e86-fdd1-4f03-8e22-14db70389dbd",
|
||||
"nextNodeCode": "07ecda1d-7a0a-47b5-8a91-6186c9473742",
|
||||
"coordinate": "450,300;510,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "2bfa3919-78cf-4bc1-b59b-df463a4546f9",
|
||||
"nodeName": "副经理",
|
||||
"permissionFlag": "role:1@@role:3@@role:4",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination\"}]",
|
||||
"coordinate": "860,200|860,200",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "2bfa3919-78cf-4bc1-b59b-df463a4546f9",
|
||||
"nextNodeCode": "394e1cc8-b8b2-4189-9f81-44448e88ac32",
|
||||
"coordinate": "910,200;1000,200;1000,275"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "ec17f60e-94e0-4d96-a3ce-3417e9d32d60",
|
||||
"nodeName": "组长",
|
||||
"permissionFlag": "1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination\"}]",
|
||||
"coordinate": "860,400|860,400",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "ec17f60e-94e0-4d96-a3ce-3417e9d32d60",
|
||||
"nextNodeCode": "394e1cc8-b8b2-4189-9f81-44448e88ac32",
|
||||
"coordinate": "910,400;1000,400;1000,325"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "07ecda1d-7a0a-47b5-8a91-6186c9473742",
|
||||
"nodeName": "副组长",
|
||||
"permissionFlag": "1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,transfer,copy,pop\"}]",
|
||||
"coordinate": "560,300|560,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "07ecda1d-7a0a-47b5-8a91-6186c9473742",
|
||||
"nextNodeCode": "48117e2c-6328-406b-b102-c4a9d115bb13",
|
||||
"coordinate": "610,300;675,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "3",
|
||||
"nodeCode": "48117e2c-6328-406b-b102-c4a9d115bb13",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "700,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": "default@@${leaveDays > 2}",
|
||||
"skipName": "大于两天",
|
||||
"nowNodeCode": "48117e2c-6328-406b-b102-c4a9d115bb13",
|
||||
"nextNodeCode": "2bfa3919-78cf-4bc1-b59b-df463a4546f9",
|
||||
"nextNodeType": "1",
|
||||
"coordinate": "700,275;700,200;810,200|700,237"
|
||||
},
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": "spel@@#{@testLeaveServiceImpl.eval(#leaveDays)}",
|
||||
"skipName": null,
|
||||
"nowNodeCode": "48117e2c-6328-406b-b102-c4a9d115bb13",
|
||||
"nextNodeCode": "ec17f60e-94e0-4d96-a3ce-3417e9d32d60",
|
||||
"nextNodeType": "1",
|
||||
"coordinate": "700,325;700,400;810,400"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "3",
|
||||
"nodeCode": "394e1cc8-b8b2-4189-9f81-44448e88ac32",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1000,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "394e1cc8-b8b2-4189-9f81-44448e88ac32",
|
||||
"nextNodeCode": "9c93a195-cff2-4e17-ab0a-a4f264191496",
|
||||
"coordinate": "1025,300;1130,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "9c93a195-cff2-4e17-ab0a-a4f264191496",
|
||||
"nodeName": "经理会签",
|
||||
"permissionFlag": "1@@3",
|
||||
"nodeRatio": "100.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination,pop,addSign,subSign\"}]",
|
||||
"coordinate": "1180,300|1180,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "9c93a195-cff2-4e17-ab0a-a4f264191496",
|
||||
"nextNodeCode": "a1a42056-afd1-4e90-88bc-36cbf5a66992",
|
||||
"coordinate": "1230,300;1315,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "4",
|
||||
"nodeCode": "a1a42056-afd1-4e90-88bc-36cbf5a66992",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1340,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "a1a42056-afd1-4e90-88bc-36cbf5a66992",
|
||||
"nextNodeCode": "fcfdd9f6-f526-4c1a-b71d-88afa31aebc5",
|
||||
"coordinate": "1340,325;1340,400;1430,400"
|
||||
},
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "a1a42056-afd1-4e90-88bc-36cbf5a66992",
|
||||
"nextNodeCode": "350dfa0c-a77c-4efa-8527-10efa02d8be4",
|
||||
"coordinate": "1340,275;1340,200;1430,200"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "350dfa0c-a77c-4efa-8527-10efa02d8be4",
|
||||
"nodeName": "总经理",
|
||||
"permissionFlag": "3@@1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination\"}]",
|
||||
"coordinate": "1480,200|1480,200",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "350dfa0c-a77c-4efa-8527-10efa02d8be4",
|
||||
"nextNodeCode": "c36a46ef-04f9-463f-bad7-4b395c818519",
|
||||
"coordinate": "1530,200;1640,200;1640,275"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "fcfdd9f6-f526-4c1a-b71d-88afa31aebc5",
|
||||
"nodeName": "副总经理",
|
||||
"permissionFlag": "1@@3",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination\"}]",
|
||||
"coordinate": "1480,400|1480,400",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "fcfdd9f6-f526-4c1a-b71d-88afa31aebc5",
|
||||
"nextNodeCode": "c36a46ef-04f9-463f-bad7-4b395c818519",
|
||||
"coordinate": "1530,400;1640,400;1640,325"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "4",
|
||||
"nodeCode": "c36a46ef-04f9-463f-bad7-4b395c818519",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1640,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "c36a46ef-04f9-463f-bad7-4b395c818519",
|
||||
"nextNodeCode": "3fcea762-b53a-4ae1-8365-7bec90444828",
|
||||
"coordinate": "1665,300;1770,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "1",
|
||||
"nodeCode": "3fcea762-b53a-4ae1-8365-7bec90444828",
|
||||
"nodeName": "董事",
|
||||
"permissionFlag": "1",
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": "",
|
||||
"listenerPath": "",
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[{\"code\":\"ButtonPermissionEnum\",\"value\":\"back,termination\"}]",
|
||||
"coordinate": "1820,300|1820,300",
|
||||
"version": "1",
|
||||
"skipList": [
|
||||
{
|
||||
"skipType": "PASS",
|
||||
"skipCondition": null,
|
||||
"skipName": null,
|
||||
"nowNodeCode": "3fcea762-b53a-4ae1-8365-7bec90444828",
|
||||
"nextNodeCode": "9cfbfd3e-6c04-41d6-9fc2-6787a7d2cd31",
|
||||
"coordinate": "1870,300;1960,300"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"nodeType": "2",
|
||||
"nodeCode": "9cfbfd3e-6c04-41d6-9fc2-6787a7d2cd31",
|
||||
"nodeName": "结束",
|
||||
"permissionFlag": null,
|
||||
"nodeRatio": "0.000",
|
||||
"anyNodeSkip": null,
|
||||
"listenerType": null,
|
||||
"listenerPath": null,
|
||||
"formCustom": "N",
|
||||
"formPath": null,
|
||||
"ext": "[]",
|
||||
"coordinate": "1980,300|1980,300",
|
||||
"version": "1",
|
||||
"skipList": []
|
||||
}
|
||||
],
|
||||
"flowCode": "leave6",
|
||||
"flowName": "请假申请-排他并行会签",
|
||||
"modelValue": "CLASSICS",
|
||||
"category": "103",
|
||||
"version": "1",
|
||||
"formCustom": "N",
|
||||
"formPath": "/workflow/leaveEdit/index",
|
||||
"listenerType": null,
|
||||
"listenerPath": null
|
||||
}
|
||||
3481
docs/script/sql/ruoyi-ai-v3_mysql8.sql
Normal file
@@ -1,352 +0,0 @@
|
||||
<a id="top"></a>
|
||||
|
||||
# RAG 常见故障排查(16 问题清单)
|
||||
|
||||
当知识库已经接入,系统也能正常回答,但结果仍然出现命中错误、引用旧内容、推理漂移、跨轮次失忆,或部署后表面可用但实际异常时,最常见的问题不是“模型不行”,而是**不同层的故障被混在一起处理**。
|
||||
|
||||
这份页面不重新发明一套新方法。
|
||||
它直接使用一份固定的 **16 问题清单** 作为排查主轴,让你先把问题标到正确的 **No.X**,再决定下一步查哪里、改哪里,而不是一次性乱改检索、模型、切块、会话和部署配置。
|
||||
|
||||
这份清单的核心目的只有一个:
|
||||
|
||||
**先把问题放进正确的故障域,再做修复。**
|
||||
|
||||
快速导航:
|
||||
[这页怎么用](#how-to-use) | [标签说明](#legend) | [常见症状入口](#symptoms) | [16 问题清单](#map16) | [按层排查](#by-layer) |
|
||||
|
||||
---
|
||||
|
||||
<a id="how-to-use"></a>
|
||||
|
||||
## 一、这页怎么用
|
||||
|
||||
这不是一篇“从头到尾照着做”的传统教程。
|
||||
它更像一张固定的 RAG 故障地图,作用是先帮助你**判断故障属于哪一种类型**。
|
||||
|
||||
建议按下面顺序使用:
|
||||
|
||||
### 1. 先看现象,不要先改配置
|
||||
|
||||
先回答两个问题:
|
||||
|
||||
1. 你看到的故障,最像哪一种症状
|
||||
2. 这个故障更像发生在输入检索层、推理层、状态层,还是部署层
|
||||
|
||||
在还没判断层级之前,不要先一起改这些东西:
|
||||
|
||||
- 检索条数
|
||||
- 切块大小
|
||||
- 会话配置
|
||||
- 模型参数
|
||||
- 部署顺序
|
||||
- 依赖服务
|
||||
|
||||
如果先全部一起动,问题通常只会更难定位。
|
||||
|
||||
### 2. 先给问题打上 No.X 标签
|
||||
|
||||
这份页面最重要的动作,不是“立刻修好”,而是先做一件小事:
|
||||
|
||||
**给当前问题贴上最接近的 No.X。**
|
||||
|
||||
例如:
|
||||
|
||||
- 检索结果看起来相似,但其实答非所问,先看 `No.1` 或 `No.5`
|
||||
- 切块是对的,但结论还是错,先看 `No.2`
|
||||
- 系统回答很自信,但没有根据,先看 `No.4`
|
||||
- 刚部署完就炸,先看 `No.14` 到 `No.16`
|
||||
|
||||
### 3. 一次只排一个故障域
|
||||
|
||||
同一个表面现象,背后可能是不同层的问题。
|
||||
例如“答案不对”既可能是:
|
||||
|
||||
- `No.1` 检索漂移
|
||||
- `No.2` 理解塌陷
|
||||
- `No.4` 自信乱答
|
||||
- `No.8` 根本看不到错误路径
|
||||
|
||||
所以这张表的用法不是“多选全改”,而是:
|
||||
|
||||
**先挑最接近的一项,优先验证这一项是否成立。**
|
||||
|
||||
[返回顶部](#top) | [下一节:标签说明](#legend)
|
||||
|
||||
---
|
||||
|
||||
<a id="legend"></a>
|
||||
|
||||
## 二、标签说明
|
||||
|
||||
这份 16 问题清单本身已经带有层级 / 标签结构。
|
||||
这些标签不是装饰,而是用来帮助你快速判断故障发生在哪一层。
|
||||
|
||||
### 1. 层级标签
|
||||
|
||||
- `[IN]`:输入与检索
|
||||
输入、切块、召回、语义匹配、可见性问题
|
||||
|
||||
- `[RE]`:推理与规划
|
||||
理解、推理、归纳、逻辑链、抽象处理问题
|
||||
|
||||
- `[ST]`:状态与上下文
|
||||
会话、记忆、上下文连续性、多代理状态问题
|
||||
|
||||
- `[OP]`:基础设施与部署
|
||||
启动顺序、依赖就绪、部署锁死、预部署状态问题
|
||||
|
||||
### 2. `{OBS}` 标签
|
||||
|
||||
带 `{OBS}` 的项,通常都和“**你是否看得见问题是怎么坏掉的**”有关。
|
||||
它们往往不是单纯回答错误,而是:
|
||||
|
||||
- 错误路径不可见
|
||||
- 漂移过程不可见
|
||||
- 状态熔化过程不可见
|
||||
- 多代理覆盖过程不可见
|
||||
|
||||
所以一旦你发现“我知道结果错,但我根本看不到它是怎么错的”,通常就已经很接近 `{OBS}` 类问题了。
|
||||
|
||||
### 3. 为什么要保留这些标签
|
||||
|
||||
因为同样叫“答错了”,实际含义完全不同。
|
||||
|
||||
例如:
|
||||
|
||||
- `[IN]` 的答错,常常是**拿错材料**
|
||||
- `[RE]` 的答错,常常是**拿对材料但理解错**
|
||||
- `[ST]` 的答错,常常是**前文断掉、状态漂移**
|
||||
- `[OP]` 的答错,常常是**系统根本没在完整状态下运行**
|
||||
|
||||
如果不先分层,就会掉进典型的 RAG 地狱:
|
||||
表面在改答案,实际上在盲修。
|
||||
|
||||
[返回顶部](#top) | [下一节:常见症状入口](#symptoms)
|
||||
|
||||
---
|
||||
|
||||
<a id="symptoms"></a>
|
||||
|
||||
## 三、常见症状入口
|
||||
|
||||
如果你现在还不知道该从哪一项开始,就先从症状入口反查。
|
||||
|
||||
### 1. 检索返回了错误内容,或看起来相关但其实不回答问题
|
||||
|
||||
这类问题最常见的是:
|
||||
“有命中,但命中的不是该用的内容。”
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.1](#no1) `幻觉与切块漂移`
|
||||
- [No.5](#no5) `语义 ≠ 向量嵌入`
|
||||
- [No.8](#no8) `调试是一个黑箱`
|
||||
|
||||
### 2. 切块本身是对的,但最终答案还是错的
|
||||
|
||||
这类问题不是简单没检索到,而是后面那层坏了。
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.2](#no2) `解释塌陷`
|
||||
- [No.4](#no4) `虚张声势 / 过度自信`
|
||||
- [No.6](#no6) `逻辑塌陷与恢复`
|
||||
|
||||
### 3. 多步任务一开始正常,后面越来越偏
|
||||
|
||||
这类问题通常不是单点错误,而是中途漂移或熔化。
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.3](#no3) `长推理链`
|
||||
- [No.6](#no6) `逻辑塌陷与恢复`
|
||||
- [No.9](#no9) `熵塌陷`
|
||||
|
||||
### 4. 多轮对话后开始失忆,跨轮次接不上
|
||||
|
||||
这类问题一般已经进入状态层。
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.7](#no7) `跨会话记忆断裂`
|
||||
- [No.9](#no9) `熵塌陷`
|
||||
- [No.13](#no13) `多代理混乱`
|
||||
|
||||
### 5. 遇到抽象、逻辑、规则、符号关系就崩
|
||||
|
||||
这类问题通常不是检索空,而是推理结构扛不住。
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.11](#no11) `符号塌陷`
|
||||
- [No.12](#no12) `哲学递归`
|
||||
|
||||
### 6. 你根本不知道错在哪一层,只知道结果不对
|
||||
|
||||
这类问题先不要乱调参数。
|
||||
先解决“不可见”的问题。
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.8](#no8) `调试是一个黑箱`
|
||||
|
||||
### 7. 刚部署完最容易炸,首轮调用异常,重启后偶尔恢复
|
||||
|
||||
这类问题通常不在答案逻辑,而在部署状态。
|
||||
|
||||
优先看:
|
||||
|
||||
- [No.14](#no14) `引导启动顺序`
|
||||
- [No.15](#no15) `部署死锁`
|
||||
- [No.16](#no16) `预部署塌陷`
|
||||
|
||||
[返回顶部](#top) | [下一节:16 问题清单](#map16)
|
||||
|
||||
---
|
||||
|
||||
<a id="map16"></a>
|
||||
|
||||
## 四、16 问题清单(固定主表)
|
||||
|
||||
下面这 16 项按固定顺序使用。
|
||||
不要先重组,不要先混类,先判断最接近哪一个 **No.X**。
|
||||
|
||||
| # | 问题域(含层级/标签) | 会坏在哪里 |
|
||||
|---|---|---|
|
||||
| <a id="no1"></a> 1 | `[IN] 幻觉与切块漂移 {OBS}` | 检索返回错误/无关内容 |
|
||||
| <a id="no2"></a> 2 | `[RE] 解释塌陷` | 切块是对的,逻辑是错的 |
|
||||
| <a id="no3"></a> 3 | `[RE] 长推理链 {OBS}` | 在多步任务中逐步漂移 |
|
||||
| <a id="no4"></a> 4 | `[RE] 虚张声势 / 过度自信` | 自信但没有根据的回答 |
|
||||
| <a id="no5"></a> 5 | `[IN] 语义 ≠ 向量嵌入 {OBS}` | 余弦匹配 ≠ 真实语义 |
|
||||
| <a id="no6"></a> 6 | `[RE] 逻辑塌陷与恢复 {OBS}` | 走入死胡同,需要受控重置 |
|
||||
| <a id="no7"></a> 7 | `[ST] 跨会话记忆断裂` | 线索丢失,没有连续性 |
|
||||
| <a id="no8"></a> 8 | `[IN] 调试是一个黑箱 {OBS}` | 看不到故障路径 |
|
||||
| <a id="no9"></a> 9 | `[ST] 熵塌陷` | 注意力熔化,输出失去连贯性 |
|
||||
| <a id="no10"></a> 10 | `[RE] 创造力冻结` | 平直、字面化输出 |
|
||||
| <a id="no11"></a> 11 | `[RE] 符号塌陷` | 抽象/逻辑性提示词失效 |
|
||||
| <a id="no12"></a> 12 | `[RE] 哲学递归` | 自我引用循环、悖论陷阱 |
|
||||
| <a id="no13"></a> 13 | `[ST] 多代理混乱 {OBS}` | 代理互相覆盖或使逻辑错位 |
|
||||
| <a id="no14"></a> 14 | `[OP] 引导启动顺序` | 依赖未就绪时服务先启动 |
|
||||
| <a id="no15"></a> 15 | `[OP] 部署死锁` | 基础设施中的循环等待 |
|
||||
| <a id="no16"></a> 16 | `[OP] 预部署塌陷 {OBS}` | 首次调用时版本错配 / 缺少密钥 |
|
||||
|
||||
这张表是主表。
|
||||
如果你时间很少,只做一件事也行:
|
||||
|
||||
**先从这 16 项里选出最接近的一项。**
|
||||
|
||||
[返回顶部](#top) | [下一节:按层排查](#by-layer)
|
||||
|
||||
---
|
||||
|
||||
<a id="by-layer"></a>
|
||||
|
||||
## 五、按层排查:不要改错层
|
||||
|
||||
这一节不重写 16 项,只是告诉你:
|
||||
当你已经选到某个 No.X 时,第一眼应该优先查哪一层。
|
||||
|
||||
### A. `[IN]` 层:先确认你拿到的是不是对的材料
|
||||
|
||||
对应编号:
|
||||
|
||||
- [No.1](#no1)
|
||||
- [No.5](#no5)
|
||||
- [No.8](#no8)
|
||||
|
||||
这层最常见的误判是:
|
||||
|
||||
“我以为系统理解错了,其实它一开始就拿错了东西。”
|
||||
|
||||
如果你命中了弱相关片段、表面相似文本、错误切块,后面推理再强也没用。
|
||||
所以 `[IN]` 层优先看的是:
|
||||
|
||||
1. 原始召回内容到底是什么
|
||||
2. 命中的片段是否只是“相似”,而不是“正确”
|
||||
3. 你是否能看到检索过程,还是整个过程像黑箱
|
||||
|
||||
这层如果没先排好,后面的推理诊断通常会失真。
|
||||
|
||||
### B. `[RE]` 层:材料可能是对的,但系统用错了
|
||||
|
||||
对应编号:
|
||||
|
||||
- [No.2](#no2)
|
||||
- [No.3](#no3)
|
||||
- [No.4](#no4)
|
||||
- [No.6](#no6)
|
||||
- [No.10](#no10)
|
||||
- [No.11](#no11)
|
||||
- [No.12](#no12)
|
||||
|
||||
这层最常见的误判是:
|
||||
|
||||
“我以为是检索坏了,其实是后面理解、归纳、逻辑链坏了。”
|
||||
|
||||
例如:
|
||||
|
||||
- 切块是对的,但结论错了 → 常见是 `No.2`
|
||||
- 多步任务中途开始偏 → 常见是 `No.3`
|
||||
- 回答很笃定,但完全站不住 → 常见是 `No.4`
|
||||
- 遇到抽象规则就崩 → 常见是 `No.11`
|
||||
- 陷入循环解释 → 常见是 `No.12`
|
||||
|
||||
如果 `[IN]` 层已经基本没问题,答案还是不对,就应该优先回到 `[RE]` 层判断是哪一种塌陷。
|
||||
|
||||
### C. `[ST]` 层:单轮正常,不代表状态层正常
|
||||
|
||||
对应编号:
|
||||
|
||||
- [No.7](#no7)
|
||||
- [No.9](#no9)
|
||||
- [No.13](#no13)
|
||||
|
||||
这层最常见的误判是:
|
||||
|
||||
“单轮看起来还行,所以我以为系统没问题。”
|
||||
|
||||
其实很多 RAG 地狱不是单轮错误,而是:
|
||||
|
||||
- 多轮之后前文断掉
|
||||
- 上下文越来越乱
|
||||
- 多角色、多代理之间互相覆盖
|
||||
|
||||
如果你发现:
|
||||
|
||||
- 第一轮没事,后面越来越歪
|
||||
- 切换角色后前面的约束消失
|
||||
- 多个步骤之间状态彼此污染
|
||||
|
||||
那就不要再只盯着检索条数了,应该直接回到 `[ST]` 层看 `No.7 / No.9 / No.13`。
|
||||
|
||||
### D. `[OP]` 层:别把部署问题误诊成回答问题
|
||||
|
||||
对应编号:
|
||||
|
||||
- [No.14](#no14)
|
||||
- [No.15](#no15)
|
||||
- [No.16](#no16)
|
||||
|
||||
这层最常见的误判是:
|
||||
|
||||
“答案不稳定,所以我先去调模型或检索。”
|
||||
|
||||
但如果系统根本没有在完整状态下启动,所有上层表现都会像鬼打墙。
|
||||
尤其是这些情况:
|
||||
|
||||
- 依赖还没就绪,服务先起了 → `No.14`
|
||||
- 多个组件互相等待,长期半可用 → `No.15`
|
||||
- 首次调用就因为版本、密钥、环境没对齐而塌陷 → `No.16`
|
||||
|
||||
只要你看到“刚部署最容易出事”“首轮异常最严重”“重启后暂时恢复”,就要优先怀疑 `[OP]` 层,而不是先改提示词或参数。
|
||||
|
||||
[返回顶部](#top) |
|
||||
|
||||
---
|
||||
|
||||
<a id="issue-report"></a>
|
||||
|
||||
|
||||
## 六、快速返回
|
||||
|
||||
[返回顶部](#top) | [这页怎么用](#how-to-use) | [标签说明](#legend) | [常见症状入口](#symptoms) | [16 问题清单](#map16) | [按层排查](#by-layer)
|
||||
452
docs/工作流模块说明.md
@@ -1,452 +0,0 @@
|
||||
# Ruoyi-AI 工作流模块详细说明文档
|
||||
|
||||
## 概述
|
||||
|
||||
Ruoyi-AI 工作流模块是一个基于 LangGraph4j 的智能工作流引擎,支持可视化工作流设计、AI 模型集成、条件分支、人机交互等高级功能。该模块采用微服务架构,提供完整的
|
||||
RESTful API 和流式响应支持。
|
||||
|
||||
## 模块架构
|
||||
|
||||
### 1. 模块结构
|
||||
|
||||
```
|
||||
ruoyi-ai/
|
||||
├── ruoyi-modules/
|
||||
│ └── ruoyi-workflow/ # 工作流核心模块
|
||||
│ ├── pom.xml
|
||||
│ └── src/main/java/org/ruoyi/workflow/
|
||||
│ └── controller/ # 控制器层
|
||||
│ ├── WorkflowController.java
|
||||
│ ├── WorkflowRuntimeController.java
|
||||
│ └── admin/ # 管理端控制器
|
||||
│ ├── AdminWorkflowController.java
|
||||
│ └── AdminWorkflowComponentController.java
|
||||
└── ruoyi-modules-api/
|
||||
└── ruoyi-workflow-api/ # 工作流API模块
|
||||
├── pom.xml
|
||||
└── src/main/java/org/ruoyi/workflow/
|
||||
├── entity/ # 实体类
|
||||
├── dto/ # 数据传输对象
|
||||
├── service/ # 服务接口
|
||||
├── mapper/ # 数据访问层
|
||||
├── workflow/ # 工作流核心逻辑
|
||||
├── enums/ # 枚举类
|
||||
├── util/ # 工具类
|
||||
└── exception/ # 异常处理
|
||||
```
|
||||
|
||||
### 2. 核心依赖
|
||||
|
||||
- **LangGraph4j**: 1.5.3 - 工作流图执行引擎
|
||||
- **LangChain4j**: 1.2.0 - AI 模型集成框架
|
||||
- **Spring Boot**: 3.x - 应用框架
|
||||
- **MyBatis Plus**: 数据访问层
|
||||
- **Redis**: 缓存和状态管理
|
||||
- **Swagger/OpenAPI**: API 文档
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 工作流管理
|
||||
|
||||
#### 1.1 工作流定义
|
||||
|
||||
- **创建工作流**: 支持自定义标题、描述、公开性设置
|
||||
- **编辑工作流**: 可视化节点编辑、连接线配置
|
||||
- **版本控制**: 支持工作流的版本管理和回滚
|
||||
- **权限管理**: 支持公开/私有工作流设置
|
||||
|
||||
#### 1.2 工作流执行
|
||||
|
||||
- **流式执行**: 基于 SSE 的实时流式响应
|
||||
- **状态管理**: 完整的执行状态跟踪
|
||||
- **错误处理**: 详细的错误信息和异常处理
|
||||
- **中断恢复**: 支持工作流中断和恢复执行
|
||||
|
||||
### 2. 节点类型
|
||||
|
||||
#### 2.1 基础节点
|
||||
|
||||
- **Start**: 开始节点,定义工作流入口
|
||||
- **End**: 结束节点,定义工作流出口
|
||||
|
||||
#### 2.2 AI 模型节点
|
||||
|
||||
- **Answer**: 大语言模型问答节点
|
||||
- **Dalle3**: DALL-E 3 图像生成
|
||||
- **Tongyiwanx**: 通义万相图像生成
|
||||
- **Classifier**: 内容分类节点
|
||||
|
||||
#### 2.3 数据处理节点
|
||||
|
||||
- **DocumentExtractor**: 文档信息提取
|
||||
- **KeywordExtractor**: 关键词提取
|
||||
- **FaqExtractor**: 常见问题提取
|
||||
- **KnowledgeRetrieval**: 知识库检索
|
||||
|
||||
#### 2.4 控制流节点
|
||||
|
||||
- **Switcher**: 条件分支节点
|
||||
- **HumanFeedback**: 人机交互节点
|
||||
|
||||
#### 2.5 外部集成节点
|
||||
|
||||
- **Google**: Google 搜索集成
|
||||
- **MailSend**: 邮件发送
|
||||
- **HttpRequest**: HTTP 请求
|
||||
- **Template**: 模板转换
|
||||
|
||||
### 3. 数据流管理
|
||||
|
||||
#### 3.1 输入输出定义
|
||||
|
||||
```java
|
||||
// 节点输入输出数据结构
|
||||
public class NodeIOData {
|
||||
private String name; // 参数名称
|
||||
private NodeIODataContent content; // 参数内容
|
||||
}
|
||||
|
||||
// 支持的数据类型
|
||||
public enum WfIODataTypeEnum {
|
||||
TEXT, // 文本
|
||||
NUMBER, // 数字
|
||||
BOOLEAN, // 布尔值
|
||||
FILES, // 文件
|
||||
OPTIONS // 选项
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 参数引用
|
||||
|
||||
- **节点间引用**: 支持上游节点输出作为下游节点输入
|
||||
- **参数映射**: 自动处理参数名称映射
|
||||
- **类型转换**: 自动进行数据类型转换
|
||||
|
||||
## 数据库设计
|
||||
|
||||
### 1. 核心表结构
|
||||
|
||||
#### 1.1 工作流定义表 (t_workflow)
|
||||
|
||||
```sql
|
||||
CREATE TABLE t_workflow (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid VARCHAR(32) NOT NULL DEFAULT '',
|
||||
title VARCHAR(100) NOT NULL DEFAULT '',
|
||||
remark TEXT NOT NULL DEFAULT '',
|
||||
user_id BIGINT NOT NULL DEFAULT 0,
|
||||
is_public TINYINT(1) NOT NULL DEFAULT 0,
|
||||
is_enable TINYINT(1) NOT NULL DEFAULT 1,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
is_deleted TINYINT(1) NOT NULL DEFAULT 0
|
||||
);
|
||||
```
|
||||
|
||||
#### 1.2 工作流节点表 (t_workflow_node)
|
||||
|
||||
```sql
|
||||
CREATE TABLE t_workflow_node (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid VARCHAR(32) NOT NULL DEFAULT '',
|
||||
workflow_id BIGINT NOT NULL DEFAULT 0,
|
||||
workflow_component_id BIGINT NOT NULL DEFAULT 0,
|
||||
user_id BIGINT NOT NULL DEFAULT 0,
|
||||
title VARCHAR(100) NOT NULL DEFAULT '',
|
||||
remark VARCHAR(500) NOT NULL DEFAULT '',
|
||||
input_config JSON NOT NULL DEFAULT ('{}'),
|
||||
node_config JSON NOT NULL DEFAULT ('{}'),
|
||||
position_x DOUBLE NOT NULL DEFAULT 0,
|
||||
position_y DOUBLE NOT NULL DEFAULT 0,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
is_deleted TINYINT(1) NOT NULL DEFAULT 0
|
||||
);
|
||||
```
|
||||
|
||||
#### 1.3 工作流边表 (t_workflow_edge)
|
||||
|
||||
```sql
|
||||
CREATE TABLE t_workflow_edge (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid VARCHAR(32) NOT NULL DEFAULT '',
|
||||
workflow_id BIGINT NOT NULL DEFAULT 0,
|
||||
source_node_uuid VARCHAR(32) NOT NULL DEFAULT '',
|
||||
source_handle VARCHAR(32) NOT NULL DEFAULT '',
|
||||
target_node_uuid VARCHAR(32) NOT NULL DEFAULT '',
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
is_deleted TINYINT(1) NOT NULL DEFAULT 0
|
||||
);
|
||||
```
|
||||
|
||||
#### 1.4 工作流运行时表 (t_workflow_runtime)
|
||||
|
||||
```sql
|
||||
CREATE TABLE t_workflow_runtime (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid VARCHAR(32) NOT NULL DEFAULT '',
|
||||
user_id BIGINT NOT NULL DEFAULT 0,
|
||||
workflow_id BIGINT NOT NULL DEFAULT 0,
|
||||
input JSON NOT NULL DEFAULT ('{}'),
|
||||
output JSON NOT NULL DEFAULT ('{}'),
|
||||
status SMALLINT NOT NULL DEFAULT 1,
|
||||
status_remark VARCHAR(250) NOT NULL DEFAULT '',
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
is_deleted TINYINT(1) NOT NULL DEFAULT 0
|
||||
);
|
||||
```
|
||||
|
||||
#### 1.5 工作流组件表 (t_workflow_component)
|
||||
|
||||
```sql
|
||||
CREATE TABLE t_workflow_component (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
uuid VARCHAR(32) DEFAULT '' NOT NULL,
|
||||
name VARCHAR(32) DEFAULT '' NOT NULL,
|
||||
title VARCHAR(100) DEFAULT '' NOT NULL,
|
||||
remark TEXT NOT NULL,
|
||||
display_order INT DEFAULT 0 NOT NULL,
|
||||
is_enable TINYINT(1) DEFAULT 0 NOT NULL,
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
is_deleted TINYINT(1) DEFAULT 0 NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### 1. 工作流管理接口
|
||||
|
||||
#### 1.1 基础操作
|
||||
|
||||
```http
|
||||
# 创建工作流
|
||||
POST /workflow/add
|
||||
Content-Type: application/json
|
||||
{
|
||||
"title": "工作流标题",
|
||||
"remark": "工作流描述",
|
||||
"isPublic": false
|
||||
}
|
||||
|
||||
# 更新工作流
|
||||
POST /workflow/update
|
||||
Content-Type: application/json
|
||||
{
|
||||
"uuid": "工作流UUID",
|
||||
"title": "新标题",
|
||||
"remark": "新描述"
|
||||
}
|
||||
|
||||
# 删除工作流
|
||||
POST /workflow/del/{uuid}
|
||||
|
||||
# 启用/禁用工作流
|
||||
POST /workflow/enable/{uuid}?enable=true
|
||||
```
|
||||
|
||||
#### 1.2 搜索和查询
|
||||
|
||||
```http
|
||||
# 搜索我的工作流
|
||||
GET /workflow/mine/search?keyword=关键词&isPublic=true¤tPage=1&pageSize=10
|
||||
|
||||
# 搜索公开工作流
|
||||
GET /workflow/public/search?keyword=关键词¤tPage=1&pageSize=10
|
||||
|
||||
# 获取工作流组件列表
|
||||
GET /workflow/public/component/list
|
||||
```
|
||||
|
||||
### 2. 工作流执行接口
|
||||
|
||||
#### 2.1 流式执行
|
||||
|
||||
```http
|
||||
# 流式执行工作流
|
||||
POST /workflow/run
|
||||
Content-Type: application/json
|
||||
Accept: text/event-stream
|
||||
{
|
||||
"uuid": "工作流UUID",
|
||||
"inputs": [
|
||||
{
|
||||
"name": "input",
|
||||
"content": {
|
||||
"type": 1,
|
||||
"textContent": "用户输入内容"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 运行时管理
|
||||
|
||||
```http
|
||||
# 恢复中断的工作流
|
||||
POST /workflow/runtime/resume/{runtimeUuid}
|
||||
Content-Type: application/json
|
||||
{
|
||||
"feedbackContent": "用户反馈内容"
|
||||
}
|
||||
|
||||
# 查询工作流执行历史
|
||||
GET /workflow/runtime/page?wfUuid=工作流UUID¤tPage=1&pageSize=10
|
||||
|
||||
# 查询运行时节点详情
|
||||
GET /workflow/runtime/nodes/{runtimeUuid}
|
||||
|
||||
# 清理运行时数据
|
||||
POST /workflow/runtime/clear?wfUuid=工作流UUID
|
||||
```
|
||||
|
||||
### 3. 管理端接口
|
||||
|
||||
#### 3.1 工作流管理
|
||||
|
||||
```http
|
||||
# 搜索所有工作流
|
||||
POST /admin/workflow/search
|
||||
Content-Type: application/json
|
||||
{
|
||||
"title": "搜索关键词",
|
||||
"isPublic": true,
|
||||
"isEnable": true
|
||||
}
|
||||
|
||||
# 启用/禁用工作流
|
||||
POST /admin/workflow/enable?uuid=工作流UUID&isEnable=true
|
||||
```
|
||||
|
||||
## 核心实现
|
||||
|
||||
### 1. 工作流引擎 (WorkflowEngine)
|
||||
|
||||
工作流引擎是整个模块的核心,负责:
|
||||
|
||||
- 工作流图的构建和编译
|
||||
- 节点执行调度
|
||||
- 状态管理和持久化
|
||||
- 流式输出处理
|
||||
|
||||
```java
|
||||
public class WorkflowEngine {
|
||||
// 核心执行方法
|
||||
public void run(User user, List<ObjectNode> userInputs, SseEmitter sseEmitter) {
|
||||
// 1. 验证工作流状态
|
||||
// 2. 创建运行时实例
|
||||
// 3. 构建状态图
|
||||
// 4. 执行工作流
|
||||
// 5. 处理流式输出
|
||||
}
|
||||
|
||||
// 恢复执行方法
|
||||
public void resume(String userInput) {
|
||||
// 1. 更新状态
|
||||
// 2. 继续执行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 节点工厂 (WfNodeFactory)
|
||||
|
||||
节点工厂负责根据组件类型创建对应的节点实例:
|
||||
|
||||
```java
|
||||
public class WfNodeFactory {
|
||||
public static AbstractWfNode create(WorkflowComponent component,
|
||||
WorkflowNode node,
|
||||
WfState wfState,
|
||||
WfNodeState nodeState) {
|
||||
// 根据组件类型创建对应的节点实例
|
||||
switch (component.getName()) {
|
||||
case "Answer":
|
||||
return new LLMAnswerNode(component, node, wfState, nodeState);
|
||||
case "Switcher":
|
||||
return new SwitcherNode(component, node, wfState, nodeState);
|
||||
// ... 其他节点类型
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 图构建器 (WorkflowGraphBuilder)
|
||||
|
||||
图构建器负责将工作流定义转换为可执行的状态图:
|
||||
|
||||
```java
|
||||
public class WorkflowGraphBuilder {
|
||||
public StateGraph<WfNodeState> build(WorkflowNode startNode) {
|
||||
// 1. 构建编译节点树
|
||||
// 2. 转换为状态图
|
||||
// 3. 添加节点和边
|
||||
// 4. 处理条件分支
|
||||
// 5. 处理并行执行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 流式响应机制
|
||||
|
||||
### 1. SSE 事件类型
|
||||
|
||||
工作流执行过程中会发送多种类型的 SSE 事件:
|
||||
|
||||
```javascript
|
||||
// 节点开始执行
|
||||
[NODE_RUN_节点UUID] - 节点执行开始事件
|
||||
|
||||
// 节点输入数据
|
||||
[NODE_INPUT_节点UUID] - 节点输入数据事件
|
||||
|
||||
// 节点输出数据
|
||||
[NODE_OUTPUT_节点UUID] - 节点输出数据事件
|
||||
|
||||
// 流式内容块
|
||||
[NODE_CHUNK_节点UUID] - 流式内容块事件
|
||||
|
||||
// 等待用户输入
|
||||
[NODE_WAIT_FEEDBACK_BY_节点UUID] - 等待用户输入事件
|
||||
```
|
||||
|
||||
### 2. 流式处理流程
|
||||
|
||||
1. **初始化**: 创建工作流运行时实例
|
||||
2. **节点执行**: 逐个执行工作流节点
|
||||
3. **实时输出**: 通过 SSE 实时推送执行结果
|
||||
4. **状态更新**: 实时更新节点和工作流状态
|
||||
5. **错误处理**: 捕获并处理执行过程中的错误
|
||||
|
||||
## 扩展开发
|
||||
|
||||
### 1. 自定义节点开发
|
||||
|
||||
要开发自定义工作流节点,需要:
|
||||
|
||||
1. **创建节点类**:继承 `AbstractWfNode`
|
||||
2. **实现处理逻辑**:重写 `onProcess()` 方法
|
||||
3. **定义配置类**:创建节点配置类
|
||||
4. **注册组件**:在组件表中注册新组件
|
||||
|
||||
```java
|
||||
public class CustomNode extends AbstractWfNode {
|
||||
@Override
|
||||
protected NodeProcessResult onProcess() {
|
||||
// 实现自定义处理逻辑
|
||||
List<NodeIOData> outputs = new ArrayList<>();
|
||||
// ... 处理逻辑
|
||||
return NodeProcessResult.success(outputs);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 自定义组件注册
|
||||
|
||||
```sql
|
||||
-- 在 t_workflow_component 表中添加新组件
|
||||
INSERT INTO t_workflow_component (uuid, name, title, remark, is_enable)
|
||||
VALUES (REPLACE(UUID(), '-', ''), 'CustomNode', '自定义节点', '自定义节点描述', true);
|
||||
```
|
||||
@@ -1,42 +0,0 @@
|
||||
## 接口信息
|
||||
|
||||
**接口路径**: `POST /resource/oss/upload`
|
||||
**请求类型**: `multipart/form-data`
|
||||
**权限要求**: `system:oss:upload`
|
||||
**业务类型**: [INSERT]
|
||||
|
||||
### 接口描述
|
||||
上传OSS对象存储接口,用于将文件上传到对象存储服务。
|
||||
|
||||
### 请求参数
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
| ---- | ------------- | ---- | ------ |
|
||||
| file | MultipartFile | 是 | 要上传的文件 |
|
||||
|
||||
### 请求头
|
||||
- `Content-Type`: `multipart/form-data`
|
||||
|
||||
### 返回值
|
||||
返回 `R<SysOssUploadVo>` 类型,包含以下字段:
|
||||
| 字段名 | 类型 | 说明 |
|
||||
| -------- | ------ | ------- |
|
||||
| url | String | 文件访问URL |
|
||||
| fileName | String | 原始文件名 |
|
||||
| ossId | String | 文件ID |
|
||||
|
||||
### 响应示例
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"url": "fileid://xxx",
|
||||
"fileName": "example.jpg",
|
||||
"ossId": "123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 异常情况
|
||||
- 当上传文件为空时,返回错误信息:"上传文件不能为空"
|
||||
BIN
image/00.png
|
Before Width: | Height: | Size: 78 KiB |
BIN
image/qq.png
|
Before Width: | Height: | Size: 267 KiB |
BIN
image/wx.png
|
Before Width: | Height: | Size: 144 KiB |
324
pom.xml
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -9,58 +9,77 @@
|
||||
<version>${revision}</version>
|
||||
|
||||
<name>ruoyi-ai</name>
|
||||
<url>https://gitee.com/ageerle/ruoyi-ai</url>
|
||||
<description>AI助手</description>
|
||||
<url>>https://gitee.com/ageerle/ruoyi-ai</url>
|
||||
<description>全栈式AI开发平台</description>
|
||||
|
||||
<properties>
|
||||
<revision>1.0.0</revision>
|
||||
<spring-boot.version>3.4.4</spring-boot.version>
|
||||
<revision>3.0.0</revision>
|
||||
<spring-boot.version>3.5.8</spring-boot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
<mysql.version>8.0.33</mysql.version>
|
||||
<mybatis.version>3.5.16</mybatis.version>
|
||||
<springdoc.version>2.8.13</springdoc.version>
|
||||
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
||||
<poi.version>5.2.3</poi.version>
|
||||
<easyexcel.version>3.2.1</easyexcel.version>
|
||||
<fastexcel.version>1.3.0</fastexcel.version>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<satoken.version>1.34.0</satoken.version>
|
||||
<mybatis-plus.version>3.5.11</mybatis-plus.version>
|
||||
<satoken.version>1.44.0</satoken.version>
|
||||
<mybatis-plus.version>3.5.14</mybatis-plus.version>
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<hutool.version>5.8.35</hutool.version>
|
||||
<okhttp.version>4.10.0</okhttp.version>
|
||||
<hutool.version>5.8.40</hutool.version>
|
||||
<spring-boot-admin.version>3.5.5</spring-boot-admin.version>
|
||||
<redisson.version>3.51.0</redisson.version>
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<dynamic-ds.version>4.3.1</dynamic-ds.version>
|
||||
<spring-boot-admin.version>3.0.3</spring-boot-admin.version>
|
||||
<redisson.version>3.20.1</redisson.version>
|
||||
<lock4j.version>2.2.4</lock4j.version>
|
||||
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
|
||||
<xxl-job.version>2.4.0</xxl-job.version>
|
||||
<mapstruct-plus.version>1.2.1</mapstruct-plus.version>
|
||||
<snailjob.version>1.8.0</snailjob.version>
|
||||
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||
<lombok.version>1.18.26</lombok.version>
|
||||
<bouncycastle.version>1.72</bouncycastle.version>
|
||||
<!-- Apache Commons Compress 版本 -->
|
||||
<commons-compress.version>1.26.2</commons-compress.version>
|
||||
<lombok.version>1.18.40</lombok.version>
|
||||
<bouncycastle.version>1.80</bouncycastle.version>
|
||||
<justauth.version>1.16.7</justauth.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
<!-- OSS 配置 -->
|
||||
<aws-java-sdk-s3.version>1.12.400</aws-java-sdk-s3.version>
|
||||
<aws.sdk.version>2.28.22</aws.sdk.version>
|
||||
<!-- SMS 配置 -->
|
||||
<aliyun.sms.version>2.0.23</aliyun.sms.version>
|
||||
<tencent.sms.version>3.1.687</tencent.sms.version>
|
||||
<sms4j.version>3.3.5</sms4j.version>
|
||||
<!-- 限制框架中的fastjson版本 -->
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<!-- 面向运行时的D-ORM依赖 -->
|
||||
<anyline.version>8.7.2-20250603</anyline.version>
|
||||
<!-- 工作流配置 -->
|
||||
<warm-flow.version>1.8.2</warm-flow.version>
|
||||
<!-- 企业微信SDK -->
|
||||
<weixin-java-cp.version>4.6.0</weixin-java-cp.version>
|
||||
<!-- Jackson XML -->
|
||||
<jackson-dataformat-xml.version>2.18.2</jackson-dataformat-xml.version>
|
||||
<!-- AI 相关依赖 -->
|
||||
<langchain4j.version>1.11.0</langchain4j.version>
|
||||
<langchain4j.community.version>1.11.0-beta19</langchain4j.community.version>
|
||||
<langgraph4j.version>1.5.3</langgraph4j.version>
|
||||
<weaviate.version>1.19.6</weaviate.version>
|
||||
<dify.version>1.0.7</dify.version>
|
||||
<!-- gRPC 版本 - 解决 Milvus SDK 依赖冲突 -->
|
||||
<grpc.version>1.62.2</grpc.version>
|
||||
<!-- Apache Commons Compress - 用于POI处理ZIP格式 -->
|
||||
<commons-compress.version>1.27.1</commons-compress.version>
|
||||
|
||||
<!-- Neo4j 相关版本 -->
|
||||
<neo4j-driver.version>5.26.0</neo4j-driver.version>
|
||||
<neo4j-cypher-dsl.version>2024.1.0</neo4j-cypher-dsl.version>
|
||||
<langchain4j-neo4j.version>1.2.0-beta8</langchain4j-neo4j.version>
|
||||
|
||||
<avatar-generator.version>1.1.0</avatar-generator.version>
|
||||
<jsoup.version>1.21.2</jsoup.version>
|
||||
<knife4j.version>4.4.0</knife4j.version>
|
||||
<swagger-annotations.version>2.2.8</swagger-annotations.version>
|
||||
<google-api-client.version>2.6.0</google-api-client.version>
|
||||
<commons-collections4.version>4.5.0</commons-collections4.version>
|
||||
|
||||
<!-- 插件版本 -->
|
||||
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
|
||||
<maven-war-plugin.version>3.2.2</maven-war-plugin.version>
|
||||
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
|
||||
<maven-surefire-plugin.version>3.0.0</maven-surefire-plugin.version>
|
||||
<maven-jar-plugin.version>3.4.2</maven-jar-plugin.version>
|
||||
<maven-war-plugin.version>3.4.0</maven-war-plugin.version>
|
||||
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
|
||||
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
|
||||
<!-- 打包默认跳过测试 -->
|
||||
<skipTests>true</skipTests>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
@@ -69,7 +88,9 @@
|
||||
<properties>
|
||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||
<profiles.active>local</profiles.active>
|
||||
<logging.level>debug</logging.level>
|
||||
<logging.level>info</logging.level>
|
||||
<monitor.username>ruoyi</monitor.username>
|
||||
<monitor.password>123456</monitor.password>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
@@ -77,7 +98,9 @@
|
||||
<properties>
|
||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||
<profiles.active>dev</profiles.active>
|
||||
<logging.level>debug</logging.level>
|
||||
<logging.level>info</logging.level>
|
||||
<monitor.username>ruoyi</monitor.username>
|
||||
<monitor.password>123456</monitor.password>
|
||||
</properties>
|
||||
<activation>
|
||||
<!-- 默认环境 -->
|
||||
@@ -89,6 +112,8 @@
|
||||
<properties>
|
||||
<profiles.active>prod</profiles.active>
|
||||
<logging.level>warn</logging.level>
|
||||
<monitor.username>ruoyi</monitor.username>
|
||||
<monitor.password>123456</monitor.password>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
@@ -97,12 +122,6 @@
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -112,6 +131,15 @@
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- gRPC BOM - 解决 Milvus SDK 依赖冲突,强制统一版本 -->
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-bom</artifactId>
|
||||
<version>${grpc.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool 的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
@@ -149,25 +177,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>${easyexcel.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml-schemas</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<groupId>cn.idev.excel</groupId>
|
||||
<artifactId>fastexcel</artifactId>
|
||||
<version>${fastexcel.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- velocity代码生成使用模板 -->
|
||||
@@ -201,6 +213,12 @@
|
||||
<version>${satoken.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- dynamic-datasource 多数据源-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
|
||||
<version>${dynamic-ds.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
@@ -226,13 +244,6 @@
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- dynamic-datasource 多数据源-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
|
||||
<version>${dynamic-ds.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sql性能分析插件 -->
|
||||
<dependency>
|
||||
<groupId>p6spy</groupId>
|
||||
@@ -240,24 +251,43 @@
|
||||
<version>${p6spy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- AWS SDK for Java 2.x -->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>${aws-java-sdk-s3.version}</version>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<version>${aws.sdk.version}</version>
|
||||
</dependency>
|
||||
<!-- 基于 AWS CRT 的 S3 客户端的性能增强的 S3 传输管理器 -->
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3-transfer-manager</artifactId>
|
||||
<version>${aws.sdk.version}</version>
|
||||
</dependency>
|
||||
<!-- 将基于 Netty 的 HTTP 客户端从类路径中移除 -->
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>netty-nio-client</artifactId>
|
||||
<version>${aws.sdk.version}</version>
|
||||
</dependency>
|
||||
<!--短信sms4j-->
|
||||
<dependency>
|
||||
<groupId>org.dromara.sms4j</groupId>
|
||||
<artifactId>sms4j-spring-boot-starter</artifactId>
|
||||
<version>${sms4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>dysmsapi20170525</artifactId>
|
||||
<version>${aliyun.sms.version}</version>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||
<version>${spring-boot-admin.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||
<version>${tencent.sms.version}</version>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
<version>${spring-boot-admin.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--redisson-->
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||
@@ -270,10 +300,16 @@
|
||||
<version>${lock4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SnailJob Client -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId>
|
||||
<version>${alibaba-ttl.version}</version>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-job-client-starter</artifactId>
|
||||
<version>${snailjob.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-job-client-job-core</artifactId>
|
||||
<version>${snailjob.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 加密包引入 -->
|
||||
@@ -283,19 +319,31 @@
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons Compress -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons-compress.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.linpeilie</groupId>
|
||||
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
|
||||
<version>${mapstruct-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Warm-Flow国产工作流引擎, 在线文档:http://warm-flow.cn/ -->
|
||||
<dependency>
|
||||
<groupId>org.dromara.warm</groupId>
|
||||
<artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId>
|
||||
<version>${warm-flow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara.warm</groupId>
|
||||
<artifactId>warm-flow-plugin-ui-sb-web</artifactId>
|
||||
<version>${warm-flow.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JustAuth 的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>me.zhyd.oauth</groupId>
|
||||
<artifactId>JustAuth</artifactId>
|
||||
<version>${justauth.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 离线IP地址定位库 ip2region -->
|
||||
<dependency>
|
||||
<groupId>org.lionsoul</groupId>
|
||||
@@ -303,37 +351,18 @@
|
||||
<version>${ip2region.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-chat</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-knowledge-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-chat-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-system-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
@@ -342,61 +371,47 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-graph</artifactId>
|
||||
<artifactId>ruoyi-chat</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Neo4j Driver -->
|
||||
<dependency>
|
||||
<groupId>org.neo4j.driver</groupId>
|
||||
<artifactId>neo4j-java-driver</artifactId>
|
||||
<version>${neo4j-driver.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Neo4j Cypher DSL -->
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-cypher-dsl</artifactId>
|
||||
<version>${neo4j-cypher-dsl.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Langchain4j Neo4j 扩展 -->
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-community-neo4j</artifactId>
|
||||
<version>${langchain4j-neo4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-aihuman</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 工作流模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-workflow</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- AI流程编排模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-workflow-api</artifactId>
|
||||
<artifactId>ruoyi-aiflow</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson XML -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<version>${jackson-dataformat-xml.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons Compress - 用于POI处理ZIP格式,解决导出Excel时的NoSuchMethodError -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons-compress.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ruoyi-modules</module>
|
||||
<module>ruoyi-modules-api</module>
|
||||
<module>ruoyi-admin</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ruoyi-extend</module>
|
||||
<module>ruoyi-modules</module>
|
||||
</modules>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
@@ -404,7 +419,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.verison}</version>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
@@ -447,6 +462,7 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<argLine>-Dfile.encoding=UTF-8</argLine>
|
||||
<!-- 根据打包环境执行对应的@Tag测试方法 -->
|
||||
<groups>${profiles.active}</groups>
|
||||
<!-- 排除标签 -->
|
||||
@@ -503,8 +519,8 @@
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>https://maven.aliyun.com/repository/public/</url>
|
||||
<name>huawei nexus</name>
|
||||
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
@@ -514,8 +530,8 @@
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>https://maven.aliyun.com/repository/public/</url>
|
||||
<name>huawei nexus</name>
|
||||
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
@@ -525,4 +541,6 @@
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
|
||||
|
||||
31
ruoyi-admin/Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-rocky:17.0.16-cds
|
||||
#FROM bellsoft/liberica-openjdk-rocky:21.0.8-cds
|
||||
#FROM findepi/graalvm:java17-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
||||
RUN mkdir -p /ruoyi/server/logs \
|
||||
/ruoyi/server/temp \
|
||||
/ruoyi/skywalking/agent
|
||||
|
||||
WORKDIR /ruoyi/server
|
||||
|
||||
ENV SERVER_PORT=8080 SNAIL_PORT=28080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
|
||||
|
||||
EXPOSE ${SERVER_PORT}
|
||||
# 暴露 snail job 客户端端口 用于定时任务调度中心通信
|
||||
EXPOSE ${SNAIL_PORT}
|
||||
|
||||
ADD ./target/ruoyi-admin.jar ./app.jar
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
|
||||
-Dsnail-job.port=${SNAIL_PORT} \
|
||||
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
|
||||
#-Dskywalking.agent.service_name=ruoyi-server \
|
||||
#-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
|
||||
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
|
||||
-jar app.jar
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ruoyi-ai</artifactId>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
@@ -24,22 +23,46 @@
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Oracle -->
|
||||
<!-- <!– mp支持的数据库均支持 只需要增加对应的jdbc依赖即可 –>-->
|
||||
<!-- <!– Oracle –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.oracle.database.jdbc</groupId>-->
|
||||
<!-- <artifactId>ojdbc8</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <!– 兼容oracle低版本 –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.oracle.database.nls</groupId>-->
|
||||
<!-- <artifactId>orai18n</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <!– PostgreSql –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.postgresql</groupId>-->
|
||||
<!-- <artifactId>postgresql</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <!– SqlServer –>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.microsoft.sqlserver</groupId>-->
|
||||
<!-- <artifactId>mssql-jdbc</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-doc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- PostgreSql -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-social</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SqlServer -->
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-ratelimiter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-mail</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,31 +70,53 @@
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-chat</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 知识图谱模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-graph</artifactId>
|
||||
<artifactId>ruoyi-chat</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工作流模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-workflow</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- AI流程编排模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-aihuman</artifactId>
|
||||
<artifactId>ruoyi-aiflow</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- skywalking 整合 logback -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.apache.skywalking</groupId>-->
|
||||
<!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
|
||||
<!-- <version>${与你的agent探针版本保持一致}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.apache.skywalking</groupId>-->
|
||||
<!-- <artifactId>apm-toolkit-trace</artifactId>-->
|
||||
<!-- <version>${与你的agent探针版本保持一致}</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -3,23 +3,20 @@ package org.ruoyi;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = {"org.ruoyi", "org.ruoyi.aihuman"})
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@SpringBootApplication
|
||||
public class RuoYiAIApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(RuoYiAIApplication.class);
|
||||
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||
application.run(args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ RuoYiAI启动成功 ლ(´ڡ`ლ)゙");
|
||||
System.out.println("(♥◠‿◠)ノ゙ RuoYi-AI启动成功 ლ(´ڡ`ლ)゙");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.ruoyi.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* BeanDefinitionRegistry后置处理器
|
||||
* 解决 MapStruct Plus 生成的 mapper 冲突问题
|
||||
*
|
||||
* @author ruoyi team
|
||||
*/
|
||||
@Configuration
|
||||
public class MapperConflictResolver implements BeanDefinitionRegistryPostProcessor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MapperConflictResolver.class);
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
||||
String[] beanNames = registry.getBeanDefinitionNames();
|
||||
|
||||
// 查找冲突的 mapper bean
|
||||
for (String beanName : beanNames) {
|
||||
if (beanName.equals("chatMessageBoToChatMessageMapperImpl")) {
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
|
||||
String beanClassName = beanDefinition.getBeanClassName();
|
||||
|
||||
log.info("Found mapper bean: {} -> {}", beanName, beanClassName);
|
||||
|
||||
// 如果是 org.ruoyi.domain.bo.chat 包下的(冲突的),移除它
|
||||
if (beanClassName != null && beanClassName.startsWith("org.ruoyi.domain.bo.chat")) {
|
||||
log.warn("Removing conflicting bean definition: {} ({})", beanName, beanClassName);
|
||||
registry.removeBeanDefinition(beanName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
// 不需要实现
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,70 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.core.constant.Constants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.ruoyi.common.core.constant.SystemConstants;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.core.domain.model.*;
|
||||
import org.ruoyi.common.core.utils.MapstructUtils;
|
||||
import org.ruoyi.common.core.utils.StreamUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.common.core.domain.model.LoginBody;
|
||||
import org.ruoyi.common.core.domain.model.RegisterBody;
|
||||
import org.ruoyi.common.core.domain.model.SocialLoginBody;
|
||||
import org.ruoyi.common.core.utils.*;
|
||||
import org.ruoyi.common.encrypt.annotation.ApiEncrypt;
|
||||
import org.ruoyi.common.json.utils.JsonUtils;
|
||||
import org.ruoyi.common.ratelimiter.annotation.RateLimiter;
|
||||
import org.ruoyi.common.ratelimiter.enums.LimitType;
|
||||
import org.ruoyi.common.satoken.utils.LoginHelper;
|
||||
import org.ruoyi.common.social.config.properties.SocialLoginConfigProperties;
|
||||
import org.ruoyi.common.social.config.properties.SocialProperties;
|
||||
import org.ruoyi.common.social.utils.SocialUtils;
|
||||
import org.ruoyi.common.sse.dto.SseMessageDto;
|
||||
import org.ruoyi.common.sse.utils.SseMessageUtils;
|
||||
import org.ruoyi.common.tenant.helper.TenantHelper;
|
||||
import org.ruoyi.system.domain.bo.SysTenantBo;
|
||||
import org.ruoyi.system.domain.vo.LoginTenantVo;
|
||||
import org.ruoyi.system.domain.vo.LoginVo;
|
||||
import org.ruoyi.system.domain.vo.SysTenantVo;
|
||||
import org.ruoyi.system.domain.vo.TenantListVo;
|
||||
import org.ruoyi.system.service.ISysTenantService;
|
||||
import org.ruoyi.system.service.SysLoginService;
|
||||
import org.ruoyi.system.service.SysRegisterService;
|
||||
import org.ruoyi.system.domain.vo.*;
|
||||
import org.ruoyi.system.service.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 认证
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@SaIgnore
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
private final SocialProperties socialProperties;
|
||||
private final SysLoginService loginService;
|
||||
private final SysRegisterService registerService;
|
||||
private final ISysConfigService configService;
|
||||
private final ISysTenantService tenantService;
|
||||
private final ISysSocialService socialUserService;
|
||||
private final ISysClientService clientService;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
@@ -48,64 +72,103 @@ public class AuthController {
|
||||
* @param body 登录信息
|
||||
* @return 结果
|
||||
*/
|
||||
@ApiEncrypt
|
||||
@PostMapping("/login")
|
||||
public R<LoginVo> login(@Validated @RequestBody LoginBody body) {
|
||||
body.setTenantId(Constants.TENANT_ID);
|
||||
LoginVo loginVo = new LoginVo();
|
||||
// 生成令牌
|
||||
String token = loginService.login(
|
||||
body.getTenantId(),
|
||||
body.getUsername(), body.getPassword(),
|
||||
body.getCode(), body.getUuid());
|
||||
loginVo.setToken(token);
|
||||
// 兼容后台管理登录
|
||||
loginVo.setAccess_token(token);
|
||||
loginVo.setUserInfo(LoginHelper.getLoginUser());
|
||||
public R<LoginVo> login(@RequestBody String body) {
|
||||
LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
|
||||
ValidatorUtils.validate(loginBody);
|
||||
// 授权类型和客户端id
|
||||
String clientId = loginBody.getClientId();
|
||||
String grantType = loginBody.getGrantType();
|
||||
log.info("登录请求 - clientId: {}, grantType: {}", clientId, grantType);
|
||||
SysClientVo client = clientService.queryByClientId(clientId);
|
||||
log.info("查询客户端结果 - client: {}, grantType: {}", client, client != null ? client.getGrantType() : "null");
|
||||
// 查询不到 client 或 client 内不包含 grantType
|
||||
if (ObjectUtil.isNull(client)) {
|
||||
log.info("客户端id: {} 不存在!", clientId);
|
||||
return R.fail(MessageUtils.message("auth.grant.type.error"));
|
||||
}
|
||||
if (!StringUtils.contains(client.getGrantType(), grantType)) {
|
||||
log.info("客户端id: {} 认证类型:{} 不匹配! 数据库grantType: {}", clientId, grantType, client.getGrantType());
|
||||
return R.fail(MessageUtils.message("auth.grant.type.error"));
|
||||
} else if (!SystemConstants.NORMAL.equals(client.getStatus())) {
|
||||
return R.fail(MessageUtils.message("auth.grant.type.blocked"));
|
||||
}
|
||||
// 校验租户
|
||||
loginService.checkTenant(loginBody.getTenantId());
|
||||
// 登录
|
||||
LoginVo loginVo = IAuthStrategy.login(body, client, grantType);
|
||||
|
||||
Long userId = LoginHelper.getUserId();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
SseMessageDto dto = new SseMessageDto();
|
||||
dto.setMessage("欢迎登录ruoyi-ai后台管理系统");
|
||||
dto.setUserIds(List.of(userId));
|
||||
SseMessageUtils.publishMessage(dto);
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信登录
|
||||
* 获取跳转URL
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @param source 登录来源
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/smsLogin")
|
||||
public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody body) {
|
||||
LoginVo loginVo = new LoginVo();
|
||||
// 生成令牌
|
||||
String token = loginService.smsLogin(body.getTenantId(), body.getPhonenumber(), body.getSmsCode());
|
||||
loginVo.setToken(token);
|
||||
return R.ok(loginVo);
|
||||
@GetMapping("/binding/{source}")
|
||||
public R<String> authBinding(@PathVariable("source") String source,
|
||||
@RequestParam String tenantId, @RequestParam String domain) {
|
||||
SocialLoginConfigProperties obj = socialProperties.getType().get(source);
|
||||
if (ObjectUtil.isNull(obj)) {
|
||||
return R.fail(source + "平台账号暂不支持");
|
||||
}
|
||||
AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("tenantId", tenantId);
|
||||
map.put("domain", domain);
|
||||
map.put("state", AuthStateUtils.createState());
|
||||
String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8));
|
||||
return R.ok("操作成功", authorizeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 访客登录
|
||||
* 前端回调绑定授权(需要token)
|
||||
*
|
||||
* @param loginBody 登录信息
|
||||
* @return token信息
|
||||
*/
|
||||
@PostMapping("/visitorLogin")
|
||||
public R<LoginVo> visitorLogin(@RequestBody VisitorLoginBody loginBody) {
|
||||
LoginVo loginVo = new LoginVo();
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件登录
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @param loginBody 请求体
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/emailLogin")
|
||||
public R<LoginVo> emailLogin(@Validated @RequestBody EmailLoginBody body) {
|
||||
LoginVo loginVo = new LoginVo();
|
||||
// 生成令牌
|
||||
String token = loginService.emailLogin(body.getTenantId(), body.getEmail(), body.getEmailCode());
|
||||
loginVo.setToken(token);
|
||||
return R.ok(loginVo);
|
||||
@PostMapping("/social/callback")
|
||||
public R<Void> socialCallback(@RequestBody SocialLoginBody loginBody) {
|
||||
// 校验token
|
||||
StpUtil.checkLogin();
|
||||
// 获取第三方登录信息
|
||||
AuthResponse<AuthUser> response = SocialUtils.loginAuth(
|
||||
loginBody.getSource(), loginBody.getSocialCode(),
|
||||
loginBody.getSocialState(), socialProperties);
|
||||
AuthUser authUserData = response.getData();
|
||||
// 判断授权响应是否成功
|
||||
if (!response.ok()) {
|
||||
return R.fail(response.getMsg());
|
||||
}
|
||||
loginService.socialRegister(authUserData);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 取消授权(需要token)
|
||||
*
|
||||
* @param socialId socialId
|
||||
*/
|
||||
@DeleteMapping(value = "/unlock/{socialId}")
|
||||
public R<Void> unlockSocial(@PathVariable Long socialId) {
|
||||
// 校验token
|
||||
StpUtil.checkLogin();
|
||||
Boolean rows = socialUserService.deleteWithValidById(socialId);
|
||||
return rows ? R.ok() : R.fail("取消授权失败");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
@@ -118,42 +181,58 @@ public class AuthController {
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
@ApiEncrypt
|
||||
@PostMapping("/register")
|
||||
public R<Void> register(@Validated @RequestBody RegisterBody user, HttpServletRequest request) {
|
||||
String domainName = request.getServerName();
|
||||
user.setDomainName(domainName);
|
||||
public R<Void> register(@Validated @RequestBody RegisterBody user) {
|
||||
if (!configService.selectRegisterEnabled(user.getTenantId())) {
|
||||
return R.fail("当前系统没有开启注册功能!");
|
||||
}
|
||||
registerService.register(user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
@PostMapping("/reset/password")
|
||||
@SaIgnore
|
||||
public R<Void> resetPassWord(@Validated @RequestBody RegisterBody user) {
|
||||
registerService.resetPassWord(user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录页面租户下拉框
|
||||
*
|
||||
* @return 租户列表
|
||||
*/
|
||||
@RateLimiter(time = 60, count = 20, limitType = LimitType.IP)
|
||||
@GetMapping("/tenant/list")
|
||||
public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
|
||||
// 返回对象
|
||||
LoginTenantVo result = new LoginTenantVo();
|
||||
boolean enable = TenantHelper.isEnable();
|
||||
result.setTenantEnabled(enable);
|
||||
// 如果未开启租户这直接返回
|
||||
if (!enable) {
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
|
||||
List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
|
||||
try {
|
||||
// 如果只超管返回所有租户
|
||||
if (LoginHelper.isSuperAdmin()) {
|
||||
result.setVoList(voList);
|
||||
return R.ok(result);
|
||||
}
|
||||
} catch (NotLoginException ignored) {
|
||||
}
|
||||
|
||||
// 获取域名
|
||||
String host = new URL(request.getRequestURL().toString()).getHost();
|
||||
String host;
|
||||
String referer = request.getHeader("referer");
|
||||
if (StringUtils.isNotBlank(referer)) {
|
||||
// 这里从referer中取值是为了本地使用hosts添加虚拟域名,方便本地环境调试
|
||||
host = referer.split("//")[1].split("/")[0];
|
||||
} else {
|
||||
host = new URL(request.getRequestURL().toString()).getHost();
|
||||
}
|
||||
// 根据域名进行筛选
|
||||
List<TenantListVo> list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host));
|
||||
// 返回对象
|
||||
LoginTenantVo vo = new LoginTenantVo();
|
||||
vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
|
||||
vo.setTenantEnabled(TenantHelper.isEnable());
|
||||
return R.ok(vo);
|
||||
List<TenantListVo> list = StreamUtils.filter(voList, vo ->
|
||||
StringUtils.equalsIgnoreCase(vo.getDomain(), host));
|
||||
result.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,38 +5,36 @@ import cn.hutool.captcha.AbstractCaptcha;
|
||||
import cn.hutool.captcha.generator.CodeGenerator;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.common.core.constant.Constants;
|
||||
import org.ruoyi.common.core.constant.GlobalConstants;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.core.service.ConfigService;
|
||||
import org.ruoyi.common.core.exception.ServiceException;
|
||||
import org.ruoyi.common.core.utils.SpringUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.common.core.utils.reflect.ReflectUtils;
|
||||
import org.ruoyi.common.mail.config.properties.MailProperties;
|
||||
import org.ruoyi.common.mail.utils.MailUtils;
|
||||
import org.ruoyi.common.ratelimiter.annotation.RateLimiter;
|
||||
import org.ruoyi.common.ratelimiter.enums.LimitType;
|
||||
import org.ruoyi.common.redis.utils.RedisUtils;
|
||||
import org.ruoyi.common.sms.config.properties.SmsProperties;
|
||||
import org.ruoyi.common.sms.core.SmsTemplate;
|
||||
import org.ruoyi.common.sms.entity.SmsResult;
|
||||
import org.ruoyi.common.web.config.properties.CaptchaProperties;
|
||||
import org.ruoyi.common.web.enums.CaptchaType;
|
||||
import org.ruoyi.system.domain.request.EmailRequest;
|
||||
import org.dromara.sms4j.api.SmsBlend;
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||
import org.ruoyi.system.domain.vo.CaptchaVo;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* 验证码操作处理
|
||||
@@ -51,31 +49,28 @@ import java.util.Map;
|
||||
public class CaptchaController {
|
||||
|
||||
private final CaptchaProperties captchaProperties;
|
||||
private final SmsProperties smsProperties;
|
||||
private final ConfigService configService;
|
||||
private final MailProperties mailProperties;
|
||||
|
||||
/**
|
||||
* 短信验证码
|
||||
*
|
||||
* @param phonenumber 用户手机号
|
||||
*/
|
||||
@RateLimiter(key = "#phonenumber", time = 60, count = 1)
|
||||
@GetMapping("/resource/sms/code")
|
||||
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
|
||||
if (!smsProperties.getEnabled()) {
|
||||
return R.fail("当前系统没有开启短信功能!");
|
||||
}
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
// 验证码模板id
|
||||
// 验证码模板id 自行处理 (查数据库或写死均可)
|
||||
String templateId = "";
|
||||
Map<String, String> map = new HashMap<>(1);
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
|
||||
map.put("code", code);
|
||||
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
|
||||
SmsResult result = smsTemplate.send(phonenumber, templateId, map);
|
||||
if (!result.isSuccess()) {
|
||||
log.error("验证码短信发送异常 => {}", result);
|
||||
return R.fail(result.getMessage());
|
||||
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
|
||||
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
|
||||
if (!smsResponse.isSuccess()) {
|
||||
log.error("验证码短信发送异常 => {}", smsResponse);
|
||||
return R.fail(smsResponse.getData().toString());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
@@ -83,24 +78,32 @@ public class CaptchaController {
|
||||
/**
|
||||
* 邮箱验证码
|
||||
*
|
||||
* @param emailRequest 用户邮箱
|
||||
* @param email 邮箱
|
||||
*/
|
||||
@PostMapping("/resource/email/code")
|
||||
public R<Void> emailCode(@RequestBody @Valid EmailRequest emailRequest) {
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + emailRequest.getUsername();
|
||||
@GetMapping("/resource/email/code")
|
||||
public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
|
||||
if (!mailProperties.getEnabled()) {
|
||||
return R.fail("当前系统没有开启邮箱功能!");
|
||||
}
|
||||
SpringUtils.getAopProxy(this).emailCodeImpl(email);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱验证码
|
||||
* 独立方法避免验证码关闭之后仍然走限流
|
||||
*/
|
||||
@RateLimiter(key = "#email", time = 60, count = 1)
|
||||
public void emailCodeImpl(String email) {
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
// 自定义邮箱模板
|
||||
String model = configService.getConfigValue("mail", "mailModel");
|
||||
String mailTitle = configService.getConfigValue("mail", "mailTitle");
|
||||
String replacedModel = model.replace("{code}", code);
|
||||
try {
|
||||
MailUtils.sendHtml(emailRequest.getUsername(), mailTitle, replacedModel);
|
||||
MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
|
||||
} catch (Exception e) {
|
||||
log.error("邮箱验证码发送异常 => {}", e.getMessage());
|
||||
return R.fail(e.getMessage());
|
||||
log.error("验证码短信发送异常 => {}", e.getMessage());
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,33 +111,47 @@ public class CaptchaController {
|
||||
*/
|
||||
@GetMapping("/auth/code")
|
||||
public R<CaptchaVo> getCode() {
|
||||
CaptchaVo captchaVo = new CaptchaVo();
|
||||
boolean captchaEnabled = captchaProperties.getEnable();
|
||||
if (!captchaEnabled) {
|
||||
CaptchaVo captchaVo = new CaptchaVo();
|
||||
captchaVo.setCaptchaEnabled(false);
|
||||
return R.ok(captchaVo);
|
||||
}
|
||||
return R.ok(SpringUtils.getAopProxy(this).getCodeImpl());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
* 独立方法避免验证码关闭之后仍然走限流
|
||||
*/
|
||||
@RateLimiter(time = 60, count = 10, limitType = LimitType.IP)
|
||||
public CaptchaVo getCodeImpl() {
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtil.simpleUUID();
|
||||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid;
|
||||
// 生成验证码
|
||||
CaptchaType captchaType = captchaProperties.getType();
|
||||
boolean isMath = CaptchaType.MATH == captchaType;
|
||||
Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
|
||||
CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
|
||||
CodeGenerator codeGenerator;
|
||||
if (CaptchaType.MATH == captchaType) {
|
||||
codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), captchaProperties.getNumberLength(), false);
|
||||
} else {
|
||||
codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), captchaProperties.getCharLength());
|
||||
}
|
||||
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
||||
captcha.setGenerator(codeGenerator);
|
||||
captcha.createCode();
|
||||
// 如果是数学验证码,使用SpEL表达式处理验证码结果
|
||||
String code = captcha.getCode();
|
||||
if (isMath) {
|
||||
if (CaptchaType.MATH == captchaType) {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
|
||||
code = exp.getValue(String.class);
|
||||
}
|
||||
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
CaptchaVo captchaVo = new CaptchaVo();
|
||||
captchaVo.setUuid(uuid);
|
||||
captchaVo.setImg(captcha.getImageBase64());
|
||||
return R.ok(captchaVo);
|
||||
return captchaVo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.core.utils.SpringUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -10,6 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class IndexController {
|
||||
|
||||
@@ -18,8 +22,7 @@ public class IndexController {
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
return "RuoYi AI启动成功!";
|
||||
return StringUtils.format("欢迎使用{}后台管理框架,请通过前端地址访问。", SpringUtils.getApplicationName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,44 @@
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: false
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
metadata:
|
||||
username: ${spring.boot.admin.client.username}
|
||||
userpassword: ${spring.boot.admin.client.password}
|
||||
username: @monitor.username@
|
||||
password: @monitor.password@
|
||||
|
||||
--- # mcp配置信息
|
||||
mcp:
|
||||
sse:
|
||||
enabled: false
|
||||
url: http://localhost:8085/sse
|
||||
|
||||
--- # 上传文件地址
|
||||
sys:
|
||||
upload:
|
||||
path: D:\\DownLoad
|
||||
|
||||
--- # snail-job 配置
|
||||
snail-job:
|
||||
enabled: false
|
||||
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
|
||||
group: "ruoyi_group"
|
||||
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
|
||||
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
|
||||
server:
|
||||
host: 127.0.0.1
|
||||
port: 17888
|
||||
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
|
||||
namespace: ${spring.profiles.active}
|
||||
# 随主应用端口漂移
|
||||
port: 2${server.port}
|
||||
# 客户端ip指定
|
||||
host:
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
@@ -15,9 +56,17 @@ spring:
|
||||
master:
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai-agent?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: root
|
||||
# agent:
|
||||
# url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
# # url: jdbc:mysql://localhost:3306/agent_db
|
||||
# username: root
|
||||
# password: root
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
@@ -32,26 +81,33 @@ spring:
|
||||
idleTimeout: 600000
|
||||
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
|
||||
maxLifetime: 1800000
|
||||
# 连接测试query(配置检测连接是否有效)
|
||||
connectionTestQuery: SELECT 1
|
||||
# 多久检查一次连接的活性
|
||||
keepaliveTime: 30000
|
||||
mail:
|
||||
username: xx
|
||||
|
||||
|
||||
|
||||
--- # 上传文件地址
|
||||
sys:
|
||||
upload:
|
||||
path: D:\\DownLoad
|
||||
|
||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||
spring.data:
|
||||
redis:
|
||||
# 地址
|
||||
host: 127.0.0.1
|
||||
host: localhost
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码(如没有密码请注释掉)
|
||||
# password: 123456
|
||||
# redis 密码必须配置
|
||||
# password: 123456
|
||||
# 连接超时时间
|
||||
timeout: 10S
|
||||
timeout: 10s
|
||||
# 是否开启ssl
|
||||
ssl.enabled: false
|
||||
|
||||
# redisson 配置
|
||||
redisson:
|
||||
# redis key前缀
|
||||
keyPrefix:
|
||||
@@ -61,8 +117,8 @@ redisson:
|
||||
nettyThreads: 8
|
||||
# 单节点配置
|
||||
singleServerConfig:
|
||||
# 客户端名称
|
||||
clientName: ${ruoyi.name}
|
||||
# 客户端名称 不能用中文
|
||||
clientName: ruoyi-ai
|
||||
# 最小空闲连接数
|
||||
connectionMinimumIdleSize: 8
|
||||
# 连接池大小
|
||||
@@ -74,35 +130,142 @@ redisson:
|
||||
# 发布和订阅连接池大小
|
||||
subscriptionConnectionPoolSize: 50
|
||||
|
||||
--- # sms 短信
|
||||
sms:
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: false
|
||||
# 阿里云 dysmsapi.aliyuncs.com
|
||||
# 腾讯云 sms.tencentcloudapi.com
|
||||
endpoint: "dysmsapi.aliyuncs.com"
|
||||
accessKeyId: xxxxxxx
|
||||
accessKeySecret: xxxxxx
|
||||
signName: 测试
|
||||
# 腾讯专用
|
||||
sdkAppId:
|
||||
|
||||
pdf:
|
||||
extract:
|
||||
service:
|
||||
url: http://localhost:8080
|
||||
ai-api:
|
||||
url: https://api.pandarobot.chat/v1/chat/completions
|
||||
key: sk-xxxx
|
||||
transition:
|
||||
# 是否开启mineru
|
||||
enable-minerU: true
|
||||
# mineru conda环境路径
|
||||
conda-env-path: "F:\\ProgramData\\Computer\\Anaconda\\envs\\mineru"
|
||||
# 是否开启图片OCR
|
||||
enable-ocr: true
|
||||
|
||||
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: xxx@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: xxx@163.com
|
||||
# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
|
||||
pass: xxxxxxxxxx
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
|
||||
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
|
||||
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
|
||||
sms:
|
||||
# 配置源类型用于标定配置来源(interface,yaml)
|
||||
config-type: yaml
|
||||
# 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制
|
||||
restricted: true
|
||||
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
|
||||
minute-max: 1
|
||||
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
|
||||
account-max: 30
|
||||
# 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
|
||||
blends:
|
||||
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
|
||||
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
|
||||
config1:
|
||||
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: alibaba
|
||||
# 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。
|
||||
access-key-id: 您的accessKey
|
||||
# 称为accessSecret有些称之为apiSecret
|
||||
access-key-secret: 您的accessKeySecret
|
||||
signature: 您的短信签名
|
||||
sdk-app-id: 您的sdkAppId
|
||||
config2:
|
||||
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: tencent
|
||||
access-key-id: 您的accessKey
|
||||
access-key-secret: 您的accessKeySecret
|
||||
signature: 您的短信签名
|
||||
sdk-app-id: 您的sdkAppId
|
||||
|
||||
|
||||
--- # 三方授权
|
||||
justauth:
|
||||
# 前端外网访问地址
|
||||
address: http://localhost:80
|
||||
type:
|
||||
maxkey:
|
||||
# maxkey 服务器地址
|
||||
# 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
|
||||
server-url: http://sso.maxkey.top
|
||||
client-id: 876892492581044224
|
||||
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
|
||||
redirect-uri: ${justauth.address}/social-callback?source=maxkey
|
||||
topiam:
|
||||
# topiam 服务器地址
|
||||
server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol
|
||||
client-id: 449c4*********937************759
|
||||
client-secret: ac7***********1e0************28d
|
||||
redirect-uri: ${justauth.address}/social-callback?source=topiam
|
||||
scopes: [openid, email, phone, profile]
|
||||
qq:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=qq
|
||||
union-id: false
|
||||
weibo:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=weibo
|
||||
gitee:
|
||||
client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98
|
||||
client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitee
|
||||
dingtalk:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=dingtalk
|
||||
baidu:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=baidu
|
||||
csdn:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=csdn
|
||||
coding:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=coding
|
||||
coding-group-name: xx
|
||||
oschina:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=oschina
|
||||
alipay_wallet:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
|
||||
alipay-public-key: MIIB**************DAQAB
|
||||
wechat_open:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=wechat_open
|
||||
wechat_mp:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
|
||||
wechat_enterprise:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
|
||||
agent-id: 1000002
|
||||
gitlab:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitlab
|
||||
gitea:
|
||||
# 前端改动 https://gitee.com/JavaLionLi/plus-ui/pulls/204
|
||||
# gitea 服务器地址
|
||||
server-url: https://demo.gitea.com
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitea
|
||||
|
||||
AGENT_ALLOWED_TABLES: ""
|
||||
|
||||
271
ruoyi-admin/src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,271 @@
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: false
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
metadata:
|
||||
username: ${spring.boot.admin.client.username}
|
||||
userpassword: ${spring.boot.admin.client.password}
|
||||
username: @monitor.username@
|
||||
password: @monitor.password@
|
||||
|
||||
--- # mcp配置信息
|
||||
mcp:
|
||||
sse:
|
||||
enabled: false
|
||||
url: http://localhost:8085/sse
|
||||
|
||||
--- # 上传文件地址
|
||||
sys:
|
||||
upload:
|
||||
path: D:\\DownLoad
|
||||
|
||||
--- # snail-job 配置
|
||||
snail-job:
|
||||
enabled: false
|
||||
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
|
||||
group: "ruoyi_group"
|
||||
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
|
||||
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
|
||||
server:
|
||||
host: 127.0.0.1
|
||||
port: 17888
|
||||
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
|
||||
namespace: ${spring.profiles.active}
|
||||
# 随主应用端口漂移
|
||||
port: 2${server.port}
|
||||
# 客户端ip指定
|
||||
host:
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
||||
dynamic:
|
||||
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
||||
p6spy: true
|
||||
# 设置默认的数据源或者数据源组,默认值即为 master
|
||||
primary: master
|
||||
# 严格模式 匹配不到数据源则报错
|
||||
strict: true
|
||||
datasource:
|
||||
# 主库数据源
|
||||
master:
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-ai-agent?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: root
|
||||
# agent:
|
||||
# url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
# # url: jdbc:mysql://localhost:3306/agent_db
|
||||
# username: root
|
||||
# password: root
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
maxPoolSize: 20
|
||||
# 最小空闲线程数量
|
||||
minIdle: 10
|
||||
# 配置获取连接等待超时的时间
|
||||
connectionTimeout: 30000
|
||||
# 校验超时时间
|
||||
validationTimeout: 5000
|
||||
# 空闲连接存活最大时间,默认10分钟
|
||||
idleTimeout: 600000
|
||||
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
|
||||
maxLifetime: 1800000
|
||||
# 多久检查一次连接的活性
|
||||
keepaliveTime: 30000
|
||||
|
||||
|
||||
|
||||
--- # 上传文件地址
|
||||
sys:
|
||||
upload:
|
||||
path: D:\\DownLoad
|
||||
|
||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||
spring.data:
|
||||
redis:
|
||||
# 地址
|
||||
host: localhost
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# redis 密码必须配置
|
||||
# password: 123456
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
# 是否开启ssl
|
||||
ssl.enabled: false
|
||||
|
||||
# redisson 配置
|
||||
redisson:
|
||||
# redis key前缀
|
||||
keyPrefix:
|
||||
# 线程池数量
|
||||
threads: 4
|
||||
# Netty线程池数量
|
||||
nettyThreads: 8
|
||||
# 单节点配置
|
||||
singleServerConfig:
|
||||
# 客户端名称 不能用中文
|
||||
clientName: ruoyi-ai
|
||||
# 最小空闲连接数
|
||||
connectionMinimumIdleSize: 8
|
||||
# 连接池大小
|
||||
connectionPoolSize: 32
|
||||
# 连接空闲超时,单位:毫秒
|
||||
idleConnectionTimeout: 10000
|
||||
# 命令等待超时,单位:毫秒
|
||||
timeout: 3000
|
||||
# 发布和订阅连接池大小
|
||||
subscriptionConnectionPoolSize: 50
|
||||
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: false
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: xxx@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: xxx@163.com
|
||||
# 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
|
||||
pass: xxxxxxxxxx
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
|
||||
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
|
||||
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
|
||||
sms:
|
||||
# 配置源类型用于标定配置来源(interface,yaml)
|
||||
config-type: yaml
|
||||
# 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制
|
||||
restricted: true
|
||||
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
|
||||
minute-max: 1
|
||||
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
|
||||
account-max: 30
|
||||
# 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
|
||||
blends:
|
||||
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
|
||||
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
|
||||
config1:
|
||||
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: alibaba
|
||||
# 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。
|
||||
access-key-id: 您的accessKey
|
||||
# 称为accessSecret有些称之为apiSecret
|
||||
access-key-secret: 您的accessKeySecret
|
||||
signature: 您的短信签名
|
||||
sdk-app-id: 您的sdkAppId
|
||||
config2:
|
||||
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: tencent
|
||||
access-key-id: 您的accessKey
|
||||
access-key-secret: 您的accessKeySecret
|
||||
signature: 您的短信签名
|
||||
sdk-app-id: 您的sdkAppId
|
||||
|
||||
|
||||
--- # 三方授权
|
||||
justauth:
|
||||
# 前端外网访问地址
|
||||
address: http://localhost:80
|
||||
type:
|
||||
maxkey:
|
||||
# maxkey 服务器地址
|
||||
# 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
|
||||
server-url: http://sso.maxkey.top
|
||||
client-id: 876892492581044224
|
||||
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
|
||||
redirect-uri: ${justauth.address}/social-callback?source=maxkey
|
||||
topiam:
|
||||
# topiam 服务器地址
|
||||
server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol
|
||||
client-id: 449c4*********937************759
|
||||
client-secret: ac7***********1e0************28d
|
||||
redirect-uri: ${justauth.address}/social-callback?source=topiam
|
||||
scopes: [openid, email, phone, profile]
|
||||
qq:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=qq
|
||||
union-id: false
|
||||
weibo:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=weibo
|
||||
gitee:
|
||||
client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98
|
||||
client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitee
|
||||
dingtalk:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=dingtalk
|
||||
baidu:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=baidu
|
||||
csdn:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=csdn
|
||||
coding:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=coding
|
||||
coding-group-name: xx
|
||||
oschina:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=oschina
|
||||
alipay_wallet:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
|
||||
alipay-public-key: MIIB**************DAQAB
|
||||
wechat_open:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=wechat_open
|
||||
wechat_mp:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
|
||||
wechat_enterprise:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
|
||||
agent-id: 1000002
|
||||
gitlab:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitlab
|
||||
gitea:
|
||||
# 前端改动 https://gitee.com/JavaLionLi/plus-ui/pulls/204
|
||||
# gitea 服务器地址
|
||||
server-url: https://demo.gitea.com
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitea
|
||||
|
||||
AGENT_ALLOWED_TABLES: "abtest_rule,abtest_project,agent_ban_log,agent_ban_logs,agent_install_sub_task,agent_install_sum_task,agent_install_task"
|
||||
@@ -1,29 +1,6 @@
|
||||
# 项目相关配置
|
||||
ruoyi:
|
||||
# 名称
|
||||
name: "ruoyi-ai"
|
||||
# 版本
|
||||
version: ${revision}
|
||||
# 版权年份
|
||||
copyrightYear: 2025
|
||||
# 实例演示开关
|
||||
demoEnabled: false
|
||||
|
||||
captcha:
|
||||
enable: false
|
||||
# 页面 <参数设置> 可开启关闭 验证码校验
|
||||
# 验证码类型 math 数组计算 char 字符验证
|
||||
type: MATH
|
||||
# line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
|
||||
category: CIRCLE
|
||||
# 数字验证码位数
|
||||
numberLength: 1
|
||||
# 字符验证码长度
|
||||
charLength: 4
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
# 服务器的HTTP端口,默认为8080
|
||||
# 服务器的HTTP端口,默认为6039
|
||||
port: 6039
|
||||
servlet:
|
||||
# 应用的访问路径
|
||||
@@ -43,6 +20,18 @@ server:
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
|
||||
worker: 256
|
||||
|
||||
captcha:
|
||||
# 是否启用验证码校验
|
||||
enable: false
|
||||
# 验证码类型 math 数组计算 char 字符验证
|
||||
type: MATH
|
||||
# line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
|
||||
category: CIRCLE
|
||||
# 数字验证码位数
|
||||
numberLength: 1
|
||||
# 字符验证码长度
|
||||
charLength: 4
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
@@ -63,7 +52,24 @@ user:
|
||||
# Spring配置
|
||||
spring:
|
||||
application:
|
||||
name: ${ruoyi.name}
|
||||
name: ruoyi-ai
|
||||
# ⚠️ 禁用 Spring Boot 的 Neo4j 自动配置
|
||||
# 默认情况下,如果类路径上存在 neo4j-java-driver,Spring Boot 会尝试自动配置
|
||||
# 这会导致应用在启动时尝试连接到 Neo4j,即使我们没有需要它
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration
|
||||
threads:
|
||||
# 开启虚拟线程 仅jdk21可用
|
||||
virtual:
|
||||
enabled: false
|
||||
task:
|
||||
execution:
|
||||
# 从 springboot 3.5 开始 spring自带线程池
|
||||
# 不再需要 AsyncConfig与ThreadPoolConfig 可直接注入线程池使用
|
||||
thread-name-prefix: async-
|
||||
# 由spring自己初始化线程池
|
||||
mode: force
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
@@ -74,10 +80,12 @@ spring:
|
||||
servlet:
|
||||
multipart:
|
||||
# 单个文件大小
|
||||
max-file-size: 50MB
|
||||
max-file-size: 10MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 200MB
|
||||
max-request-size: 20MB
|
||||
mvc:
|
||||
# 设置静态资源路径 防止所有请求都去查静态资源
|
||||
static-path-pattern: /static/**
|
||||
format:
|
||||
date-time: yyyy-MM-dd HH:mm:ss
|
||||
jackson:
|
||||
@@ -96,20 +104,10 @@ spring:
|
||||
sa-token:
|
||||
# token名称 (同时也是cookie名称)
|
||||
token-name: Authorization
|
||||
# token有效期 设为7天 (必定过期) 单位: 秒
|
||||
timeout: 604800
|
||||
# token临时有效期 (指定时间无操作就过期) 单位: 秒
|
||||
activity-timeout: 604800
|
||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
is-share: false
|
||||
# 是否尝试从header里读取token
|
||||
is-read-header: true
|
||||
# 是否尝试从cookie里读取token
|
||||
is-read-cookie: false
|
||||
# token前缀
|
||||
token-prefix: "Bearer"
|
||||
# jwt秘钥
|
||||
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
|
||||
|
||||
@@ -117,51 +115,20 @@ sa-token:
|
||||
security:
|
||||
# 排除路径
|
||||
excludes:
|
||||
# 获取模型信息
|
||||
- /system/model/modelList
|
||||
# 支付回调
|
||||
- /pay/returnUrl
|
||||
- /pay/notifyUrl
|
||||
# 上传文件
|
||||
- /resource/oss/upload
|
||||
# 重置密码
|
||||
- /auth/reset/password
|
||||
# 聊天接口
|
||||
- /chat/send
|
||||
# 文件上传
|
||||
- /chat/upload
|
||||
# 代码生成调用
|
||||
- /tool/gen/getByTableName
|
||||
- /tool/gen/batchGenCode
|
||||
# 静态资源
|
||||
- /*.html
|
||||
- /**/*.html
|
||||
- /**/*.css
|
||||
- /**/*.js
|
||||
# 公共路径
|
||||
- /favicon.ico
|
||||
- /error
|
||||
# swagger 文档配置
|
||||
- /*/api-docs
|
||||
- /*/api-docs/**
|
||||
- /v3/api-docs
|
||||
- /v3/api-docs/**
|
||||
- /v3/api-docs/swagger-config
|
||||
- /swagger-ui.html
|
||||
- /swagger-ui/**
|
||||
- /doc.html
|
||||
- /webjars/**
|
||||
- /swagger-resources
|
||||
- /swagger-resources/**
|
||||
# actuator 监控配置
|
||||
- /actuator
|
||||
- /actuator/**
|
||||
- /workflow/**
|
||||
- /admin/workflow/**
|
||||
- /warm-flow-ui/config
|
||||
- /workflow/run
|
||||
# 多租户配置
|
||||
tenant:
|
||||
# 是否开启
|
||||
enable: false
|
||||
enable: true
|
||||
# 排除表
|
||||
excludes:
|
||||
- sys_menu
|
||||
@@ -171,53 +138,27 @@ tenant:
|
||||
- sys_role_menu
|
||||
- sys_user_post
|
||||
- sys_user_role
|
||||
|
||||
knowledge-role:
|
||||
enable: false
|
||||
- sys_client
|
||||
- sys_oss_config
|
||||
- flow_spel
|
||||
|
||||
# MyBatisPlus配置
|
||||
# https://baomidou.com/config/
|
||||
mybatis-plus:
|
||||
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
|
||||
# 例如 com.**.**.mapper
|
||||
# 自定义配置 是否全局开启逻辑删除 关闭后 所有逻辑删除功能将失效
|
||||
enableLogicDelete: true
|
||||
# 多包名使用 例如 org.ruoyi.**.mapper,org.xxx.**.mapper
|
||||
mapperPackage: org.ruoyi.**.mapper
|
||||
# 对应的 XML 文件位置
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 实体扫描,多个package用逗号或者分号分隔
|
||||
typeAliasesPackage: org.ruoyi.**.domain
|
||||
# 启动时是否检查 MyBatis XML 文件的存在,默认不检查
|
||||
checkConfigLocation: false
|
||||
configuration:
|
||||
# 自动驼峰命名规则(camel case)映射
|
||||
mapUnderscoreToCamelCase: true
|
||||
# MyBatis 自动映射策略
|
||||
# NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
|
||||
autoMappingBehavior: FULL
|
||||
# MyBatis 自动映射时未知列或未知属性处理策
|
||||
# NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
|
||||
autoMappingUnknownColumnBehavior: NONE
|
||||
# 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
# 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||
logImpl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||
global-config:
|
||||
# 是否打印 Logo banner
|
||||
banner: true
|
||||
dbConfig:
|
||||
# 主键类型
|
||||
# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
|
||||
# 如需改为自增 需要将数据库表全部设置为自增
|
||||
idType: ASSIGN_ID
|
||||
# 逻辑已删除值
|
||||
logicDeleteValue: 2
|
||||
# 逻辑未删除值
|
||||
logicNotDeleteValue: 0
|
||||
# 字段验证策略之 insert,在 insert 的时候的字段验证策略
|
||||
# IGNORED 忽略 NOT_NULL 非NULL NOT_EMPTY 非空 DEFAULT 默认 NEVER 不加入 SQL
|
||||
insertStrategy: NOT_NULL
|
||||
# 字段验证策略之 update,在 update 的时候的字段验证策略
|
||||
updateStrategy: NOT_NULL
|
||||
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
|
||||
where-strategy: NOT_NULL
|
||||
|
||||
# 数据加密
|
||||
mybatis-encryptor:
|
||||
@@ -233,57 +174,58 @@ mybatis-encryptor:
|
||||
publicKey:
|
||||
privateKey:
|
||||
|
||||
# api接口加密
|
||||
api-decrypt:
|
||||
# 是否开启全局接口加密
|
||||
enabled: false
|
||||
# AES 加密头标识
|
||||
headerFlag: encrypt-key
|
||||
# 响应加密公钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换
|
||||
# 对应前端解密私钥 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
|
||||
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ==
|
||||
# 请求解密私钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换
|
||||
# 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
|
||||
privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=
|
||||
|
||||
springdoc:
|
||||
api-docs:
|
||||
# 是否开启接口文档
|
||||
enabled: true
|
||||
# swagger-ui:
|
||||
# # 持久化认证数据
|
||||
# persistAuthorization: true
|
||||
info:
|
||||
# 标题
|
||||
title: '标题:ruoyi-ai 接口文档'
|
||||
title: '标题:ruoyi-ai管理系统_接口文档'
|
||||
# 描述
|
||||
description: ''
|
||||
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
|
||||
# 版本
|
||||
version: '版本号: ${ruoyi.version}'
|
||||
version: '版本号: ${project.version}'
|
||||
# 作者信息
|
||||
contact:
|
||||
name: ageerle
|
||||
name: ageerle
|
||||
email: ageerle@163.com
|
||||
url: https://gitee.com/ageerle/ruoyi-ai
|
||||
components:
|
||||
# 鉴权方式配置
|
||||
security-schemes:
|
||||
apiKey:
|
||||
type: APIKEY
|
||||
in: HEADER
|
||||
name: ${sa-token.token-name}
|
||||
#这里定义了两个分组,可定义多个,也可以不定义
|
||||
packages-to-scan: org.ruoyi
|
||||
|
||||
knife4j:
|
||||
enable: true
|
||||
setting:
|
||||
language: zh_cn
|
||||
#这里定义了两个分组,可定义多个,也可以不定义
|
||||
group-configs:
|
||||
- group: 1.演示模块
|
||||
packages-to-scan: org.ruoyi.demo
|
||||
- group: 2.通用模块
|
||||
packages-to-scan: org.ruoyi.web
|
||||
- group: 3.系统模块
|
||||
packages-to-scan: org.ruoyi.system
|
||||
- group: 4.代码生成模块
|
||||
packages-to-scan: org.ruoyi.generator
|
||||
- group: 5.工作流模块
|
||||
packages-to-scan: org.ruoyi.workflow
|
||||
- group: 6.MCP模块
|
||||
packages-to-scan: org.ruoyi.mcp
|
||||
|
||||
# 防止XSS攻击
|
||||
xss:
|
||||
# 过滤开关
|
||||
enabled: true
|
||||
# 排除链接(多个用逗号分隔)
|
||||
excludes: /system/notice,/v3/api-docs/**,/doc.html,/swagger-ui/**,/swagger-ui.html,/swagger-resources/**,/webjars/**,/druid/**,/actuator/**,/favicon.ico
|
||||
# 匹配链接
|
||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||
|
||||
# 全局线程池相关配置
|
||||
thread-pool:
|
||||
# 是否开启线程池
|
||||
enabled: false
|
||||
# 队列最大长度
|
||||
queueCapacity: 128
|
||||
# 线程池维护线程所允许的空闲时间
|
||||
keepAliveSeconds: 300
|
||||
# 排除链接
|
||||
excludeUrls:
|
||||
- /system/notice
|
||||
|
||||
--- # 分布式锁 lock4j 全局配置
|
||||
lock4j:
|
||||
@@ -303,43 +245,39 @@ management:
|
||||
show-details: ALWAYS
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
health:
|
||||
# 禁用 Neo4j 健康检查(当知识图谱功能未启用时)
|
||||
neo4j:
|
||||
enabled: false
|
||||
|
||||
# websocket
|
||||
# websocket
|
||||
websocket:
|
||||
--- # 默认/推荐使用sse推送
|
||||
sse:
|
||||
enabled: true
|
||||
path: /resource/sse
|
||||
|
||||
--- # websocket
|
||||
websocket:
|
||||
# 如果关闭 需要和前端开关一起关闭
|
||||
enabled: false
|
||||
# 路径
|
||||
path: '/resource/websocket'
|
||||
path: /resource/websocket
|
||||
# 设置访问源地址
|
||||
allowedOrigins: '*'
|
||||
|
||||
spring:
|
||||
ai:
|
||||
openai:
|
||||
api-key: sk-xx
|
||||
base-url: https://api.pandarobot.chat/
|
||||
mcp:
|
||||
client:
|
||||
enabled: false
|
||||
name: ruoyi-ai-mcp
|
||||
sse:
|
||||
connections:
|
||||
server:
|
||||
url: http://127.0.0.1:8081
|
||||
stdio:
|
||||
servers-configuration: classpath:mcp-server.json
|
||||
request-timeout: 300s
|
||||
--- # warm-flow工作流配置
|
||||
warm-flow:
|
||||
# 是否开启工作流,默认true
|
||||
enabled: true
|
||||
# 是否开启设计器ui
|
||||
ui: true
|
||||
# 是否显示流程图顶部文字
|
||||
top-text-show: true
|
||||
# 是否渲染节点悬浮提示,默认true
|
||||
node-tooltip: true
|
||||
# 默认Authorization,如果有多个token,用逗号分隔
|
||||
token-name: ${sa-token.token-name},clientid
|
||||
|
||||
# 向量库配置
|
||||
vector-store:
|
||||
# 向量存储类型 可选(weaviate/milvus)
|
||||
# 如需修改向量库类型,请修改此配置值!
|
||||
type: weaviate
|
||||
|
||||
type: milvus
|
||||
# Weaviate配置
|
||||
weaviate:
|
||||
protocol: http
|
||||
@@ -349,56 +287,3 @@ vector-store:
|
||||
milvus:
|
||||
url: http://localhost:19530
|
||||
collectionname: LocalKnowledge
|
||||
|
||||
|
||||
--- # Neo4j 知识图谱配置
|
||||
#neo4j:
|
||||
# uri: bolt://117.72.192.162:7687
|
||||
# username: neo4j
|
||||
# password: MySecurePass123!
|
||||
# database: neo4j
|
||||
# max-connection-pool-size: 50
|
||||
# connection-timeout-seconds: 30
|
||||
|
||||
# 知识图谱配置
|
||||
knowledge:
|
||||
graph:
|
||||
# 是否启用知识图谱功能
|
||||
enabled: false
|
||||
# 图数据库类型: neo4j 或 apache-age
|
||||
database-type: neo4j
|
||||
# 是否自动创建索引
|
||||
auto-create-index: true
|
||||
# 批量处理大小
|
||||
batch-size: 1000
|
||||
# 最大重试次数
|
||||
max-retry-count: 3
|
||||
|
||||
# 实体抽取配置
|
||||
extraction:
|
||||
# 置信度阈值(低于此值的实体将被过滤)
|
||||
confidence-threshold: 0.7
|
||||
# 最大实体数量(每个文档)
|
||||
max-entities-per-doc: 100
|
||||
# 最大关系数量(每个文档)
|
||||
max-relations-per-doc: 200
|
||||
# 文本分片大小(用于长文档)
|
||||
chunk-size: 2000
|
||||
# 分片重叠大小
|
||||
chunk-overlap: 200
|
||||
|
||||
# 查询配置
|
||||
query:
|
||||
# 默认查询限制数量
|
||||
default-limit: 100
|
||||
# 最大查询限制数量
|
||||
max-limit: 1000
|
||||
# 路径查询最大深度
|
||||
max-path-depth: 5
|
||||
# 查询超时时间(秒)
|
||||
timeout-seconds: 30
|
||||
# 是否启用查询缓存
|
||||
cache-enabled: true
|
||||
# 缓存过期时间(分钟)
|
||||
cache-expire-minutes: 60
|
||||
|
||||
|
||||
@@ -1,2 +1,8 @@
|
||||
Application Version: ${revision}
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
__________ _____.___.__ _____ .___
|
||||
\______ \__ __ ____\__ | |__| / _ \ | |
|
||||
| _/ | \/ _ \/ | | | ______ / /_\ \| |
|
||||
| | \ | ( <_> )____ | | /_____/ / | \ |
|
||||
|____|_ /____/ \____// ______|__| \____|__ /___|
|
||||
\/ \/ \/
|
||||
|
||||
@@ -17,6 +17,7 @@ user.username.length.valid=账户长度必须在{min}到{max}个字符之间
|
||||
user.password.not.blank=用户密码不能为空
|
||||
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
|
||||
user.password.not.valid=* 5-50个字符
|
||||
user.password.format.valid=密码必须包含大写字母、小写字母、数字和特殊字符
|
||||
user.email.not.valid=邮箱格式错误
|
||||
user.email.not.blank=邮箱不能为空
|
||||
user.phonenumber.not.blank=用户手机号不能为空
|
||||
@@ -28,6 +29,10 @@ user.register.error=注册失败,请联系系统管理人员
|
||||
user.notfound=请重新登录
|
||||
user.forcelogout=管理员强制退出,请重新登录
|
||||
user.unknown.error=未知错误,请重新登录
|
||||
auth.grant.type.error=认证权限类型错误
|
||||
auth.grant.type.blocked=认证权限类型已禁用
|
||||
auth.grant.type.not.blank=认证权限类型不能为空
|
||||
auth.clientid.not.blank=认证客户端id不能为空
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
|
||||
upload.filename.exceed.length=上传的文件名最长{0}个字符
|
||||
@@ -46,7 +51,10 @@ sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}
|
||||
email.code.not.blank=邮箱验证码不能为空
|
||||
email.code.retry.limit.count=邮箱验证码输入错误{0}次
|
||||
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
|
||||
xcx.code.not.blank=小程序code不能为空
|
||||
xcx.code.not.blank=小程序[code]不能为空
|
||||
social.source.not.blank=第三方登录平台[source]不能为空
|
||||
social.code.not.blank=第三方登录平台[code]不能为空
|
||||
social.state.not.blank=第三方登录平台[state]不能为空
|
||||
##租户
|
||||
tenant.number.not.blank=租户编号不能为空
|
||||
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
|
||||
|
||||
@@ -17,6 +17,7 @@ user.username.length.valid=Account length must be between {min} and {max} charac
|
||||
user.password.not.blank=Password cannot be empty
|
||||
user.password.length.valid=Password length must be between {min} and {max} characters
|
||||
user.password.not.valid=* 5-50 characters
|
||||
user.password.format.valid=Password must contain uppercase, lowercase, digit, and special character
|
||||
user.email.not.valid=Mailbox format error
|
||||
user.email.not.blank=Mailbox cannot be blank
|
||||
user.phonenumber.not.blank=Phone number cannot be blank
|
||||
@@ -28,6 +29,10 @@ user.register.error=Register failed, please contact system administrator
|
||||
user.notfound=Please login again
|
||||
user.forcelogout=The administrator is forced to exit,please login again
|
||||
user.unknown.error=Unknown error, please login again
|
||||
auth.grant.type.error=Auth grant type error
|
||||
auth.grant.type.blocked=Auth grant type disabled
|
||||
auth.grant.type.not.blank=Auth grant type cannot be blank
|
||||
auth.clientid.not.blank=Auth clientid cannot be blank
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=The uploaded file size exceeds the limit file size!<br/>the maximum allowed file size is:{0}MB!
|
||||
upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters
|
||||
@@ -46,7 +51,10 @@ sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {
|
||||
email.code.not.blank=Email code cannot be blank
|
||||
email.code.retry.limit.count=Email code input error {0} times
|
||||
email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes
|
||||
xcx.code.not.blank=Mini program code cannot be blank
|
||||
xcx.code.not.blank=Mini program [code] cannot be blank
|
||||
social.source.not.blank=Social login platform [source] cannot be blank
|
||||
social.code.not.blank=Social login platform [code] cannot be blank
|
||||
social.state.not.blank=Social login platform [state] cannot be blank
|
||||
##租户
|
||||
tenant.number.not.blank=Tenant number cannot be blank
|
||||
tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator
|
||||
|
||||
@@ -17,6 +17,7 @@ user.username.length.valid=账户长度必须在{min}到{max}个字符之间
|
||||
user.password.not.blank=用户密码不能为空
|
||||
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
|
||||
user.password.not.valid=* 5-50个字符
|
||||
user.password.format.valid=密码必须包含大写字母、小写字母、数字和特殊字符
|
||||
user.email.not.valid=邮箱格式错误
|
||||
user.email.not.blank=邮箱不能为空
|
||||
user.phonenumber.not.blank=用户手机号不能为空
|
||||
@@ -28,6 +29,10 @@ user.register.error=注册失败,请联系系统管理人员
|
||||
user.notfound=请重新登录
|
||||
user.forcelogout=管理员强制退出,请重新登录
|
||||
user.unknown.error=未知错误,请重新登录
|
||||
auth.grant.type.error=认证权限类型错误
|
||||
auth.grant.type.blocked=认证权限类型已禁用
|
||||
auth.grant.type.not.blank=认证权限类型不能为空
|
||||
auth.clientid.not.blank=认证客户端id不能为空
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
|
||||
upload.filename.exceed.length=上传的文件名最长{0}个字符
|
||||
@@ -46,7 +51,10 @@ sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}
|
||||
email.code.not.blank=邮箱验证码不能为空
|
||||
email.code.retry.limit.count=邮箱验证码输入错误{0}次
|
||||
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
|
||||
xcx.code.not.blank=小程序code不能为空
|
||||
xcx.code.not.blank=小程序[code]不能为空
|
||||
social.source.not.blank=第三方登录平台[source]不能为空
|
||||
social.code.not.blank=第三方登录平台[code]不能为空
|
||||
social.state.not.blank=第三方登录平台[state]不能为空
|
||||
##租户
|
||||
tenant.number.not.blank=租户编号不能为空
|
||||
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration>
|
||||
<property name="log.path" value="./logs"/>
|
||||
<property name="console.log.pattern"
|
||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
@@ -38,7 +38,7 @@
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
@@ -60,7 +60,7 @@
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
@@ -98,32 +98,32 @@
|
||||
</appender>
|
||||
|
||||
<!-- 整合 skywalking 控制台输出 tid -->
|
||||
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
|
||||
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
|
||||
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
|
||||
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
|
||||
<!-- </layout>-->
|
||||
<!-- <charset>utf-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
<!-- </appender>-->
|
||||
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
|
||||
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
|
||||
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
|
||||
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
|
||||
<!-- </layout>-->
|
||||
<!-- <charset>utf-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
<!-- </appender>-->
|
||||
|
||||
<!-- 整合 skywalking 推送采集日志 -->
|
||||
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
|
||||
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
|
||||
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
|
||||
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
|
||||
<!-- </layout>-->
|
||||
<!-- <charset>utf-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
<!-- </appender>-->
|
||||
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
|
||||
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
|
||||
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
|
||||
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
|
||||
<!-- </layout>-->
|
||||
<!-- <charset>utf-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
<!-- </appender>-->
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="console"/>
|
||||
<appender-ref ref="async_info"/>
|
||||
<appender-ref ref="async_error"/>
|
||||
<appender-ref ref="file_console"/>
|
||||
<!-- <appender-ref ref="sky_log"/>-->
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="async_info" />
|
||||
<appender-ref ref="async_error" />
|
||||
<appender-ref ref="file_console" />
|
||||
<!-- <appender-ref ref="sky_log"/>-->
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"fileSystem": {
|
||||
"command": "C:\\Program Files\\nodejs\\npx.cmd",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"D:\\"
|
||||
]
|
||||
},
|
||||
"search1api": {
|
||||
"command": "C:\\Program Files\\nodejs\\npx.cmd",
|
||||
"args": [
|
||||
"-y",
|
||||
"search1api-mcp"
|
||||
],
|
||||
"env": {
|
||||
"SEARCH1API_KEY": "xx"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
exclude=SELECT 1
|
||||
|
Before Width: | Height: | Size: 78 KiB |
@@ -1,28 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ruoyi-ai</artifactId>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<description>
|
||||
common 通用模块
|
||||
</description>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-common-bom</module>
|
||||
<module>ruoyi-common-chat</module>
|
||||
<module>ruoyi-common-social</module>
|
||||
<module>ruoyi-common-core</module>
|
||||
<module>ruoyi-common-doc</module>
|
||||
<module>ruoyi-common-excel</module>
|
||||
<module>ruoyi-common-idempotent</module>
|
||||
<module>ruoyi-common-job</module>
|
||||
<module>ruoyi-common-log</module>
|
||||
<module>ruoyi-common-mail</module>
|
||||
<module>ruoyi-common-mybatis</module>
|
||||
@@ -38,8 +33,15 @@
|
||||
<module>ruoyi-common-json</module>
|
||||
<module>ruoyi-common-encrypt</module>
|
||||
<module>ruoyi-common-tenant</module>
|
||||
<module>ruoyi-common-chat</module>
|
||||
<module>ruoyi-common-pay</module>
|
||||
<module>ruoyi-common-websocket</module>
|
||||
<module>ruoyi-common-sse</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<description>
|
||||
common 通用模块
|
||||
</description>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>1.0.0</revision>
|
||||
<revision>3.0.0</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -26,6 +26,13 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 对话模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-chat</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 接口模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
@@ -47,6 +54,13 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 调度模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-job</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志记录 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
@@ -110,6 +124,12 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-social</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web服务 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
@@ -152,29 +172,21 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- chat模块 -->
|
||||
<!-- WebSocket模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-chat</artifactId>
|
||||
<artifactId>ruoyi-common-websocket</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信模块 -->
|
||||
<!-- SSE模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-wechat</artifactId>
|
||||
<artifactId>ruoyi-common-sse</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 支付模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-pay</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,97 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common-chat</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-common-chat 模块
|
||||
ruoyi-common-chat chat服务
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<retrofit2.version>2.9.0</retrofit2.version>
|
||||
<azure.version>1.0.0-beta.12</azure.version>
|
||||
<chatglm.version>release-V4-2.3.0</chatglm.version>
|
||||
<okhttp.version>2.7.5</okhttp.version>
|
||||
<jtokkit.version>0.5.0</jtokkit.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- SpringWeb模块 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 序列化模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-json</artifactId>
|
||||
<artifactId>ruoyi-common-sse</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- redis模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-redis</artifactId>
|
||||
<artifactId>ruoyi-common-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.azure</groupId>
|
||||
<artifactId>azure-ai-openai</artifactId>
|
||||
<version>${azure.version}</version>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j</artifactId>
|
||||
<version>${langchain4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>retrofit</artifactId>
|
||||
<version>${retrofit2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>converter-jackson</artifactId>
|
||||
<version>${retrofit2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>adapter-rxjava2</artifactId>
|
||||
<version>${retrofit2.version}</version>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.knuddels</groupId>
|
||||
<artifactId>jtokkit</artifactId>
|
||||
<version>${jtokkit.version}</version>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>${swagger-annotations.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.bigmodel.openapi</groupId>
|
||||
<artifactId>oapi-java-sdk</artifactId>
|
||||
<version>${chatglm.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package org.ruoyi.workflow.base;
|
||||
package org.ruoyi.common.chat.base;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.ruoyi.common.chat.entity.User;
|
||||
import org.ruoyi.common.chat.enums.UserStatusEnum;
|
||||
import org.ruoyi.common.core.domain.model.LoginUser;
|
||||
import org.ruoyi.common.core.exception.base.BaseException;
|
||||
import org.ruoyi.common.satoken.utils.LoginHelper;
|
||||
import org.ruoyi.workflow.entity.User;
|
||||
import org.ruoyi.workflow.enums.UserStatusEnum;
|
||||
|
||||
import static org.ruoyi.workflow.enums.ErrorEnum.A_USER_NOT_FOUND;
|
||||
import static org.ruoyi.common.chat.enums.ErrorEnum.A_USER_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* 线程上下文适配器,统一接入 Sa-Token 登录态。
|
||||
@@ -103,8 +103,7 @@ public class ThreadContext {
|
||||
private static User mapToWorkflowUser(LoginUser loginUser) {
|
||||
User user = new User();
|
||||
user.setId(loginUser.getUserId());
|
||||
String nickname = loginUser.getNickName();
|
||||
user.setName(StringUtils.defaultIfBlank(nickname, loginUser.getUsername()));
|
||||
user.setName(loginUser.getUsername());
|
||||
user.setEmail(loginUser.getUsername());
|
||||
user.setUuid(String.valueOf(loginUser.getUserId()));
|
||||
user.setUserStatus(UserStatusEnum.NORMAL);
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.ruoyi.common.chat.config;
|
||||
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @date 2023-03-10
|
||||
*/
|
||||
@Slf4j
|
||||
public class LocalCache {
|
||||
/**
|
||||
* 缓存时长
|
||||
*/
|
||||
public static final long TIMEOUT = 30 * DateUnit.MINUTE.getMillis();
|
||||
/**
|
||||
* 缓存对象
|
||||
*/
|
||||
public static final TimedCache<String, Object> CACHE = CacheUtil.newTimedCache(TIMEOUT);
|
||||
/**
|
||||
* 清理间隔
|
||||
*/
|
||||
private static final long CLEAN_TIMEOUT = 30 * DateUnit.MINUTE.getMillis();
|
||||
|
||||
static {
|
||||
//启动定时任务
|
||||
CACHE.schedulePrune(CLEAN_TIMEOUT);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.ruoyi.common.chat.constant;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-06
|
||||
*/
|
||||
public class OpenAIConst {
|
||||
|
||||
public final static String OPENAI_HOST = "https://api.openai.com/";
|
||||
|
||||
public final static String apiUrl = "v1/chat/completions";
|
||||
|
||||
public final static int SUCCEED_CODE = 200;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.ruoyi.common.chat.domain.bo.chat;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.common.chat.entity.chat.ChatMessage;
|
||||
import org.ruoyi.common.core.validate.AddGroup;
|
||||
import org.ruoyi.common.core.validate.EditGroup;
|
||||
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
|
||||
/**
|
||||
* 聊天消息业务对象 chat_message
|
||||
*
|
||||
* @author ageerle
|
||||
* @date 2025-12-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = ChatMessage.class, reverseConvertGenerate = false)
|
||||
public class ChatMessageBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@NotNull(message = "用户id不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 对话角色
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 累计 Tokens
|
||||
*/
|
||||
private Long totalTokens;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.ruoyi.common.chat.domain.bo.chat;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.common.chat.entity.chat.ChatModel;
|
||||
import org.ruoyi.common.core.validate.EditGroup;
|
||||
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 模型管理业务对象 chat_model
|
||||
*
|
||||
* @author ageerle
|
||||
* @date 2025-12-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = ChatModel.class, reverseConvertGenerate = false)
|
||||
public class ChatModelBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 模型分类
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 模型供应商
|
||||
*/
|
||||
private String providerCode;
|
||||
|
||||
/**
|
||||
* 模型描述
|
||||
*/
|
||||
private String modelDescribe;
|
||||
|
||||
/**
|
||||
* 是否显示
|
||||
*/
|
||||
private String modelShow;
|
||||
|
||||
/**
|
||||
* 向量维度
|
||||
*/
|
||||
private Integer modelDimension;
|
||||
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String apiHost;
|
||||
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.ruoyi.common.chat.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 聊天消息DTO - 用于上下文传递
|
||||
*
|
||||
* @author ageerle@163.com
|
||||
* @date 2025/12/13
|
||||
*/
|
||||
@Data
|
||||
public class ChatMessageDTO {
|
||||
|
||||
/**
|
||||
* 消息角色: system/user/assistant
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
public static ChatMessageDTO system(String content) {
|
||||
ChatMessageDTO msg = new ChatMessageDTO();
|
||||
msg.role = "system";
|
||||
msg.content = content;
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static ChatMessageDTO user(String content) {
|
||||
ChatMessageDTO msg = new ChatMessageDTO();
|
||||
msg.role = "user";
|
||||
msg.content = content;
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static ChatMessageDTO assistant(String content) {
|
||||
ChatMessageDTO msg = new ChatMessageDTO();
|
||||
msg.role = "assistant";
|
||||
msg.content = content;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,40 @@
|
||||
package org.ruoyi.common.chat.request;
|
||||
package org.ruoyi.common.chat.domain.dto.request;
|
||||
|
||||
import dev.langchain4j.data.message.ChatMessage;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import org.ruoyi.common.chat.entity.chat.Message;
|
||||
import org.ruoyi.common.chat.domain.dto.ChatMessageDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 对话请求对象
|
||||
* 对话请求对象
|
||||
*
|
||||
* @author ageerle
|
||||
* @sine 2023-04-08
|
||||
* @date 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
public class ChatRequest {
|
||||
|
||||
@NotEmpty(message = "对话消息不能为空")
|
||||
List<Message> messages;
|
||||
|
||||
private List<ChatMessageDTO> messages;
|
||||
@NotEmpty(message = "传入的模型不能为空")
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 提示词
|
||||
* 工作流请求体
|
||||
*/
|
||||
private String prompt;
|
||||
|
||||
private WorkFlowRunner workFlowRunner;
|
||||
|
||||
/**
|
||||
* 系统提示词
|
||||
* 人机交互信息体
|
||||
*/
|
||||
private String sysPrompt;
|
||||
|
||||
private ReSumeRunner reSumeRunner;
|
||||
|
||||
/**
|
||||
* 消息id
|
||||
* 是否启用工作流
|
||||
*/
|
||||
private Long messageId;
|
||||
|
||||
/**
|
||||
* 是否开启流式对话
|
||||
*/
|
||||
private Boolean stream = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 知识库id
|
||||
*/
|
||||
private String kid;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
private Boolean enableWorkFlow;
|
||||
|
||||
/**
|
||||
* 会话id
|
||||
@@ -64,10 +47,9 @@ public class ChatRequest {
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 对话角色
|
||||
* 知识库id
|
||||
*/
|
||||
private String role;
|
||||
|
||||
private String knowledgeId;
|
||||
|
||||
/**
|
||||
* 对话id(每个聊天窗口都不一样)
|
||||
@@ -75,9 +57,9 @@ public class ChatRequest {
|
||||
private Long uuid;
|
||||
|
||||
/**
|
||||
* 是否有附件
|
||||
* 是否为人机交互用户继续输入
|
||||
*/
|
||||
private Boolean hasAttachment;
|
||||
private Boolean isResume;
|
||||
|
||||
/**
|
||||
* 是否启用深度思考
|
||||
@@ -89,9 +71,19 @@ public class ChatRequest {
|
||||
*/
|
||||
private Boolean autoSelectModel;
|
||||
|
||||
/**
|
||||
* 是否支持联网
|
||||
*/
|
||||
private Boolean enableInternet;
|
||||
|
||||
/**
|
||||
* 会话令牌(为避免在非Web线程中获取Request,入口处注入)
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 原生对话对象
|
||||
*/
|
||||
private List<ChatMessage> chatMessages;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.ruoyi.common.chat.domain.dto.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 人机交互输入信息
|
||||
*/
|
||||
@Data
|
||||
public class ReSumeRunner {
|
||||
/**
|
||||
* 运行节点UUID
|
||||
*/
|
||||
private String runtimeUuid;
|
||||
|
||||
/**
|
||||
* 人机交互用户输入信息
|
||||
*/
|
||||
private String feedbackContent;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.ruoyi.common.chat.domain.dto.request;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 工作流请求体信息
|
||||
*/
|
||||
@Data
|
||||
public class WorkFlowRunner {
|
||||
private List<ObjectNode> inputs;
|
||||
private String uuid;
|
||||
}
|
||||
@@ -1,24 +1,22 @@
|
||||
package org.ruoyi.domain.vo;
|
||||
package org.ruoyi.common.chat.domain.vo.chat;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.ruoyi.common.chat.entity.chat.ChatMessage;
|
||||
import org.ruoyi.common.excel.annotation.ExcelDictFormat;
|
||||
import org.ruoyi.common.excel.convert.ExcelDictConvert;
|
||||
import org.ruoyi.domain.ChatMessage;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 聊天消息视图对象 chat_message
|
||||
*
|
||||
* @author ageerle
|
||||
* @date 2025-04-08
|
||||
* @date 2025-12-14
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@@ -34,17 +32,18 @@ public class ChatMessageVo implements Serializable {
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
@ExcelProperty(value = "会话id")
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@ExcelProperty(value = "用户id")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@@ -57,12 +56,6 @@ public class ChatMessageVo implements Serializable {
|
||||
@ExcelProperty(value = "对话角色")
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 扣除金额
|
||||
*/
|
||||
@ExcelProperty(value = "扣除金额")
|
||||
private BigDecimal deductCost;
|
||||
|
||||
/**
|
||||
* 累计 Tokens
|
||||
*/
|
||||
@@ -75,12 +68,6 @@ public class ChatMessageVo implements Serializable {
|
||||
@ExcelProperty(value = "模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 计费类型(1-token计费,2-次数计费)
|
||||
*/
|
||||
@ExcelProperty(value = "计费类型", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_model_billing")
|
||||
private String billingType;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
@@ -89,11 +76,4 @@ public class ChatMessageVo implements Serializable {
|
||||
private String remark;
|
||||
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
package org.ruoyi.domain.vo;
|
||||
package org.ruoyi.common.chat.domain.vo.chat;
|
||||
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.ruoyi.common.sensitive.annotation.Sensitive;
|
||||
import org.ruoyi.common.sensitive.core.SensitiveStrategy;
|
||||
import org.ruoyi.domain.ChatModel;
|
||||
import org.ruoyi.common.chat.entity.chat.ChatModel;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 聊天模型视图对象 chat_model
|
||||
* 模型管理视图对象 chat_model
|
||||
*
|
||||
* @author ageerle
|
||||
* @date 2025-04-08
|
||||
* @date 2025-12-14
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@@ -45,23 +42,18 @@ public class ChatModelVo implements Serializable {
|
||||
@ExcelProperty(value = "模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 模型供应商
|
||||
*/
|
||||
@ExcelProperty(value = "模型供应商")
|
||||
private String providerCode;
|
||||
|
||||
/**
|
||||
* 模型描述
|
||||
*/
|
||||
@ExcelProperty(value = "模型描述")
|
||||
private String modelDescribe;
|
||||
|
||||
/**
|
||||
* 模型价格
|
||||
*/
|
||||
@ExcelProperty(value = "模型价格")
|
||||
private Double modelPrice;
|
||||
|
||||
/**
|
||||
* 计费类型
|
||||
*/
|
||||
@ExcelProperty(value = "计费类型")
|
||||
private String modelType;
|
||||
|
||||
/**
|
||||
* 是否显示
|
||||
@@ -70,15 +62,10 @@ public class ChatModelVo implements Serializable {
|
||||
private String modelShow;
|
||||
|
||||
/**
|
||||
* 模型维度
|
||||
* 向量维度
|
||||
*/
|
||||
private Integer dimension;
|
||||
|
||||
/**
|
||||
* 系统提示词
|
||||
*/
|
||||
@ExcelProperty(value = "系统提示词")
|
||||
private String systemPrompt;
|
||||
@ExcelProperty(value = "向量维度")
|
||||
private Integer modelDimension;
|
||||
|
||||
/**
|
||||
* 请求地址
|
||||
@@ -89,27 +76,14 @@ public class ChatModelVo implements Serializable {
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
@Sensitive(strategy = SensitiveStrategy.PHONE)
|
||||
@ExcelProperty(value = "密钥")
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 优先级(值越大优先级越高)
|
||||
*/
|
||||
@ExcelProperty(value = "优先级")
|
||||
private Integer priority;
|
||||
|
||||
/**
|
||||
* 模型供应商
|
||||
*/
|
||||
@ExcelProperty(value = "模型供应商")
|
||||
private String providerName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.ruoyi.workflow.entity;
|
||||
package org.ruoyi.common.chat.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
@@ -1,48 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.Tts;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TextToSpeech {
|
||||
|
||||
@Builder.Default
|
||||
private String model = Model.TTS_1.getName();
|
||||
/**
|
||||
* 音频声音源
|
||||
*
|
||||
* @see TtsVoice
|
||||
*/
|
||||
private String voice;
|
||||
/**
|
||||
* 输入内容
|
||||
*/
|
||||
private String input;
|
||||
/**
|
||||
* 输出音频文件格式
|
||||
*
|
||||
* @see TtsFormat
|
||||
*/
|
||||
@JsonProperty("response_format")
|
||||
private String responseFormat;
|
||||
/**
|
||||
* 速度调节,默认是1,取值范围0.25——4.0
|
||||
*/
|
||||
private Double speed;
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Model {
|
||||
TTS_1("tts-1"),
|
||||
TTS_1_HD("tts-1-hd"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.Tts;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TtsFormat {
|
||||
MP3("mp3"),
|
||||
OPUS("opus"),
|
||||
AAC("aac"),
|
||||
FLAC("flac"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.Tts;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 生成不同声音的音频
|
||||
* <p>具体语音效果参考:https://platform.openai.com/docs/guides/text-to-speech</p>
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TtsVoice {
|
||||
|
||||
ALLOY("alloy"),
|
||||
ECHO("echo"),
|
||||
FABLE("fable"),
|
||||
ONYX("onyx"),
|
||||
NOVA("nova"),
|
||||
SHIMMER("shimmer"),
|
||||
;
|
||||
|
||||
private final String name;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package org.ruoyi.workflow.entity;
|
||||
package org.ruoyi.common.chat.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.workflow.enums.UserStatusEnum;
|
||||
import org.ruoyi.common.chat.enums.UserStatusEnum;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 金额消耗信息
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class BillingUsage {
|
||||
|
||||
@JsonProperty("object")
|
||||
private String object;
|
||||
/**
|
||||
* 账号金额消耗明细
|
||||
*/
|
||||
@JsonProperty("daily_costs")
|
||||
private List<DailyCost> dailyCosts;
|
||||
/**
|
||||
* 总使用金额:美分
|
||||
*/
|
||||
@JsonProperty("total_usage")
|
||||
private BigDecimal totalUsage;
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 余额查询接口返回值
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-18
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class CreditGrantsResponse implements Serializable {
|
||||
private String object;
|
||||
/**
|
||||
* 总金额:美元
|
||||
*/
|
||||
@JsonProperty("total_granted")
|
||||
private BigDecimal totalGranted;
|
||||
/**
|
||||
* 总使用金额:美元
|
||||
*/
|
||||
@JsonProperty("total_used")
|
||||
private BigDecimal totalUsed;
|
||||
/**
|
||||
* 总剩余金额:美元
|
||||
*/
|
||||
@JsonProperty("total_available")
|
||||
private BigDecimal totalAvailable;
|
||||
/**
|
||||
* 余额明细
|
||||
*/
|
||||
private Grants grants;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 金额消耗列表
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DailyCost {
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
@JsonProperty("timestamp")
|
||||
private long timestamp;
|
||||
/**
|
||||
* 模型消耗金额详情
|
||||
*/
|
||||
@JsonProperty("line_items")
|
||||
private List<LineItem> lineItems;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-18
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Datum {
|
||||
private String object;
|
||||
private String id;
|
||||
/**
|
||||
* 赠送金额:美元
|
||||
*/
|
||||
@JsonProperty("grant_amount")
|
||||
private BigDecimal grantAmount;
|
||||
/**
|
||||
* 使用金额:美元
|
||||
*/
|
||||
@JsonProperty("used_amount")
|
||||
private BigDecimal usedAmount;
|
||||
/**
|
||||
* 生效时间戳
|
||||
*/
|
||||
@JsonProperty("effective_at")
|
||||
private Long effectiveAt;
|
||||
/**
|
||||
* 过期时间戳
|
||||
*/
|
||||
@JsonProperty("expires_at")
|
||||
private Long expiresAt;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-18
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Grants {
|
||||
private String object;
|
||||
@JsonProperty("data")
|
||||
private List<Datum> data;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* openKey信息
|
||||
*
|
||||
* @author admin
|
||||
* @date 2023/6/15
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class KeyInfo {
|
||||
/**
|
||||
* 订阅类型
|
||||
*/
|
||||
private String planTitle;
|
||||
/**
|
||||
* key值
|
||||
*/
|
||||
private String keyValue;
|
||||
/**
|
||||
* 剩余额度
|
||||
*/
|
||||
private Double remaining;
|
||||
|
||||
/**
|
||||
* 账户总余额
|
||||
*/
|
||||
private Double totalAmount;
|
||||
|
||||
/**
|
||||
* 已使用的额度
|
||||
*/
|
||||
private Double totalUsage;
|
||||
|
||||
/**
|
||||
* 截至日期
|
||||
*/
|
||||
private LocalDate limitDate;
|
||||
|
||||
/**
|
||||
* 是否绑卡
|
||||
*/
|
||||
private Boolean isHasPaymentMethod;
|
||||
|
||||
/**
|
||||
* 最高可用模型
|
||||
*/
|
||||
private String model;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 金额消耗列表
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class LineItem {
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 消耗金额
|
||||
*/
|
||||
private BigDecimal cost;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Plan {
|
||||
private String title;
|
||||
private String id;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.billing;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 账户信息
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
public class Subscription {
|
||||
|
||||
@JsonProperty("object")
|
||||
private String object;
|
||||
|
||||
/**
|
||||
* 付款方式
|
||||
*/
|
||||
@JsonProperty("has_payment_method")
|
||||
private boolean hasPaymentMethod;
|
||||
|
||||
@JsonProperty("canceled")
|
||||
private boolean canceled;
|
||||
@JsonProperty("canceled_at")
|
||||
private Object canceledAt;
|
||||
|
||||
@JsonProperty("delinquent")
|
||||
private Object delinquent;
|
||||
@JsonProperty("access_until")
|
||||
private long accessUntil;
|
||||
@JsonProperty("soft_limit")
|
||||
private long softLimit;
|
||||
@JsonProperty("hard_limit")
|
||||
private long hardLimit;
|
||||
@JsonProperty("system_hard_limit")
|
||||
private long systemHardLimit;
|
||||
@JsonProperty("soft_limit_usd")
|
||||
private double softLimitUsd;
|
||||
@JsonProperty("hard_limit_usd")
|
||||
private double hardLimitUsd;
|
||||
@JsonProperty("system_hard_limit_usd")
|
||||
private double systemHardLimitUsd;
|
||||
/**
|
||||
* 计划
|
||||
*/
|
||||
@JsonProperty("plan")
|
||||
private Plan plan;
|
||||
|
||||
/**
|
||||
* 账户名称
|
||||
*/
|
||||
@JsonProperty("account_name")
|
||||
private String accountName;
|
||||
|
||||
@JsonProperty("po_number")
|
||||
private Object poNumber;
|
||||
|
||||
/**
|
||||
* 账单邮箱
|
||||
*/
|
||||
@JsonProperty("billing_email")
|
||||
private Object billingEmail;
|
||||
@JsonProperty("tax_ids")
|
||||
private Object taxIds;
|
||||
@JsonProperty("billing_address")
|
||||
private Object billingAddress;
|
||||
@JsonProperty("business_address")
|
||||
private Object businessAddress;
|
||||
@JsonProperty("primary")
|
||||
private Boolean primary;
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import org.ruoyi.common.chat.entity.chat.tool.Tools;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.ruoyi.common.chat.entity.chat.BaseChatCompletion.Model.GPT_3_5_TURBO;
|
||||
|
||||
/**
|
||||
* chat模型基础类
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 1.1.2
|
||||
* 2023-11-10
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseChatCompletion implements Serializable {
|
||||
|
||||
@NonNull
|
||||
@Builder.Default
|
||||
private String model = GPT_3_5_TURBO.getName();
|
||||
|
||||
/**
|
||||
* 指定模型必须输出的格式的对象。
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@JsonProperty("response_format")
|
||||
private ResponseFormat responseFormat;
|
||||
|
||||
/**
|
||||
* 已过时
|
||||
*
|
||||
* @see #tools
|
||||
*/
|
||||
@Deprecated
|
||||
private List<Functions> functions;
|
||||
|
||||
/**
|
||||
* 取值:null,auto或者自定义
|
||||
* functions没有值的时候默认为:null
|
||||
* functions存在值得时候默认为:auto
|
||||
* 也可以自定义
|
||||
* <p>已过时</p>
|
||||
*
|
||||
* @see #toolChoice
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonProperty("function_call")
|
||||
private Object functionCall;
|
||||
|
||||
/**
|
||||
* 模型可能调用的工具列表。
|
||||
* 当前版本仅支持:functions
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private List<Tools> tools;
|
||||
|
||||
/**
|
||||
* 取值:String或者ToolChoiceObj
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@JsonProperty("tool_choice")
|
||||
private Object toolChoice;
|
||||
|
||||
/**
|
||||
* 使用什么取样温度,0到2之间。较高的值(如0.8)将使输出更加随机,而较低的值(如0.2)将使输出更加集中和确定。
|
||||
* <p>
|
||||
* We generally recommend altering this or but not both.top_p
|
||||
*/
|
||||
@Builder.Default
|
||||
private double temperature = 0.2;
|
||||
|
||||
/**
|
||||
* 使用温度采样的替代方法称为核心采样,其中模型考虑具有top_p概率质量的令牌的结果。因此,0.1 意味着只考虑包含前 10% 概率质量的代币。
|
||||
* <p>
|
||||
* 我们通常建议更改此设置,但不要同时更改两者。temperature
|
||||
*/
|
||||
@JsonProperty("top_p")
|
||||
@Builder.Default
|
||||
private Double topP = 1d;
|
||||
|
||||
|
||||
/**
|
||||
* 为每个提示生成的完成次数。
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer n = 1;
|
||||
|
||||
|
||||
/**
|
||||
* 是否流式输出.
|
||||
* default:false
|
||||
*/
|
||||
@Builder.Default
|
||||
private boolean stream = false;
|
||||
/**
|
||||
* 停止输出标识
|
||||
*/
|
||||
private List<String> stop;
|
||||
/**
|
||||
* 最大支持4096
|
||||
*/
|
||||
@JsonProperty("max_tokens")
|
||||
@Builder.Default
|
||||
private Integer maxTokens = 2048;
|
||||
|
||||
|
||||
@JsonProperty("presence_penalty")
|
||||
@Builder.Default
|
||||
private double presencePenalty = 0;
|
||||
|
||||
/**
|
||||
* -2.0 ~~ 2.0
|
||||
*/
|
||||
@JsonProperty("frequency_penalty")
|
||||
@Builder.Default
|
||||
private double frequencyPenalty = 0;
|
||||
|
||||
@JsonProperty("logit_bias")
|
||||
private Map logitBias;
|
||||
/**
|
||||
* 用户唯一值,确保接口不被重复调用
|
||||
*/
|
||||
private String user;
|
||||
|
||||
/**
|
||||
* @since 1.1.2
|
||||
*/
|
||||
private Integer seed;
|
||||
|
||||
|
||||
/**
|
||||
* 最新模型参考官方文档:
|
||||
* <a href="https://platform.openai.com/docs/models/model-endpoint-compatibility">官方稳定模型列表</a>
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Model {
|
||||
/**
|
||||
* gpt-3.5-turbo
|
||||
*/
|
||||
GPT_3_5_TURBO("gpt-3.5-turbo"),
|
||||
/**
|
||||
* 临时模型,不建议使用,2023年9 月 13 日将被弃用
|
||||
*/
|
||||
@Deprecated
|
||||
GPT_3_5_TURBO_0301("gpt-3.5-turbo-0301"),
|
||||
/**
|
||||
* gpt-3.5-turbo-0613 支持函数
|
||||
*/
|
||||
GPT_3_5_TURBO_1106("gpt-3.5-turbo-1106"),
|
||||
|
||||
GPT_3_5_TURBO_0613("gpt-3.5-turbo-0613"),
|
||||
/**
|
||||
* gpt-3.5-turbo-16k 超长上下文
|
||||
*/
|
||||
GPT_3_5_TURBO_16K("gpt-3.5-turbo-16k"),
|
||||
/**
|
||||
* gpt-3.5-turbo-16k-0613 超长上下文 支持函数
|
||||
*/
|
||||
GPT_3_5_TURBO_16K_0613("gpt-3.5-turbo-16k-0613"),
|
||||
/**
|
||||
* gpt-3.5-turbo-0125 超长上下文 支持函数
|
||||
*/
|
||||
GPT_3_5_TURBO_0125("gpt-3.5-turbo-0125"),
|
||||
/**
|
||||
* GPT4.0
|
||||
*/
|
||||
GPT_4("gpt-4"),
|
||||
/**
|
||||
* 临时模型,不建议使用,2023年9 月 13 日将被弃用
|
||||
*/
|
||||
@Deprecated
|
||||
GPT_4_0314("gpt-4-0314"),
|
||||
/**
|
||||
* GPT4.0 超长上下文
|
||||
*/
|
||||
GPT_4_32K("gpt-4-32k"),
|
||||
/**
|
||||
* 临时模型,不建议使用,2023年9 月 13 日将被弃用
|
||||
*/
|
||||
@Deprecated
|
||||
GPT_4_32K_0314("gpt-4-32k-0314"),
|
||||
|
||||
/**
|
||||
* gpt-4-0613,支持函数
|
||||
*/
|
||||
GPT_4_0613("gpt-4-0613"),
|
||||
/**
|
||||
* gpt-4-0613,支持函数
|
||||
*/
|
||||
GPT_4_32K_0613("gpt-4-32k-0613"),
|
||||
/**
|
||||
* 支持数组模式,支持function call,支持可重复输出
|
||||
*/
|
||||
GPT_4_1106_PREVIEW("gpt-4-1106-preview"),
|
||||
/**
|
||||
* 支持图片
|
||||
*/
|
||||
GPT_4_VISION_PREVIEW("gpt-4-vision-preview"),
|
||||
/**
|
||||
* gpt-4-0613,支持函数
|
||||
*/
|
||||
GPT_4_0125_PREVIEW("gpt-4-0125-preview"),
|
||||
|
||||
/**
|
||||
* GPT_4_ALL
|
||||
*/
|
||||
GPT_4_ALL("gpt-4-all"),
|
||||
|
||||
GPT_4_GIZMO("gpt-4-gizmo"),
|
||||
|
||||
NET("net"),
|
||||
|
||||
CLAUDE_3_SONNET("claude-3-sonnet-20240229"),
|
||||
|
||||
GEMINI_PRO("gemini-pro"),
|
||||
|
||||
STABLE_DIFFUSION("stable-diffusion"),
|
||||
|
||||
SUNO_V3("suno-v3"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ChatType {
|
||||
/**
|
||||
* 对话类型 - 输入
|
||||
*/
|
||||
CHAT_IN("in"),
|
||||
/**
|
||||
* 对话类型 - 输出
|
||||
*/
|
||||
CHAT_OUT("out"),
|
||||
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.ruoyi.common.chat.entity.chat.tool.ToolCalls;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 1.1.2
|
||||
* 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@AllArgsConstructor
|
||||
public class BaseMessage implements Serializable {
|
||||
|
||||
/**
|
||||
* 目前支持四个中角色参考官网,进行情景输入:
|
||||
* https://platform.openai.com/docs/guides/chat/introduction
|
||||
*/
|
||||
private String role;
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The tool calls generated by the model, such as function calls.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@JsonProperty("tool_calls")
|
||||
private List<ToolCalls> toolCalls;
|
||||
|
||||
/**
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@JsonProperty("tool_call_id")
|
||||
private String toolCallId;
|
||||
|
||||
@Deprecated
|
||||
@JsonProperty("function_call")
|
||||
private FunctionCall functionCall;
|
||||
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param role 角色
|
||||
* @param name name
|
||||
* @param functionCall functionCall
|
||||
*/
|
||||
public BaseMessage(String role, String name, FunctionCall functionCall) {
|
||||
this.role = role;
|
||||
this.name = name;
|
||||
this.functionCall = functionCall;
|
||||
}
|
||||
|
||||
public BaseMessage() {
|
||||
}
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Role {
|
||||
|
||||
SYSTEM("system"),
|
||||
USER("user"),
|
||||
ASSISTANT("assistant"),
|
||||
FUNCTION("function"),
|
||||
TOOL("tool"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ChatChoice implements Serializable {
|
||||
private long index;
|
||||
/**
|
||||
* 请求参数stream为true返回是delta
|
||||
*/
|
||||
@JsonProperty("delta")
|
||||
private Message delta;
|
||||
/**
|
||||
* 请求参数stream为false返回是message
|
||||
*/
|
||||
@JsonProperty("message")
|
||||
private Message message;
|
||||
@JsonProperty("finish_reason")
|
||||
private String finishReason;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* chat模型参数
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Slf4j
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ChatCompletion extends BaseChatCompletion implements Serializable {
|
||||
|
||||
/**
|
||||
* 问题描述
|
||||
*/
|
||||
@NonNull
|
||||
private List<Message> messages;
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import org.ruoyi.common.chat.entity.common.Usage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* chat答案类
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ChatCompletionResponse implements Serializable {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private List<ChatChoice> choices;
|
||||
private Usage usage;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* : chat模型附带图片的参数
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 1.1.2
|
||||
* 2023-11-10
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@Slf4j
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ChatCompletionWithPicture extends BaseChatCompletion implements Serializable {
|
||||
/**
|
||||
* 问题描述
|
||||
*/
|
||||
private List<MessagePicture> messages;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
|
||||
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
import org.ruoyi.common.chat.service.chat.IChatService;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
/**
|
||||
* 聊天对话上下文对象
|
||||
*
|
||||
* @author zengxb
|
||||
* @date 2026-02-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Builder
|
||||
public class ChatContext {
|
||||
|
||||
/**
|
||||
* 模型管理视图对象
|
||||
*/
|
||||
@NotNull(message = "模型管理视图对象不能为空")
|
||||
private ChatModelVo chatModelVo;
|
||||
|
||||
/**
|
||||
* 对话请求对象
|
||||
*/
|
||||
@NotNull(message = "对话请求对象不能为空")
|
||||
private ChatRequest chatRequest;
|
||||
|
||||
/**
|
||||
* SSe连接对象
|
||||
*/
|
||||
@NotNull(message = "SSe连接对象不能为空")
|
||||
private SseEmitter emitter;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* Token
|
||||
*/
|
||||
@NotNull(message = "Token不能为空")
|
||||
private String tokenValue;
|
||||
|
||||
/**
|
||||
* 响应处理器
|
||||
*/
|
||||
private StreamingChatResponseHandler handler;
|
||||
|
||||
/**
|
||||
* 聊天服务实例
|
||||
*/
|
||||
private IChatService chatService;
|
||||
}
|
||||
@@ -1,24 +1,23 @@
|
||||
package org.ruoyi.domain;
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.core.domain.BaseEntity;
|
||||
import org.ruoyi.common.tenant.core.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 聊天消息对象 chat_message
|
||||
*
|
||||
* @author ageerle
|
||||
* @date 2025-04-08
|
||||
* @date 2025-12-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("chat_message")
|
||||
public class ChatMessage extends BaseEntity {
|
||||
public class ChatMessage extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
@@ -29,16 +28,16 @@ public class ChatMessage extends BaseEntity {
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
private Long sessionId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@@ -49,10 +48,6 @@ public class ChatMessage extends BaseEntity {
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 扣除金额
|
||||
*/
|
||||
private BigDecimal deductCost;
|
||||
|
||||
/**
|
||||
* 累计 Tokens
|
||||
@@ -69,10 +64,5 @@ public class ChatMessage extends BaseEntity {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 计费类型(1-token计费,2-次数计费,null-普通消息)
|
||||
*/
|
||||
private String billingType;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,25 +1,23 @@
|
||||
package org.ruoyi.domain;
|
||||
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.ruoyi.core.domain.BaseEntity;
|
||||
import org.ruoyi.common.tenant.core.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
|
||||
/**
|
||||
* 聊天模型对象 chat_model
|
||||
* 模型管理对象 chat_model
|
||||
*
|
||||
* @author ageerle
|
||||
* @date 2025-04-08
|
||||
* @date 2025-12-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("chat_model")
|
||||
public class ChatModel extends BaseEntity {
|
||||
public class ChatModel extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
@@ -40,20 +38,16 @@ public class ChatModel extends BaseEntity {
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 模型供应商
|
||||
*/
|
||||
private String providerCode;
|
||||
|
||||
/**
|
||||
* 模型描述
|
||||
*/
|
||||
private String modelDescribe;
|
||||
|
||||
/**
|
||||
* 模型价格
|
||||
*/
|
||||
private Double modelPrice;
|
||||
|
||||
/**
|
||||
* 计费类型
|
||||
*/
|
||||
private String modelType;
|
||||
|
||||
/**
|
||||
* 是否显示
|
||||
@@ -61,31 +55,20 @@ public class ChatModel extends BaseEntity {
|
||||
private String modelShow;
|
||||
|
||||
/**
|
||||
* 系统提示词
|
||||
* 向量维度
|
||||
*/
|
||||
private String systemPrompt;
|
||||
private Integer modelDimension;
|
||||
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String apiHost;
|
||||
|
||||
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
private Integer priority;
|
||||
|
||||
/**
|
||||
* 模型供应商
|
||||
*/
|
||||
private String providerName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author https://www.unfbx.com
|
||||
* @since 1.1.2
|
||||
* 2023-11-10
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@Slf4j
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Content {
|
||||
/**
|
||||
* 输入类型:text、image_url
|
||||
*
|
||||
* @see Type
|
||||
*/
|
||||
private String type;
|
||||
private String text;
|
||||
@JsonProperty("image_url")
|
||||
private ImageUrl imageUrl;
|
||||
|
||||
/**
|
||||
* 生成图片风格
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type {
|
||||
TEXT("text"),
|
||||
IMAGE_URL("image_url"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FastGPTAnswerResponse {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private List<FastGPTChatChoice> choices;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FastGPTChatChoice implements Serializable {
|
||||
private long index;
|
||||
/**
|
||||
* 请求参数stream为true返回是delta
|
||||
*/
|
||||
@JsonProperty("delta")
|
||||
private Message delta;
|
||||
/**
|
||||
* 请求参数stream为false返回是message
|
||||
*/
|
||||
@JsonProperty("message")
|
||||
private Message message;
|
||||
@JsonProperty("finish_reason")
|
||||
private String finishReason;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FastGPTChatCompletion extends ChatCompletion implements Serializable {
|
||||
|
||||
/**
|
||||
* 是否使用FastGPT提供的上下文
|
||||
*/
|
||||
private String chatId;
|
||||
|
||||
|
||||
/**
|
||||
* 是否返回详细信息;stream模式下会通过event进行区分,非stream模式结果保存在responseData中.
|
||||
*/
|
||||
private boolean detail;
|
||||
|
||||
|
||||
/**
|
||||
* 运行时变量
|
||||
* 模块变量,一个对象,会替换模块中,输入fastgpt框内容里的{{key}}
|
||||
*/
|
||||
private Variables variables;
|
||||
|
||||
/**
|
||||
* responseChatItemId: string | undefined 。
|
||||
* 如果传入,则会将该值作为本次对话的响应消息的 ID,
|
||||
* FastGPT 会自动将该 ID 存入数据库。请确保,
|
||||
* 在当前chatId下,responseChatItemId是唯一的。
|
||||
*/
|
||||
private String responseChatItemId;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 函数调用返回值
|
||||
*
|
||||
* @author https://www.unfbx.com
|
||||
* @since 2023-06-14
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FunctionCall {
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 方法参数
|
||||
*/
|
||||
private String arguments;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 方法参数实体类,实例数据如下
|
||||
* <pre>
|
||||
* {
|
||||
* "name": "get_current_weather",
|
||||
* "description": "Get the current weather in a given location",
|
||||
* "parameters": {
|
||||
* "type": "object",
|
||||
* "properties": {
|
||||
* "location": {
|
||||
* "type": "string",
|
||||
* "description": "The city and state, e.g. San Francisco, CA"
|
||||
* },
|
||||
* "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
|
||||
* },
|
||||
* "required": ["location"]
|
||||
* },
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-06-14
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class Functions implements Serializable {
|
||||
/**
|
||||
* 方法名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 方法描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 方法参数
|
||||
* 扩展参数可以继承Parameters自己实现,json格式的数据
|
||||
*/
|
||||
private Parameters parameters;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author https://www.unfbx.com
|
||||
* 2023-11-10
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@Slf4j
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ImageUrl {
|
||||
/**
|
||||
* 图片地址,支持base64. eg: data:image/jpeg;base64,{base64_image} <p\>
|
||||
* https://platform.openai.com/docs/guides/vision
|
||||
*/
|
||||
private String url;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package org.ruoyi.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import org.ruoyi.common.chat.entity.chat.tool.ToolCalls;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Message extends BaseMessage implements Serializable {
|
||||
|
||||
private Object content;
|
||||
@JsonProperty("reasoning_content")
|
||||
private String reasoningContent;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param role 角色
|
||||
* @param name name
|
||||
* @param content content
|
||||
* @param functionCall functionCall
|
||||
*/
|
||||
public Message(String role, String name, String content, List<ToolCalls> toolCalls, String toolCallId, FunctionCall functionCall) {
|
||||
this.content = content;
|
||||
super.setRole(role);
|
||||
super.setName(name);
|
||||
super.setToolCalls(toolCalls);
|
||||
super.setToolCallId(toolCallId);
|
||||
super.setFunctionCall(functionCall);
|
||||
}
|
||||
|
||||
public Message() {
|
||||
}
|
||||
|
||||
private Message(Builder builder) {
|
||||
setContent(builder.content);
|
||||
super.setRole(builder.role);
|
||||
super.setName(builder.name);
|
||||
super.setFunctionCall(builder.functionCall);
|
||||
super.setToolCalls(builder.toolCalls);
|
||||
super.setToolCallId(builder.toolCallId);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String role;
|
||||
private String content;
|
||||
private String name;
|
||||
private String toolCallId;
|
||||
private List<ToolCalls> toolCalls;
|
||||
private FunctionCall functionCall;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder role(Role role) {
|
||||
this.role = role.getName();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder role(String role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder functionCall(FunctionCall functionCall) {
|
||||
this.functionCall = functionCall;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder toolCalls(List<ToolCalls> toolCalls) {
|
||||
this.toolCalls = toolCalls;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder toolCallId(String toolCallId) {
|
||||
this.toolCallId = toolCallId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Message build() {
|
||||
return new Message(this);
|
||||
}
|
||||
}
|
||||
}
|
||||