init
18
.editorconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
# 空格替代Tab缩进在各种编辑工具下效果一致
|
||||
[*]
|
||||
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
|
||||
48
.gitignore
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
######################################################################
|
||||
# Build Tools
|
||||
|
||||
.gradle
|
||||
/build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################################################################
|
||||
# IDE
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### JRebel ###
|
||||
rebel.xml
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/*
|
||||
nbbuild/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
######################################################################
|
||||
# Others
|
||||
*.log
|
||||
*.xml.versionsBackup
|
||||
*.swp
|
||||
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
||||
|
||||
.flattened-pom.xml
|
||||
20
LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 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
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
36
README.en.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# ruoyi-ai-pro
|
||||
|
||||
#### Description
|
||||
ruoyi-ai-pro
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
83
README.md
@@ -1,2 +1,81 @@
|
||||
# ruoyi-ai
|
||||
基于ruoyi-plus实现AI聊天和绘画功能-后端 本项目完全开源免费! 后台管理界面使用elementUI服务端使用Java17+SpringBoot3.X
|
||||
## 平台简介
|
||||
[](https://gitee.com/ageerle/ruoyi-ai/blob/master/LICENSE)
|
||||
[](https://www.jetbrains.com/?from=ruoyi-chatgpt)
|
||||
<br>
|
||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
> 基于ruoyi-plus实现AI聊天和绘画功能-后端
|
||||
|
||||
> 本项目完全开源免费!
|
||||
后台管理界面使用elementUI服务端使用Java17+SpringBoot3.X
|
||||
|
||||
实现功能
|
||||
1. 接入ChatGPT-4-1106-preview,gpt-4-vision-preview,dall-e-3模型
|
||||
2. 支持ChatGPT-4-All alltools版本,集成识图、画图、联网和code interpreter
|
||||
3. 支持GPTS 可以使用openai的所有的GPTs
|
||||
4. 接入AzureOpenAI
|
||||
5. 接入文生图模型Midjourney( 史上最强AI画图)
|
||||
6. 接入微信支付
|
||||
7. 支持微信小程序
|
||||
|
||||
>测试功能: 私有知识库
|
||||
|
||||
>项目地址
|
||||
<ul>
|
||||
<li>后端: https://gitee.com/ageerle/ruoyi-ai</li>
|
||||
<li>小程序端: https://gitee.com/ageerle/ruoyi-uniapp</li>
|
||||
<li>前端-后台管理: https://gitee.com/ageerle/ruoyi-admin</li>
|
||||
<li>前端-用户端: https://gitee.com/ageerle/ruoyi-web</li>
|
||||
<li>演示地址: web.pandarobot.chat</li>
|
||||
</ul>
|
||||
|
||||
|
||||
## 小程序演示
|
||||
<div>
|
||||
<img style="margin:10px" src="./image/03.png" alt="drawing" width="300px" height="400px"/>
|
||||
<img style="margin:10px" src="./image/04.png" alt="drawing" width="300px" height="400px"/>
|
||||
</div>
|
||||
|
||||
## H5演示
|
||||
<div>
|
||||
<img style="margin:10px" src="./image/05.png" alt="drawing" width="300px" height="400px"/>
|
||||
<img style="margin:10px" src="./image/06.png" alt="drawing" width="300px" height="400px"/>
|
||||
</div>
|
||||
|
||||
## PC端演示
|
||||
<div>
|
||||
<img style="margin-top:10px" src="./image/07.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px" src="./image/08.png" alt="drawing" width="550px" height="300px"/>
|
||||
</div>
|
||||
|
||||
## MJ绘图
|
||||
<div>
|
||||
<img style="margin-top:10px" src="./image/10.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px" src="./image/11.png" alt="drawing" width="550px" height="300px"/>
|
||||
</div>
|
||||
|
||||
## 微信智能助手
|
||||
<div>
|
||||
<img style="margin-top:10px" src="./image/09.png" alt="drawing" width="550px" height="300px"/>
|
||||
</div>
|
||||
|
||||
## 私有知识库管理(开发中)
|
||||
<div>
|
||||
<img style="margin-top:10px" src="./image/12.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px" src="./image/私有知识库业务架构图.drawio.png" alt="drawing" width="550px" height="300px"/>
|
||||
</div>
|
||||
|
||||
## 进群学习
|
||||
<div>
|
||||
<img src="./image/01.png" alt="drawing" width="300px" height="300px"/>
|
||||
<img src="./image/02.png" alt="drawing" width="300px" height="300px"/>
|
||||
</div>
|
||||
|
||||
|
||||
## 参考项目
|
||||
<ol>
|
||||
<li>https://github.com/Grt1228/chatgpt-java</li>
|
||||
<li>https://gitee.com/dromara/RuoYi-Vue-Plus</li>
|
||||
</ol>
|
||||
|
||||
BIN
image/01.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
image/02.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
image/03.png
Normal file
|
After Width: | Height: | Size: 674 KiB |
BIN
image/04.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
image/05.png
Normal file
|
After Width: | Height: | Size: 918 KiB |
BIN
image/06.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
image/07.png
Normal file
|
After Width: | Height: | Size: 184 KiB |
BIN
image/08.png
Normal file
|
After Width: | Height: | Size: 532 KiB |
BIN
image/09.png
Normal file
|
After Width: | Height: | Size: 184 KiB |
BIN
image/10.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
image/11.png
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
image/12.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
image/私有知识库业务架构图.drawio.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
471
pom.xml
Normal file
@@ -0,0 +1,471 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-ai</artifactId>
|
||||
<version>${revision}</version>
|
||||
|
||||
<name>ruoyi-ai</name>
|
||||
<url>https://gitee.com/ageerle/ruoyi-ai</url>
|
||||
<description>AI助手后台管理系统</description>
|
||||
|
||||
<properties>
|
||||
<revision>1.0.0</revision>
|
||||
<spring-boot.version>3.0.6</spring-boot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
<spring-boot.mybatis>3.0.1</spring-boot.mybatis>
|
||||
<springdoc.version>2.1.0</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>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<satoken.version>1.34.0</satoken.version>
|
||||
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<hutool.version>5.8.18</hutool.version>
|
||||
<okhttp.version>4.10.0</okhttp.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>
|
||||
<dynamic-ds.version>3.6.1</dynamic-ds.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>
|
||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||
<lombok.version>1.18.26</lombok.version>
|
||||
<bouncycastle.version>1.72</bouncycastle.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
|
||||
<!-- 临时修复 snakeyaml 漏洞 -->
|
||||
<snakeyaml.version>1.33</snakeyaml.version>
|
||||
|
||||
<!-- OSS 配置 -->
|
||||
<aws-java-sdk-s3.version>1.12.400</aws-java-sdk-s3.version>
|
||||
<!-- SMS 配置 -->
|
||||
<aliyun.sms.version>2.0.23</aliyun.sms.version>
|
||||
<tencent.sms.version>3.1.687</tencent.sms.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>
|
||||
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
|
||||
<weixin-java-miniapp.version>4.5.0</weixin-java-miniapp.version>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>local</id>
|
||||
<properties>
|
||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||
<profiles.active>local</profiles.active>
|
||||
<logging.level>debug</logging.level>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
<properties>
|
||||
<!-- 环境标识,需要与配置文件的名称相对应 -->
|
||||
<profiles.active>dev</profiles.active>
|
||||
<logging.level>debug</logging.level>
|
||||
</properties>
|
||||
<activation>
|
||||
<!-- 默认环境 -->
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>prod</id>
|
||||
<properties>
|
||||
<profiles.active>prod</profiles.active>
|
||||
<logging.level>warn</logging.level>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- SpringBoot的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool 的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-bom</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- common 的依赖配置-->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-bom</artifactId>
|
||||
<version>${revision}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.therapi</groupId>
|
||||
<artifactId>therapi-runtime-javadoc</artifactId>
|
||||
<version>${therapi-javadoc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</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>
|
||||
</dependency>
|
||||
|
||||
<!-- velocity代码生成使用模板 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
<version>${velocity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>${satoken.version}</version>
|
||||
</dependency>
|
||||
<!-- Sa-Token 整合 jwt -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-jwt</artifactId>
|
||||
<version>${satoken.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
<version>${satoken.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- dynamic-datasource 多数据源-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic-ds.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>${spring-boot.mybatis}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-annotation</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sql性能分析插件 -->
|
||||
<dependency>
|
||||
<groupId>p6spy</groupId>
|
||||
<artifactId>p6spy</artifactId>
|
||||
<version>${p6spy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>${aws-java-sdk-s3.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>dysmsapi20170525</artifactId>
|
||||
<version>${aliyun.sms.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||
<version>${tencent.sms.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||
<version>${spring-boot-admin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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>
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||
<version>${lock4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- xxl-job-core -->
|
||||
<dependency>
|
||||
<groupId>com.xuxueli</groupId>
|
||||
<artifactId>xxl-job-core</artifactId>
|
||||
<version>${xxl-job.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId>
|
||||
<version>${alibaba-ttl.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 临时修复 snakeyaml 漏洞 -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>${snakeyaml.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 加密包引入 -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15to18</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.linpeilie</groupId>
|
||||
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
|
||||
<version>${mapstruct-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 离线IP地址定位库 ip2region -->
|
||||
<dependency>
|
||||
<groupId>org.lionsoul</groupId>
|
||||
<artifactId>ip2region</artifactId>
|
||||
<version>${ip2region.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-job</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-demo</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-admin</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ruoyi-modules</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.verison}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>com.github.therapi</groupId>
|
||||
<artifactId>therapi-runtime-javadoc-scribe</artifactId>
|
||||
<version>${therapi-javadoc.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>io.github.linpeilie</groupId>
|
||||
<artifactId>mapstruct-plus-processor</artifactId>
|
||||
<version>${mapstruct-plus.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>${mapstruct-plus.lombok.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 单元测试使用 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<!-- 根据打包环境执行对应的@Tag测试方法 -->
|
||||
<groups>${profiles.active}</groups>
|
||||
<!-- 排除标签 -->
|
||||
<excludedGroups>exclude</excludedGroups>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 统一版本号管理 -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>flatten-maven-plugin</artifactId>
|
||||
<version>${flatten-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<updatePomFile>true</updatePomFile>
|
||||
<flattenMode>resolveCiFriendliesOnly</flattenMode>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>flatten</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>flatten</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>flatten.clean</id>
|
||||
<phase>clean</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<!-- 关闭过滤 -->
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<!-- 引入所有 匹配文件进行过滤 -->
|
||||
<includes>
|
||||
<include>application*</include>
|
||||
<include>bootstrap*</include>
|
||||
<include>banner*</include>
|
||||
</includes>
|
||||
<!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>https://maven.aliyun.com/repository/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>https://maven.aliyun.com/repository/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
||||
|
||||
23
ruoyi-admin/Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
||||
FROM findepi/graalvm:java17-native
|
||||
|
||||
MAINTAINER Lion Li
|
||||
|
||||
RUN mkdir -p /ruoyi/server/logs \
|
||||
/ruoyi/server/temp \
|
||||
/ruoyi/skywalking/agent
|
||||
|
||||
WORKDIR /ruoyi/server
|
||||
|
||||
ENV SERVER_PORT=8080
|
||||
|
||||
EXPOSE ${SERVER_PORT}
|
||||
|
||||
ADD ./target/ruoyi-admin.jar ./app.jar
|
||||
|
||||
ENTRYPOINT ["java", \
|
||||
"-Djava.security.egd=file:/dev/./urandom", \
|
||||
"-Dserver.port=${SERVER_PORT}", \
|
||||
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
|
||||
# "-Dskywalking.agent.service_name=ruoyi-server", \
|
||||
# "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \
|
||||
"-jar", "app.jar"]
|
||||
138
ruoyi-admin/pom.xml
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>com.xmzs</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>ruoyi-admin</artifactId>
|
||||
|
||||
<description>
|
||||
web服务入口
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<!-- Oracle -->
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</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.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-doc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-chat</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- demo模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-demo</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>-->
|
||||
|
||||
<!-- 添加thumbnailator依赖 -->
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>0.4.11</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<warName>${project.artifactId}</warName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
23
ruoyi-admin/src/main/java/com/xmzs/PandaApplication.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.xmzs;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@SpringBootApplication
|
||||
public class PandaApplication {
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(PandaApplication.class);
|
||||
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||
application.run(args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ panda智能助手启动成功 ლ(´ڡ`ლ)゙");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.xmzs;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
|
||||
/**
|
||||
* web容器中进行部署
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class PandaServletInitializer extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(PandaApplication.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.xmzs.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.xmzs.common.core.constant.Constants;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.core.domain.model.*;
|
||||
import com.xmzs.common.core.utils.MapstructUtils;
|
||||
import com.xmzs.common.core.utils.StreamUtils;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
import com.xmzs.common.satoken.utils.LoginHelper;
|
||||
import com.xmzs.common.tenant.helper.TenantHelper;
|
||||
import com.xmzs.system.domain.bo.SysTenantBo;
|
||||
import com.xmzs.system.domain.vo.LoginTenantVo;
|
||||
import com.xmzs.system.domain.vo.SysTenantVo;
|
||||
import com.xmzs.system.domain.vo.TenantListVo;
|
||||
import com.xmzs.system.service.ISysTenantService;
|
||||
|
||||
|
||||
import com.xmzs.system.service.SysLoginService;
|
||||
import com.xmzs.system.service.SysRegisterService;
|
||||
import com.xmzs.web.domain.vo.LoginVo;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 认证
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
private final SysLoginService loginService;
|
||||
private final SysRegisterService registerService;
|
||||
private final ISysTenantService tenantService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @return 结果
|
||||
*/
|
||||
@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.setUserInfo(LoginHelper.getLoginUser());
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信登录
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件登录
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 游客登录
|
||||
*
|
||||
* @param loginBody
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/visitorLogin")
|
||||
public R<LoginVo> xcxLogin(@RequestBody VisitorLoginBody loginBody) {
|
||||
return R.ok(loginService.visitorLogin(loginBody));
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public R<Void> logout() {
|
||||
loginService.logout();
|
||||
return R.ok("退出成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
@PostMapping("/register")
|
||||
public R<Void> register(@Validated @RequestBody RegisterBody user) {
|
||||
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 租户列表
|
||||
*/
|
||||
@GetMapping("/tenant/list")
|
||||
public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
|
||||
List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
|
||||
List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
|
||||
// 获取域名
|
||||
String 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.xmzs.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.captcha.AbstractCaptcha;
|
||||
import cn.hutool.captcha.generator.CodeGenerator;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.xmzs.common.core.constant.Constants;
|
||||
import com.xmzs.common.core.constant.GlobalConstants;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.core.utils.SpringUtils;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
import com.xmzs.common.core.utils.reflect.ReflectUtils;
|
||||
import com.xmzs.common.mail.config.properties.MailProperties;
|
||||
import com.xmzs.common.mail.utils.MailUtils;
|
||||
import com.xmzs.common.redis.utils.RedisUtils;
|
||||
import com.xmzs.common.sms.config.properties.SmsProperties;
|
||||
import com.xmzs.common.sms.core.SmsTemplate;
|
||||
import com.xmzs.common.sms.entity.SmsResult;
|
||||
import com.xmzs.common.web.config.properties.CaptchaProperties;
|
||||
import com.xmzs.common.web.enums.CaptchaType;
|
||||
import com.xmzs.web.domain.request.EmailRequest;
|
||||
import com.xmzs.web.domain.vo.CaptchaVo;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 验证码操作处理
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class CaptchaController {
|
||||
|
||||
private final CaptchaProperties captchaProperties;
|
||||
private final SmsProperties smsProperties;
|
||||
private final MailProperties mailProperties;
|
||||
|
||||
/**
|
||||
* 短信验证码
|
||||
*
|
||||
* @param phonenumber 用户手机号
|
||||
*/
|
||||
@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 自行处理 (查数据库或写死均可)
|
||||
String templateId = "";
|
||||
Map<String, String> map = new HashMap<>(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());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱验证码
|
||||
*
|
||||
* @param emailRequest 用户邮箱
|
||||
*/
|
||||
@PostMapping("/resource/email/code")
|
||||
public R<Void> emailCode(@RequestBody @Valid EmailRequest emailRequest) {
|
||||
if (!mailProperties.getEnabled()) {
|
||||
return R.fail("当前系统没有开启邮箱功能!");
|
||||
}
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + emailRequest.getUsername();
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
try {
|
||||
MailUtils.sendText(emailRequest.getUsername(), "【GPT助手】登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
|
||||
} catch (Exception e) {
|
||||
log.error("验证码短信发送异常 => {}", e.getMessage());
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*/
|
||||
@GetMapping("/code")
|
||||
public R<CaptchaVo> getCode() {
|
||||
CaptchaVo captchaVo = new CaptchaVo();
|
||||
boolean captchaEnabled = captchaProperties.getEnable();
|
||||
if (!captchaEnabled) {
|
||||
captchaVo.setCaptchaEnabled(false);
|
||||
return R.ok(captchaVo);
|
||||
}
|
||||
// 保存验证码信息
|
||||
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);
|
||||
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
||||
captcha.setGenerator(codeGenerator);
|
||||
captcha.createCode();
|
||||
String code = captcha.getCode();
|
||||
if (isMath) {
|
||||
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.setUuid(uuid);
|
||||
captchaVo.setImg(captcha.getImageBase64());
|
||||
return R.ok(captchaVo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.xmzs.controller;
|
||||
|
||||
|
||||
import com.xmzs.common.chat.domain.request.ChatRequest;
|
||||
import com.xmzs.common.chat.domain.request.Dall3Request;
|
||||
import com.xmzs.common.chat.entity.images.Item;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.core.domain.model.LoginUser;
|
||||
import com.xmzs.common.core.exception.base.BaseException;
|
||||
import com.xmzs.common.mybatis.core.page.PageQuery;
|
||||
import com.xmzs.common.mybatis.core.page.TableDataInfo;
|
||||
import com.xmzs.common.satoken.utils.LoginHelper;
|
||||
import com.xmzs.system.domain.bo.ChatMessageBo;
|
||||
import com.xmzs.system.domain.vo.ChatMessageVo;
|
||||
import com.xmzs.system.service.IChatMessageService;
|
||||
import com.xmzs.system.service.SseService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @date 2023-03-01
|
||||
*/
|
||||
@Controller
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ChatController {
|
||||
|
||||
private final SseService sseService;
|
||||
|
||||
private final IChatMessageService chatMessageService;
|
||||
|
||||
/**
|
||||
* 聊天接口
|
||||
*/
|
||||
@PostMapping("/chat")
|
||||
@ResponseBody
|
||||
public SseEmitter sseChat(@RequestBody @Valid ChatRequest chatRequest) {
|
||||
if("gpt-4-all".equals(chatRequest.getModel())
|
||||
|| chatRequest.getModel().startsWith("gpt-4-gizmo")
|
||||
|| chatRequest.getModel().startsWith("net-")
|
||||
){
|
||||
return sseService.transitChat(chatRequest);
|
||||
}
|
||||
if("azure-gpt-3.5".equals(chatRequest.getModel())){
|
||||
return sseService.azureChat(chatRequest);
|
||||
}
|
||||
return sseService.sseChat(chatRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/dall3")
|
||||
@ResponseBody
|
||||
public R<List<Item>> dall3(@RequestBody @Valid Dall3Request request) {
|
||||
return R.ok(sseService.dall3(request));
|
||||
}
|
||||
|
||||
@PostMapping("/mjTask")
|
||||
@ResponseBody
|
||||
public R<String> mjTask() {
|
||||
sseService.mjTask();
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 聊天记录
|
||||
*/
|
||||
@PostMapping("/chatList")
|
||||
@ResponseBody
|
||||
public R<TableDataInfo<ChatMessageVo>> list(@RequestBody @Valid ChatMessageBo chatRequest,@RequestBody PageQuery pageQuery) {
|
||||
// 默认查询当前登录用户消息记录
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new BaseException("用户未登录!");
|
||||
}
|
||||
chatRequest.setUserId(loginUser.getUserId());
|
||||
TableDataInfo<ChatMessageVo> chatMessageVoTableDataInfo = chatMessageService.queryPageList(chatRequest, pageQuery);
|
||||
return R.ok(chatMessageVoTableDataInfo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xmzs.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* 首页
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
||||
|
||||
/**
|
||||
* 访问首页,提示语
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
return "index.html";
|
||||
}
|
||||
}
|
||||
151
ruoyi-admin/src/main/java/com/xmzs/controller/PayController.java
Normal file
@@ -0,0 +1,151 @@
|
||||
package com.xmzs.controller;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import com.xmzs.common.config.PayConfig;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.core.domain.model.LoginUser;
|
||||
import com.xmzs.common.core.exception.base.BaseException;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
import com.xmzs.common.oss.core.OssClient;
|
||||
import com.xmzs.common.oss.entity.UploadResult;
|
||||
import com.xmzs.common.oss.factory.OssFactory;
|
||||
import com.xmzs.common.response.PayResponse;
|
||||
import com.xmzs.common.satoken.utils.LoginHelper;
|
||||
import com.xmzs.common.service.PayService;
|
||||
import com.xmzs.common.utils.MD5Util;
|
||||
import com.xmzs.system.domain.bo.PaymentOrdersBo;
|
||||
import com.xmzs.system.domain.bo.SysUserBo;
|
||||
import com.xmzs.system.domain.request.OrderRequest;
|
||||
import com.xmzs.system.domain.vo.PaymentOrdersVo;
|
||||
import com.xmzs.system.domain.vo.SysUserVo;
|
||||
import com.xmzs.system.service.IPaymentOrdersService;
|
||||
import com.xmzs.system.service.ISysUserService;
|
||||
import com.xmzs.system.util.OrderNumberGenerator;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/pay")
|
||||
@Slf4j
|
||||
public class PayController {
|
||||
|
||||
private final PayService payService;
|
||||
|
||||
private final ISysUserService userService;
|
||||
|
||||
private final IPaymentOrdersService paymentOrdersService;
|
||||
|
||||
/**
|
||||
* 获取支付二维码
|
||||
*
|
||||
* @Date 2023/7/3
|
||||
* @param response
|
||||
* @return void
|
||||
**/
|
||||
@PostMapping("/payUrl")
|
||||
public R<PaymentOrdersVo> payUrl(HttpServletResponse response, @RequestBody OrderRequest orderRequest) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
// 创建订单
|
||||
PaymentOrdersBo paymentOrders = new PaymentOrdersBo();
|
||||
paymentOrders.setOrderName(orderRequest.getName());
|
||||
paymentOrders.setAmount(new BigDecimal(orderRequest.getMoney()));
|
||||
String orderNo = OrderNumberGenerator.generate();
|
||||
paymentOrders.setOrderNo(orderNo);
|
||||
paymentOrders.setUserId(loginUser.getUserId());
|
||||
// TODO 支付状态默认待支付 - 添加枚举
|
||||
paymentOrders.setPaymentStatus("1");
|
||||
paymentOrdersService.insertByBo(paymentOrders);
|
||||
String payUrl = payService.getPayUrl(orderNo, orderRequest.getName(), Double.parseDouble(orderRequest.getMoney()), "192.168.1.6");
|
||||
byte[] bytes = QrCodeUtil.generatePng(payUrl, 300, 300);
|
||||
OssClient storage = OssFactory.instance();
|
||||
UploadResult upload=storage.upload(bytes, storage.getPath("qrCode",".png"), "image/png");
|
||||
PaymentOrdersVo paymentOrdersVo = new PaymentOrdersVo();
|
||||
BeanUtil.copyProperties(paymentOrders,paymentOrdersVo);
|
||||
paymentOrdersVo.setUrl(upload.getUrl());
|
||||
return R.ok(paymentOrdersVo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 跳转通知地址
|
||||
*
|
||||
* @Date 2023/7/3
|
||||
* @param
|
||||
* @return void
|
||||
**/
|
||||
@PostMapping("/notifyUrl")
|
||||
public void notifyUrl() {
|
||||
log.info("notifyUrl===========");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单信息
|
||||
*
|
||||
*/
|
||||
@PostMapping("/orderInfo")
|
||||
public R<PaymentOrdersVo> orderInfo(@RequestBody OrderRequest orderRequest) {
|
||||
if(StringUtils.isEmpty(orderRequest.getOrderNo())){
|
||||
throw new BaseException("订单号不能为空!");
|
||||
}
|
||||
PaymentOrdersBo paymentOrdersBo = new PaymentOrdersBo();
|
||||
paymentOrdersBo.setOrderNo(orderRequest.getOrderNo());
|
||||
List<PaymentOrdersVo> paymentOrdersList = paymentOrdersService.queryList(paymentOrdersBo);
|
||||
if (CollectionUtil.isEmpty(paymentOrdersList)){
|
||||
throw new BaseException("订单不存在!");
|
||||
}
|
||||
PaymentOrdersVo paymentOrdersVo = paymentOrdersList.get(0);
|
||||
return R.ok(paymentOrdersVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转通知地址
|
||||
*
|
||||
* @Date 2023/7/3
|
||||
* @param payResponse
|
||||
* @return void
|
||||
**/
|
||||
@GetMapping("/returnUrl")
|
||||
public String returnUrl(PayResponse payResponse) {
|
||||
// 校验签名
|
||||
String mdString = "money=" + payResponse.getMoney() + "&name=" + payResponse.getName() +
|
||||
"&out_trade_no=" + payResponse.getOut_trade_no() + "&pid=" + PayConfig.pid +
|
||||
"&trade_no=" + payResponse.getTrade_no() + "&trade_status=" + payResponse.getTrade_status() +
|
||||
"&type=" + payResponse.getType() + PayConfig.key;
|
||||
String sign = MD5Util.GetMD5Code(mdString);
|
||||
if(!sign.equals(payResponse.getSign())){
|
||||
throw new BaseException("校验签名失败!");
|
||||
}
|
||||
double money = Double.parseDouble(payResponse.getMoney());
|
||||
log.info("支付订单号{}",payResponse);
|
||||
PaymentOrdersBo paymentOrdersBo = new PaymentOrdersBo();
|
||||
paymentOrdersBo.setOrderNo(payResponse.getOut_trade_no());
|
||||
List<PaymentOrdersVo> paymentOrdersList = paymentOrdersService.queryList(paymentOrdersBo);
|
||||
if (CollectionUtil.isEmpty(paymentOrdersList)){
|
||||
throw new BaseException("订单不存在!");
|
||||
}
|
||||
// 订单状态修改为已支付
|
||||
PaymentOrdersVo paymentOrdersVo = paymentOrdersList.get(0);
|
||||
paymentOrdersVo.setPaymentStatus("2");
|
||||
paymentOrdersVo.setPaymentMethod(payResponse.getType());
|
||||
BeanUtil.copyProperties(paymentOrdersVo,paymentOrdersBo);
|
||||
paymentOrdersService.updateByBo(paymentOrdersBo);
|
||||
SysUserVo sysUserVo = userService.selectUserById(paymentOrdersVo.getUserId());
|
||||
sysUserVo.setUserBalance(sysUserVo.getUserBalance()+money);
|
||||
SysUserBo sysUserBo = new SysUserBo();
|
||||
BeanUtil.copyProperties(sysUserVo,sysUserBo);
|
||||
// 设置为付费用户
|
||||
sysUserBo.setUserGrade("1");
|
||||
userService.updateUser(sysUserBo);
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
150
ruoyi-admin/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,150 @@
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
username: ruoyi
|
||||
password: 123456
|
||||
|
||||
--- # xxl-job 配置
|
||||
xxl.job:
|
||||
# 执行器开关
|
||||
enabled: false
|
||||
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
|
||||
admin-addresses: http://localhost:9100/xxl-job-admin
|
||||
# 执行器通讯TOKEN:非空时启用
|
||||
access-token: xxl-job
|
||||
executor:
|
||||
# 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
|
||||
appname: xxl-job-executor
|
||||
# 执行器端口号 执行器从9101开始往后写
|
||||
port: 9101
|
||||
# 执行器注册:默认IP:PORT
|
||||
address:
|
||||
# 执行器IP:默认自动获取IP
|
||||
ip:
|
||||
# 执行器运行日志文件存储磁盘路径
|
||||
logpath: ./logs/xxl-job
|
||||
# 执行器日志文件保存天数:大于3生效
|
||||
logretentiondays: 30
|
||||
|
||||
--- # 数据源配置
|
||||
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/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: ry-vue
|
||||
password: ry-vue
|
||||
|
||||
# 从库数据源
|
||||
# slave:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
# username:
|
||||
# password:
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||
# username: ROOT
|
||||
# password: root
|
||||
# hikari:
|
||||
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||
# postgres:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||
# username: root
|
||||
# password: root
|
||||
# sqlserver:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||
# username: SA
|
||||
# password: root
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
maxPoolSize: 20
|
||||
# 最小空闲线程数量
|
||||
minIdle: 10
|
||||
# 配置获取连接等待超时的时间
|
||||
connectionTimeout: 30000
|
||||
# 校验超时时间
|
||||
validationTimeout: 5000
|
||||
# 空闲连接存活最大时间,默认10分钟
|
||||
idleTimeout: 600000
|
||||
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
|
||||
maxLifetime: 1800000
|
||||
# 连接测试query(配置检测连接是否有效)
|
||||
connectionTestQuery: SELECT 1
|
||||
# 多久检查一次连接的活性
|
||||
keepaliveTime: 30000
|
||||
|
||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||
spring.data:
|
||||
redis:
|
||||
# 地址
|
||||
host: localhost
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码(如没有密码请注释掉)
|
||||
# password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
# 是否开启ssl
|
||||
ssl: false
|
||||
|
||||
redisson:
|
||||
# redis key前缀
|
||||
keyPrefix:
|
||||
# 线程池数量
|
||||
threads: 4
|
||||
# Netty线程池数量
|
||||
nettyThreads: 8
|
||||
# 单节点配置
|
||||
singleServerConfig:
|
||||
# 客户端名称
|
||||
clientName: ${ruoyi.name}
|
||||
# 最小空闲连接数
|
||||
connectionMinimumIdleSize: 8
|
||||
# 连接池大小
|
||||
connectionPoolSize: 32
|
||||
# 连接空闲超时,单位:毫秒
|
||||
idleConnectionTimeout: 10000
|
||||
# 命令等待超时,单位:毫秒
|
||||
timeout: 3000
|
||||
# 发布和订阅连接池大小
|
||||
subscriptionConnectionPoolSize: 50
|
||||
|
||||
--- # sms 短信
|
||||
sms:
|
||||
enabled: false
|
||||
# 阿里云 dysmsapi.aliyuncs.com
|
||||
# 腾讯云 sms.tencentcloudapi.com
|
||||
endpoint: "dysmsapi.aliyuncs.com"
|
||||
accessKeyId: xxxxxxx
|
||||
accessKeySecret: xxxxxx
|
||||
signName: 测试
|
||||
# 腾讯专用
|
||||
sdkAppId:
|
||||
174
ruoyi-admin/src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,174 @@
|
||||
--- # 临时文件存储位置 避免临时文件被系统清理报错
|
||||
spring.servlet.multipart.location: /ruoyi/server/temp
|
||||
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
username: ruoyi
|
||||
password: 123456
|
||||
|
||||
--- # xxl-job 配置
|
||||
xxl.job:
|
||||
# 执行器开关
|
||||
enabled: false
|
||||
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
|
||||
admin-addresses: http://localhost:9100/xxl-job-admin
|
||||
# 执行器通讯TOKEN:非空时启用
|
||||
access-token: xxl-job
|
||||
executor:
|
||||
# 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
|
||||
appname: xxl-job-executor
|
||||
# 执行器端口号 执行器从9101开始往后写
|
||||
port: 9101
|
||||
# 执行器注册:默认IP:PORT
|
||||
address:
|
||||
# 执行器IP:默认自动获取IP
|
||||
ip:
|
||||
# 执行器运行日志文件存储磁盘路径
|
||||
logpath: ./logs/xxl-job
|
||||
# 执行器日志文件保存天数:大于3生效
|
||||
logretentiondays: 30
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
||||
dynamic:
|
||||
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
||||
p6spy: false
|
||||
# 设置默认的数据源或者数据源组,默认值即为 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://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: root
|
||||
# 从库数据源
|
||||
slave:
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username:
|
||||
password:
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||
# username: ROOT
|
||||
# password: root
|
||||
# hikari:
|
||||
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||
# postgres:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||
# username: root
|
||||
# password: root
|
||||
# sqlserver:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||
# username: SA
|
||||
# password: root
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
maxPoolSize: 20
|
||||
# 最小空闲线程数量
|
||||
minIdle: 10
|
||||
# 配置获取连接等待超时的时间
|
||||
connectionTimeout: 30000
|
||||
# 校验超时时间
|
||||
validationTimeout: 5000
|
||||
# 空闲连接存活最大时间,默认10分钟
|
||||
idleTimeout: 600000
|
||||
# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
|
||||
maxLifetime: 1800000
|
||||
# 连接测试query(配置检测连接是否有效)
|
||||
connectionTestQuery: SELECT 1
|
||||
# 多久检查一次连接的活性
|
||||
keepaliveTime: 30000
|
||||
|
||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||
spring.data:
|
||||
redis:
|
||||
# 地址
|
||||
host: localhost
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码(如没有密码请注释掉)
|
||||
# password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
# 是否开启ssl
|
||||
ssl: false
|
||||
|
||||
redisson:
|
||||
# redis key前缀
|
||||
keyPrefix:
|
||||
# 线程池数量
|
||||
threads: 16
|
||||
# Netty线程池数量
|
||||
nettyThreads: 32
|
||||
# 单节点配置
|
||||
singleServerConfig:
|
||||
# 客户端名称
|
||||
clientName: ${ruoyi.name}
|
||||
# 最小空闲连接数
|
||||
connectionMinimumIdleSize: 32
|
||||
# 连接池大小
|
||||
connectionPoolSize: 64
|
||||
# 连接空闲超时,单位:毫秒
|
||||
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 短信
|
||||
sms:
|
||||
enabled: false
|
||||
# 阿里云 dysmsapi.aliyuncs.com
|
||||
# 腾讯云 sms.tencentcloudapi.com
|
||||
endpoint: "dysmsapi.aliyuncs.com"
|
||||
accessKeyId: xxxxxxx
|
||||
accessKeySecret: xxxxxx
|
||||
signName: 测试
|
||||
# 腾讯专用
|
||||
sdkAppId:
|
||||
345
ruoyi-admin/src/main/resources/application.yml
Normal file
@@ -0,0 +1,345 @@
|
||||
# 项目相关配置
|
||||
ruoyi:
|
||||
# 名称
|
||||
name: "xmzs"
|
||||
# 版本
|
||||
version: ${revision}
|
||||
# 版权年份
|
||||
copyrightYear: 2023
|
||||
# 实例演示开关
|
||||
demoEnabled: true
|
||||
# 获取ip地址开关
|
||||
addressEnabled: false
|
||||
|
||||
captcha:
|
||||
enable: false
|
||||
# 页面 <参数设置> 可开启关闭 验证码校验
|
||||
# 验证码类型 math 数组计算 char 字符验证
|
||||
type: MATH
|
||||
# line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
|
||||
category: CIRCLE
|
||||
# 数字验证码位数
|
||||
numberLength: 1
|
||||
# 字符验证码长度
|
||||
charLength: 4
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
# 服务器的HTTP端口,默认为8080
|
||||
port: 6039
|
||||
servlet:
|
||||
# 应用的访问路径
|
||||
context-path: /
|
||||
# undertow 配置
|
||||
undertow:
|
||||
# HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的
|
||||
max-http-post-size: -1
|
||||
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
|
||||
# 每块buffer的空间大小,越小的空间被利用越充分
|
||||
buffer-size: 512
|
||||
# 是否分配的直接内存
|
||||
direct-buffers: true
|
||||
threads:
|
||||
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
|
||||
io: 8
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
|
||||
worker: 256
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
com.xmzs: @logging.level@
|
||||
org.springframework: warn
|
||||
config: classpath:logback-plus.xml
|
||||
|
||||
# 用户配置
|
||||
user:
|
||||
password:
|
||||
# 密码最大错误次数
|
||||
maxRetryCount: 5
|
||||
# 密码锁定时间(默认10分钟)
|
||||
lockTime: 10
|
||||
|
||||
# Spring配置
|
||||
spring:
|
||||
application:
|
||||
name: ${ruoyi.name}
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
basename: i18n/messages
|
||||
profiles:
|
||||
active: @profiles.active@
|
||||
# 文件上传
|
||||
servlet:
|
||||
multipart:
|
||||
# 单个文件大小
|
||||
max-file-size: 10MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 20MB
|
||||
mvc:
|
||||
format:
|
||||
date-time: yyyy-MM-dd HH:mm:ss
|
||||
jackson:
|
||||
# 日期格式化
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
serialization:
|
||||
# 格式化输出
|
||||
indent_output: false
|
||||
# 忽略无法转换的对象
|
||||
fail_on_empty_beans: false
|
||||
deserialization:
|
||||
# 允许对象忽略json中不存在的属性
|
||||
fail_on_unknown_properties: false
|
||||
|
||||
# Sa-Token配置
|
||||
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
|
||||
|
||||
# security配置
|
||||
security:
|
||||
# 排除路径
|
||||
excludes:
|
||||
# 修改用户头像
|
||||
- /system/user/edit/avatar
|
||||
- /pay/returnUrl
|
||||
- /pay/notifyUrl
|
||||
# 上传文件
|
||||
- /resource/oss/upload
|
||||
# 重置密码
|
||||
- /auth/reset/password
|
||||
# 聊天接口
|
||||
- /chat
|
||||
# 静态资源
|
||||
- /*.html
|
||||
- /**/*.html
|
||||
- /**/*.css
|
||||
- /**/*.js
|
||||
# 公共路径
|
||||
- /favicon.ico
|
||||
- /error
|
||||
# swagger 文档配置
|
||||
- /*/api-docs
|
||||
- /*/api-docs/**
|
||||
# actuator 监控配置
|
||||
- /actuator
|
||||
- /actuator/**
|
||||
# 多租户配置
|
||||
tenant:
|
||||
# 是否开启
|
||||
enable: false
|
||||
# 排除表
|
||||
excludes:
|
||||
- sys_menu
|
||||
- sys_tenant
|
||||
- sys_tenant_package
|
||||
- sys_role_dept
|
||||
- sys_role_menu
|
||||
- sys_user_post
|
||||
- sys_user_role
|
||||
|
||||
# MyBatisPlus配置
|
||||
# https://baomidou.com/config/
|
||||
mybatis-plus:
|
||||
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
|
||||
# 例如 com.**.**.mapper
|
||||
mapperPackage: com.xmzs.**.mapper
|
||||
# 对应的 XML 文件位置
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 实体扫描,多个package用逗号或者分号分隔
|
||||
typeAliasesPackage: com.xmzs.**.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.nologging.NoLoggingImpl
|
||||
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:
|
||||
# 是否开启加密
|
||||
enable: false
|
||||
# 默认加密算法
|
||||
algorithm: BASE64
|
||||
# 编码方式 BASE64/HEX。默认BASE64
|
||||
encode: BASE64
|
||||
# 安全秘钥 对称算法的秘钥 如:AES,SM4
|
||||
password:
|
||||
# 公私钥 非对称算法的公私钥 如:SM2,RSA
|
||||
publicKey:
|
||||
privateKey:
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: true
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: xxx@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: xxx@163.com
|
||||
# 密码(填写授权码)
|
||||
pass: pass
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
|
||||
# Swagger配置
|
||||
swagger:
|
||||
info:
|
||||
# 标题
|
||||
title: '标题:${ruoyi.name}多租户管理系统_接口文档'
|
||||
# 描述
|
||||
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
|
||||
# 版本
|
||||
version: '版本号: ${ruoyi.version}'
|
||||
# 作者信息
|
||||
contact:
|
||||
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}
|
||||
|
||||
springdoc:
|
||||
api-docs:
|
||||
# 是否开启接口文档
|
||||
enabled: true
|
||||
swagger-ui:
|
||||
# 持久化认证数据
|
||||
persistAuthorization: true
|
||||
#这里定义了两个分组,可定义多个,也可以不定义
|
||||
group-configs:
|
||||
- group: 1.演示模块
|
||||
packages-to-scan: com.xmzs.demo
|
||||
- group: 2.通用模块
|
||||
packages-to-scan: com.xmzs.web
|
||||
- group: 3.系统模块
|
||||
packages-to-scan: com.xmzs.system
|
||||
- group: 4.代码生成模块
|
||||
packages-to-scan: com.xmzs.generator
|
||||
|
||||
# 防止XSS攻击
|
||||
xss:
|
||||
# 过滤开关
|
||||
enabled: true
|
||||
# 排除链接(多个用逗号分隔)
|
||||
excludes: /system/notice
|
||||
# 匹配链接
|
||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||
|
||||
# 全局线程池相关配置
|
||||
thread-pool:
|
||||
# 是否开启线程池
|
||||
enabled: false
|
||||
# 队列最大长度
|
||||
queueCapacity: 128
|
||||
# 线程池维护线程所允许的空闲时间
|
||||
keepAliveSeconds: 300
|
||||
|
||||
--- # 分布式锁 lock4j 全局配置
|
||||
lock4j:
|
||||
# 获取分布式锁超时时间,默认为 3000 毫秒
|
||||
acquire-timeout: 3000
|
||||
# 分布式锁的超时时间,默认为 30 秒
|
||||
expire: 30000
|
||||
|
||||
--- # Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
endpoint:
|
||||
health:
|
||||
show-details: ALWAYS
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
|
||||
--- # websocket
|
||||
websocket:
|
||||
enabled: true
|
||||
# 路径
|
||||
path: ''
|
||||
# 设置访问源地址
|
||||
allowedOrigins: '*'
|
||||
# AI助手配置信息
|
||||
chat:
|
||||
apiKey: ''
|
||||
apiHost: ''
|
||||
# 中转接口
|
||||
transit:
|
||||
apiKey: ''
|
||||
apiHost: 'https://api.gptgod.online/'
|
||||
# 微信小程序配置信息
|
||||
wx:
|
||||
miniapp:
|
||||
configs:
|
||||
- appid: # 你的appid
|
||||
secret: # 你的secret
|
||||
token: #微信小程序消息服务器配置的token
|
||||
aesKey: #微信小程序消息服务器配置的EncodingAESKey
|
||||
msgDataFormat: JSON
|
||||
baidu:
|
||||
# 是否开启文本审核
|
||||
enabled: false
|
||||
# 文本审核
|
||||
textReview:
|
||||
apiKey: '' # apiKey
|
||||
secretKey: '' # secretKey
|
||||
|
||||
9
ruoyi-admin/src/main/resources/banner.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
Application Version: ${revision}
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
██ ██ ██ ██
|
||||
██████ ░██ ░██ ░██ █████ ██████ ░██
|
||||
░██░░░██ ██████ ███████ ░██ ██████ █████ ░██ ██████ ██████ ██░░░██░██░░░██ ██████
|
||||
░██ ░██ ░░░░░░██ ░░██░░░██ ██████ ░░░░░░██ █████ ██░░░██░██████ ░░░░░░██ ░░░██░ ░██ ░██░██ ░██░░░██░
|
||||
░██████ ███████ ░██ ░██ ██░░░██ ███████ ░░░░░ ░██ ░░ ░██░░░██ ███████ ░██ ░░██████░██████ ░██
|
||||
░██░░░ ██░░░░██ ░██ ░██░██ ░██ ██░░░░██ ░██ ██░██ ░██ ██░░░░██ ░██ ░░░░░██░██░░░ ░██
|
||||
░██ ░░████████ ███ ░██░░██████░░████████ ░░█████ ░██ ░██░░████████ ░░██ █████ ░██ ░░██
|
||||
54
ruoyi-admin/src/main/resources/i18n/messages.properties
Normal file
@@ -0,0 +1,54 @@
|
||||
#错误消息
|
||||
not.null=* 必须填写
|
||||
user.jcaptcha.error=验证码错误
|
||||
user.jcaptcha.expire=验证码已失效
|
||||
user.not.exists=对不起, 您的账号:{0} 不存在.
|
||||
user.password.not.match=用户不存在/密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
|
||||
user.password.delete=对不起,您的账号:{0} 已被删除
|
||||
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
user.logout.success=退出成功
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
user.username.not.blank=用户名不能为空
|
||||
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
|
||||
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
|
||||
user.password.not.blank=用户密码不能为空
|
||||
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
|
||||
user.password.not.valid=* 5-50个字符
|
||||
user.email.not.valid=邮箱格式错误
|
||||
user.email.not.blank=邮箱不能为空
|
||||
user.phonenumber.not.blank=用户手机号不能为空
|
||||
user.mobile.phone.number.not.valid=手机号格式错误
|
||||
user.login.success=登录成功
|
||||
user.register.success=注册成功
|
||||
user.register.save.error=保存用户 {0} 失败,注册账号已存在
|
||||
user.register.error=注册失败,请联系系统管理人员
|
||||
user.notfound=请重新登录
|
||||
user.forcelogout=管理员强制退出,请重新登录
|
||||
user.unknown.error=未知错误,请重新登录
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
|
||||
upload.filename.exceed.length=上传的文件名最长{0}个字符
|
||||
##权限
|
||||
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
|
||||
repeat.submit.message=不允许重复提交,请稍候再试
|
||||
rate.limiter.message=访问过于频繁,请稍候再试
|
||||
sms.code.not.blank=短信验证码不能为空
|
||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
||||
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不能为空
|
||||
##租户
|
||||
tenant.number.not.blank=租户编号不能为空
|
||||
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
|
||||
tenant.blocked=对不起,您的租户已禁用,请联系管理员
|
||||
tenant.expired=对不起,您的租户已过期,请联系管理员
|
||||
@@ -0,0 +1,54 @@
|
||||
#错误消息
|
||||
not.null=* Required fill in
|
||||
user.jcaptcha.error=Captcha error
|
||||
user.jcaptcha.expire=Captcha invalid
|
||||
user.not.exists=Sorry, your account: {0} does not exist
|
||||
user.password.not.match=User does not exist/Password error
|
||||
user.password.retry.limit.count=Password input error {0} times
|
||||
user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes
|
||||
user.password.delete=Sorry, your account:{0} has been deleted
|
||||
user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
|
||||
role.blocked=Role disabled,please contact administrators
|
||||
user.logout.success=Exit successful
|
||||
length.not.valid=The length must be between {min} and {max} characters
|
||||
user.username.not.blank=Username cannot be blank
|
||||
user.username.not.valid=* 2 to 20 chinese characters, letters, numbers or underscores, and must start with a non number
|
||||
user.username.length.valid=Account length must be between {min} and {max} characters
|
||||
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.email.not.valid=Mailbox format error
|
||||
user.email.not.blank=Mailbox cannot be blank
|
||||
user.phonenumber.not.blank=Phone number cannot be blank
|
||||
user.mobile.phone.number.not.valid=Phone number format error
|
||||
user.login.success=Login successful
|
||||
user.register.success=Register successful
|
||||
user.register.save.error=Failed to save user {0}, The registered account already exists
|
||||
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
|
||||
##文件上传消息
|
||||
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
|
||||
##权限
|
||||
no.permission=You do not have permission to the data,please contact your administrator to add permissions [{0}]
|
||||
no.create.permission=You do not have permission to create data,please contact your administrator to add permissions [{0}]
|
||||
no.update.permission=You do not have permission to modify data,please contact your administrator to add permissions [{0}]
|
||||
no.delete.permission=You do not have permission to delete data,please contact your administrator to add permissions [{0}]
|
||||
no.export.permission=You do not have permission to export data,please contact your administrator to add permissions [{0}]
|
||||
no.view.permission=You do not have permission to view data,please contact your administrator to add permissions [{0}]
|
||||
repeat.submit.message=Repeat submit is not allowed, please try again later
|
||||
rate.limiter.message=Visit too frequently, please try again later
|
||||
sms.code.not.blank=Sms code cannot be blank
|
||||
sms.code.retry.limit.count=Sms code input error {0} times
|
||||
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
|
||||
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
|
||||
##租户
|
||||
tenant.number.not.blank=Tenant number cannot be blank
|
||||
tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator
|
||||
tenant.blocked=Sorry, your tenant is disabled. Please contact the administrator
|
||||
tenant.expired=Sorry, your tenant has expired. Please contact the administrator.
|
||||
@@ -0,0 +1,54 @@
|
||||
#错误消息
|
||||
not.null=* 必须填写
|
||||
user.jcaptcha.error=验证码错误
|
||||
user.jcaptcha.expire=验证码已失效
|
||||
user.not.exists=对不起, 您的账号:{0} 不存在.
|
||||
user.password.not.match=用户不存在/密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
|
||||
user.password.delete=对不起,您的账号:{0} 已被删除
|
||||
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
user.logout.success=退出成功
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
user.username.not.blank=用户名不能为空
|
||||
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
|
||||
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
|
||||
user.password.not.blank=用户密码不能为空
|
||||
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
|
||||
user.password.not.valid=* 5-50个字符
|
||||
user.email.not.valid=邮箱格式错误
|
||||
user.email.not.blank=邮箱不能为空
|
||||
user.phonenumber.not.blank=用户手机号不能为空
|
||||
user.mobile.phone.number.not.valid=手机号格式错误
|
||||
user.login.success=登录成功
|
||||
user.register.success=注册成功
|
||||
user.register.save.error=保存用户 {0} 失败,注册账号已存在
|
||||
user.register.error=注册失败,请联系系统管理人员
|
||||
user.notfound=请重新登录
|
||||
user.forcelogout=管理员强制退出,请重新登录
|
||||
user.unknown.error=未知错误,请重新登录
|
||||
##文件上传消息
|
||||
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
|
||||
upload.filename.exceed.length=上传的文件名最长{0}个字符
|
||||
##权限
|
||||
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
|
||||
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
|
||||
repeat.submit.message=不允许重复提交,请稍候再试
|
||||
rate.limiter.message=访问过于频繁,请稍候再试
|
||||
sms.code.not.blank=短信验证码不能为空
|
||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
|
||||
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不能为空
|
||||
##租户
|
||||
tenant.number.not.blank=租户编号不能为空
|
||||
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
|
||||
tenant.blocked=对不起,您的租户已禁用,请联系管理员
|
||||
tenant.expired=对不起,您的租户已过期,请联系管理员
|
||||
BIN
ruoyi-admin/src/main/resources/ip2region.xdb
Normal file
129
ruoyi-admin/src/main/resources/logback-plus.xml
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-console.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大 1天 -->
|
||||
<maxHistory>1</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- info异步输出 -->
|
||||
<appender name="async_info" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
||||
<queueSize>512</queueSize>
|
||||
<!-- 添加附加的appender,最多只能添加一个 -->
|
||||
<appender-ref ref="file_info"/>
|
||||
</appender>
|
||||
|
||||
<!-- error异步输出 -->
|
||||
<appender name="async_error" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
|
||||
<discardingThreshold>0</discardingThreshold>
|
||||
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
|
||||
<queueSize>512</queueSize>
|
||||
<!-- 添加附加的appender,最多只能添加一个 -->
|
||||
<appender-ref ref="file_error"/>
|
||||
</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>-->
|
||||
|
||||
<!-- 整合 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>-->
|
||||
|
||||
<!--系统操作日志-->
|
||||
<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"/>-->
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
1
ruoyi-admin/src/main/resources/spy.properties
Normal file
@@ -0,0 +1 @@
|
||||
exclude=SELECT 1
|
||||
BIN
ruoyi-admin/src/main/resources/static/1.jpg
Normal file
|
After Width: | Height: | Size: 469 KiB |
755
ruoyi-admin/src/main/resources/static/index.html
Normal file
@@ -0,0 +1,755 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>开发教程分享</title>
|
||||
<meta name="description" content="搜索">
|
||||
</head>
|
||||
<body>
|
||||
<!--header start-->
|
||||
<div class="header">
|
||||
<div class="h_top">
|
||||
<!--h_nav start-->
|
||||
<div class="h_nav">
|
||||
<ul>
|
||||
<li><a href="#">首页</a></li>
|
||||
<li><a href="#">课程</a></li>
|
||||
<li><a href="#">问答</a></li>
|
||||
<li><a href="#">专栏</a></li>
|
||||
<li><a href="#">论坛</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--end h_nav-->
|
||||
|
||||
<!--h_search start-->
|
||||
<div class="h_search">
|
||||
<input type="text" class="h_text">
|
||||
</div>
|
||||
<!--end h_search-->
|
||||
</div>
|
||||
</div>
|
||||
<!--end header-->
|
||||
|
||||
<!--banner start-->
|
||||
<div class="banner">
|
||||
<img src="1.jpg" width="70%;" height="80%;" id="img1">
|
||||
</div>
|
||||
<!--end banner-->
|
||||
|
||||
<!--menu start-->
|
||||
<div class="menu">
|
||||
<div class="m_con">
|
||||
|
||||
<div class="m_list">
|
||||
<h2>软件教程</h2>
|
||||
<ul>
|
||||
<li><a href="#">网页制作</a></li>
|
||||
<li><a href="#">Java</a></li>
|
||||
<li><a href="#">微信二次开发</a></li>
|
||||
<li><a href="#">C++</a></li>
|
||||
<li><a href="#">Android</a></li>
|
||||
<li><a href="#">iOS</a></li>
|
||||
<li><a href="#">PHP</a></li>
|
||||
<li><a href="#">游戏开发</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="m_list">
|
||||
<h2>技能学习</h2>
|
||||
<ul>
|
||||
<li><a href="#">网络营销</a></li>
|
||||
<li><a href="#">SEO</a></li>
|
||||
<li><a href="#">淘宝美工</a></li>
|
||||
<li><a href="#">影楼后期</a></li>
|
||||
<li><a href="#">淘宝运营</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="m_list">
|
||||
<h2>语言学习</h2>
|
||||
<ul>
|
||||
<li><a href="#">韩语</a></li>
|
||||
<li><a href="#">日语</a></li>
|
||||
<li><a href="#">泰语</a></li>
|
||||
<li><a href="#">西班牙语</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!--footer start-->
|
||||
<div class="footer">
|
||||
<div class="f_con">
|
||||
<div class="f_desc">
|
||||
<dl>
|
||||
<dt>关于我们</dt>
|
||||
<dd><a href="#">熊猫问问</a></dd>
|
||||
<dd><a href="#">加入我们</a></dd>
|
||||
<dd><a href="#">联系我们</a></dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>学习资讯</dt>
|
||||
<dd><a href="#">学习课程</a></dd>
|
||||
<dd><a href="#">就业指南</a></dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>服务中心</dt>
|
||||
<dd><a href="#">安卓APP</a></dd>
|
||||
<dd><a href="#">IOS APP</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="f_tel">
|
||||
<div class="f_time">
|
||||
<p class="f_phone">400-009-6359</p>
|
||||
<p class="f_price">
|
||||
<span>周一至周六 9:30-23:00</span>
|
||||
<span>(仅收市话费)</span>
|
||||
</p>
|
||||
<p class="f_mm">24小时在线客服</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--end footer-->
|
||||
|
||||
<!--copyright start-->
|
||||
<div class="copyright">
|
||||
Copyright © 2023-2023 版权所有:xmzs 备案号:<a href="https://beian.miit.gov.cn/">鄂ICP备2023007672号</a>
|
||||
</div>
|
||||
<!--end copyright-->
|
||||
|
||||
</body>
|
||||
|
||||
<style>
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img{
|
||||
margin-top: 10px;
|
||||
margin-left: 20%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 12px;
|
||||
font-family: "微软雅黑";
|
||||
color: #666;
|
||||
background: #eeeff3;
|
||||
}
|
||||
|
||||
/*header start*/
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
background: #15171f;
|
||||
}
|
||||
|
||||
.header .h_top {
|
||||
width: 1180px;
|
||||
height: 70px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header .h_top .h_logo {
|
||||
width: 220px;
|
||||
padding-top: 16px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
/*h_nav start*/
|
||||
.header .h_top .h_nav {
|
||||
width: 650px;
|
||||
height: 70px;
|
||||
float: left;
|
||||
color: #fff;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.header .h_top .h_nav ul li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.header .h_top .h_nav ul li a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
line-height: 70px;
|
||||
padding: 0 20px 0 20px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
margin: 0 5px 0 5px;
|
||||
}
|
||||
|
||||
.header .h_top .h_nav ul li a:hover {
|
||||
background: #323744;
|
||||
}
|
||||
|
||||
/*end h_nav*/
|
||||
|
||||
/*h_search start*/
|
||||
.header .h_top .h_search {
|
||||
width: 160px;
|
||||
height: 32px;
|
||||
border: 1px solid #323744;
|
||||
background: #323744;
|
||||
float: left;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.header .h_top .h_search:hover {
|
||||
border: 1px solid #818997;
|
||||
}
|
||||
|
||||
.header .h_top .h_search .h_text {
|
||||
width: 125px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
background: #323744;
|
||||
font-size: 14px;
|
||||
font-family: "微软雅黑";
|
||||
color: #fff;
|
||||
line-height: 32px;
|
||||
padding-left: 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.header .h_top .h_search .h_btn {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-top: 5px;
|
||||
background: url("picture/pe_icon.png") no-repeat -368px 0;
|
||||
}
|
||||
|
||||
/*end h_search*/
|
||||
|
||||
/*h_message start*/
|
||||
.header .h_top .h_message {
|
||||
width: 112px;
|
||||
height: 70px;
|
||||
float: left;
|
||||
margin-left: 34px;
|
||||
}
|
||||
|
||||
.header .h_top .h_message .h_info {
|
||||
width: 52px;
|
||||
height: 70px;
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header .h_top .h_message .h_info:hover {
|
||||
background: #323744;
|
||||
}
|
||||
|
||||
.header .h_top .h_message .h_info a {
|
||||
width: 22px;
|
||||
height: 16px;
|
||||
display: block;
|
||||
background: url("picture/pe_icon.png") no-repeat -368px -23px;
|
||||
margin: 26px auto;
|
||||
}
|
||||
|
||||
.header .h_top .h_message .h_info i {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
display: block;
|
||||
background: #eb6b83;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #FFF;
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: 34px;
|
||||
}
|
||||
|
||||
.header .h_top .h_message .h_pic a {
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.header .h_top .h_message .h_pic a img {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
/*end h_message*/
|
||||
|
||||
/*banner start*/
|
||||
.banner {
|
||||
width: 100%;
|
||||
height:60%;
|
||||
}
|
||||
|
||||
/*end banner*/
|
||||
|
||||
/*menu start*/
|
||||
.menu {
|
||||
width: 100%;
|
||||
height: 110px;
|
||||
border-bottom: 1px solid #d9dce1;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.menu .m_con {
|
||||
width: 1180px;
|
||||
height: 110px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.menu .m_con .m_list {
|
||||
width: 215px;
|
||||
height: 80px;
|
||||
border-right: 1px solid #d9dce1;
|
||||
margin-top: 12px;
|
||||
margin-left: 20px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.menu .m_con .m_list h2 {
|
||||
font-size: 18px;
|
||||
color: #5580fb;
|
||||
font-weight: 500;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.menu .m_con .m_list ul li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.menu .m_con .m_list ul li a {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.menu .m_con .m_list ul li a:hover {
|
||||
color: #5580fb;
|
||||
}
|
||||
|
||||
.menu .m_con .m_list_end {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.course_list .c_course {
|
||||
width: 222px;
|
||||
height: 185px;
|
||||
float: left;
|
||||
margin: 0 7px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_con {
|
||||
width: 222px;
|
||||
height: 185px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*c_first start*/
|
||||
.course_list .c_course .c_first {
|
||||
background: #5580fb;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_first h2 {
|
||||
padding-top: 50px;
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_first p {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_first a {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*end c_first*/
|
||||
|
||||
/*c_list start*/
|
||||
.course_list .c_course .c_list .c_yy {
|
||||
width: 222px;
|
||||
height: 145px;
|
||||
background: #000;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0.6;
|
||||
filter: alpha(opacity=60);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list .c_desc {
|
||||
width: 222px;
|
||||
height: 145px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
color: #999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list:hover .c_desc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list:hover .c_yy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list .c_desc p {
|
||||
padding-left: 15px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list .c_desc .c_title {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list .c_tit_main {
|
||||
text-align: center;
|
||||
display: block;
|
||||
line-height: 40px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list .c_tit_main:hover {
|
||||
color: #5580fb;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_list .c_desc .c_btn {
|
||||
width: 80px;
|
||||
height: 30px;
|
||||
background: #5580fb;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
margin: 10px auto;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_zhiye {
|
||||
background: #7784a9;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_yuyan {
|
||||
background: #3faa77;
|
||||
}
|
||||
|
||||
.course_list .c_course .c_student {
|
||||
background: #6a9a36;
|
||||
}
|
||||
|
||||
/*end c_list*/
|
||||
|
||||
.teams {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
/*teacher start*/
|
||||
.teacher {
|
||||
width: 1180px;
|
||||
margin: 0 auto;
|
||||
border-bottom: 1px solid #d9dce1;
|
||||
}
|
||||
|
||||
.teacher h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.teacher .t_team {
|
||||
width: 1180px;
|
||||
}
|
||||
|
||||
.teacher .t_team ul li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
width: 216px;
|
||||
height: 66px;
|
||||
margin: 30px 9px;
|
||||
}
|
||||
|
||||
.teacher .t_team ul li:hover {
|
||||
background: #EFEFEF;
|
||||
}
|
||||
|
||||
.teacher .t_team ul li .t_pic {
|
||||
width: 66px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.teacher .t_team ul li .t_desc {
|
||||
width: 130px;
|
||||
height: 66px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.teacher .t_team ul li .t_desc p {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.teacher .t_team ul li .t_desc a {
|
||||
font-size: 14px;
|
||||
color: #5580fb;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.student h2 {
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
line-height: 70px;
|
||||
}
|
||||
|
||||
.student .s_box ul li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
width: 216px;
|
||||
height: 280px;
|
||||
margin-right: 22px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.student .s_box ul .s_en_li {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.student .s_box ul li .s_yy {
|
||||
width: 216px;
|
||||
height: 280px;
|
||||
background: #000;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0.6;
|
||||
filter: alpha(opacity=60);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.student .s_box ul li .s_desc {
|
||||
width: 216px;
|
||||
height: 280px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
color: #fff;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.student .s_box ul li .s_desc h3 {
|
||||
padding: 15px 0 0 20px;
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.student .s_box ul li .s_desc p {
|
||||
padding: 20px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.student .s_box ul li .s_desc a {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: block;
|
||||
border-radius: 30px;
|
||||
background: #5580fb;
|
||||
margin: 0 auto;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.student .s_box ul li:hover .s_yy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.student .s_box ul li:hover .s_desc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.links h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 70px;
|
||||
}
|
||||
|
||||
.links .l_a {
|
||||
width: 1180px;
|
||||
color: #8e949f;
|
||||
}
|
||||
|
||||
.links .l_a a {
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
text-decoration: none;
|
||||
color: #8e949f;
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.links .l_a a:hover {
|
||||
color: #5580fb;
|
||||
}
|
||||
|
||||
/*end links*/
|
||||
|
||||
/*footer start*/
|
||||
.footer {
|
||||
width: 100%;
|
||||
background: #15171f;
|
||||
}
|
||||
|
||||
.footer .f_con {
|
||||
width: 1180px;
|
||||
margin: 0px auto;
|
||||
color: #51555d;
|
||||
padding: 40px 0 40px 0;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl {
|
||||
float: left;
|
||||
margin-right: 60px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dt {
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd {
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd a {
|
||||
text-decoration: none;
|
||||
color: #51555d;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd .share {
|
||||
width: 35px;
|
||||
height: 34px;
|
||||
display: block;
|
||||
float: left;
|
||||
background: url("picture/pe_icon.png") no-repeat;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd .f_wb {
|
||||
background-position: -227px -77px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd .f_wb:hover {
|
||||
background-position: -227px -113px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd .f_qq {
|
||||
background-position: -265px -77px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_desc dl dd .f_qq:hover {
|
||||
background-position: -265px -113px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel {
|
||||
width: 365px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_qrcode {
|
||||
width: 153px;
|
||||
height: 135px;
|
||||
border-right: 1px solid #202328;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_time {
|
||||
float: left;
|
||||
padding-left: 51px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_time .f_price {
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_time .f_price span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_time .f_phone {
|
||||
font-size: 24px;
|
||||
color: #fff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_time .f_price span {
|
||||
line-height: 24px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.footer .f_con .f_tel .f_time .f_mm {
|
||||
width: 152px;
|
||||
height: 39px;
|
||||
text-align: center;
|
||||
border: 1px solid #292c35;
|
||||
line-height: 39px;
|
||||
font-size: 14px;
|
||||
border-radius: 19px;
|
||||
}
|
||||
|
||||
/*end footer*/
|
||||
|
||||
/*copyright start*/
|
||||
.copyright {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
background: #191b24;
|
||||
line-height: 54px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
/*end copyright*/
|
||||
|
||||
</style>
|
||||
|
||||
</html>
|
||||
|
||||
45
ruoyi-admin/src/test/java/com/xmzs/test/AssertUnitTest.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* 断言单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@DisplayName("断言单元测试案例")
|
||||
public class AssertUnitTest {
|
||||
|
||||
@DisplayName("测试 assertEquals 方法")
|
||||
@Test
|
||||
public void testAssertEquals() {
|
||||
Assertions.assertEquals("666", new String("666"));
|
||||
Assertions.assertNotEquals("666", new String("666"));
|
||||
}
|
||||
|
||||
@DisplayName("测试 assertSame 方法")
|
||||
@Test
|
||||
public void testAssertSame() {
|
||||
Object obj = new Object();
|
||||
Object obj1 = obj;
|
||||
Assertions.assertSame(obj, obj1);
|
||||
Assertions.assertNotSame(obj, obj1);
|
||||
}
|
||||
|
||||
@DisplayName("测试 assertTrue 方法")
|
||||
@Test
|
||||
public void testAssertTrue() {
|
||||
Assertions.assertTrue(true);
|
||||
Assertions.assertFalse(true);
|
||||
}
|
||||
|
||||
@DisplayName("测试 assertNull 方法")
|
||||
@Test
|
||||
public void testAssertNull() {
|
||||
Assertions.assertNull(null);
|
||||
Assertions.assertNotNull(null);
|
||||
}
|
||||
|
||||
}
|
||||
70
ruoyi-admin/src/test/java/com/xmzs/test/DemoUnitTest.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import com.xmzs.common.core.config.RuoYiConfig;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
|
||||
@DisplayName("单元测试案例")
|
||||
public class DemoUnitTest {
|
||||
|
||||
@Autowired
|
||||
private RuoYiConfig ruoYiConfig;
|
||||
|
||||
@DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
|
||||
@Test
|
||||
public void testTest() {
|
||||
System.out.println(ruoYiConfig);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@DisplayName("测试 @Disabled 注解")
|
||||
@Test
|
||||
public void testDisabled() {
|
||||
System.out.println(ruoYiConfig);
|
||||
}
|
||||
|
||||
@Timeout(value = 2L, unit = TimeUnit.SECONDS)
|
||||
@DisplayName("测试 @Timeout 注解")
|
||||
@Test
|
||||
public void testTimeout() throws InterruptedException {
|
||||
Thread.sleep(3000);
|
||||
System.out.println(ruoYiConfig);
|
||||
}
|
||||
|
||||
|
||||
@DisplayName("测试 @RepeatedTest 注解")
|
||||
@RepeatedTest(3)
|
||||
public void testRepeatedTest() {
|
||||
System.out.println(666);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void testBeforeAll() {
|
||||
System.out.println("@BeforeAll ==================");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void testBeforeEach() {
|
||||
System.out.println("@BeforeEach ==================");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void testAfterEach() {
|
||||
System.out.println("@AfterEach ==================");
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void testAfterAll() {
|
||||
System.out.println("@AfterAll ==================");
|
||||
}
|
||||
|
||||
}
|
||||
72
ruoyi-admin/src/test/java/com/xmzs/test/ParamUnitTest.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import com.xmzs.common.core.enums.UserType;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 带参数单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@DisplayName("带参数单元测试案例")
|
||||
public class ParamUnitTest {
|
||||
|
||||
@DisplayName("测试 @ValueSource 注解")
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"t1", "t2", "t3"})
|
||||
public void testValueSource(String str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
@DisplayName("测试 @NullSource 注解")
|
||||
@ParameterizedTest
|
||||
@NullSource
|
||||
public void testNullSource(String str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
@DisplayName("测试 @EnumSource 注解")
|
||||
@ParameterizedTest
|
||||
@EnumSource(UserType.class)
|
||||
public void testEnumSource(UserType type) {
|
||||
System.out.println(type.getUserType());
|
||||
}
|
||||
|
||||
@DisplayName("测试 @MethodSource 注解")
|
||||
@ParameterizedTest
|
||||
@MethodSource("getParam")
|
||||
public void testMethodSource(String str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
public static Stream<String> getParam() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("t1");
|
||||
list.add("t2");
|
||||
list.add("t3");
|
||||
return list.stream();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void testBeforeEach() {
|
||||
System.out.println("@BeforeEach ==================");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void testAfterEach() {
|
||||
System.out.println("@AfterEach ==================");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
54
ruoyi-admin/src/test/java/com/xmzs/test/TagUnitTest.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* 标签单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootTest
|
||||
@DisplayName("标签单元测试案例")
|
||||
public class TagUnitTest {
|
||||
|
||||
@Tag("dev")
|
||||
@DisplayName("测试 @Tag dev")
|
||||
@Test
|
||||
public void testTagDev() {
|
||||
System.out.println("dev");
|
||||
}
|
||||
|
||||
@Tag("prod")
|
||||
@DisplayName("测试 @Tag prod")
|
||||
@Test
|
||||
public void testTagProd() {
|
||||
System.out.println("prod");
|
||||
}
|
||||
|
||||
@Tag("local")
|
||||
@DisplayName("测试 @Tag local")
|
||||
@Test
|
||||
public void testTagLocal() {
|
||||
System.out.println("local");
|
||||
}
|
||||
|
||||
@Tag("exclude")
|
||||
@DisplayName("测试 @Tag exclude")
|
||||
@Test
|
||||
public void testTagExclude() {
|
||||
System.out.println("exclude");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void testBeforeEach() {
|
||||
System.out.println("@BeforeEach ==================");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void testAfterEach() {
|
||||
System.out.println("@AfterEach ==================");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
46
ruoyi-common/pom.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>com.xmzs</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-common-bom</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>
|
||||
<module>ruoyi-common-oss</module>
|
||||
<module>ruoyi-common-ratelimiter</module>
|
||||
<module>ruoyi-common-redis</module>
|
||||
<module>ruoyi-common-satoken</module>
|
||||
<module>ruoyi-common-security</module>
|
||||
<module>ruoyi-common-sms</module>
|
||||
<module>ruoyi-common-web</module>
|
||||
<module>ruoyi-common-translation</module>
|
||||
<module>ruoyi-common-sensitive</module>
|
||||
<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>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<description>
|
||||
common 通用模块
|
||||
</description>
|
||||
|
||||
</project>
|
||||
178
ruoyi-common/ruoyi-common-bom/pom.xml
Normal file
@@ -0,0 +1,178 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-bom</artifactId>
|
||||
<version>${revision}</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<description>
|
||||
ruoyi-common-bom common依赖项
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>1.0.0</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- 核心模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 接口模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-doc</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- excel -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-excel</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 幂等 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-idempotent</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 调度模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-job</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志记录 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-log</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 邮件服务 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-mail</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库服务 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-mybatis</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- OSS -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-oss</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 限流 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-ratelimiter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 缓存服务 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-redis</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- satoken -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-satoken</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 安全模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-security</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 短信模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-sms</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web服务 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-web</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 翻译模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-translation</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 脱敏模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-sensitive</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 序列化模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-json</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库加解密模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-encrypt</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 租户模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-tenant</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- chat模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-chat</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 支付模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-pay</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
86
ruoyi-common/ruoyi-common-chat/pom.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>com.xmzs</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 模块
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<retrofit2.version>2.9.0</retrofit2.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-json</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-satoken</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-common-json</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</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>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.knuddels</groupId>
|
||||
<artifactId>jtokkit</artifactId>
|
||||
<version>0.5.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- azure-ai -->
|
||||
<dependency>
|
||||
<groupId>com.azure</groupId>
|
||||
<artifactId>azure-ai-openai</artifactId>
|
||||
<version>1.0.0-beta.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.12</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.xmzs.common.chat.config;
|
||||
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import com.xmzs.common.chat.openai.OpenAiStreamClient;
|
||||
import com.xmzs.common.chat.openai.function.KeyRandomStrategy;
|
||||
import com.xmzs.common.chat.openai.interceptor.OpenAILogger;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* chat配置类
|
||||
*
|
||||
* @author: wangle
|
||||
* @date: 2023/5/16
|
||||
*/
|
||||
@Configuration
|
||||
public class ChatConfig {
|
||||
@Value("${chat.apiKey}")
|
||||
private List<String> apiKey;
|
||||
@Value("${chat.apiHost}")
|
||||
private String apiHost;
|
||||
|
||||
@Bean(name = "openAiStreamClient")
|
||||
public OpenAiStreamClient openAiStreamClient() {
|
||||
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
|
||||
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
.Builder()
|
||||
.addInterceptor(httpLoggingInterceptor)
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.writeTimeout(600, TimeUnit.SECONDS)
|
||||
.readTimeout(600, TimeUnit.SECONDS)
|
||||
.build();
|
||||
return OpenAiStreamClient
|
||||
.builder()
|
||||
.apiHost(apiHost)
|
||||
.apiKey(apiKey)
|
||||
//自定义key使用策略 默认随机策略
|
||||
.keyStrategy(new KeyRandomStrategy())
|
||||
.okHttpClient(okHttpClient)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.xmzs.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();
|
||||
/**
|
||||
* 清理间隔
|
||||
*/
|
||||
private static final long CLEAN_TIMEOUT = 30 * DateUnit.MINUTE.getMillis();
|
||||
|
||||
/**
|
||||
* 缓存对象
|
||||
*/
|
||||
public static final TimedCache<String, Object> CACHE = CacheUtil.newTimedCache(TIMEOUT);
|
||||
|
||||
|
||||
static {
|
||||
//启动定时任务
|
||||
CACHE.schedulePrune(CLEAN_TIMEOUT);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.xmzs.common.chat.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.xmzs.common.chat.config.properties.WebSocketProperties;
|
||||
import com.xmzs.common.chat.handler.PlusWebSocketHandler;
|
||||
import com.xmzs.common.chat.interceptor.PlusWebSocketInterceptor;
|
||||
import com.xmzs.common.chat.listener.WebSocketTopicListener;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import org.springframework.web.socket.WebSocketHandler;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||
import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||
|
||||
/**
|
||||
* WebSocket 配置
|
||||
*
|
||||
* @author zendwang
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnProperty(value = "websocket.enabled", havingValue = "true")
|
||||
@EnableConfigurationProperties(WebSocketProperties.class)
|
||||
@EnableWebSocket
|
||||
public class WebSocketConfig {
|
||||
|
||||
@Bean
|
||||
public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor handshakeInterceptor,
|
||||
WebSocketHandler webSocketHandler,
|
||||
WebSocketProperties webSocketProperties) {
|
||||
if (StrUtil.isBlank(webSocketProperties.getPath())) {
|
||||
webSocketProperties.setPath("/websocket");
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) {
|
||||
webSocketProperties.setAllowedOrigins("*");
|
||||
}
|
||||
|
||||
return registry -> registry
|
||||
.addHandler(webSocketHandler, webSocketProperties.getPath())
|
||||
.addInterceptors(handshakeInterceptor)
|
||||
.setAllowedOrigins(webSocketProperties.getAllowedOrigins());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandshakeInterceptor handshakeInterceptor() {
|
||||
return new PlusWebSocketInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketHandler webSocketHandler() {
|
||||
return new PlusWebSocketHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketTopicListener topicListener() {
|
||||
return new WebSocketTopicListener();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xmzs.common.chat.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* WebSocket 配置项
|
||||
*
|
||||
* @author zendwang
|
||||
*/
|
||||
@ConfigurationProperties("websocket")
|
||||
@Data
|
||||
public class WebSocketProperties {
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* 路径
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 设置访问源地址
|
||||
*/
|
||||
private String allowedOrigins;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xmzs.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 int SUCCEED_CODE = 200;
|
||||
|
||||
public final static double GPT3_COST = 0.03;
|
||||
|
||||
public final static double GPT4_COST = 0.3;
|
||||
|
||||
/** 绘图费用 */
|
||||
public final static double DALL3_COST = 0.3;
|
||||
|
||||
/** 绘图费用-高清 */
|
||||
public final static double DALL3_HD_COST = 0.6;
|
||||
|
||||
/** mdjourney绘图费用 */
|
||||
public final static double MJ_COST = 0.3;
|
||||
|
||||
/** 默认账户余额 */
|
||||
public final static double USER_BALANCE = 5;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xmzs.common.chat.constant;
|
||||
|
||||
/**
|
||||
* websocket的常量配置
|
||||
*
|
||||
* @author zendwang
|
||||
*/
|
||||
public interface WebSocketConstants {
|
||||
/**
|
||||
* websocketSession中的参数的key
|
||||
*/
|
||||
String LOGIN_USER_KEY = "loginUser";
|
||||
|
||||
/**
|
||||
* 订阅的频道
|
||||
*/
|
||||
String WEB_SOCKET_TOPIC = "global:websocket";
|
||||
|
||||
/**
|
||||
* 前端心跳检查的命令
|
||||
*/
|
||||
String PING = "ping";
|
||||
|
||||
/**
|
||||
* 服务端心跳恢复的字符串
|
||||
*/
|
||||
String PONG = "pong";
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author hncboy
|
||||
* @date 2023/3/23 13:17
|
||||
* 消息处理请求
|
||||
*/
|
||||
@Data
|
||||
public class ChatProcessRequest {
|
||||
|
||||
private String prompt;
|
||||
|
||||
private Options options;
|
||||
|
||||
private String systemMessage;
|
||||
|
||||
@Data
|
||||
public static class Options {
|
||||
|
||||
private String conversationId;
|
||||
|
||||
/**
|
||||
* 这里的父级消息指的是回答的父级消息 id
|
||||
* 前端发送问题,需要上下文的话传回答的父级消息 id
|
||||
*/
|
||||
private String parentMessageId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
import com.xmzs.common.chat.entity.chat.Content;
|
||||
import com.xmzs.common.chat.entity.chat.Message;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @sine 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
public class ChatRequest {
|
||||
|
||||
@NotEmpty(message = "传入的模型不能为空")
|
||||
private String model;
|
||||
|
||||
@NotEmpty(message = "对话消息不能为空")
|
||||
List<Message> messages;
|
||||
|
||||
List<Content> content;
|
||||
|
||||
private String prompt;
|
||||
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 需要识别的图片地址
|
||||
*/
|
||||
private String imgurl;
|
||||
|
||||
/**
|
||||
* gpt的默认设置
|
||||
*/
|
||||
private String systemMessage = "";
|
||||
|
||||
private double top_p = 1;
|
||||
|
||||
private double temperature = 0.2;
|
||||
|
||||
/**
|
||||
* 上下文的条数
|
||||
*/
|
||||
private Integer contentNumber = 10;
|
||||
|
||||
/**
|
||||
* 是否携带上下文
|
||||
*/
|
||||
private Boolean usingContext = Boolean.TRUE;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @sine 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
public class Dall3Request {
|
||||
|
||||
@NotEmpty(message = "传入的模型不能为空")
|
||||
private String model;
|
||||
|
||||
@NotEmpty(message = "提示词不能为空")
|
||||
private String prompt;
|
||||
|
||||
/** 图片大小 */
|
||||
@NotEmpty(message = "图片大小不能为空")
|
||||
private String size ;
|
||||
|
||||
/** 图片质量 */
|
||||
@NotEmpty(message = "图片质量不能为空")
|
||||
private String quality;
|
||||
|
||||
/** 图片风格 */
|
||||
@NotEmpty(message = "图片风格不能为空")
|
||||
private String style;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @sine 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
public class SaveMsgRequest {
|
||||
|
||||
@NotEmpty(message = "传入的模型不能为空")
|
||||
private String model;
|
||||
|
||||
@NotEmpty(message = "对话消息不能为空")
|
||||
private String msg;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xmzs.common.chat.domain.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @sine 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
public class ChatResponse {
|
||||
/**
|
||||
* 问题消耗tokens
|
||||
*/
|
||||
@JsonProperty("question_tokens")
|
||||
private long questionTokens = 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.xmzs.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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import com.xmzs.common.chat.constant.OpenAIConst;
|
||||
import com.xmzs.common.chat.entity.chat.tool.Tools;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.xmzs.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"),
|
||||
/**
|
||||
* 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"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ChatType {
|
||||
/**
|
||||
* 对话类型 - 输入
|
||||
*/
|
||||
CHAT_IN("in"),
|
||||
/**
|
||||
* 对话类型 - 输出
|
||||
*/
|
||||
CHAT_OUT("out"),
|
||||
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
public static double getModelCost(String modelName) {
|
||||
return switch (modelName) {
|
||||
case "gpt-3.5-turbo-0613" -> OpenAIConst.GPT3_COST;
|
||||
default -> OpenAIConst.GPT4_COST;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.unfbx.chatgpt.entity.chat.tool.ToolCalls;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.*;
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.xmzs.common.chat.entity.common.Usage;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.*;
|
||||
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,43 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xmzs.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;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.xmzs.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 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 implements Serializable {
|
||||
|
||||
/**
|
||||
* 目前支持四个中角色参考官网,进行情景输入:
|
||||
* https://platform.openai.com/docs/guides/chat/introduction
|
||||
*/
|
||||
private String role;
|
||||
|
||||
private String content;
|
||||
|
||||
private String name;
|
||||
|
||||
@JsonProperty("function_call")
|
||||
private FunctionCall functionCall;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param role 角色
|
||||
* @param content 描述主题信息
|
||||
* @param name name
|
||||
* @param functionCall functionCall
|
||||
*/
|
||||
public Message(String role, String content, String name, FunctionCall functionCall) {
|
||||
this.role = role;
|
||||
this.content = content;
|
||||
this.name = name;
|
||||
this.functionCall = functionCall;
|
||||
}
|
||||
|
||||
public Message() {
|
||||
}
|
||||
|
||||
private Message(Builder builder) {
|
||||
setRole(builder.role);
|
||||
setContent(builder.content);
|
||||
setName(builder.name);
|
||||
setFunctionCall(builder.functionCall);
|
||||
}
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Role {
|
||||
|
||||
SYSTEM("system"),
|
||||
USER("user"),
|
||||
ASSISTANT("assistant"),
|
||||
FUNCTION("function"),
|
||||
;
|
||||
private String name;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String role;
|
||||
private String content;
|
||||
private String name;
|
||||
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 Message build() {
|
||||
return new Message(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.unfbx.chatgpt.entity.chat.tool.ToolCalls;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
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)
|
||||
@AllArgsConstructor
|
||||
public class MessagePicture extends BaseMessage implements Serializable {
|
||||
/**
|
||||
* Content数组支持多图片输入
|
||||
* https://platform.openai.com/docs/guides/vision
|
||||
*/
|
||||
private List<Content> content;
|
||||
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param role 角色
|
||||
* @param name name
|
||||
* @param content content
|
||||
* @param functionCall functionCall
|
||||
*/
|
||||
public MessagePicture(String role, String name, List<Content> 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 MessagePicture() {
|
||||
}
|
||||
|
||||
private MessagePicture(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 final class Builder {
|
||||
private String role;
|
||||
private List<Content> 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(List<Content> 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 MessagePicture build() {
|
||||
return new MessagePicture(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
/**
|
||||
* 描述:方法参数类,扩展参数可以继承Parameters自己实现
|
||||
* 参考:
|
||||
* <pre>
|
||||
* {
|
||||
* "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 Parameters implements Serializable {
|
||||
/**
|
||||
* 参数类型
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 参数属性、描述
|
||||
*/
|
||||
private Object properties;
|
||||
/**
|
||||
* 方法必输字段
|
||||
*/
|
||||
private List<String> required;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 指定模型必须输出的格式的对象。
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ResponseFormat {
|
||||
/**
|
||||
* 默认:text
|
||||
*
|
||||
* @see Type
|
||||
*/
|
||||
private String type;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type {
|
||||
JSON_OBJECT("json_object"),
|
||||
TEXT("text"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.xmzs.common.chat.entity.chat.tool;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ToolCall 的 Function参数
|
||||
* The function that the model called.
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ToolCallFunction implements Serializable {
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 方法参数
|
||||
*/
|
||||
private String arguments;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.unfbx.chatgpt.entity.chat.tool;
|
||||
|
||||
import com.xmzs.common.chat.entity.chat.tool.ToolCallFunction;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The tool calls generated by the model, such as function calls.
|
||||
*
|
||||
* @author <a href="https://www.unfbx.com">unfbx</a>
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ToolCalls implements Serializable {
|
||||
/**
|
||||
* The ID of the tool call.
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* The type of the tool. Currently, only function is supported.
|
||||
*/
|
||||
private String type;
|
||||
|
||||
private ToolCallFunction function;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type {
|
||||
FUNCTION("function"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xmzs.common.chat.entity.chat.tool;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* choice和object同时存在是以object为准
|
||||
*
|
||||
* @author <a href="https://www.unfbx.com">unfbx</a>
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
public class ToolChoice implements Serializable {
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Choice {
|
||||
NONE("none"),
|
||||
AUTO("auto"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.xmzs.common.chat.entity.chat.tool;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* @author <a href="https://www.unfbx.com">unfbx</a>
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ToolChoiceObj {
|
||||
/**
|
||||
* 需要调用的方法名称
|
||||
*/
|
||||
private ToolChoiceObjFunction function;
|
||||
/**
|
||||
* 工具的类型。目前仅支持函数。
|
||||
*
|
||||
* @see Type
|
||||
*/
|
||||
private String type;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type {
|
||||
FUNCTION("function"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xmzs.common.chat.entity.chat.tool;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author <a href="https://www.unfbx.com">unfbx</a>
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ToolChoiceObjFunction {
|
||||
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.xmzs.common.chat.entity.chat.tool;
|
||||
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="https://www.unfbx.com">unfbx</a>
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Tools implements Serializable {
|
||||
|
||||
/**
|
||||
* 目前只支持:function
|
||||
*
|
||||
* @see Type
|
||||
*/
|
||||
private String type;
|
||||
|
||||
private ToolsFunction function;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type {
|
||||
FUNCTION("function"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.xmzs.common.chat.entity.chat.tool;
|
||||
|
||||
|
||||
import com.xmzs.common.chat.entity.chat.Parameters;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="https://www.unfbx.com">unfbx</a>
|
||||
* @since 1.1.2
|
||||
* 2023-11-09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ToolsFunction implements Serializable {
|
||||
|
||||
/**
|
||||
* 要调用的函数的名称。必须是 a-z、A-Z、0-9,或包含下划线和破折号,最大长度为 64
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 对函数功能的描述,模型使用它来选择何时以及如何调用该函数。
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 函数接受的参数,描述为 JSON Schema 对象
|
||||
* 扩展参数可以继承Parameters自己实现,json格式的数据
|
||||
*/
|
||||
private Parameters parameters;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xmzs.common.chat.entity.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Choice implements Serializable {
|
||||
private String text;
|
||||
private long index;
|
||||
private Object logprobs;
|
||||
@JsonProperty("finish_reason")
|
||||
private String finishReason;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xmzs.common.chat.entity.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DeleteResponse implements Serializable {
|
||||
private String id;
|
||||
private String object;
|
||||
private boolean deleted;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xmzs.common.chat.entity.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class OpenAiResponse<T> implements Serializable {
|
||||
private String object;
|
||||
private List<T> data;
|
||||
private Error error;
|
||||
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Error {
|
||||
private String message;
|
||||
private String type;
|
||||
private String param;
|
||||
private String code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.xmzs.common.chat.entity.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Usage implements Serializable {
|
||||
@JsonProperty("prompt_tokens")
|
||||
private long promptTokens;
|
||||
@JsonProperty("completion_tokens")
|
||||
private long completionTokens;
|
||||
@JsonProperty("total_tokens")
|
||||
private long totalTokens;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.xmzs.common.chat.entity.completions;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 描述: 问题类
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-11
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@Slf4j
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Completion implements Serializable {
|
||||
|
||||
@NonNull
|
||||
@Builder.Default
|
||||
private String model = Model.DAVINCI_003.getName();
|
||||
/**
|
||||
* 问题描述
|
||||
*/
|
||||
@NonNull
|
||||
private String prompt;
|
||||
/**
|
||||
* 完成输出后的后缀,用于格式化输出结果
|
||||
*/
|
||||
private String suffix;
|
||||
|
||||
/**
|
||||
* 最大支持4096
|
||||
*/
|
||||
@JsonProperty("max_tokens")
|
||||
@Builder.Default
|
||||
private Integer maxTokens = 2048;
|
||||
/**
|
||||
* 使用什么取样温度,0到2之间。较高的值(如0.8)将使输出更加随机,而较低的值(如0.2)将使输出更加集中和确定。
|
||||
* <p>
|
||||
* We generally recommend altering this or but not both.top_p
|
||||
*/
|
||||
@Builder.Default
|
||||
private double temperature = 0;
|
||||
|
||||
/**
|
||||
* 使用温度采样的替代方法称为核心采样,其中模型考虑具有top_p概率质量的令牌的结果。因此,0.1 意味着只考虑包含前 10% 概率质量的代币。
|
||||
* <p>
|
||||
* 我们通常建议更改此设置,但不要同时更改两者。temperature
|
||||
*/
|
||||
@JsonProperty("top_p")
|
||||
@Builder.Default
|
||||
private Double topP = 1d;
|
||||
|
||||
/**
|
||||
* 为每个提示生成的完成次数。
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer n = 1;
|
||||
|
||||
@Builder.Default
|
||||
private boolean stream = false;
|
||||
/**
|
||||
* 最大值:5
|
||||
*/
|
||||
private Integer logprobs;
|
||||
|
||||
@Builder.Default
|
||||
private boolean echo = false;
|
||||
|
||||
private List<String> stop;
|
||||
|
||||
@JsonProperty("presence_penalty")
|
||||
@Builder.Default
|
||||
private double presencePenalty = 0;
|
||||
|
||||
/**
|
||||
* -2.0 ~~ 2.0
|
||||
*/
|
||||
@JsonProperty("frequency_penalty")
|
||||
@Builder.Default
|
||||
private double frequencyPenalty = 0;
|
||||
|
||||
@JsonProperty("best_of")
|
||||
@Builder.Default
|
||||
private Integer bestOf = 1;
|
||||
|
||||
@JsonProperty("logit_bias")
|
||||
private Map logitBias;
|
||||
/**
|
||||
* 用户唯一值,确保接口不被重复调用
|
||||
*/
|
||||
private String user;
|
||||
|
||||
/**
|
||||
* 获取当前参数的tokens数
|
||||
* @return token数量
|
||||
*/
|
||||
// public long tokens() {
|
||||
// if (StrUtil.isBlank(this.prompt) || StrUtil.isBlank(this.model)) {
|
||||
// log.warn("参数异常model:{},prompt:{}", this.model, this.prompt);
|
||||
// return 0;
|
||||
// }
|
||||
// return TikTokensUtil.tokens(this.model, this.prompt);
|
||||
// }
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Model {
|
||||
DAVINCI_003("text-davinci-003"),
|
||||
DAVINCI_002("text-davinci-002"),
|
||||
DAVINCI("davinci"),
|
||||
;
|
||||
private String name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.xmzs.common.chat.entity.completions;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.xmzs.common.chat.entity.common.Choice;
|
||||
import com.xmzs.common.chat.entity.common.OpenAiResponse;
|
||||
import com.xmzs.common.chat.entity.common.Usage;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述: 答案类
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-11
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class CompletionResponse extends OpenAiResponse implements Serializable {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private Choice[] choices;
|
||||
private Usage usage;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.xmzs.common.chat.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 消息的dto
|
||||
*
|
||||
* @author zendwang
|
||||
*/
|
||||
@Data
|
||||
public class WebSocketMessageDto implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 需要推送到的session key 列表
|
||||
*/
|
||||
private List<Long> sessionKeys;
|
||||
|
||||
/**
|
||||
* 需要发送的消息
|
||||
*/
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.xmzs.common.chat.entity.edits;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Getter
|
||||
@Builder
|
||||
@Slf4j
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Edit implements Serializable {
|
||||
/**
|
||||
* 编辑模型,目前支持两种
|
||||
*/
|
||||
@NonNull
|
||||
private String model;
|
||||
|
||||
@NonNull
|
||||
private String input;
|
||||
/**
|
||||
* 提示说明。告知模型如何修改。
|
||||
*/
|
||||
@NonNull
|
||||
private String instruction;
|
||||
|
||||
|
||||
/**
|
||||
* 使用什么取样温度,0到2之间。较高的值(如0.8)将使输出更加随机,而较低的值(如0.2)将使输出更加集中和确定。
|
||||
*
|
||||
* We generally recommend altering this or but not both.top_p
|
||||
*/
|
||||
@Builder.Default
|
||||
private double temperature = 0;
|
||||
|
||||
/**
|
||||
* 使用温度采样的替代方法称为核心采样,其中模型考虑具有top_p概率质量的令牌的结果。因此,0.1 意味着只考虑包含前 10% 概率质量的代币。
|
||||
*
|
||||
* 我们通常建议更改此设置,但不要同时更改两者。temperature
|
||||
*/
|
||||
@JsonProperty("top_p")
|
||||
@Builder.Default
|
||||
private Double topP = 1d;
|
||||
|
||||
/**
|
||||
* 为每个提示生成的完成次数。
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer n = 1;
|
||||
|
||||
public void setModel(Model model) {
|
||||
this.model = model.getName();
|
||||
}
|
||||
|
||||
public void setTemperature(double temperature) {
|
||||
if (temperature > 2 || temperature < 0) {
|
||||
log.error("temperature参数异常,temperature属于[0,2]");
|
||||
this.temperature = 2;
|
||||
return;
|
||||
}
|
||||
if (temperature < 0) {
|
||||
log.error("temperature参数异常,temperature属于[0,2]");
|
||||
this.temperature = 0;
|
||||
return;
|
||||
}
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
|
||||
public void setTopP(Double topP) {
|
||||
this.topP = topP;
|
||||
}
|
||||
|
||||
public void setN(Integer n) {
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
public void setInput(String input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public void setInstruction(String instruction) {
|
||||
this.instruction = instruction;
|
||||
}
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Model {
|
||||
TEXT_DAVINCI_EDIT_001("text-davinci-edit-001"),
|
||||
CODE_DAVINCI_EDIT_001("code-davinci-edit-001"),
|
||||
;
|
||||
private String name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.xmzs.common.chat.entity.edits;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.xmzs.common.chat.entity.common.Choice;
|
||||
import com.xmzs.common.chat.entity.common.Usage;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class EditResponse implements Serializable {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private Choice[] choices;
|
||||
private Usage usage;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.xmzs.common.chat.entity.embeddings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Getter
|
||||
@Slf4j
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Embedding implements Serializable {
|
||||
@NonNull
|
||||
@Builder.Default
|
||||
private String model = Model.TEXT_EMBEDDING_ADA_002.getName();
|
||||
/**
|
||||
* 必选项:长度不能超过:8192
|
||||
*/
|
||||
@NonNull
|
||||
private List<String> input;
|
||||
|
||||
private String user;
|
||||
|
||||
public void setModel(Model model) {
|
||||
if (Objects.isNull(model)) {
|
||||
model = Model.TEXT_EMBEDDING_ADA_002;
|
||||
}
|
||||
this.model = model.getName();
|
||||
}
|
||||
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Model {
|
||||
TEXT_EMBEDDING_ADA_002("text-embedding-ada-002"),
|
||||
;
|
||||
private String name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xmzs.common.chat.entity.embeddings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.xmzs.common.chat.entity.common.Usage;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class EmbeddingResponse implements Serializable {
|
||||
|
||||
private String object;
|
||||
private List<Item> data;
|
||||
private String model;
|
||||
private Usage usage;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.xmzs.common.chat.entity.embeddings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Item implements Serializable {
|
||||
private String object;
|
||||
private List<BigDecimal> embedding;
|
||||
private Integer index;
|
||||
}
|
||||