feat(知识库): 增加知识库模块
392
application.yml
@@ -1,392 +0,0 @@
|
||||
# 项目相关配置
|
||||
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:
|
||||
|
||||
# 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: false
|
||||
# 路径
|
||||
path: ''
|
||||
# 设置访问源地址
|
||||
allowedOrigins: '*'
|
||||
|
||||
# 微信小程序配置信息
|
||||
wx:
|
||||
miniapp:
|
||||
configs:
|
||||
- appid: # 你的appid
|
||||
secret: # 你的secret
|
||||
token: #微信小程序消息服务器配置的token
|
||||
aesKey: #微信小程序消息服务器配置的EncodingAESKey
|
||||
msgDataFormat: JSON
|
||||
baidu:
|
||||
# 是否开启文本审核
|
||||
enabled: false
|
||||
# 文本审核
|
||||
textReview:
|
||||
apiKey: '' # apiKey
|
||||
secretKey: '' # secretKey
|
||||
appKey: xxxxxxxxxxxxxxxxx
|
||||
secretKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
wechat:
|
||||
# 是否使用微信 true/false
|
||||
enable: true
|
||||
# 生成的登录二维码路径 默认与项目同级
|
||||
qrPath: "./"
|
||||
|
||||
keyword:
|
||||
# 重置会话指令
|
||||
reset: "重置会话"
|
||||
# ai画图指令(DALL·E模型 https://platform.openai.com/docs/models/dall-e)
|
||||
# generation 根据关键词生成图片(https://platform.openai.com/docs/guides/images/generations)
|
||||
image: "ai画图"
|
||||
# ai语音指令(TTS模型 https://platform.openai.com/docs/api-reference/audio)
|
||||
audio: "ai语音"
|
||||
|
||||
mj:
|
||||
api-secret: 'sk-xx'
|
||||
task-store:
|
||||
type: in_memory
|
||||
timeout: 30d
|
||||
translate-way: gpt
|
||||
# proxy:
|
||||
# host: 127.0.0.1
|
||||
# port: 10809
|
||||
ng-discord:
|
||||
server: 'https://xxx.pandarobot.chat/'
|
||||
cdn: 'https://xxx.pandarobot.chat/'
|
||||
wss: 'https://xxx.pandarobot.chat/'
|
||||
openai:
|
||||
gpt-api-url: 'https://api.pandarobot.chat/'
|
||||
gpt-api-key: 'sk-xx'
|
||||
accounts:
|
||||
- guild-id: 'xx'
|
||||
channel-id: 'xx'
|
||||
user-token: 'xx'
|
||||
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: true
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: ageerle@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: ageerle@163.com
|
||||
# 密码(填写授权码)
|
||||
pass: TOGXBVPYFVPFRQMQ
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
|
||||
# chatgpt配置信息
|
||||
chat:
|
||||
apiKey: 'sk-xxx'
|
||||
apiHost: 'https://api.pandarobot.chat/'
|
||||
|
||||
# 支付配置信息
|
||||
pay:
|
||||
pid: 'xxx'
|
||||
key: 'xxx'
|
||||
payUrl: 'https://pay.pandarobot.chat/mapi.php'
|
||||
notify_url: 'https://www.pandarobot.chat/pay/returnUrl'
|
||||
return_url: 'https://www.pandarobot.chat/pay/notifyUrl'
|
||||
type: 'wxpay'
|
||||
device: 'pc'
|
||||
sign_type: 'MD5'
|
||||
@@ -57,7 +57,10 @@
|
||||
<artifactId>ruoyi-fusion</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-knowledge</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- demo模块 -->
|
||||
@@ -78,6 +81,12 @@
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>0.4.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.ollama4j</groupId>
|
||||
<artifactId>ollama4j</artifactId>
|
||||
<version>1.0.79</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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智能助手启动成功 ლ(´ڡ`ლ)゙");
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
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")
|
||||
@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(), "【熊猫助手】登录验证码", "您本次验证码为:" + 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
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.Tts.TextToSpeech;
|
||||
import com.xmzs.common.chat.entity.files.UploadFileResponse;
|
||||
import com.xmzs.common.chat.entity.images.Item;
|
||||
import com.xmzs.common.chat.entity.whisper.WhisperResponse;
|
||||
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.ISseService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
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 ISseService ISseService;
|
||||
|
||||
private final IChatMessageService chatMessageService;
|
||||
|
||||
/**
|
||||
* 聊天接口
|
||||
*/
|
||||
@PostMapping("/chat")
|
||||
@ResponseBody
|
||||
public SseEmitter sseChat(@RequestBody @Valid ChatRequest chatRequest, HttpServletResponse response) {
|
||||
return ISseService.sseChat(chatRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
@PostMapping("/v1/upload")
|
||||
@ResponseBody
|
||||
public UploadFileResponse upload(@RequestPart("file") MultipartFile file) {
|
||||
return ISseService.upload(file);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 语音转文本
|
||||
*
|
||||
* @param file
|
||||
*/
|
||||
@PostMapping("/audio")
|
||||
@ResponseBody
|
||||
public WhisperResponse audio(@RequestParam("file") MultipartFile file) {
|
||||
WhisperResponse whisperResponse = ISseService.speechToTextTranscriptionsV2(file);
|
||||
return whisperResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本转语音
|
||||
*
|
||||
* @param textToSpeech
|
||||
*/
|
||||
@PostMapping("/speech")
|
||||
@ResponseBody
|
||||
public ResponseEntity<Resource> speech(@RequestBody TextToSpeech textToSpeech) {
|
||||
return ISseService.textToSpeed(textToSpeech);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/dall3")
|
||||
@ResponseBody
|
||||
public R<List<Item>> dall3(@RequestBody @Valid Dall3Request request) {
|
||||
return R.ok(ISseService.dall3(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 聊天记录
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
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";
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
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 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;
|
||||
|
||||
private final PayConfig payConfig;
|
||||
|
||||
/**
|
||||
* 获取支付二维码
|
||||
*
|
||||
* @Date 2023/7/3
|
||||
* @return void
|
||||
**/
|
||||
@PostMapping("/payUrl")
|
||||
public R<PaymentOrdersVo> payUrl(@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.getPid() +
|
||||
"&trade_no=" + payResponse.getTrade_no() + "&trade_status=" + payResponse.getTrade_status() +
|
||||
"&type=" + payResponse.getType() + payConfig.getKey();
|
||||
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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.xmzs.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.wechat.Wechat;
|
||||
import com.xmzs.common.wechat.controller.LoginController;
|
||||
import com.xmzs.common.wechat.core.MsgCenter;
|
||||
import com.xmzs.system.cofing.KeywordConfig;
|
||||
import com.xmzs.system.cofing.WechatConfig;
|
||||
import com.xmzs.system.handler.WechatMessageHandler;
|
||||
import com.xmzs.system.service.ISseService;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 个人微信扩展控制器
|
||||
*
|
||||
* @author WangLe
|
||||
*/
|
||||
@SaIgnore
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class WeChatController {
|
||||
|
||||
@Getter
|
||||
private Wechat wechatBot;
|
||||
|
||||
private final WechatConfig wechatConfig;
|
||||
|
||||
private final ISseService sseService;
|
||||
|
||||
private final KeywordConfig keywordConfig;
|
||||
|
||||
/**
|
||||
* 获取微信登录二维码
|
||||
*
|
||||
*/
|
||||
@GetMapping("/getQr")
|
||||
public R<String> getQr() {
|
||||
//微信
|
||||
if (wechatConfig.getEnable()){
|
||||
log.info("正在登录微信,请按提示操作:");
|
||||
wechatBot = new Wechat(new WechatMessageHandler(sseService, keywordConfig));
|
||||
// 登陆
|
||||
LoginController login = new LoginController();
|
||||
String qrCode = login.login_1();
|
||||
new Thread(login::login_2).start();
|
||||
wechatBot.start();
|
||||
return R.ok(qrCode);
|
||||
}else {
|
||||
return R.fail();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,12 +10,12 @@ import org.springframework.boot.context.metrics.buffering.BufferingApplicationSt
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class RuoYiApplication {
|
||||
public class RuoYiAIApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(RuoYiApplication.class);
|
||||
SpringApplication application = new SpringApplication(RuoYiAIApplication.class);
|
||||
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||
application.run(args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ RuoYiAi启动成功 ლ(´ڡ`ლ)゙");
|
||||
System.out.println("(♥◠‿◠)ノ゙ RuoYiAI启动成功 ლ(´ڡ`ლ)゙");
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,11 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class RuoYiServletInitializer extends SpringBootServletInitializer {
|
||||
public class RuoYiAIServletInitializer extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(RuoYiApplication.class);
|
||||
return application.sources(RuoYiAIApplication.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.theokanning.openai.completion.chat.ChatMessageRole;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.ruoyi.common.chat.config.ChatConfig;
|
||||
import org.ruoyi.common.chat.domain.request.ChatRequest;
|
||||
import org.ruoyi.common.chat.entity.chat.ChatCompletion;
|
||||
import org.ruoyi.common.chat.entity.chat.Message;
|
||||
import org.ruoyi.common.chat.openai.OpenAiStreamClient;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.core.validate.AddGroup;
|
||||
import org.ruoyi.common.excel.utils.ExcelUtil;
|
||||
import org.ruoyi.common.log.annotation.Log;
|
||||
import org.ruoyi.common.log.enums.BusinessType;
|
||||
import org.ruoyi.common.mybatis.core.page.PageQuery;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
import org.ruoyi.common.satoken.utils.LoginHelper;
|
||||
import org.ruoyi.common.web.core.BaseController;
|
||||
import org.ruoyi.knowledge.domain.bo.KnowledgeAttachBo;
|
||||
import org.ruoyi.knowledge.domain.bo.KnowledgeFragmentBo;
|
||||
import org.ruoyi.knowledge.domain.bo.KnowledgeInfoBo;
|
||||
import org.ruoyi.knowledge.domain.req.KnowledgeInfoUploadRequest;
|
||||
import org.ruoyi.knowledge.domain.vo.KnowledgeAttachVo;
|
||||
import org.ruoyi.knowledge.domain.vo.KnowledgeFragmentVo;
|
||||
import org.ruoyi.knowledge.domain.vo.KnowledgeInfoVo;
|
||||
import org.ruoyi.knowledge.service.EmbeddingService;
|
||||
import org.ruoyi.knowledge.service.IKnowledgeAttachService;
|
||||
import org.ruoyi.knowledge.service.IKnowledgeFragmentService;
|
||||
import org.ruoyi.knowledge.service.IKnowledgeInfoService;
|
||||
import org.ruoyi.system.listener.SSEEventSourceListener;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.ruoyi.knowledge.chain.vectorstore.VectorStore;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 知识库
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2024-10-21
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/knowledge")
|
||||
public class KnowledgeController extends BaseController {
|
||||
|
||||
private final IKnowledgeInfoService knowledgeInfoService;
|
||||
|
||||
private final VectorStore vectorStore;
|
||||
|
||||
private final IKnowledgeAttachService attachService;
|
||||
|
||||
private final IKnowledgeFragmentService fragmentService;
|
||||
|
||||
private final EmbeddingService embeddingService;
|
||||
|
||||
private OpenAiStreamClient openAiStreamClient;
|
||||
|
||||
private final ChatConfig chatConfig;
|
||||
|
||||
/**
|
||||
* 知识库对话
|
||||
*/
|
||||
@PostMapping("/send")
|
||||
public SseEmitter send(@RequestBody @Valid ChatRequest chatRequest) {
|
||||
|
||||
openAiStreamClient = chatConfig.getOpenAiStreamClient();
|
||||
SseEmitter sseEmitter = new SseEmitter(0L);
|
||||
SSEEventSourceListener openAIEventSourceListener = new SSEEventSourceListener(sseEmitter);
|
||||
|
||||
List<Message> messages = chatRequest.getMessages();
|
||||
String content = messages.get(messages.size() - 1).getContent().toString();
|
||||
List<String> nearestList;
|
||||
List<Double> queryVector = embeddingService.getQueryVector(content);
|
||||
nearestList = vectorStore.nearest(queryVector,chatRequest.getKid());
|
||||
for (String prompt : nearestList) {
|
||||
Message sysMessage = Message.builder().content(prompt).role(Message.Role.USER).build();
|
||||
messages.add(sysMessage);
|
||||
}
|
||||
Message userMessage = Message.builder().content(content + (nearestList.size() > 0 ? "\n\n注意:回答问题时,须严格根据我给你的系统上下文内容原文进行回答,请不要自己发挥,回答时保持原来文本的段落层级" : "") ).role(Message.Role.USER).build();
|
||||
messages.add(userMessage);
|
||||
|
||||
|
||||
ChatCompletion completion = ChatCompletion
|
||||
.builder()
|
||||
.messages(messages)
|
||||
.model(chatRequest.getModel())
|
||||
.temperature(chatRequest.getTemperature())
|
||||
.topP(chatRequest.getTop_p())
|
||||
.stream(true)
|
||||
.build();
|
||||
openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener);
|
||||
|
||||
return sseEmitter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户信息查询本地知识库
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<KnowledgeInfoVo> list(KnowledgeInfoBo bo, PageQuery pageQuery) {
|
||||
if(!StpUtil.isLogin()){
|
||||
throw new SecurityException("请先去登录!");
|
||||
}
|
||||
bo.setUid(LoginHelper.getUserId());
|
||||
return knowledgeInfoService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 新增知识库
|
||||
*/
|
||||
@Log(title = "知识库", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/save")
|
||||
public R<Void> save(@Validated(AddGroup.class) @RequestBody KnowledgeInfoBo bo) {
|
||||
knowledgeInfoService.saveOne(bo);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除知识库
|
||||
*/
|
||||
@PostMapping("/remove/{id}")
|
||||
public R<String> remove(@PathVariable String id){
|
||||
knowledgeInfoService.removeKnowledge(id);
|
||||
return R.ok("删除知识库成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改知识库
|
||||
*/
|
||||
@Log(title = "知识库", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
public R<Void> edit( @RequestBody KnowledgeInfoBo bo) {
|
||||
return toAjax(knowledgeInfoService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出知识库列表
|
||||
*/
|
||||
@Log(title = "知识库", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(KnowledgeInfoBo bo, HttpServletResponse response) {
|
||||
List<KnowledgeInfoVo> list = knowledgeInfoService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "知识库", KnowledgeInfoVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询知识附件信息
|
||||
*/
|
||||
@GetMapping("/detail/{kid}")
|
||||
public TableDataInfo<KnowledgeAttachVo> attach(KnowledgeAttachBo bo, PageQuery pageQuery,@PathVariable String kid){
|
||||
bo.setKid(kid);
|
||||
return attachService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传知识库附件
|
||||
*/
|
||||
@PostMapping(value = "/attach/upload")
|
||||
public R<String> upload(KnowledgeInfoUploadRequest request){
|
||||
knowledgeInfoService.upload(request);
|
||||
return R.ok("上传知识库附件成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知识库附件详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@GetMapping("attach/info/{id}")
|
||||
public R<KnowledgeAttachVo> getAttachInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(attachService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除知识库附件
|
||||
*
|
||||
*/
|
||||
@PostMapping("attach/remove/{kid}")
|
||||
public R<Void> removeAttach(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable String kid) {
|
||||
attachService.removeKnowledgeAttach(kid);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询知识片段
|
||||
*/
|
||||
@GetMapping("/fragment/list/{docId}")
|
||||
public TableDataInfo<KnowledgeFragmentVo> fragmentList(KnowledgeFragmentBo bo, PageQuery pageQuery, @PathVariable String docId) {
|
||||
bo.setDocId(docId);
|
||||
return fragmentService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
|
||||
import io.github.ollama4j.OllamaAPI;
|
||||
import io.github.ollama4j.exceptions.OllamaBaseException;
|
||||
import io.github.ollama4j.models.chat.OllamaChatMessageRole;
|
||||
import io.github.ollama4j.models.chat.OllamaChatRequestBuilder;
|
||||
import io.github.ollama4j.models.chat.OllamaChatRequestModel;
|
||||
import io.github.ollama4j.models.chat.OllamaChatResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 描述:Ollama API调用
|
||||
*
|
||||
* @author ageerle@163.com
|
||||
* date 2024/11/6
|
||||
*/
|
||||
@RestController
|
||||
public class OllamaController {
|
||||
|
||||
|
||||
@RequestMapping(value = "/qianwen-ai2")
|
||||
private void ollama2(@RequestParam(value = "msg") String msg) {
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws OllamaBaseException, IOException, InterruptedException {
|
||||
|
||||
String host = "http://localhost:11434/";
|
||||
|
||||
OllamaAPI ollama = new OllamaAPI(host);
|
||||
OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance("qwen2.5:7b");
|
||||
// 设置超时时间
|
||||
ollama.setRequestTimeoutSeconds(100);
|
||||
// create first user question
|
||||
String text = "";
|
||||
|
||||
String json = "{\"instruction\": \"解答以下数学问题。\",\"input\": \"计算 2 + 3 的结果。\",\"output\": \"2 + 3 = 5\"}";
|
||||
|
||||
OllamaChatRequestModel requestModel = builder.withMessage
|
||||
(OllamaChatMessageRole.USER, "###文本:"+text+"###,理解文本内容,并且将文本内容转换为:"+json+"输出JSON格式,不要包含其他无关内容,内部使用无需脱敏")
|
||||
.withGetJsonResponse()
|
||||
.withStreaming()
|
||||
.build();
|
||||
|
||||
// start conversation with model
|
||||
OllamaChatResult chatResult = ollama.chat(requestModel);
|
||||
|
||||
System.out.println("First answer: " + chatResult.getResponse());
|
||||
|
||||
// create next userQuestion
|
||||
// requestModel = builder.withMessages(chatResult.getChatHistory()).withMessage(OllamaChatMessageRole.USER, "And what is the second largest city?").build();
|
||||
|
||||
// "continue" conversation with model
|
||||
// chatResult = ollamaAPI.chat(requestModel);
|
||||
|
||||
//System.out.println("Second answer: " + chatResult.getResponse());
|
||||
|
||||
// 历史记录
|
||||
//System.out.println("Chat History: " + chatResult.getChatHistory());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,28 +8,6 @@ spring.boot.admin.client:
|
||||
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:
|
||||
@@ -49,7 +27,8 @@ spring:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://43.139.70.230:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: ruoyi-ai
|
||||
password: TZ7yaGtSRWeeBaBJ
|
||||
password: eCaZ278N62k6fhYj
|
||||
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
maxPoolSize: 20
|
||||
@@ -78,7 +57,7 @@ spring.data:
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码(如没有密码请注释掉)
|
||||
#password:
|
||||
# password: 123456
|
||||
# 连接超时时间
|
||||
timeout: 10S
|
||||
# 是否开启ssl
|
||||
|
||||
@@ -6,7 +6,7 @@ ruoyi:
|
||||
# 版本
|
||||
version: ${revision}
|
||||
# 版权年份
|
||||
copyrightYear: 2023
|
||||
copyrightYear: 2025
|
||||
# 实例演示开关
|
||||
demoEnabled: true
|
||||
# 获取ip地址开关
|
||||
@@ -294,7 +294,7 @@ management:
|
||||
websocket:
|
||||
enabled: true
|
||||
# 路径
|
||||
path: ''
|
||||
path: '/resource/websocket'
|
||||
# 设置访问源地址
|
||||
allowedOrigins: '*'
|
||||
|
||||
@@ -308,28 +308,34 @@ wx:
|
||||
aesKey: #微信小程序消息服务器配置的EncodingAESKey
|
||||
msgDataFormat: JSON
|
||||
|
||||
# 企业微信应用
|
||||
wechat:
|
||||
# 是否使用微信 true/false
|
||||
enable: true
|
||||
# 生成的登录二维码路径 默认与项目同级
|
||||
qrPath: "./"
|
||||
# 企业微信应用
|
||||
cp:
|
||||
corpId:
|
||||
appConfigs:
|
||||
- agentId:
|
||||
secret: ''
|
||||
token: ''
|
||||
aesKey: ''
|
||||
|
||||
# 知识库配置
|
||||
chain:
|
||||
split:
|
||||
chunk:
|
||||
endspliter: "<STOP>"
|
||||
# 分块文本大小
|
||||
size: 500
|
||||
overlay: 0
|
||||
qaspliter: "######"
|
||||
size: 200
|
||||
overlay: 30
|
||||
qaspliter: "###"
|
||||
# 知识库中检索的条数
|
||||
limits: 5
|
||||
vectorization:
|
||||
type: openai
|
||||
openai:
|
||||
model: 'text-embedding-3-small'
|
||||
baidu:
|
||||
model: bge-large-zh
|
||||
zhipu:
|
||||
model: embedding-2
|
||||
# 智普API KEY
|
||||
token: xx
|
||||
vector:
|
||||
model: 'text-embedding-3-small'
|
||||
store:
|
||||
type: weaviate
|
||||
weaviate:
|
||||
@@ -341,38 +347,4 @@ chain:
|
||||
port: 19530
|
||||
dimension: 1536
|
||||
collection: LocalKnowledge
|
||||
llm:
|
||||
openai:
|
||||
token: sk-xx
|
||||
model: gpt-4-1106-preview
|
||||
chatglm:
|
||||
baseurl: http://127.0.0.1:8000/
|
||||
model: chatglm2-6b
|
||||
baidu:
|
||||
appKey: xx
|
||||
secretKey: xx
|
||||
model: ernie_bot
|
||||
zhipu:
|
||||
model: glm-4
|
||||
audio:
|
||||
type: openai
|
||||
text:
|
||||
type: openai
|
||||
function:
|
||||
type: baidu
|
||||
vision:
|
||||
type: openai
|
||||
image:
|
||||
type: openai
|
||||
|
||||
upload:
|
||||
path: /data/upload
|
||||
|
||||
proxy:
|
||||
socket:
|
||||
host: 127.0.0.1
|
||||
port: 7890
|
||||
|
||||
resource:
|
||||
domain: http://127.0.0.1:${server.port}/resources
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 469 KiB |
@@ -1,8 +0,0 @@
|
||||
@font-face {font-family: "Engravers' Old English BT";
|
||||
src: url("https://unpkg.com/dmego-home-page@latest/assets/fonts/d571b52b60b5617399ce8eab62bf3eb3.eot"); /* IE9*/
|
||||
src: url("https://unpkg.com/dmego-home-page@latest/assets/fonts/d571b52b60b5617399ce8eab62bf3eb3.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
|
||||
url("https://unpkg.com/dmego-home-page@latest/assets/fonts/d571b52b60b5617399ce8eab62bf3eb3.woff2") format("woff2"), /* chrome firefox */
|
||||
url("https://unpkg.com/dmego-home-page@latest/assets/fonts/d571b52b60b5617399ce8eab62bf3eb3.woff") format("woff"), /* chrome firefox */
|
||||
url("https://unpkg.com/dmego-home-page@latest/assets/fonts/d571b52b60b5617399ce8eab62bf3eb3.ttf") format("truetype"), /* chrome firefox opera Safari, Android, iOS 4.2+*/
|
||||
url("https://unpkg.com/dmego-home-page@latest/assets/fonts/d571b52b60b5617399ce8eab62bf3eb3.svg#Engravers' Old English BT") format("svg"); /* iOS 4.1- */
|
||||
}
|
||||
|
Before Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 251 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 115 KiB |
@@ -1,38 +0,0 @@
|
||||
const https = require('https')
|
||||
const fs = require('fs')
|
||||
|
||||
const options = {
|
||||
hostname: 'www.bing.com',
|
||||
port: 443,
|
||||
path: '/HPImageArchive.aspx?format=js&idx=0&n=8',
|
||||
method: 'GET'
|
||||
}
|
||||
|
||||
const req = https.request(options, bing_res => {
|
||||
let bing_body = [], bing_data = {};
|
||||
bing_res.on('data', (chunk) => {
|
||||
bing_body.push(chunk);
|
||||
});
|
||||
bing_res.on('end', () => {
|
||||
bing_body = Buffer.concat(bing_body);
|
||||
bing_data = JSON.parse(bing_body.toString());
|
||||
let img_array = bing_data.images;
|
||||
let img_url = [];
|
||||
img_array.forEach(img => {
|
||||
img_url.push(img.url);
|
||||
});
|
||||
var jsonpStr = "getBingImages(" + JSON.stringify(img_url) + ")";
|
||||
fs.writeFile('./assets/json/images.json', jsonpStr, (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log("JSON data is saved: " + jsonpStr);
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
req.on('error', error => {
|
||||
console.error(error)
|
||||
})
|
||||
|
||||
req.end()
|
||||
@@ -1,104 +0,0 @@
|
||||
var iUp = (function () {
|
||||
var time = 0,
|
||||
duration = 150,
|
||||
clean = function () {
|
||||
time = 0;
|
||||
},
|
||||
up = function (element) {
|
||||
setTimeout(function () {
|
||||
element.classList.add("up");
|
||||
}, time);
|
||||
time += duration;
|
||||
},
|
||||
down = function (element) {
|
||||
element.classList.remove("up");
|
||||
},
|
||||
toggle = function (element) {
|
||||
setTimeout(function () {
|
||||
element.classList.toggle("up");
|
||||
}, time);
|
||||
time += duration;
|
||||
};
|
||||
return {
|
||||
clean: clean,
|
||||
up: up,
|
||||
down: down,
|
||||
toggle: toggle
|
||||
};
|
||||
})();
|
||||
|
||||
function getBingImages(imgUrls) {
|
||||
/**
|
||||
* 获取Bing壁纸
|
||||
* 先使用 GitHub Action 每天获取 Bing 壁纸 URL 并更新 images.json 文件
|
||||
* 然后读取 images.json 文件中的数据
|
||||
*/
|
||||
var indexName = "bing-image-index";
|
||||
var index = sessionStorage.getItem(indexName);
|
||||
var panel = document.querySelector('#panel');
|
||||
if (isNaN(index) || index == 7) index = 0;
|
||||
else index++;
|
||||
var imgUrl = imgUrls[index];
|
||||
var url = "https://www.cn.bing.com" + imgUrl;
|
||||
panel.style.background = "url('" + url + "') center center no-repeat #666";
|
||||
panel.style.backgroundSize = "cover";
|
||||
sessionStorage.setItem(indexName, index);
|
||||
}
|
||||
|
||||
function decryptEmail(encoded) {
|
||||
var address = atob(encoded);
|
||||
window.location.href = "mailto:" + address;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// 获取一言数据
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function () {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
var res = JSON.parse(this.responseText);
|
||||
document.getElementById('description').innerHTML = res.hitokoto + "<br/> -「<strong>" + res.from + "</strong>」";
|
||||
}
|
||||
};
|
||||
xhr.open("GET", "https://v1.hitokoto.cn", true);
|
||||
xhr.send();
|
||||
|
||||
var iUpElements = document.querySelectorAll(".iUp");
|
||||
iUpElements.forEach(function (element) {
|
||||
iUp.up(element);
|
||||
});
|
||||
|
||||
var avatarElement = document.querySelector(".js-avatar");
|
||||
avatarElement.addEventListener('load', function () {
|
||||
avatarElement.classList.add("show");
|
||||
});
|
||||
});
|
||||
|
||||
var btnMobileMenu = document.querySelector('.btn-mobile-menu__icon');
|
||||
var navigationWrapper = document.querySelector('.navigation-wrapper');
|
||||
|
||||
btnMobileMenu.addEventListener('click', function () {
|
||||
if (navigationWrapper.style.display == "block") {
|
||||
navigationWrapper.addEventListener('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
|
||||
navigationWrapper.classList.toggle('visible');
|
||||
navigationWrapper.classList.toggle('animated');
|
||||
navigationWrapper.classList.toggle('bounceOutUp');
|
||||
navigationWrapper.removeEventListener('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', arguments.callee);
|
||||
});
|
||||
navigationWrapper.classList.toggle('animated');
|
||||
navigationWrapper.classList.toggle('bounceInDown');
|
||||
navigationWrapper.classList.toggle('animated');
|
||||
navigationWrapper.classList.toggle('bounceOutUp');
|
||||
} else {
|
||||
navigationWrapper.classList.toggle('visible');
|
||||
navigationWrapper.classList.toggle('animated');
|
||||
navigationWrapper.classList.toggle('bounceInDown');
|
||||
}
|
||||
btnMobileMenu.classList.toggle('social');
|
||||
btnMobileMenu.classList.toggle('iconfont');
|
||||
btnMobileMenu.classList.toggle('icon-list');
|
||||
btnMobileMenu.classList.toggle('social');
|
||||
btnMobileMenu.classList.toggle('iconfont');
|
||||
btnMobileMenu.classList.toggle('icon-angleup');
|
||||
btnMobileMenu.classList.toggle('animated');
|
||||
btnMobileMenu.classList.toggle('fadeIn');
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
getBingImages(["/th?id=OHR.TheRoachesPeakDistrict_EN-US9733115206_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.SanMiguelAllende_EN-US9621237021_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.JediMonastery_EN-US9398447907_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.SonoranSpring_EN-US9207877073_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.CratersOfTheMoon_EN-US6516727783_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.HawaiianLei_EN-US6290126556_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.CheetahRain_EN-US6179670004_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","/th?id=OHR.TulouFujian_EN-US6009679228_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp"])
|
||||
@@ -1 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1714852590465" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1571" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M263.1 844.8h497.7c22.9 0 41.5 18.6 41.5 41.5s-18.6 41.5-41.5 41.5H263.1c-22.9 0-41.5-18.6-41.5-41.5s18.6-41.5 41.5-41.5zM138.7 98.2h746.6c22.9 0 41.5 18.6 41.5 41.5v580.7c0 11-4.4 21.6-12.1 29.3-7.8 7.8-18.3 12.1-29.3 12.1H138.7c-11 0-21.6-4.4-29.3-12.1-7.8-7.8-12.1-18.3-12.1-29.3V139.7c-0.1-22.9 18.5-41.5 41.4-41.5z m331.8 478.9v60.4h83v-60.3c8.5-5.8 17.4-12.8 26.5-20.5l49.4 49.4 58.7-58.7-49.5-49.4c7.7-9 14.6-18 20.5-26.5h60.3v-83h-60.3c-6.4-9.1-13.3-18-20.5-26.5l49.4-49.4-58.7-58.6-49.4 49.4c-8.5-7.3-17.3-14.1-26.5-20.5v-60.3h-83V283c-8.5 5.8-17.4 12.8-26.5 20.5l-49.4-49.4-58.5 58.6 49.4 49.4c-7.2 8.5-14.1 17.3-20.5 26.5h-60.3v83h60.3c5.8 8.5 12.8 17.4 20.5 26.5L336 547.3l58.7 58.7 49.4-49.4c9.1 7.7 18 14.6 26.4 20.5z m0 0" p-id="1572"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,45 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
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 ==================");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
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 ==================");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
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 ==================");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,6 +33,7 @@
|
||||
<module>ruoyi-common-tenant</module>
|
||||
<module>ruoyi-common-chat</module>
|
||||
<module>ruoyi-common-pay</module>
|
||||
<module>ruoyi-common-wechat</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
|
||||
@@ -159,6 +159,13 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-wechat</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- AI绘画 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
|
||||
@@ -26,6 +26,18 @@
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.azure</groupId>
|
||||
<artifactId>azure-ai-openai</artifactId>
|
||||
<version>1.0.0-beta.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.ollama4j</groupId>
|
||||
<artifactId>ollama4j</artifactId>
|
||||
<version>1.0.79</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 序列化模块 -->
|
||||
<dependency>
|
||||
<groupId>org.ruoyi</groupId>
|
||||
@@ -42,11 +54,6 @@
|
||||
<artifactId>ruoyi-common-satoken</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>retrofit</artifactId>
|
||||
@@ -74,5 +81,16 @@
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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;
|
||||
|
||||
/** GPT3扣除费用 */
|
||||
public final static double GPT3_COST = 0.05;
|
||||
|
||||
/** GPT4扣除费用 */
|
||||
public final static double GPT4_COST = 0.2;
|
||||
|
||||
/** DALL普通绘图扣除费用 */
|
||||
public final static double DALL3_COST = 0.3;
|
||||
|
||||
/** DALL高清绘图扣除费用 */
|
||||
public final static double DALL3_HD_COST = 0.5;
|
||||
|
||||
/** MJ操作类型1(变化、变焦、文生图、图生图、局部重绘、混图)扣除费用 */
|
||||
public final static double MJ_COST_TYPE1 = 0.3;
|
||||
|
||||
/** MJ操作类型2(换脸、放大、图生文、prompt分析)扣除费用 */
|
||||
public final static double MJ_COST_TYPE2 = 0.1;
|
||||
|
||||
/** MJ操作类型3(查询任务进度、获取seed)扣除费用 */
|
||||
public final static double MJ_COST_TYPE3 = 0.0;
|
||||
|
||||
/** 默认账户余额 */
|
||||
public final static double USER_BALANCE = 5;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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";
|
||||
}
|
||||