1.加入ai对话框 模块日报功能
This commit is contained in:
@@ -3,14 +3,11 @@ package cn.iocoder.yudao.module.report.framework.jmreport.config;
|
|||||||
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
|
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
|
||||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||||
import cn.iocoder.yudao.module.report.framework.jmreport.core.service.JmOnlDragExternalServiceImpl;
|
|
||||||
import cn.iocoder.yudao.module.report.framework.jmreport.core.service.JmReportTokenServiceImpl;
|
import cn.iocoder.yudao.module.report.framework.jmreport.core.service.JmReportTokenServiceImpl;
|
||||||
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
|
|
||||||
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
|
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Primary;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 积木报表的配置类
|
* 积木报表的配置类
|
||||||
@@ -28,10 +25,4 @@ public class JmReportConfiguration {
|
|||||||
return new JmReportTokenServiceImpl(oAuth2TokenApi, permissionApi, securityProperties);
|
return new JmReportTokenServiceImpl(oAuth2TokenApi, permissionApi, securityProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean // 暂时注释:可以按需实现后打开
|
|
||||||
@Primary
|
|
||||||
public JmOnlDragExternalServiceImpl jmOnlDragExternalService2() {
|
|
||||||
return new JmOnlDragExternalServiceImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ public class AdminUserRespDTO {
|
|||||||
* 用户ID
|
* 用户ID
|
||||||
*/
|
*/
|
||||||
private Long id;
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
/**
|
/**
|
||||||
* 用户昵称
|
* 用户昵称
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ public class TenantRespVO {
|
|||||||
@Schema(description = "账号数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
@Schema(description = "账号数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||||
private Integer accountCount;
|
private Integer accountCount;
|
||||||
|
|
||||||
|
@Schema(description = "租户提示词", example = "")
|
||||||
|
private String tenantPrompt;
|
||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@ExcelProperty("创建时间")
|
@ExcelProperty("创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ public class TenantSaveReqVO {
|
|||||||
@NotNull(message = "账号数量不能为空")
|
@NotNull(message = "账号数量不能为空")
|
||||||
private Integer accountCount;
|
private Integer accountCount;
|
||||||
|
|
||||||
|
@Schema(description = "租户提示词", example = "")
|
||||||
|
private String tenantPrompt;
|
||||||
|
|
||||||
// ========== 仅【创建】时,需要传递的字段 ==========
|
// ========== 仅【创建】时,需要传递的字段 ==========
|
||||||
|
|
||||||
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
|
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
|
||||||
|
|||||||
@@ -85,5 +85,9 @@ public class TenantDO extends BaseDO {
|
|||||||
* 账号数量
|
* 账号数量
|
||||||
*/
|
*/
|
||||||
private Integer accountCount;
|
private Integer accountCount;
|
||||||
|
/**
|
||||||
|
* 租户提示词
|
||||||
|
*/
|
||||||
|
private String tenantPrompt;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ CREATE TABLE IF NOT EXISTS "system_tenant" (
|
|||||||
"package_id" bigint NOT NULL,
|
"package_id" bigint NOT NULL,
|
||||||
"expire_time" timestamp NOT NULL,
|
"expire_time" timestamp NOT NULL,
|
||||||
"account_count" int NOT NULL,
|
"account_count" int NOT NULL,
|
||||||
|
"tenant_prompt" varchar(2000) DEFAULT '',
|
||||||
"creator" varchar(64) DEFAULT '',
|
"creator" varchar(64) DEFAULT '',
|
||||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updater" varchar(64) DEFAULT '',
|
"updater" varchar(64) DEFAULT '',
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public class AiChatController {
|
|||||||
@RequestParam("query") String query,
|
@RequestParam("query") String query,
|
||||||
@RequestParam(value = "file", required = false) MultipartFile file,
|
@RequestParam(value = "file", required = false) MultipartFile file,
|
||||||
@RequestParam(value = "task_desc", required = false) String taskDesc,
|
@RequestParam(value = "task_desc", required = false) String taskDesc,
|
||||||
|
@RequestParam(value = "conversation_id", required = false) String conversationId,
|
||||||
HttpServletResponse response
|
HttpServletResponse response
|
||||||
) {
|
) {
|
||||||
String user = "system";
|
String user = "system";
|
||||||
@@ -45,13 +46,14 @@ public class AiChatController {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.debug("获取登录用户失败,使用默认 user: {}", e.getMessage());
|
log.debug("获取登录用户失败,使用默认 user: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
log.info("[AiChat] 收到请求 query={}, conversation_id={}", query, conversationId);
|
||||||
response.setContentType("text/event-stream;charset=UTF-8");
|
response.setContentType("text/event-stream;charset=UTF-8");
|
||||||
response.setHeader("Cache-Control", "no-cache");
|
response.setHeader("Cache-Control", "no-cache");
|
||||||
response.setHeader("Connection", "keep-alive");
|
response.setHeader("Connection", "keep-alive");
|
||||||
response.setHeader("X-Accel-Buffering", "no");
|
response.setHeader("X-Accel-Buffering", "no");
|
||||||
|
|
||||||
try (OutputStream out = response.getOutputStream()) {
|
try (OutputStream out = response.getOutputStream()) {
|
||||||
difyAiChatService.streamChat(query, file, taskDesc, user, out);
|
difyAiChatService.streamChat(query, file, taskDesc, user, conversationId, out);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("AI 图片对话流式响应异常", e);
|
log.error("AI 图片对话流式响应异常", e);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ public interface DifyAiChatService {
|
|||||||
/**
|
/**
|
||||||
* 流式发送对话请求,逐字返回 AI 响应
|
* 流式发送对话请求,逐字返回 AI 响应
|
||||||
*
|
*
|
||||||
* @param query 用户问题
|
* @param query 用户问题
|
||||||
* @param file 图片文件(可选,前端直接上传)
|
* @param file 图片文件(可选,前端直接上传)
|
||||||
* @param taskDesc 任务描述(可选,传给 Dify task_desc 做 AI 分析)
|
* @param taskDesc 任务描述(可选,传给 Dify task_desc 做 AI 分析)
|
||||||
* @param user Dify 用户标识,用于对话隔离(不同用户对话互不污染)
|
* @param user Dify 用户标识,用于对话隔离(不同用户对话互不污染)
|
||||||
* @param output 输出流,用于写入 SSE 格式的响应
|
* @param conversationId 会话 ID(可选,续接多轮对话;首次不传,后续传入 Dify 返回的 conversation_id)
|
||||||
|
* @param output 输出流,用于写入 SSE 格式的响应
|
||||||
*/
|
*/
|
||||||
void streamChat(String query, MultipartFile file, String taskDesc, String user, java.io.OutputStream output) throws Exception;
|
void streamChat(String query, MultipartFile file, String taskDesc, String user, String conversationId, java.io.OutputStream output) throws Exception;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package cn.iocoder.yudao.module.ydoyun.service.aichat;
|
package cn.iocoder.yudao.module.ydoyun.service.aichat;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
||||||
|
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -12,6 +16,7 @@ import org.springframework.web.client.RestTemplate;
|
|||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -34,10 +39,13 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
@Value("${ydoyun.dify.ai-chat.api-key:app-uch2HPKpicnPgNpJCnQJTehq}")
|
@Value("${ydoyun.dify.ai-chat.api-key:app-uch2HPKpicnPgNpJCnQJTehq}")
|
||||||
private String apiKey;
|
private String apiKey;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TenantService tenantService;
|
||||||
|
|
||||||
private final RestTemplate restTemplate = new RestTemplate();
|
private final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void streamChat(String query, MultipartFile file, String taskDesc, String user, java.io.OutputStream output) throws Exception {
|
public void streamChat(String query, MultipartFile file, String taskDesc, String user, String conversationId, java.io.OutputStream output) throws Exception {
|
||||||
// 构建请求体
|
// 构建请求体
|
||||||
String base = baseUrl.replaceAll("/$", "");
|
String base = baseUrl.replaceAll("/$", "");
|
||||||
String chatUrl = base + "/chat-messages";
|
String chatUrl = base + "/chat-messages";
|
||||||
@@ -60,6 +68,14 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
if (taskDesc != null && !taskDesc.trim().isEmpty()) {
|
if (taskDesc != null && !taskDesc.trim().isEmpty()) {
|
||||||
objectObjectHashMap.put("task_desc", taskDesc.trim());
|
objectObjectHashMap.put("task_desc", taskDesc.trim());
|
||||||
}
|
}
|
||||||
|
// 获取当前租户的 tenant_prompt 一并传入 Dify
|
||||||
|
Long tenantId = TenantContextHolder.getTenantId();
|
||||||
|
if (tenantId != null) {
|
||||||
|
TenantDO tenant = tenantService.getTenant(tenantId);
|
||||||
|
if (tenant != null && StringUtils.isNotBlank(tenant.getTenantPrompt())) {
|
||||||
|
objectObjectHashMap.put("tenant_prompt", tenant.getTenantPrompt().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, Object> requestBody = new HashMap<>();
|
Map<String, Object> requestBody = new HashMap<>();
|
||||||
requestBody.put("query", query);
|
requestBody.put("query", query);
|
||||||
@@ -69,6 +85,12 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
}
|
}
|
||||||
requestBody.put("response_mode", "streaming");
|
requestBody.put("response_mode", "streaming");
|
||||||
requestBody.put("user", user);
|
requestBody.put("user", user);
|
||||||
|
if (StringUtils.isNotBlank(conversationId)) {
|
||||||
|
requestBody.put("conversation_id", conversationId.trim());
|
||||||
|
log.info("[Dify] 续接多轮对话,conversation_id={}", conversationId.trim());
|
||||||
|
} else {
|
||||||
|
log.info("[Dify] 首次对话,未传 conversation_id");
|
||||||
|
}
|
||||||
|
|
||||||
String jsonBody = OBJECT_MAPPER.writeValueAsString(requestBody);
|
String jsonBody = OBJECT_MAPPER.writeValueAsString(requestBody);
|
||||||
log.info("Dify 请求体:{}", jsonBody);
|
log.info("Dify 请求体:{}", jsonBody);
|
||||||
@@ -96,8 +118,11 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 读取 Dify SSE 流并转发给前端
|
// 3. 读取 Dify SSE 流并转发给前端(仅转发实际回答内容,过滤 <think> 和 非 box 内容)
|
||||||
int chunkCount = 0;
|
StringBuilder fullBuffer = new StringBuilder();
|
||||||
|
int lastForwardedLen = 0;
|
||||||
|
boolean boxStarted = false;
|
||||||
|
String returnedConversationId = null;
|
||||||
try (BufferedReader reader = new BufferedReader(
|
try (BufferedReader reader = new BufferedReader(
|
||||||
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
String line;
|
String line;
|
||||||
@@ -108,21 +133,42 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
try {
|
try {
|
||||||
JsonNode node = OBJECT_MAPPER.readTree(data);
|
JsonNode node = OBJECT_MAPPER.readTree(data);
|
||||||
String event = node.path("event").asText("");
|
String event = node.path("event").asText("");
|
||||||
if (chunkCount < 3) {
|
// 提取 conversation_id 用于多轮对话(Dify 在 message / message_end 等事件中返回)
|
||||||
log.info("[Dify] SSE event: event={}, hasAnswer={}", event, node.has("answer"));
|
if (node.has("conversation_id")) {
|
||||||
|
String cid = node.get("conversation_id").asText();
|
||||||
|
if (StringUtils.isNotBlank(cid)) {
|
||||||
|
returnedConversationId = cid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 兼容 message / agent_message 事件,均含 answer 增量
|
// 兼容 message / agent_message 事件,均含 answer 增量
|
||||||
if (node.has("answer")) {
|
if (node.has("answer")) {
|
||||||
String answer = node.get("answer").asText();
|
String answer = node.get("answer").asText();
|
||||||
if (answer != null && !answer.isEmpty()) {
|
if (answer != null && !answer.isEmpty()) {
|
||||||
Map<String, Object> chunk = new HashMap<String, Object>();
|
fullBuffer.append(answer);
|
||||||
chunk.put("text", answer);
|
String bufStr = fullBuffer.toString();
|
||||||
writeSseData(output, chunk);
|
// 当 box 标记首次出现时,重置转发位置,避免之前发出的残缺前缀占位导致 box 内容被截断
|
||||||
chunkCount++;
|
boolean nowBoxStarted = bufStr.contains("<|begin_of_box|>");
|
||||||
|
if (nowBoxStarted && !boxStarted) {
|
||||||
|
boxStarted = true;
|
||||||
|
lastForwardedLen = 0;
|
||||||
|
}
|
||||||
|
String displayText = extractDisplayAnswer(bufStr);
|
||||||
|
// 移除末尾可能是 <|begin_of_box|> 残缺前缀的部分,避免把不完整的 token 发给前端
|
||||||
|
String safeText = removeTrailingPartialToken(displayText, "<|begin_of_box|>");
|
||||||
|
safeText = removeTrailingPartialToken(safeText, "<|end_of_box|>");
|
||||||
|
if (safeText.length() > lastForwardedLen) {
|
||||||
|
String toForward = safeText.substring(lastForwardedLen);
|
||||||
|
lastForwardedLen = safeText.length();
|
||||||
|
if (!toForward.isEmpty()) {
|
||||||
|
Map<String, Object> chunk = new HashMap<String, Object>();
|
||||||
|
chunk.put("text", toForward);
|
||||||
|
writeSseData(output, chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("message_end".equals(event)) {
|
if ("message_end".equals(event)) {
|
||||||
log.info("[Dify] 流式结束, 共转发 {} 个 chunk", chunkCount);
|
log.info("[Dify] 流式结束, conversation_id={}, 原始数据={}", returnedConversationId, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (node.has("code")) {
|
if (node.has("code")) {
|
||||||
@@ -137,6 +183,15 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 将 conversation_id 返回给前端,用于后续多轮对话
|
||||||
|
if (returnedConversationId != null) {
|
||||||
|
log.info("[Dify] 返回 conversation_id 给前端: {}", returnedConversationId);
|
||||||
|
Map<String, Object> convChunk = new HashMap<>();
|
||||||
|
convChunk.put("conversation_id", returnedConversationId);
|
||||||
|
writeSseData(output, convChunk);
|
||||||
|
} else {
|
||||||
|
log.warn("[Dify] Dify 响应中未包含 conversation_id,多轮对话将无法续接");
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (conn != null) conn.disconnect();
|
if (conn != null) conn.disconnect();
|
||||||
}
|
}
|
||||||
@@ -215,4 +270,55 @@ public class DifyAiChatServiceImpl implements DifyAiChatService {
|
|||||||
errData.put("error", msg);
|
errData.put("error", msg);
|
||||||
writeSseData(out, errData);
|
writeSseData(out, errData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 Dify 原始输出中提取需要展示给用户的回答内容。
|
||||||
|
* 过滤:1) <think>...</think> 块 2) 仅保留 <|begin_of_box|>...<|end_of_box|> 之间的内容
|
||||||
|
* 若没有 box 标记,则返回 </think> 之后的内容
|
||||||
|
*/
|
||||||
|
private String extractDisplayAnswer(String raw) {
|
||||||
|
if (raw == null || raw.isEmpty()) return "";
|
||||||
|
String s = raw;
|
||||||
|
// 1. 移除 <think>...</think> 块(含标签)
|
||||||
|
int thinkStart = s.indexOf("<think>");
|
||||||
|
if (thinkStart >= 0) {
|
||||||
|
int thinkEnd = s.indexOf("</think>", thinkStart);
|
||||||
|
if (thinkEnd >= 0) {
|
||||||
|
s = s.substring(0, thinkStart) + s.substring(thinkEnd + 8);
|
||||||
|
} else {
|
||||||
|
// </think> 未闭合,不展示
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2. 优先取 <|begin_of_box|>...<|end_of_box|> 之间的内容
|
||||||
|
String begin = "<|begin_of_box|>";
|
||||||
|
String end = "<|end_of_box|>";
|
||||||
|
int boxStart = s.indexOf(begin);
|
||||||
|
if (boxStart >= 0) {
|
||||||
|
int boxEnd = s.indexOf(end, boxStart);
|
||||||
|
if (boxEnd >= 0) {
|
||||||
|
return s.substring(boxStart + begin.length(), boxEnd).trim();
|
||||||
|
}
|
||||||
|
// 只有 begin 未闭合,返回 begin 之后的内容
|
||||||
|
return s.substring(boxStart + begin.length()).trim();
|
||||||
|
}
|
||||||
|
// 3. 无 box 时,返回 </think> 之后的内容(若已移除 think 则 s 已是后续内容)
|
||||||
|
return s.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 若字符串末尾是 token 的某个前缀(即 token 正在逐字符累积中),则将其去除。
|
||||||
|
* 例如:s="Hello <|beg", token="<|begin_of_box|>" → 返回 "Hello "
|
||||||
|
* 避免把尚未完整的特殊标记字符发给前端占用转发位置。
|
||||||
|
*/
|
||||||
|
private String removeTrailingPartialToken(String s, String token) {
|
||||||
|
if (s == null || s.isEmpty() || token == null || token.isEmpty()) return s;
|
||||||
|
int maxLen = Math.min(s.length(), token.length() - 1);
|
||||||
|
for (int len = maxLen; len > 0; len--) {
|
||||||
|
if (s.endsWith(token.substring(0, len))) {
|
||||||
|
return s.substring(0, s.length() - len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.ydoyun.service.reportpage;
|
|||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import cn.iocoder.yudao.module.ydoyun.config.ProcedureHttpClient;
|
import cn.iocoder.yudao.module.ydoyun.config.ProcedureHttpClient;
|
||||||
import cn.iocoder.yudao.module.ydoyun.controller.admin.reportdatabase.vo.ReportDatabaseRespVO;
|
import cn.iocoder.yudao.module.ydoyun.controller.admin.reportdatabase.vo.ReportDatabaseRespVO;
|
||||||
import cn.iocoder.yudao.module.ydoyun.controller.admin.reportpage.vo.ProcedureRequestVO;
|
import cn.iocoder.yudao.module.ydoyun.controller.admin.reportpage.vo.ProcedureRequestVO;
|
||||||
@@ -40,7 +40,7 @@ public class ReportPageService {
|
|||||||
private final DiffHttpClient diffHttpClient;
|
private final DiffHttpClient diffHttpClient;
|
||||||
private final StringRedisTemplate redisTemplate;
|
private final StringRedisTemplate redisTemplate;
|
||||||
private final AiDailyReportService aiDailyReportService;
|
private final AiDailyReportService aiDailyReportService;
|
||||||
private final AdminUserService userService;
|
private final AdminUserApi adminUserApi;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ReportMapper reportMapper;
|
private ReportMapper reportMapper;
|
||||||
@@ -284,8 +284,11 @@ public class ReportPageService {
|
|||||||
public Object executeTable(Long reportId, String tableName) {
|
public Object executeTable(Long reportId, String tableName) {
|
||||||
|
|
||||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||||
AdminUserDO user = userService.getUser(loginUser.getId());
|
AdminUserRespDTO user = adminUserApi.getUser(loginUser.getId());
|
||||||
String username = user.getUsername();
|
String username = user != null ? user.getUsername() : null;
|
||||||
|
if (username == null) {
|
||||||
|
username = "";
|
||||||
|
}
|
||||||
|
|
||||||
ReportDatabaseDO reportDatabase =
|
ReportDatabaseDO reportDatabase =
|
||||||
reportMapper.selectReportDatabaseByReportId(reportId);
|
reportMapper.selectReportDatabaseByReportId(reportId);
|
||||||
|
|||||||
Reference in New Issue
Block a user