2.0版本

This commit is contained in:
ageerle
2025-02-07 10:34:31 +08:00
parent 3c3ad701e3
commit c1cbfc2b93
968 changed files with 67565 additions and 1011 deletions

View File

@@ -4,7 +4,7 @@
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>
<groupId>org.ruoyi</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -18,9 +18,7 @@
<modules>
<module>ruoyi-demo</module>
<module>ruoyi-generator</module>
<module>ruoyi-job</module>
<module>ruoyi-midjourney</module>
<module>ruoyi-fusion</module>
<module>ruoyi-system</module>
</modules>

View File

@@ -3,7 +3,7 @@
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>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
@@ -20,82 +20,82 @@
<!-- 通用工具-->
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-doc</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-sms</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-mail</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-excel</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-web</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-ratelimiter</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-translation</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-sensitive</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-encrypt</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
</dependency>
<dependency>
<groupId>com.xmzs</groupId>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-common-pay</artifactId>
</dependency>

View File

@@ -0,0 +1,52 @@
package org.ruoyi.demo.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.mail.utils.MailUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
/**
* 邮件发送案例
*
* @author Michelle.Chung
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/mail")
public class MailController {
/**
* 发送邮件
*
* @param to 接收人
* @param subject 标题
* @param text 内容
*/
@GetMapping("/sendSimpleMessage")
public R<Void> sendSimpleMessage(String to, String subject, String text) {
MailUtils.sendText(to, subject, text);
return R.ok();
}
/**
* 发送邮件(带附件)
*
* @param to 接收人
* @param subject 标题
* @param text 内容
* @param filePath 附件路径
*/
@GetMapping("/sendMessageWithAttachment")
public R<Void> sendMessageWithAttachment(String to, String subject, String text, String filePath) {
MailUtils.sendText(to, subject, text, new File(filePath));
return R.ok();
}
}

View File

@@ -0,0 +1,95 @@
package org.ruoyi.demo.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.constant.CacheNames;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.redis.utils.RedisUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
/**
* spring-cache 演示案例
*
* @author Lion Li
*/
// 类级别 缓存统一配置
//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE)
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/cache")
public class RedisCacheController {
/**
* 测试 @Cacheable
* <p>
* 表示这个方法有了缓存的功能,方法的返回值会被缓存下来
* 下一次调用该方法前,会去检查是否缓存中已经有值
* 如果有就直接返回,不调用方法
* 如果没有,就调用方法,然后把结果缓存起来
* 这个注解「一般用在查询方法上」
* <p>
* 重点说明: 缓存注解严谨与其他筛选数据功能一起使用
* 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题
* <p>
* cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
*/
@Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null")
@GetMapping("/test1")
public R<String> test1(String key, String value) {
return R.ok("操作成功", value);
}
/**
* 测试 @CachePut
* <p>
* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用
* 它「通常用在新增或者实时更新方法上」
* <p>
* cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
*/
@CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
@GetMapping("/test2")
public R<String> test2(String key, String value) {
return R.ok("操作成功", value);
}
/**
* 测试 @CacheEvict
* <p>
* 使用了CacheEvict注解的方法,会清空指定缓存
* 「一般用在删除的方法上」
* <p>
* cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
*/
@CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
@GetMapping("/test3")
public R<String> test3(String key, String value) {
return R.ok("操作成功", value);
}
/**
* 测试设置过期时间
* 手动设置过期时间10秒
* 11秒后获取 判断是否相等
*/
@GetMapping("/test6")
public R<Boolean> test6(String key, String value) {
RedisUtils.setCacheObject(key, value);
boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10));
System.out.println("***********" + flag);
try {
Thread.sleep(11 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object obj = RedisUtils.getCacheObject(key);
return R.ok(value.equals(obj));
}
}

View File

@@ -0,0 +1,71 @@
package org.ruoyi.demo.controller;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.lock.executor.RedissonLockExecutor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.domain.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalTime;
/**
* 测试分布式锁的样例
*
* @author shenxinquan
*/
@Slf4j
@RestController
@RequestMapping("/demo/redisLock")
public class RedisLockController {
@Autowired
private LockTemplate lockTemplate;
/**
* 测试lock4j 注解
*/
@Lock4j(keys = {"#key"})
@GetMapping("/testLock4j")
public R<String> testLock4j(String key, String value) {
System.out.println("start:" + key + ",time:" + LocalTime.now().toString());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end :" + key + ",time:" + LocalTime.now().toString());
return R.ok("操作成功", value);
}
/**
* 测试lock4j 工具
*/
@GetMapping("/testLock4jLockTemplate")
public R<String> testLock4jLockTemplate(String key, String value) {
final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
if (null == lockInfo) {
throw new RuntimeException("业务处理中,请稍后再试");
}
// 获取锁成功,处理业务
try {
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
//
}
System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName());
} finally {
//释放锁
lockTemplate.releaseLock(lockInfo);
}
//结束
return R.ok("操作成功", value);
}
}

View File

@@ -0,0 +1,47 @@
package org.ruoyi.demo.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.redis.utils.RedisUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Redis 发布订阅 演示案例
*
* @author Lion Li
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/redis/pubsub")
public class RedisPubSubController {
/**
* 发布消息
*
* @param key 通道Key
* @param value 发送内容
*/
@GetMapping("/pub")
public R<Void> pub(String key, String value) {
RedisUtils.publish(key, value, consumer -> {
System.out.println("发布通道 => " + key + ", 发送值 => " + value);
});
return R.ok("操作成功");
}
/**
* 订阅消息
*
* @param key 通道Key
*/
@GetMapping("/sub")
public R<Void> sub(String key) {
RedisUtils.subscribe(key, String.class, msg -> {
System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
});
return R.ok("操作成功");
}
}

View File

@@ -0,0 +1,64 @@
package org.ruoyi.demo.controller;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.ratelimiter.annotation.RateLimiter;
import org.ruoyi.common.ratelimiter.enums.LimitType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试分布式限流样例
*
* @author Lion Li
*/
@Slf4j
@RestController
@RequestMapping("/demo/rateLimiter")
public class RedisRateLimiterController {
/**
* 测试全局限流
* 全局影响
*/
@RateLimiter(count = 2, time = 10)
@GetMapping("/test")
public R<String> test(String value) {
return R.ok("操作成功", value);
}
/**
* 测试请求IP限流
* 同一IP请求受影响
*/
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
@GetMapping("/testip")
public R<String> testip(String value) {
return R.ok("操作成功", value);
}
/**
* 测试集群实例限流
* 启动两个后端服务互不影响
*/
@RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
@GetMapping("/testcluster")
public R<String> testcluster(String value) {
return R.ok("操作成功", value);
}
/**
* 测试请求IP限流(key基于参数获取)
* 同一IP请求受影响
*
* 简单变量获取 #变量 复杂表达式 #{#变量 != 1 ? 1 : 0}
*/
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP, key = "#value")
@GetMapping("/testObj")
public R<String> testObj(String value) {
return R.ok("操作成功", value);
}
}

View File

@@ -0,0 +1,76 @@
package org.ruoyi.demo.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.utils.SpringUtils;
import org.ruoyi.common.sms.config.properties.SmsProperties;
import org.ruoyi.common.sms.core.SmsTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 短信演示案例
* 请先阅读文档 否则无法使用
*
* @author Lion Li
* @version 4.2.0
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/sms")
public class SmsController {
private final SmsProperties smsProperties;
// private final SmsTemplate smsTemplate; // 可以使用spring注入
// private final AliyunSmsTemplate smsTemplate; // 也可以注入某个厂家的模板工具
/**
* 发送短信Aliyun
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendAliyun")
public R<Object> sendAliyun(String phones, String templateId) {
if (!smsProperties.getEnabled()) {
return R.fail("当前系统没有开启短信功能!");
}
if (!SpringUtils.containsBean("aliyunSmsTemplate")) {
return R.fail("阿里云依赖未引入!");
}
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
Map<String, String> map = new HashMap<>(1);
map.put("code", "1234");
Object send = smsTemplate.send(phones, templateId, map);
return R.ok(send);
}
/**
* 发送短信Tencent
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendTencent")
public R<Object> sendTencent(String phones, String templateId) {
if (!smsProperties.getEnabled()) {
return R.fail("当前系统没有开启短信功能!");
}
if (!SpringUtils.containsBean("tencentSmsTemplate")) {
return R.fail("腾讯云依赖未引入!");
}
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
Map<String, String> map = new HashMap<>(1);
// map.put("2", "测试测试");
map.put("1", "1234");
Object send = smsTemplate.send(phones, templateId, map);
return R.ok(send);
}
}

View File

@@ -0,0 +1,31 @@
package org.ruoyi.demo.controller;
import org.ruoyi.common.core.domain.R;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* swagger3 用法示例
*
* @author Lion Li
*/
@RestController
@RequestMapping("/swagger/demo")
public class Swagger3DemoController {
/**
* 上传请求
* 必须使用 @RequestPart 注解标注为文件
*
* @param file 文件
*/
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<String> upload(@RequestPart("file") MultipartFile file) {
return R.ok("操作成功", file.getOriginalFilename());
}
}

View File

@@ -0,0 +1,90 @@
package org.ruoyi.demo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.demo.domain.TestDemo;
import org.ruoyi.demo.mapper.TestDemoMapper;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 测试批量方法
*
* @author Lion Li
* @date 2021-05-30
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/batch")
public class TestBatchController extends BaseController {
/**
* 为了便于测试 直接引入mapper
*/
private final TestDemoMapper testDemoMapper;
/**
* 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大)
* <p>
* 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度
*/
@PostMapping("/add")
// @DS("slave")
public R<Void> add() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
TestDemo testDemo = new TestDemo();
testDemo.setOrderNum(-1);
testDemo.setTestKey("批量新增");
testDemo.setValue("测试新增");
list.add(testDemo);
}
return toAjax(testDemoMapper.insertBatch(list));
}
/**
* 新增或更新 可完美替代 saveOrUpdateBatch 高性能
* <p>
* 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度
*/
@PostMapping("/addOrUpdate")
// @DS("slave")
public R<Void> addOrUpdate() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
TestDemo testDemo = new TestDemo();
testDemo.setOrderNum(-1);
testDemo.setTestKey("批量新增");
testDemo.setValue("测试新增");
list.add(testDemo);
}
testDemoMapper.insertBatch(list);
for (int i = 0; i < list.size(); i++) {
TestDemo testDemo = list.get(i);
testDemo.setTestKey("批量新增或修改");
testDemo.setValue("批量新增或修改");
if (i % 2 == 0) {
testDemo.setId(null);
}
}
return toAjax(testDemoMapper.insertOrUpdateBatch(list));
}
/**
* 删除批量方法
*/
@DeleteMapping()
// @DS("slave")
public R<Void> remove() {
return toAjax(testDemoMapper.delete(new LambdaQueryWrapper<TestDemo>()
.eq(TestDemo::getOrderNum, -1L)));
}
}

View File

@@ -0,0 +1,147 @@
package org.ruoyi.demo.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.utils.MapstructUtils;
import org.ruoyi.common.core.utils.ValidatorUtils;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.core.validate.QueryGroup;
import org.ruoyi.common.excel.core.ExcelResult;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
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.web.core.BaseController;
import org.ruoyi.demo.domain.TestDemo;
import org.ruoyi.demo.domain.bo.TestDemoBo;
import org.ruoyi.demo.domain.bo.TestDemoImportVo;
import org.ruoyi.demo.domain.vo.TestDemoVo;
import org.ruoyi.demo.service.ITestDemoService;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 测试单表Controller
*
* @author Lion Li
* @date 2021-07-26
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/demo")
public class TestDemoController extends BaseController {
private final ITestDemoService testDemoService;
/**
* 查询测试单表列表
*/
@SaCheckPermission("demo:demo:list")
@GetMapping("/list")
public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
return testDemoService.queryPageList(bo, pageQuery);
}
/**
* 自定义分页查询
*/
@SaCheckPermission("demo:demo:list")
@GetMapping("/page")
public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
return testDemoService.customPageList(bo, pageQuery);
}
/**
* 导入数据
*
* @param file 导入文件
*/
@Log(title = "测试单表", businessType = BusinessType.IMPORT)
@SaCheckPermission("demo:demo:import")
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
ExcelResult<TestDemoImportVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true);
List<TestDemo> list = MapstructUtils.convert(excelResult.getList(), TestDemo.class);
testDemoService.saveBatch(list);
return R.ok(excelResult.getAnalysis());
}
/**
* 导出测试单表列表
*/
@SaCheckPermission("demo:demo:export")
@Log(title = "测试单表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
List<TestDemoVo> list = testDemoService.queryList(bo);
// 测试雪花id导出
// for (TestDemoVo vo : list) {
// vo.setId(1234567891234567893L);
// }
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
}
/**
* 获取测试单表详细信息
*
* @param id 测试ID
*/
@SaCheckPermission("demo:demo:query")
@GetMapping("/{id}")
public R<TestDemoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(testDemoService.queryById(id));
}
/**
* 新增测试单表
*/
@SaCheckPermission("demo:demo:add")
@Log(title = "测试单表", businessType = BusinessType.INSERT)
@RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}")
@PostMapping()
public R<Void> add(@RequestBody TestDemoBo bo) {
// 使用校验工具对标 @Validated(AddGroup.class) 注解
// 用于在非 Controller 的地方校验对象
ValidatorUtils.validate(bo, AddGroup.class);
return toAjax(testDemoService.insertByBo(bo));
}
/**
* 修改测试单表
*/
@SaCheckPermission("demo:demo:edit")
@Log(title = "测试单表", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
return toAjax(testDemoService.updateByBo(bo));
}
/**
* 删除测试单表
*
* @param ids 测试ID串
*/
@SaCheckPermission("demo:demo:remove")
@Log(title = "测试单表", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(testDemoService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}

View File

@@ -0,0 +1,55 @@
package org.ruoyi.demo.controller;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.demo.domain.TestDemoEncrypt;
import org.ruoyi.demo.mapper.TestDemoEncryptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 测试数据库加解密功能
*
* @author Lion Li
*/
@Validated
@RestController
@RequestMapping("/demo/encrypt")
public class TestEncryptController {
@Autowired
private TestDemoEncryptMapper mapper;
@Value("${mybatis-encryptor.enable}")
private Boolean encryptEnable;
/**
* 测试数据库加解密
*
* @param key 测试key
* @param value 测试value
*/
@GetMapping()
public R<Map<String, TestDemoEncrypt>> test(String key, String value) {
if (!encryptEnable) {
throw new RuntimeException("加密功能未开启!");
}
Map<String, TestDemoEncrypt> map = new HashMap<>(2);
TestDemoEncrypt demo = new TestDemoEncrypt();
demo.setTestKey(key);
demo.setValue(value);
mapper.insert(demo);
map.put("加密", demo);
TestDemoEncrypt testDemo = mapper.selectById(demo.getId());
map.put("解密", testDemo);
return R.ok(map);
}
}

View File

@@ -0,0 +1,97 @@
package org.ruoyi.demo.controller;
import cn.hutool.core.collection.CollUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试Excel功能
*
* @author Lion Li
*/
@RestController
@RequestMapping("/demo/excel")
public class TestExcelController {
/**
* 单列表多数据
*/
@GetMapping("/exportTemplateOne")
public void exportTemplateOne(HttpServletResponse response) {
Map<String, String> map = new HashMap<>();
map.put("title", "单列表多数据");
map.put("test1", "数据测试1");
map.put("test2", "数据测试2");
map.put("test3", "数据测试3");
map.put("test4", "数据测试4");
map.put("testTest", "666");
List<TestObj> list = new ArrayList<>();
list.add(new TestObj("单列表测试1", "列表测试1", "列表测试2", "列表测试3", "列表测试4"));
list.add(new TestObj("单列表测试2", "列表测试5", "列表测试6", "列表测试7", "列表测试8"));
list.add(new TestObj("单列表测试3", "列表测试9", "列表测试10", "列表测试11", "列表测试12"));
ExcelUtil.exportTemplate(CollUtil.newArrayList(map, list), "单列表.xlsx", "excel/单列表.xlsx", response);
}
/**
* 多列表多数据
*/
@GetMapping("/exportTemplateMuliti")
public void exportTemplateMuliti(HttpServletResponse response) {
Map<String, String> map = new HashMap<>();
map.put("title1", "标题1");
map.put("title2", "标题2");
map.put("title3", "标题3");
map.put("title4", "标题4");
map.put("author", "Lion Li");
List<TestObj1> list1 = new ArrayList<>();
list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3"));
list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6"));
list1.add(new TestObj1("list1测试7", "list1测试8", "list1测试9"));
List<TestObj1> list2 = new ArrayList<>();
list2.add(new TestObj1("list2测试1", "list2测试2", "list2测试3"));
list2.add(new TestObj1("list2测试4", "list2测试5", "list2测试6"));
List<TestObj1> list3 = new ArrayList<>();
list3.add(new TestObj1("list3测试1", "list3测试2", "list3测试3"));
List<TestObj1> list4 = new ArrayList<>();
list4.add(new TestObj1("list4测试1", "list4测试2", "list4测试3"));
list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6"));
list4.add(new TestObj1("list4测试7", "list4测试8", "list4测试9"));
list4.add(new TestObj1("list4测试10", "list4测试11", "list4测试12"));
Map<String, Object> multiListMap = new HashMap<>();
multiListMap.put("map", map);
multiListMap.put("data1", list1);
multiListMap.put("data2", list2);
multiListMap.put("data3", list3);
multiListMap.put("data4", list4);
ExcelUtil.exportTemplateMultiList(multiListMap, "多列表.xlsx", "excel/多列表.xlsx", response);
}
@Data
@AllArgsConstructor
static class TestObj1 {
private String test1;
private String test2;
private String test3;
}
@Data
@AllArgsConstructor
static class TestObj {
private String name;
private String list1;
private String list2;
private String list3;
private String list4;
}
}

View File

@@ -0,0 +1,70 @@
package org.ruoyi.demo.controller;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.utils.MessageUtils;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试国际化
*
* @author Lion Li
*/
@Validated
@RestController
@RequestMapping("/demo/i18n")
public class TestI18nController {
/**
* 通过code获取国际化内容
* code为 messages.properties 中的 key
* <p>
* 测试使用 user.register.success
*
* @param code 国际化code
*/
@GetMapping()
public R<Void> get(String code) {
return R.ok(MessageUtils.message(code));
}
/**
* Validator 校验国际化
* 不传值 分别查看异常返回
* <p>
* 测试使用 not.null
*/
@GetMapping("/test1")
public R<Void> test1(@NotBlank(message = "{not.null}") String str) {
return R.ok(str);
}
/**
* Bean 校验国际化
* 不传值 分别查看异常返回
* <p>
* 测试使用 not.null
*/
@GetMapping("/test2")
public R<TestI18nBo> test2(@Validated TestI18nBo bo) {
return R.ok(bo);
}
@Data
public static class TestI18nBo {
@NotBlank(message = "{not.null}")
private String name;
@NotNull(message = "{not.null}")
@Range(min = 0, max = 100, message = "{length.not.valid}")
private Integer age;
}
}

View File

@@ -0,0 +1,76 @@
package org.ruoyi.demo.controller;
import lombok.Data;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.sensitive.annotation.Sensitive;
import org.ruoyi.common.sensitive.core.SensitiveService;
import org.ruoyi.common.sensitive.core.SensitiveStrategy;
import org.ruoyi.common.web.core.BaseController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试数据脱敏控制器
* <p>
* 默认管理员不过滤
* 需自行根据业务重写实现
*
* @author Lion Li
* @version 3.6.0
* @see SensitiveService
*/
@RestController
@RequestMapping("/demo/sensitive")
public class TestSensitiveController extends BaseController {
/**
* 测试数据脱敏
*/
@GetMapping("/test")
public R<TestSensitive> test() {
TestSensitive testSensitive = new TestSensitive();
testSensitive.setIdCard("210397198608215431");
testSensitive.setPhone("17640125371");
testSensitive.setAddress("北京市朝阳区某某四合院1203室");
testSensitive.setEmail("17640125371@163.com");
testSensitive.setBankCard("6226456952351452853");
return R.ok(testSensitive);
}
@Data
static class TestSensitive {
/**
* 身份证
*/
@Sensitive(strategy = SensitiveStrategy.ID_CARD)
private String idCard;
/**
* 电话
*/
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phone;
/**
* 地址
*/
@Sensitive(strategy = SensitiveStrategy.ADDRESS)
private String address;
/**
* 邮箱
*/
@Sensitive(strategy = SensitiveStrategy.EMAIL)
private String email;
/**
* 银行卡
*/
@Sensitive(strategy = SensitiveStrategy.BANK_CARD)
private String bankCard;
}
}

View File

@@ -0,0 +1,107 @@
package org.ruoyi.demo.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.core.validate.QueryGroup;
import org.ruoyi.common.excel.utils.ExcelUtil;
import org.ruoyi.common.idempotent.annotation.RepeatSubmit;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.demo.domain.bo.TestTreeBo;
import org.ruoyi.demo.domain.vo.TestTreeVo;
import org.ruoyi.demo.service.ITestTreeService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
/**
* 测试树表Controller
*
* @author Lion Li
* @date 2021-07-26
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/tree")
public class TestTreeController extends BaseController {
private final ITestTreeService testTreeService;
/**
* 查询测试树表列表
*/
@SaCheckPermission("demo:tree:list")
@GetMapping("/list")
public R<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) {
List<TestTreeVo> list = testTreeService.queryList(bo);
return R.ok(list);
}
/**
* 导出测试树表列表
*/
@SaCheckPermission("demo:tree:export")
@Log(title = "测试树表", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public void export(@Validated TestTreeBo bo, HttpServletResponse response) {
List<TestTreeVo> list = testTreeService.queryList(bo);
ExcelUtil.exportExcel(list, "测试树表", TestTreeVo.class, response);
}
/**
* 获取测试树表详细信息
*
* @param id 测试树ID
*/
@SaCheckPermission("demo:tree:query")
@GetMapping("/{id}")
public R<TestTreeVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(testTreeService.queryById(id));
}
/**
* 新增测试树表
*/
@SaCheckPermission("demo:tree:add")
@Log(title = "测试树表", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
return toAjax(testTreeService.insertByBo(bo));
}
/**
* 修改测试树表
*/
@SaCheckPermission("demo:tree:edit")
@Log(title = "测试树表", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
return toAjax(testTreeService.updateByBo(bo));
}
/**
* 删除测试树表
*
* @param ids 测试树ID串
*/
@SaCheckPermission("demo:tree:remove")
@Log(title = "测试树表", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(testTreeService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}

View File

@@ -0,0 +1,90 @@
package org.ruoyi.demo.controller.queue;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.redis.utils.QueueUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 有界队列 演示案例
* <p>
* 轻量级队列 重量级数据量 请使用 MQ
* <p>
* 集群测试通过 同一个数据只会被消费一次 做好事务补偿
* 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条
*
* @author Lion Li
* @version 3.6.0
*/
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/queue/bounded")
public class BoundedQueueController {
/**
* 添加队列数据
*
* @param queueName 队列名
* @param capacity 容量
*/
@GetMapping("/add")
public R<Void> add(String queueName, int capacity) {
// 用完了一定要销毁 否则会一直存在
boolean b = QueueUtils.destroyQueue(queueName);
log.info("通道: {} , 删除: {}", queueName, b);
// 初始化设置一次即可
if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) {
log.info("通道: {} , 设置容量: {}", queueName, capacity);
} else {
log.info("通道: {} , 设置容量失败", queueName);
return R.fail("操作失败");
}
for (int i = 0; i < 11; i++) {
String data = "data-" + i;
boolean flag = QueueUtils.addBoundedQueueObject(queueName, data);
if (flag == false) {
log.info("通道: {} , 发送数据: {} 失败, 通道已满", queueName, data);
} else {
log.info("通道: {} , 发送数据: {}", queueName, data);
}
}
return R.ok("操作成功");
}
/**
* 删除队列数据
*
* @param queueName 队列名
*/
@GetMapping("/remove")
public R<Void> remove(String queueName) {
String data = "data-" + 5;
if (QueueUtils.removeQueueObject(queueName, data)) {
log.info("通道: {} , 删除数据: {}", queueName, data);
} else {
return R.fail("操作失败");
}
return R.ok("操作成功");
}
/**
* 获取队列数据
*
* @param queueName 队列名
*/
@GetMapping("/get")
public R<Void> get(String queueName) {
String data;
do {
data = QueueUtils.getQueueObject(queueName);
log.info("通道: {} , 获取数据: {}", queueName, data);
} while (data != null);
return R.ok("操作成功");
}
}

View File

@@ -0,0 +1,90 @@
package org.ruoyi.demo.controller.queue;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.redis.utils.QueueUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* 延迟队列 演示案例
* <p>
* 轻量级队列 重量级数据量 请使用 MQ
* 例如: 创建订单30分钟后过期处理
* <p>
* 集群测试通过 同一个数据只会被消费一次 做好事务补偿
* 集群测试流程 两台集群分别开启订阅 在其中一台发送数据 观察接收消息的规律
*
* @author Lion Li
* @version 3.6.0
*/
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/queue/delayed")
public class DelayedQueueController {
/**
* 订阅队列
*
* @param queueName 队列名
*/
@GetMapping("/subscribe")
public R<Void> subscribe(String queueName) {
log.info("通道: {} 监听中......", queueName);
// 项目初始化设置一次即可
QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> {
// 观察接收时间
log.info("通道: {}, 收到数据: {}", queueName, orderNum);
});
return R.ok("操作成功");
}
/**
* 添加队列数据
*
* @param queueName 队列名
* @param orderNum 订单号
* @param time 延迟时间(秒)
*/
@GetMapping("/add")
public R<Void> add(String queueName, String orderNum, Long time) {
QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS);
// 观察发送时间
log.info("通道: {} , 发送数据: {}", queueName, orderNum);
return R.ok("操作成功");
}
/**
* 删除队列数据
*
* @param queueName 队列名
* @param orderNum 订单号
*/
@GetMapping("/remove")
public R<Void> remove(String queueName, String orderNum) {
if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) {
log.info("通道: {} , 删除数据: {}", queueName, orderNum);
} else {
return R.fail("操作失败");
}
return R.ok("操作成功");
}
/**
* 销毁队列
*
* @param queueName 队列名
*/
@GetMapping("/destroy")
public R<Void> destroy(String queueName) {
// 用完了一定要销毁 否则会一直存在
QueueUtils.destroyDelayedQueue(queueName);
return R.ok("操作成功");
}
}

View File

@@ -0,0 +1,22 @@
package org.ruoyi.demo.controller.queue;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 实体类 注意不允许使用内部类 否则会找不到类
*
* @author Lion Li
* @version 3.6.0
*/
@Data
@NoArgsConstructor
public class PriorityDemo implements Comparable<PriorityDemo> {
private String name;
private Integer orderNum;
@Override
public int compareTo(PriorityDemo other) {
return Integer.compare(getOrderNum(), other.getOrderNum());
}
}

View File

@@ -0,0 +1,89 @@
package org.ruoyi.demo.controller.queue;
import cn.hutool.core.util.RandomUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.redis.utils.QueueUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 优先队列 演示案例
* <p>
* 轻量级队列 重量级数据量 请使用 MQ
* <p>
* 集群测试通过 同一个消息只会被消费一次 做好事务补偿
* 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条
*
* @author Lion Li
* @version 3.6.0
*/
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/queue/priority")
public class PriorityQueueController {
/**
* 添加队列数据
*
* @param queueName 队列名
*/
@GetMapping("/add")
public R<Void> add(String queueName) {
// 用完了一定要销毁 否则会一直存在
boolean b = QueueUtils.destroyQueue(queueName);
log.info("通道: {} , 删除: {}", queueName, b);
for (int i = 0; i < 10; i++) {
int randomNum = RandomUtil.randomInt(10);
PriorityDemo data = new PriorityDemo();
data.setName("data-" + i);
data.setOrderNum(randomNum);
if (QueueUtils.addPriorityQueueObject(queueName, data)) {
log.info("通道: {} , 发送数据: {}", queueName, data);
} else {
log.info("通道: {} , 发送数据: {}, 发送失败", queueName, data);
}
}
return R.ok("操作成功");
}
/**
* 删除队列数据
*
* @param queueName 队列名
* @param name 对象名
* @param orderNum 排序号
*/
@GetMapping("/remove")
public R<Void> remove(String queueName, String name, Integer orderNum) {
PriorityDemo data = new PriorityDemo();
data.setName(name);
data.setOrderNum(orderNum);
if (QueueUtils.removeQueueObject(queueName, data)) {
log.info("通道: {} , 删除数据: {}", queueName, data);
} else {
return R.fail("操作失败");
}
return R.ok("操作成功");
}
/**
* 获取队列数据
*
* @param queueName 队列名
*/
@GetMapping("/get")
public R<Void> get(String queueName) {
PriorityDemo data;
do {
data = QueueUtils.getQueueObject(queueName);
log.info("通道: {} , 获取数据: {}", queueName, data);
} while (data != null);
return R.ok("操作成功");
}
}

View File

@@ -0,0 +1,68 @@
package org.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* 测试单表对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_demo")
public class TestDemo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 部门id
*/
private Long deptId;
/**
* 用户id
*/
private Long userId;
/**
* 排序号
*/
@OrderBy(asc = false, sort = 1)
private Integer orderNum;
/**
* key键
*/
private String testKey;
/**
* 值
*/
private String value;
/**
* 版本
*/
@Version
private Long version;
/**
* 删除标志
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,29 @@
package org.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.encrypt.annotation.EncryptField;
import org.ruoyi.common.encrypt.enumd.AlgorithmType;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_demo")
public class TestDemoEncrypt extends TestDemo {
/**
* key键
*/
// @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==")
@EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB")
private String testKey;
/**
* 值
*/
// @EncryptField // 什么也不写走默认yml配置
// @EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5")
@EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5")
private String value;
}

View File

@@ -0,0 +1,65 @@
package org.ruoyi.demo.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* 测试树表对象 test_tree
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_tree")
public class TestTree extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 父ID
*/
private Long parentId;
/**
* 部门id
*/
private Long deptId;
/**
* 用户id
*/
private Long userId;
/**
* 树节点名
*/
private String treeName;
/**
* 版本
*/
@Version
private Long version;
/**
* 删除标志
*/
@TableLogic
private Long delFlag;
}

View File

@@ -0,0 +1,61 @@
package org.ruoyi.demo.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
import org.ruoyi.demo.domain.TestDemo;
/**
* 测试单表业务对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TestDemo.class, reverseConvertGenerate = false)
public class TestDemoBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
* 部门id
*/
@NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long deptId;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long userId;
/**
* 排序号
*/
@NotNull(message = "排序号不能为空", groups = {AddGroup.class, EditGroup.class})
private Integer orderNum;
/**
* key键
*/
@NotBlank(message = "key键不能为空", groups = {AddGroup.class, EditGroup.class})
private String testKey;
/**
* 值
*/
@NotBlank(message = "值不能为空", groups = {AddGroup.class, EditGroup.class})
private String value;
}

View File

@@ -0,0 +1,52 @@
package org.ruoyi.demo.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 测试单表业务对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
public class TestDemoImportVo {
/**
* 部门id
*/
@NotNull(message = "部门id不能为空")
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空")
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 排序号
*/
@NotNull(message = "排序号不能为空")
@ExcelProperty(value = "排序号")
private Long orderNum;
/**
* key键
*/
@NotBlank(message = "key键不能为空")
@ExcelProperty(value = "key键")
private String testKey;
/**
* 值
*/
@NotBlank(message = "值不能为空")
@ExcelProperty(value = "")
private String value;
}

View File

@@ -0,0 +1,54 @@
package org.ruoyi.demo.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.common.core.validate.AddGroup;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.mybatis.core.domain.BaseEntity;
import org.ruoyi.demo.domain.TestTree;
/**
* 测试树表业务对象 test_tree
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TestTree.class, reverseConvertGenerate = false)
public class TestTreeBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
* 父ID
*/
private Long parentId;
/**
* 部门id
*/
@NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long deptId;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long userId;
/**
* 树节点名
*/
@NotBlank(message = "树节点名不能为空", groups = {AddGroup.class, EditGroup.class})
private String treeName;
}

View File

@@ -0,0 +1,104 @@
package org.ruoyi.demo.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.ruoyi.common.translation.annotation.Translation;
import org.ruoyi.common.translation.constant.TransConstant;
import org.ruoyi.demo.domain.TestDemo;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 测试单表视图对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TestDemo.class)
public class TestDemoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 部门id
*/
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 排序号
*/
@ExcelProperty(value = "排序号")
private Integer orderNum;
/**
* key键
*/
@ExcelProperty(value = "key键")
private String testKey;
/**
* 值
*/
@ExcelProperty(value = "")
private String value;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 创建人
*/
@ExcelProperty(value = "创建人")
private Long createBy;
/**
* 创建人账号
*/
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
@ExcelProperty(value = "创建人账号")
private String createByName;
/**
* 更新时间
*/
@ExcelProperty(value = "更新时间")
private Date updateTime;
/**
* 更新人
*/
@ExcelProperty(value = "更新人")
private Long updateBy;
/**
* 更新人账号
*/
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "updateBy")
@ExcelProperty(value = "更新人账号")
private String updateByName;
}

View File

@@ -0,0 +1,64 @@
package org.ruoyi.demo.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.ruoyi.demo.domain.TestTree;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 测试树表视图对象 test_tree
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TestTree.class)
public class TestTreeVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private Long id;
/**
* 父id
*/
@ExcelProperty(value = "父id")
private Long parentId;
/**
* 部门id
*/
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 树节点名
*/
@ExcelProperty(value = "树节点名")
private String treeName;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,13 @@
package org.ruoyi.demo.mapper;
import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
import org.ruoyi.demo.domain.TestDemoEncrypt;
/**
* 测试加密功能
*
* @author Lion Li
*/
public interface TestDemoEncryptMapper extends BaseMapperPlus<TestDemoEncrypt, TestDemoEncrypt> {
}

View File

@@ -0,0 +1,58 @@
package org.ruoyi.demo.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.ruoyi.common.mybatis.annotation.DataColumn;
import org.ruoyi.common.mybatis.annotation.DataPermission;
import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
import org.ruoyi.demo.domain.TestDemo;
import org.ruoyi.demo.domain.vo.TestDemoVo;
import java.util.Collection;
import java.util.List;
/**
* 测试单表Mapper接口
*
* @author Lion Li
* @date 2021-07-26
*/
public interface TestDemoMapper extends BaseMapperPlus<TestDemo, TestDemoVo> {
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper);
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
<P extends IPage<TestDemo>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
List<TestDemo> selectList(@Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
int updateById(@Param(Constants.ENTITY) TestDemo entity);
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
int deleteBatchIds(@Param(Constants.COLL) Collection<?> idList);
}

View File

@@ -0,0 +1,21 @@
package org.ruoyi.demo.mapper;
import org.ruoyi.common.mybatis.annotation.DataColumn;
import org.ruoyi.common.mybatis.annotation.DataPermission;
import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
import org.ruoyi.demo.domain.TestTree;
import org.ruoyi.demo.domain.vo.TestTreeVo;
/**
* 测试树表Mapper接口
*
* @author Lion Li
* @date 2021-07-26
*/
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
public interface TestTreeMapper extends BaseMapperPlus<TestTree, TestTreeVo> {
}

View File

@@ -0,0 +1,71 @@
package org.ruoyi.demo.service;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.demo.domain.TestDemo;
import org.ruoyi.demo.domain.bo.TestDemoBo;
import org.ruoyi.demo.domain.vo.TestDemoVo;
import java.util.Collection;
import java.util.List;
/**
* 测试单表Service接口
*
* @author Lion Li
* @date 2021-07-26
*/
public interface ITestDemoService {
/**
* 查询单个
*
* @return
*/
TestDemoVo queryById(Long id);
/**
* 查询列表
*/
TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery);
/**
* 自定义分页查询
*/
TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery);
/**
* 查询列表
*/
List<TestDemoVo> queryList(TestDemoBo bo);
/**
* 根据新增业务对象插入测试单表
*
* @param bo 测试单表新增业务对象
* @return
*/
Boolean insertByBo(TestDemoBo bo);
/**
* 根据编辑业务对象修改测试单表
*
* @param bo 测试单表编辑业务对象
* @return
*/
Boolean updateByBo(TestDemoBo bo);
/**
* 校验并删除数据
*
* @param ids 主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 批量保存
*/
Boolean saveBatch(List<TestDemo> list);
}

View File

@@ -0,0 +1,52 @@
package org.ruoyi.demo.service;
import org.ruoyi.demo.domain.bo.TestTreeBo;
import org.ruoyi.demo.domain.vo.TestTreeVo;
import java.util.Collection;
import java.util.List;
/**
* 测试树表Service接口
*
* @author Lion Li
* @date 2021-07-26
*/
public interface ITestTreeService {
/**
* 查询单个
*
* @return
*/
TestTreeVo queryById(Long id);
/**
* 查询列表
*/
List<TestTreeVo> queryList(TestTreeBo bo);
/**
* 根据新增业务对象插入测试树表
*
* @param bo 测试树表新增业务对象
* @return
*/
Boolean insertByBo(TestTreeBo bo);
/**
* 根据编辑业务对象修改测试树表
*
* @param bo 测试树表编辑业务对象
* @return
*/
Boolean updateByBo(TestTreeBo bo);
/**
* 校验并删除数据
*
* @param ids 主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,110 @@
package org.ruoyi.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.utils.MapstructUtils;
import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.demo.domain.TestDemo;
import org.ruoyi.demo.domain.bo.TestDemoBo;
import org.ruoyi.demo.domain.vo.TestDemoVo;
import org.ruoyi.demo.mapper.TestDemoMapper;
import org.ruoyi.demo.service.ITestDemoService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 测试单表Service业务层处理
*
* @author Lion Li
* @date 2021-07-26
*/
@RequiredArgsConstructor
@Service
public class TestDemoServiceImpl implements ITestDemoService {
private final TestDemoMapper baseMapper;
@Override
public TestDemoVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
@Override
public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
Page<TestDemoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 自定义分页查询
*/
@Override
public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
Page<TestDemoVo> result = baseMapper.customPageList(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<TestDemoVo> queryList(TestDemoBo bo) {
return baseMapper.selectVoList(buildQueryWrapper(bo));
}
private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
return lqw;
}
@Override
public Boolean insertByBo(TestDemoBo bo) {
TestDemo add = MapstructUtils.convert(bo, TestDemo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
@Override
public Boolean updateByBo(TestDemoBo bo) {
TestDemo update = MapstructUtils.convert(bo, TestDemo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*
* @param entity 实体类数据
*/
private void validEntityBeforeSave(TestDemo entity) {
//TODO 做一些数据校验,如唯一约束
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public Boolean saveBatch(List<TestDemo> list) {
return baseMapper.insertBatch(list);
}
}

View File

@@ -0,0 +1,87 @@
package org.ruoyi.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.utils.MapstructUtils;
import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.demo.domain.TestTree;
import org.ruoyi.demo.domain.bo.TestTreeBo;
import org.ruoyi.demo.domain.vo.TestTreeVo;
import org.ruoyi.demo.mapper.TestTreeMapper;
import org.ruoyi.demo.service.ITestTreeService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 测试树表Service业务层处理
*
* @author Lion Li
* @date 2021-07-26
*/
// @DS("slave") // 切换从库查询
@RequiredArgsConstructor
@Service
public class TestTreeServiceImpl implements ITestTreeService {
private final TestTreeMapper baseMapper;
@Override
public TestTreeVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
// @DS("slave") // 切换从库查询
@Override
public List<TestTreeVo> queryList(TestTreeBo bo) {
LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
return lqw;
}
@Override
public Boolean insertByBo(TestTreeBo bo) {
TestTree add = MapstructUtils.convert(bo, TestTree.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
@Override
public Boolean updateByBo(TestTreeBo bo) {
TestTree update = MapstructUtils.convert(bo, TestTree.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*
* @param entity 实体类数据
*/
private void validEntityBeforeSave(TestTree entity) {
//TODO 做一些数据校验,如唯一约束
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -2,9 +2,9 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xmzs.demo.mapper.TestDemoMapper">
<mapper namespace="org.ruoyi.demo.mapper.TestDemoMapper">
<select id="customPageList" resultType="com.xmzs.demo.domain.vo.TestDemoVo">
<select id="customPageList" resultType="org.ruoyi.demo.domain.vo.TestDemoVo">
SELECT * FROM test_demo ${ew.customSqlSegment}
</select>

View File

@@ -2,6 +2,6 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xmzs.demo.mapper.TestTreeMapper">
<mapper namespace="org.ruoyi.demo.mapper.TestTreeMapper">
</mapper>

View File

@@ -0,0 +1,119 @@
<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/maven-v4_0_0.xsd">
<parent>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-fusion</artifactId>
<description>
AI绘画
</description>
<properties>
<hutool.version>5.8.18</hutool.version>
<org-json.version>20220924</org-json.version>
<jda.version>5.0.0-beta.9</jda.version>
<chatgpt-java.version>1.1.2-beta0</chatgpt-java.version>
<dataurl.version>2.0.0</dataurl.version>
<knife4j.verison>4.1.0</knife4j.verison>
<user-agent-utils.verison>1.21</user-agent-utils.verison>
<httpclient.verison>4.5.14</httpclient.verison>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-cache</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${org-json.version}</version>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>${jda.version}</version>
<exclusions>
<exclusion>
<groupId>club.minnced</groupId>
<artifactId>opus-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.unfbx</groupId>
<artifactId>chatgpt-java</artifactId>
<version>${chatgpt-java.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-simple</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>eu.maxschuster</groupId>
<artifactId>dataurl</artifactId>
<version>${dataurl.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>${knife4j.verison}</version>
</dependency>
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>${user-agent-utils.verison}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,114 @@
package org.ruoyi.fusion.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.chat.domain.request.ChatRequest;
import org.ruoyi.common.chat.domain.request.Dall3Request;
import org.ruoyi.common.chat.entity.Tts.TextToSpeech;
import org.ruoyi.common.chat.entity.files.UploadFileResponse;
import org.ruoyi.common.chat.entity.images.Item;
import org.ruoyi.common.chat.entity.whisper.WhisperResponse;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.domain.model.LoginUser;
import org.ruoyi.common.core.exception.base.BaseException;
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.system.domain.bo.ChatMessageBo;
import org.ruoyi.system.domain.vo.ChatMessageVo;
import org.ruoyi.system.service.IChatMessageService;
import org.ruoyi.system.service.ISseService;
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 ageerle@163.com
* @date 2023-03-01
*/
@Controller
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/chat")
public class ChatController {
private final ISseService ISseService;
private final IChatMessageService chatMessageService;
/**
* 聊天接口
*/
@PostMapping("/send")
@ResponseBody
public SseEmitter sseChat(@RequestBody @Valid ChatRequest chatRequest, HttpServletRequest request) {
return ISseService.sseChat(chatRequest,request);
}
/**
* 上传文件
*/
@PostMapping("/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);
}
}

View File

@@ -0,0 +1,42 @@
package org.ruoyi.fusion.controller;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.apache.commons.lang3.math.NumberUtils;
import org.ruoyi.fusion.domain.InsightFace;
import org.ruoyi.fusion.util.MjOkHttpUtil;
import org.ruoyi.system.service.IChatCostService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "任务查询")
@RestController
@RequestMapping("/mj")
@RequiredArgsConstructor
@Slf4j
public class FaceController {
private final IChatCostService chatCostService;
private final MjOkHttpUtil mjOkHttpUtil;
@ApiOperation(value = "换脸")
@PostMapping("/insight-face/swap")
public String insightFace(@RequestBody InsightFace insightFace) {
// 扣除接口费用并且保存消息记录
chatCostService.taskDeduct("mj","Face Changing", NumberUtils.toDouble(mjOkHttpUtil.getKey("faceSwapping"), 0.1));
// 创建请求体这里使用JSON作为媒体类型
String insightFaceJson = JSONUtil.toJsonStr(insightFace);
String url = "mj/insight-face/swap";
Request request = mjOkHttpUtil.createPostRequest(url, insightFaceJson);
return mjOkHttpUtil.executeRequest(request);
}
}

View File

@@ -0,0 +1,51 @@
package org.ruoyi.fusion.controller;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.apache.commons.lang3.math.NumberUtils;
import org.ruoyi.common.core.utils.OkHttpUtil;
import org.ruoyi.system.cofing.OkHttpConfig;
import org.ruoyi.system.domain.GenerateLuma;
import org.ruoyi.system.service.IChatCostService;
import org.springframework.web.bind.annotation.*;
/**
* 描述:文生视频
*
* @author ageerle@163.com
* date 2024/6/27
*/
@RestController
@RequestMapping("/luma")
@RequiredArgsConstructor
@Slf4j
public class LumaController {
private final OkHttpConfig okHttpConfig;
private final IChatCostService chatCostService;
@ApiOperation(value = "文生视频")
@PostMapping("/generations/")
public String generateVideo(@RequestBody GenerateLuma generateLuma) {
OkHttpUtil okHttpUtil = okHttpConfig.getOkHttpUtil("luma");
chatCostService.taskDeduct("luma", "文生视频", NumberUtils.toDouble(okHttpConfig.getGenerate(), 0.3));
String generateJson = JSONUtil.toJsonStr(generateLuma);
String url = "luma/generations";
Request request = okHttpUtil.createPostRequest(url, generateJson);
return okHttpUtil.executeRequest(request);
}
@ApiOperation(value = "文生视频任务查询")
@GetMapping("/generations/{taskId}")
public String getGenerationTask(@PathVariable String taskId) {
OkHttpUtil okHttpUtil = okHttpConfig.getOkHttpUtil("luma");
String url = "luma/generations/" + taskId;
Request request = okHttpUtil.createGetRequest(url);
return okHttpUtil.executeRequest(request);
}
}

View File

@@ -0,0 +1,134 @@
package org.ruoyi.fusion.controller;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.apache.commons.lang3.math.NumberUtils;
import org.ruoyi.fusion.dto.*;
import org.ruoyi.fusion.enums.ActionType;
import org.ruoyi.fusion.util.MjOkHttpUtil;
import org.ruoyi.system.service.IChatCostService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@Api(tags = "任务提交")
@RestController
@RequestMapping("/mj/submit")
@RequiredArgsConstructor
@Slf4j
public class SubmitController {
private final IChatCostService chatCostService;
private final MjOkHttpUtil mjOkHttpUtil;
@ApiOperation(value = "绘图变化")
@PostMapping("/change")
public String change(@RequestBody SubmitChangeDTO changeDTO) {
String jsonStr = JSONUtil.toJsonStr(changeDTO);
String url = "mj/submit/change";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "执行动作")
@PostMapping("/action")
public String action(@RequestBody SubmitActionDTO changeDTO) {
ActionType actionType = ActionType.fromCustomId(getAction(changeDTO.getCustomId()));
Optional.ofNullable(actionType).ifPresentOrElse(
type -> {
switch (type) {
case UP_SAMPLE:
chatCostService.taskDeduct("mj","enlarge", NumberUtils.toDouble(mjOkHttpUtil.getKey("upsample"), 0.3));
break;
case IN_PAINT:
// 局部重绘已经扣费,不执行任何操作
break;
default:
chatCostService.taskDeduct("mj","change", NumberUtils.toDouble(mjOkHttpUtil.getKey("change"), 0.3));
break;
}
},
() -> chatCostService.taskDeduct("mj","change", NumberUtils.toDouble(mjOkHttpUtil.getKey("change"), 0.3))
);
String jsonStr = JSONUtil.toJsonStr(changeDTO);
String url = "mj/submit/action";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "绘图变化-simple")
@PostMapping("/simple-change")
public String simpleChange(@RequestBody SubmitSimpleChangeDTO simpleChangeDTO) {
String jsonStr = JSONUtil.toJsonStr(simpleChangeDTO);
String url = "mj/submit/simple-change";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "提交图生图、混图任务")
@PostMapping("/blend")
public String blend(@RequestBody SubmitBlendDTO blendDTO) {
chatCostService.taskDeduct("mj","blend", NumberUtils.toDouble(mjOkHttpUtil.getKey("blend"), 0.3));
String jsonStr = JSONUtil.toJsonStr(blendDTO);
String url = "mj/submit/blend";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "提交图生文任务")
@PostMapping("/describe")
public String describe(@RequestBody SubmitDescribeDTO describeDTO) {
chatCostService.taskDeduct("mj","describe", NumberUtils.toDouble(mjOkHttpUtil.getKey("describe"), 0.1));
String jsonStr = JSONUtil.toJsonStr(describeDTO);
String url = "mj/submit/describe";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "提交文生图任务")
@PostMapping("/imagine")
public String imagine(@RequestBody SubmitImagineDTO imagineDTO) {
chatCostService.taskDeduct("mj",imagineDTO.getPrompt(), NumberUtils.toDouble(mjOkHttpUtil.getKey("imagine"), 0.3));
String jsonStr = JSONUtil.toJsonStr(imagineDTO);
String url = "mj/submit/imagine";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "提交局部重绘任务")
@PostMapping("/modal")
public String modal(@RequestBody SubmitModalDTO submitModalDTO) {
chatCostService.taskDeduct("mj","repaint ", NumberUtils.toDouble(mjOkHttpUtil.getKey("inpaint"), 0.1));
String jsonStr = JSONUtil.toJsonStr(submitModalDTO);
String url = "mj/submit/modal";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "提交提示词分析任务")
@PostMapping("/shorten")
public String shorten(@RequestBody SubmitShortenDTO submitShortenDTO) {
chatCostService.taskDeduct("mj","shorten", NumberUtils.toDouble(mjOkHttpUtil.getKey("shorten"), 0.1));
String jsonStr = JSONUtil.toJsonStr(submitShortenDTO);
String url = "mj/submit/shorten";
Request request = mjOkHttpUtil.createPostRequest(url, jsonStr);
return mjOkHttpUtil.executeRequest(request);
}
public String getAction(String customId) {
if (customId == null || customId.isEmpty()) {
return null;
}
String[] parts = customId.split("::");
return customId.endsWith("SOLO") ? parts[1] : parts[2];
}
}

View File

@@ -0,0 +1,68 @@
package org.ruoyi.fusion.controller;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.apache.commons.lang3.math.NumberUtils;
import org.ruoyi.common.core.utils.OkHttpUtil;
import org.ruoyi.system.cofing.OkHttpConfig;
import org.ruoyi.system.domain.GenerateLyric;
import org.ruoyi.system.domain.GenerateSuno;
import org.ruoyi.system.service.IChatCostService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/sunoapi")
@RequiredArgsConstructor
@Slf4j
public class SunoController {
private final OkHttpConfig okHttpConfig;
private final IChatCostService chatCostService;
@ApiOperation(value = "文生歌曲")
@PostMapping("/generate")
public String generate(@RequestBody GenerateSuno generateSuno) {
OkHttpUtil okHttpUtil = okHttpConfig.getOkHttpUtil("suno");
// 扣除接口费用并且保存消息记录
chatCostService.taskDeduct("suno","文生歌曲", NumberUtils.toDouble(okHttpConfig.getGenerate(), 0.3));
// 创建请求体这里使用JSON作为媒体类型
String generateJson = JSONUtil.toJsonStr(generateSuno);
String url = "suno/generate";
Request request = okHttpUtil.createPostRequest(url, generateJson);
return okHttpUtil.executeRequest(request);
}
@ApiOperation(value = "生成歌词")
@PostMapping("/generate/lyrics/")
public String generate(@RequestBody GenerateLyric generateLyric) {
OkHttpUtil okHttpUtil = okHttpConfig.getOkHttpUtil("suno");
String generateJson = JSONUtil.toJsonStr(generateLyric);
String url = "task/suno/v1/submit/lyrics";
Request request = okHttpUtil.createPostRequest(url, generateJson);
return okHttpUtil.executeRequest(request);
}
@ApiOperation(value = "查询歌词任务")
@GetMapping("/lyrics/{taskId}")
public String lyrics(@PathVariable String taskId) {
OkHttpUtil okHttpUtil = okHttpConfig.getOkHttpUtil("suno");
String url = "task/suno/v1/fetch/"+taskId;
Request request = okHttpUtil.createGetRequest(url);
return okHttpUtil.executeRequest(request);
}
@ApiOperation(value = "查询歌曲任务")
@GetMapping("/feed/{taskId}")
public String feed(@PathVariable String taskId) {
OkHttpUtil okHttpUtil = okHttpConfig.getOkHttpUtil("suno");
String url = "suno/feed/"+taskId;
Request request = okHttpUtil.createGetRequest(url);
return okHttpUtil.executeRequest(request);
}
}

View File

@@ -0,0 +1,48 @@
package org.ruoyi.fusion.controller;
import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.ruoyi.fusion.dto.TaskConditionDTO;
import org.ruoyi.fusion.util.MjOkHttpUtil;
import org.springframework.web.bind.annotation.*;
@Api(tags = "任务查询")
@RestController
@RequestMapping("/mj/task")
@RequiredArgsConstructor
@Slf4j
public class TaskController {
private final MjOkHttpUtil mjOkHttpUtil;
@ApiOperation(value = "指定ID获取任务")
@GetMapping("/{id}/fetch")
public String fetch(@ApiParam(value = "任务ID") @PathVariable String id) {
String url = "mj/task/" + id + "/fetch";
Request request = mjOkHttpUtil.createGetRequest(url);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "根据ID列表查询任务")
@PostMapping("/list-by-condition")
public String listByIds(@RequestBody TaskConditionDTO conditionDTO) {
String url = "mj/task/list-by-condition";
String conditionJson = JSONUtil.toJsonStr(conditionDTO);
Request request = mjOkHttpUtil.createPostRequest(url,conditionJson);
return mjOkHttpUtil.executeRequest(request);
}
@ApiOperation(value = "获取任务图片的seed")
@GetMapping("/{id}/image-seed")
public String getSeed(@ApiParam(value = "任务ID") @PathVariable String id) {
String url = "mj/task/" + id + "/image-seed";
Request request = mjOkHttpUtil.createGetRequest(url);
return mjOkHttpUtil.executeRequest(request);
}
}

View File

@@ -0,0 +1,120 @@
package org.ruoyi.fusion.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.validate.EditGroup;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.satoken.utils.LoginHelper;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.system.domain.bo.VoiceRoleBo;
import org.ruoyi.system.domain.vo.VoiceRoleVo;
import org.ruoyi.system.request.RoleListDto;
import org.ruoyi.system.request.RoleRequest;
import org.ruoyi.system.request.SimpleGenerateRequest;
import org.ruoyi.system.response.SimpleGenerateDataResponse;
import org.ruoyi.system.response.rolelist.RoleListVO;
import org.ruoyi.system.service.IVoiceRoleService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* 配音角色
*
* @author Lion Li
* @date 2024-03-19
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/voice")
public class VoiceController extends BaseController {
private final IVoiceRoleService voiceRoleService;
/**
* 查询配音角色列表
*/
@GetMapping("/list")
public List<VoiceRoleVo> list(VoiceRoleBo bo) {
if(LoginHelper.getUserId() == null){
return new ArrayList<>();
}
bo.setCreateBy(LoginHelper.getUserId());
return voiceRoleService.queryList(bo);
}
/**
* 获取配音角色详细信息
*
* @param id 主键
*/
@SaCheckPermission("system:role:query")
@GetMapping("/{id}")
public R<VoiceRoleVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(voiceRoleService.queryById(id));
}
/**
* 新增配音角色
*/
@Log(title = "配音角色", businessType = BusinessType.INSERT)
@PostMapping("/add")
public R<Void> add(@RequestBody RoleRequest roleRequest) {
return toAjax(voiceRoleService.insertByBo(roleRequest));
}
/**
* 修改配音角色
*/
@SaCheckPermission("system:role:edit")
@Log(title = "配音角色", businessType = BusinessType.UPDATE)
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody VoiceRoleBo bo) {
return toAjax(voiceRoleService.updateByBo(bo));
}
/**
* 删除配音角色
*
* @param ids 主键串
*/
@Log(title = "配音角色", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(voiceRoleService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 实时语音生成
*/
@PostMapping("/simpleGenerate")
public R<SimpleGenerateDataResponse> simpleGenerate(@RequestBody SimpleGenerateRequest simpleGenerateRequest) {
return R.ok(voiceRoleService.simpleGenerate(simpleGenerateRequest));
}
/**
* 角色市场
*/
@GetMapping("/roleList")
public R<List<RoleListVO>> roleList() {
return R.ok(voiceRoleService.roleList());
}
/**
* 收藏角色
*/
@PostMapping("/copyRole")
public R<String> copyRole(@RequestBody RoleListDto roleListDto) {
voiceRoleService.copyRole(roleListDto);
return R.ok();
}
}

View File

@@ -0,0 +1,72 @@
package org.ruoyi.fusion.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class DomainObject implements Serializable {
@Getter
@Setter
@ApiModelProperty("ID")
protected String id;
@Setter
protected Map<String, Object> properties; // 扩展属性,仅支持基本类型
@JsonIgnore
private final transient Object lock = new Object();
public void sleep() throws InterruptedException {
synchronized (this.lock) {
this.lock.wait();
}
}
public void awake() {
synchronized (this.lock) {
this.lock.notifyAll();
}
}
public DomainObject setProperty(String name, Object value) {
getProperties().put(name, value);
return this;
}
public DomainObject removeProperty(String name) {
getProperties().remove(name);
return this;
}
public Object getProperty(String name) {
return getProperties().get(name);
}
@SuppressWarnings("unchecked")
public <T> T getPropertyGeneric(String name) {
return (T) getProperty(name);
}
public <T> T getProperty(String name, Class<T> clz) {
return getProperty(name, clz, null);
}
public <T> T getProperty(String name, Class<T> clz, T defaultValue) {
Object value = getProperty(name);
return value == null ? defaultValue : clz.cast(value);
}
public Map<String, Object> getProperties() {
if (this.properties == null) {
this.properties = new HashMap<>();
}
return this.properties;
}
}

View File

@@ -0,0 +1,22 @@
package org.ruoyi.fusion.domain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @author WangLe
*/
@Data
@ApiModel("Discord账号")
public class InsightFace implements Serializable {
/**本人头像json*/
@ApiModelProperty("本人头像json")
private String sourceBase64;
/**明星头像json*/
@ApiModelProperty("明星头像json")
private String targetBase64;
}

View File

@@ -0,0 +1,16 @@
package org.ruoyi.fusion.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public abstract class BaseSubmitDTO {
@ApiModelProperty("自定义参数")
protected String state;
@ApiModelProperty("回调地址, 为空时使用全局notifyHook")
protected String notifyHook;
}

View File

@@ -0,0 +1,18 @@
package org.ruoyi.fusion.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel("变化任务提交参数")
public class SubmitActionDTO {
private String customId;
private String taskId;
private String state;
private String notifyHook;
}

View File

@@ -0,0 +1,21 @@
package org.ruoyi.fusion.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.fusion.enums.BlendDimensions;
import java.util.List;
@Data
@ApiModel("Blend提交参数")
@EqualsAndHashCode(callSuper = true)
public class SubmitBlendDTO extends BaseSubmitDTO {
@ApiModelProperty(value = "图片base64数组", required = true, example = "[\"data:image/png;base64,xxx1\", \"data:image/png;base64,xxx2\"]")
private List<String> base64Array;
@ApiModelProperty(value = "比例: PORTRAIT(2:3); SQUARE(1:1); LANDSCAPE(3:2)", example = "SQUARE")
private BlendDimensions dimensions = BlendDimensions.SQUARE;
}

Some files were not shown because too many files have changed in this diff Show More