feat: 1. 调整项目结构 2.增加插件管理

This commit is contained in:
ageer
2025-03-31 19:13:27 +08:00
parent 6382e177bf
commit 412e8bdc10
495 changed files with 646 additions and 121 deletions

View File

@@ -0,0 +1,129 @@
package org.ruoyi.chat.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.request.translation.TranslationRequest;
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 sseService;
private final IChatMessageService chatMessageService;
/**
* 聊天接口
*/
@PostMapping("/send")
@ResponseBody
public SseEmitter sseChat(@RequestBody @Valid ChatRequest chatRequest, HttpServletRequest request) {
if (chatRequest.getModel().startsWith("ollama")) {
return sseService.ollamaChat(chatRequest);
}
return sseService.sseChat(chatRequest,request);
}
/**
* 上传文件
*/
@PostMapping("/upload")
@ResponseBody
public UploadFileResponse upload(@RequestPart("file") MultipartFile file) {
return sseService.upload(file);
}
/**
* 语音转文本
*
* @param file
*/
@PostMapping("/audio")
@ResponseBody
public WhisperResponse audio(@RequestParam("file") MultipartFile file) {
WhisperResponse whisperResponse = sseService.speechToTextTranscriptionsV2(file);
return whisperResponse;
}
/**
* 文本转语音
*
* @param textToSpeech
*/
@PostMapping("/speech")
@ResponseBody
public ResponseEntity<Resource> speech(@RequestBody TextToSpeech textToSpeech) {
return sseService.textToSpeed(textToSpeech);
}
/**
* 文本翻译
*
* @param
*/
@PostMapping("/translation")
@ResponseBody
public String translation(@RequestBody TranslationRequest translationRequest) {
return sseService.translation(translationRequest);
}
@PostMapping("/dall3")
@ResponseBody
public R<List<Item>> dall3(@RequestBody @Valid Dall3Request request) {
return R.ok(sseService.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,58 @@
package org.ruoyi.chat.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
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.system.domain.vo.cover.CoverParamVo;
import org.ruoyi.system.domain.vo.cover.CoverVo;
import org.ruoyi.system.domain.vo.cover.CoverCallbackVo;
import org.ruoyi.system.domain.vo.cover.MusicVo;
import org.ruoyi.system.service.ICoverService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 绘声美音-翻唱
*
* @author NSL
* @since 2024-12-25
*/
@Api(tags = "歌曲翻唱")
@RequiredArgsConstructor
@RestController
@RequestMapping("/cover")
public class CoverController extends BaseController {
private final ICoverService coverService;
@ApiOperation(value = "查找歌曲")
@GetMapping("/searchMusic")
public R<List<MusicVo>> searchMusic(String musicName) {
return R.ok(coverService.searchMusic(musicName));
}
@ApiOperation(value = "翻唱歌曲")
@PostMapping("/saveCoverTask")
public R<Void> saveCoverTask(@RequestBody CoverParamVo coverParamVo) {
coverService.saveCoverTask(coverParamVo);
return R.ok("翻唱歌曲处理中请等待10分钟-30分钟翻唱结果请到翻唱记录中查询");
}
@ApiOperation(value = "查询翻唱记录")
@PostMapping("/searchCoverRecord")
public R<TableDataInfo<CoverVo>> searchCoverRecord(@RequestBody PageQuery pageQuery) {
return R.ok(coverService.searchCoverRecord(pageQuery));
}
@ApiOperation(value = "翻唱回调接口")
@PostMapping("/callback")
public R<Void> callback(@RequestBody CoverCallbackVo coverCallbackVo) {
coverService.callback(coverCallbackVo);
return R.ok();
}
}

View File

@@ -0,0 +1,42 @@
package org.ruoyi.chat.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.chat.domain.InsightFace;
import org.ruoyi.chat.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,52 @@
package org.ruoyi.chat.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,79 @@
package org.ruoyi.chat.controller;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.system.domain.vo.ppt.*;
import org.ruoyi.system.service.IPptService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
/**
* AI_PPT
*
* @author NSL
* @since 2024-12-30
*/
@Api(tags = "AI-PPT")
@RequiredArgsConstructor
@RestController
@RequestMapping("/ppt")
public class PptController extends BaseController {
private final IPptService pptService;
@ApiOperation(value = "获取API Token")
@GetMapping("/getApiToken")
public R<String> getApiToken() {
return R.ok(pptService.getApiToken());
}
@ApiOperation(value = "同步流式生成 PPT")
@PostMapping("/syncStreamGeneratePpt")
public R<Void> syncStreamGeneratePpt(String title) {
pptService.syncStreamGeneratePpt(title);
return R.ok();
}
@ApiOperation(value = "查询所有PPT列表")
@PostMapping("/selectPptList")
public R<Void> selectPptList(@RequestBody PptAllQueryDto pptQueryVo) {
pptService.selectPptList(pptQueryVo);
return R.ok();
}
@ApiOperation(value = "生成大纲")
@PostMapping(value = "/generateOutline", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
public SseEmitter generateOutline(@RequestBody PptGenerateOutlineDto generateOutlineDto) {
return pptService.generateOutline(generateOutlineDto);
}
@ApiOperation(value = "生成大纲内容")
@PostMapping(value = "/generateContent", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
public SseEmitter generateOutline(@RequestBody PptGenerateContentDto generateContentDto) {
return pptService.generateContent(generateContentDto);
}
@ApiOperation(value = "分页查询 PPT 模板")
@PostMapping("/getTemplates")
public R<JSONObject> getPptTemplates(@RequestBody PptTemplateQueryDto pptQueryVo) {
return R.ok(pptService.getPptTemplates(pptQueryVo));
}
@ApiOperation(value = "生成 PPT")
@PostMapping("/generatePptx")
public R<JSONObject> generatePptx(@RequestBody PptGeneratePptxDto pptQueryVo) {
return R.ok(pptService.generatePptx(pptQueryVo));
}
@ApiOperation(value = "生成PPT成功回调接口")
@PostMapping("/successCallback")
public R<Void> successCallback() {
pptService.successCallback();
return R.ok();
}
}

View File

@@ -0,0 +1,134 @@
package org.ruoyi.chat.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.chat.dto.*;
import org.ruoyi.chat.enums.ActionType;
import org.ruoyi.chat.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.chat.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.chat.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.chat.dto.TaskConditionDTO;
import org.ruoyi.chat.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,52 @@
package org.ruoyi.chat.controller;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.system.request.RoleListDto;
import org.ruoyi.system.request.SimpleGenerateRequest;
import org.ruoyi.system.response.SimpleGenerateDataResponse;
import org.ruoyi.system.response.rolelist.ChatAppStoreVO;
import org.ruoyi.system.service.IChatAppStoreService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 应用市场
*
* @author Lion Li
* @date 2024-03-19
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/voice")
public class VoiceController extends BaseController {
private final IChatAppStoreService voiceRoleService;
/**
* 实时语音生成
*/
@PostMapping("/simpleGenerate")
public R<SimpleGenerateDataResponse> simpleGenerate(@RequestBody SimpleGenerateRequest simpleGenerateRequest) {
return R.ok(voiceRoleService.simpleGenerate(simpleGenerateRequest));
}
/**
* 角色市场
*/
@GetMapping("/roleList")
public R<List<ChatAppStoreVO>> 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.chat.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.chat.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.chat.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.chat.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.chat.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.chat.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;
}

View File

@@ -0,0 +1,25 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.ruoyi.chat.enums.TaskAction;
@Data
@ApiModel("变化任务提交参数")
@EqualsAndHashCode(callSuper = true)
public class SubmitChangeDTO extends BaseSubmitDTO {
@ApiModelProperty(value = "任务ID", required = true, example = "\"1320098173412546\"")
private String taskId;
@ApiModelProperty(value = "UPSCALE(放大); VARIATION(变换); REROLL(重新生成)", required = true,
allowableValues = "UPSCALE, VARIATION, REROLL", example = "UPSCALE")
private TaskAction action;
@ApiModelProperty(value = "序号(1~4), action为UPSCALE,VARIATION时必传", allowableValues = "range[1, 4]", example = "1")
private Integer index;
}

View File

@@ -0,0 +1,15 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@ApiModel("Describe提交参数")
@EqualsAndHashCode(callSuper = true)
public class SubmitDescribeDTO extends BaseSubmitDTO {
@ApiModelProperty(value = "图片base64", required = true, example = "data:image/png;base64,xxx")
private String base64;
}

View File

@@ -0,0 +1,26 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@Data
@ApiModel("Imagine提交参数")
@EqualsAndHashCode(callSuper = true)
public class SubmitImagineDTO extends BaseSubmitDTO {
@ApiModelProperty(value = "提示词", required = true, example = "Cat")
private String prompt;
@ApiModelProperty(value = "垫图base64数组")
private List<String> base64Array;
@ApiModelProperty(hidden = true)
@Deprecated(since = "3.0", forRemoval = true)
private String base64;
}

View File

@@ -0,0 +1,19 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("局部重绘提交参数")
public class SubmitModalDTO extends BaseSubmitDTO{
private String maskBase64;
private String taskId;
private String prompt;
}

View File

@@ -0,0 +1,17 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("prompt分析提交参数")
public class SubmitShortenDTO extends BaseSubmitDTO{
private String botType;
private String prompt;
}

View File

@@ -0,0 +1,17 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@ApiModel("变化任务提交参数-simple")
@EqualsAndHashCode(callSuper = true)
public class SubmitSimpleChangeDTO extends BaseSubmitDTO {
@ApiModelProperty(value = "变化描述: ID $action$index", required = true, example = "1320098173412546 U2")
private String content;
}

View File

@@ -0,0 +1,14 @@
package org.ruoyi.chat.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.List;
@Data
@ApiModel("任务查询参数")
public class TaskConditionDTO {
private List<String> ids;
}

View File

@@ -0,0 +1,32 @@
package org.ruoyi.chat.enums;
import lombok.Getter;
/**
* @author WangLe
*/
@Getter
public enum ActionType {
IN_PAINT("Inpaint"), // 局部重绘操作
RE_ROLL("reroll"), // 重绘操作
UP_SAMPLE("upsample"), // 放大操作
ZOOM("zoom"), // 变焦操作
UPSCALE("upscale"), // 高清放大操作
VARIATION("variation"); // 变化操作
private final String action;
ActionType(String action) {
this.action = action;
}
public static ActionType fromCustomId(String customId) {
for (ActionType type : values()) {
if (type.getAction().equals(customId)) {
return type;
}
}
return null;
}
}

View File

@@ -0,0 +1,21 @@
package org.ruoyi.chat.enums;
import lombok.Getter;
@Getter
public enum BlendDimensions {
PORTRAIT("2:3"),
SQUARE("1:1"),
LANDSCAPE("3:2");
private final String value;
BlendDimensions(String value) {
this.value = value;
}
}

View File

@@ -0,0 +1,30 @@
package org.ruoyi.chat.enums;
public enum TaskAction {
/**
* 生成图片.
*/
IMAGINE,
/**
* 选中放大.
*/
UPSCALE,
/**
* 选中其中的一张图,生成四张相似的.
*/
VARIATION,
/**
* 重新执行.
*/
REROLL,
/**
* 图转prompt.
*/
DESCRIBE,
/**
* 多图混合.
*/
BLEND
}

View File

@@ -0,0 +1,87 @@
package org.ruoyi.chat.util;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.ruoyi.common.core.service.ConfigService;
import org.ruoyi.system.domain.bo.SysModelBo;
import org.ruoyi.system.domain.vo.SysModelVo;
import org.ruoyi.system.service.ISysModelService;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author WangLe
*/
@RequiredArgsConstructor
@Component
@Slf4j
public class MjOkHttpUtil {
private final ISysModelService sysModelService;
private final ConfigService configService;
private static final String API_SECRET_HEADER = "mj-api-secret";
private String apiKey;
private String apiHost;
private final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(300, TimeUnit.SECONDS)
.writeTimeout(300, TimeUnit.SECONDS)
.readTimeout(300, TimeUnit.SECONDS)
.build();
public String executeRequest(Request request) {
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
return response.body() != null ? response.body().string() : null;
} catch (IOException e) {
// 这里应根据实际情况使用适当的日志记录方式
log.error("请求失败: {}",e.getMessage());
return null;
}
}
public Request createPostRequest(String url, String json) {
MediaType JSON = MediaType.get("application/json; charset=utf-8");
RequestBody body = RequestBody.create(json, JSON);
return new Request.Builder()
.url(apiHost + url)
.post(body)
.header(API_SECRET_HEADER, apiKey)
.build();
}
public Request createGetRequest(String url) {
return new Request.Builder()
.url(apiHost + url)
.header(API_SECRET_HEADER, apiKey)
.build();
}
@PostConstruct
public void init() {
SysModelBo sysModelBo = new SysModelBo();
sysModelBo.setModelName("midjourney");
List<SysModelVo> sysModelList = sysModelService.queryList(sysModelBo);
if (!sysModelList.isEmpty()) {
SysModelVo model = sysModelList.get(0);
this.apiKey = model.getApiKey();
this.apiHost = model.getApiHost();
}
}
public String getKey(String key) {
return configService.getConfigValue("mj", key);
}
}