feat(dify): 实现工作流与部门关联功能
- 新增 WorkflowDept 实体类和相关 DTO - 实现 AppEntityRepository 中的 selectByAppType 方法 - 更新 AppEntityService 接口,添加按类型获取应用列表的方法- 实现 V1ServerController 中的 link 方法,用于关联工作流和部门 - 新增 WorkflowDeptRepository 和 WorkflowDeptService 接口 - 更新 SpringSecurityConfig,添加并发会话控制策略 -调整应用配置文件,增加全局和广州 API 配置
This commit is contained in:
parent
0d30f40f0e
commit
2ea43b840c
@ -1,17 +0,0 @@
|
|||||||
package com.zsc.edu.dify.framework;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author zhuang
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class RestClientConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RestClient restClient() {
|
|
||||||
return RestClient.builder().build();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.zsc.edu.dify.framework;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
import reactor.netty.http.client.HttpClient;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhuang
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class WebClientConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RestClient restClient() {
|
||||||
|
// 配置超时参数
|
||||||
|
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
||||||
|
requestFactory.setConnectTimeout((int) Duration.ofMinutes(30).toMillis()); // 设置连接超时时间为5秒
|
||||||
|
requestFactory.setReadTimeout((int) Duration.ofMinutes(30).toMillis()); // 设置读取超时时间为5秒
|
||||||
|
|
||||||
|
return RestClient.builder()
|
||||||
|
.requestFactory(requestFactory)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.zsc.edu.dify.framework.json;
|
package com.zsc.edu.dify.framework.json;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -13,7 +14,8 @@ public class JsonConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Jackson2ObjectMapperBuilderCustomizer customizer() {
|
public Jackson2ObjectMapperBuilderCustomizer customizer() {
|
||||||
return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)
|
return builder -> builder
|
||||||
|
.serializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
.serializationInclusion(JsonInclude.Include.NON_EMPTY);
|
.serializationInclusion(JsonInclude.Include.NON_EMPTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class CustomAccessDeniedHandler implements AccessDeniedHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||||
AccessDeniedException ex) throws IOException, ServletException {
|
AccessDeniedException ex) throws IOException, ServletException {
|
||||||
// ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
response.setContentType("application/json;charset=utf-8");
|
response.setContentType("application/json;charset=utf-8");
|
||||||
ExceptionResult result;
|
ExceptionResult result;
|
||||||
if (ex instanceof MissingCsrfTokenException) {
|
if (ex instanceof MissingCsrfTokenException) {
|
||||||
@ -39,9 +39,9 @@ public class CustomAccessDeniedHandler implements AccessDeniedHandler {
|
|||||||
result = new ExceptionResult("凭证已过期,请重新登录", HttpStatus.UNAUTHORIZED.value(),
|
result = new ExceptionResult("凭证已过期,请重新登录", HttpStatus.UNAUTHORIZED.value(),
|
||||||
LocalDateTime.now());
|
LocalDateTime.now());
|
||||||
} else if (ex instanceof AuthorizationDeniedException) {
|
} else if (ex instanceof AuthorizationDeniedException) {
|
||||||
// 403
|
// 会话已存在,禁止重复登录,返回401
|
||||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||||
result = new ExceptionResult("当前账号已在其他设备登录,请先退出再尝试登录", HttpStatus.FORBIDDEN.value(),
|
result = new ExceptionResult("当前账号已在其他设备登录,请先退出再尝试登录", HttpStatus.UNAUTHORIZED.value(),
|
||||||
LocalDateTime.now());
|
LocalDateTime.now());
|
||||||
} else {
|
} else {
|
||||||
// 403
|
// 403
|
||||||
|
@ -10,7 +10,6 @@ import org.springframework.security.authentication.ProviderManager;
|
|||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
|
||||||
import org.springframework.security.core.session.SessionRegistry;
|
import org.springframework.security.core.session.SessionRegistry;
|
||||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
@ -39,6 +38,7 @@ public class SpringSecurityConfig {
|
|||||||
private final CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
|
private final CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
|
||||||
private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
|
private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
|
||||||
private final CustomAccessDeniedHandler customAccessDeniedHandler;
|
private final CustomAccessDeniedHandler customAccessDeniedHandler;
|
||||||
|
private final CustomSessionInformationExpiredStrategy customSessionInformationExpiredStrategy;
|
||||||
// private final SessionRegistry sessionRegistry;
|
// private final SessionRegistry sessionRegistry;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@ -59,6 +59,14 @@ public class SpringSecurityConfig {
|
|||||||
return new HttpSessionEventPublisher();
|
return new HttpSessionEventPublisher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy() {
|
||||||
|
ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
|
||||||
|
concurrentSessionControlAuthenticationStrategy.setMaximumSessions(1);
|
||||||
|
concurrentSessionControlAuthenticationStrategy.setExceptionIfMaximumExceeded(true);
|
||||||
|
return concurrentSessionControlAuthenticationStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PersistentTokenRepository persistentTokenRepository() {
|
public PersistentTokenRepository persistentTokenRepository() {
|
||||||
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
|
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
|
||||||
@ -75,7 +83,7 @@ public class SpringSecurityConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public JsonAuthenticationFilter jsonAuthenticationFilter() throws Exception {
|
public JsonAuthenticationFilter jsonAuthenticationFilter() {
|
||||||
JsonAuthenticationFilter filter = new JsonAuthenticationFilter();
|
JsonAuthenticationFilter filter = new JsonAuthenticationFilter();
|
||||||
filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
|
filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
|
||||||
filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
|
filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
|
||||||
@ -89,13 +97,11 @@ public class SpringSecurityConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
return http
|
return http
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers(HttpMethod.GET, "/api/rest/user/menu","/api/rest/user/register","/api/rest/user/send-email").permitAll()
|
.requestMatchers(HttpMethod.GET, "/api/rest/user/menu","/api/rest/user/register","/api/rest/user/send-email").permitAll()
|
||||||
.requestMatchers(HttpMethod.POST, "/api/rest/user/login","/api/rest/user/register").permitAll()
|
.requestMatchers(HttpMethod.POST, "/api/rest/user/login","/api/rest/user/register").permitAll()
|
||||||
.requestMatchers("/api/rest/user/me").permitAll()
|
.requestMatchers("/api/rest/user/me").permitAll()
|
||||||
.requestMatchers("/v1/**").authenticated()
|
|
||||||
.requestMatchers("/api/**").authenticated()
|
.requestMatchers("/api/**").authenticated()
|
||||||
)
|
)
|
||||||
.addFilterAt(jsonAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
.addFilterAt(jsonAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||||
@ -115,13 +121,14 @@ public class SpringSecurityConfig {
|
|||||||
.rememberMe(rememberMe -> rememberMe
|
.rememberMe(rememberMe -> rememberMe
|
||||||
.userDetailsService(userDetailsService)
|
.userDetailsService(userDetailsService)
|
||||||
.tokenRepository(persistentTokenRepository()))
|
.tokenRepository(persistentTokenRepository()))
|
||||||
.csrf(csrf ->
|
.csrf(csrf -> csrf
|
||||||
csrf.ignoringRequestMatchers("v1/**","/api/internal/**", "/api/rest/user/logout","/api/rest/user/register"))
|
.sessionAuthenticationStrategy(concurrentSessionControlAuthenticationStrategy())
|
||||||
|
.ignoringRequestMatchers("v1/**","/api/internal/**", "/api/rest/user/logout","/api/rest/user/register"))
|
||||||
.sessionManagement(session -> session
|
.sessionManagement(session -> session
|
||||||
.maximumSessions(1)
|
.maximumSessions(1)
|
||||||
.maxSessionsPreventsLogin(true)
|
.maxSessionsPreventsLogin(true)
|
||||||
.sessionRegistry(sessionRegistry())
|
.sessionRegistry(sessionRegistry())
|
||||||
// .expiredSessionStrategy(customSessionInformationExpiredStrategy)
|
.expiredSessionStrategy(customSessionInformationExpiredStrategy)
|
||||||
).build();
|
).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,11 @@ public class PPTController {
|
|||||||
* @param request
|
* @param request
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PostMapping("/run")
|
@PostMapping("/run/{appId}")
|
||||||
@OperationLogAnnotation(content = "'dify工作流'", operationType = "运行")
|
@OperationLogAnnotation(content = "'dify工作流'", operationType = "运行")
|
||||||
public WorkflowRunResponse runWorkflow(@RequestBody WorkflowRunRequest request) {
|
public WorkflowRunResponse runWorkflow(@RequestBody WorkflowRunRequest request, @PathVariable String appId) {
|
||||||
request.setUserId(SecurityUtil.getUserInfo().id.toString());
|
request.setUserId(SecurityUtil.getUserInfo().id.toString());
|
||||||
return ExceptionUtil.difyException(() -> difyWorkflowService.run(request, "ee3889b6-50fa-463e-b956-3b93447727fc"));
|
return ExceptionUtil.difyException(() -> difyWorkflowService.run(request, appId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,11 +30,11 @@ public class Spider2Controller {
|
|||||||
* @param request
|
* @param request
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PostMapping("/run")
|
@PostMapping("/run/{appId}")
|
||||||
@OperationLogAnnotation(content = "'dify工作流'", operationType = "运行")
|
@OperationLogAnnotation(content = "'dify工作流'", operationType = "运行")
|
||||||
public WorkflowRunResponse runWorkflow(@RequestBody WorkflowRunRequest request) {
|
public WorkflowRunResponse runWorkflow(@RequestBody WorkflowRunRequest request, @PathVariable String appId) {
|
||||||
request.setUserId(SecurityUtil.getUserInfo().id.toString());
|
request.setUserId(SecurityUtil.getUserInfo().id.toString());
|
||||||
return ExceptionUtil.difyException(() -> difyWorkflowService.run(request, "c736edd0-925d-4877-9223-56aab7342311"));
|
return ExceptionUtil.difyException(() -> difyWorkflowService.run(request, appId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.zsc.edu.dify.modules.dify.dto.SpiderDto;
|
import com.zsc.edu.dify.modules.dify.dto.SpiderDto;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@ -21,8 +22,11 @@ public class SpiderController {
|
|||||||
@Resource
|
@Resource
|
||||||
private ObjectMapper objectMapper;
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
private static final String SPIDER_URL = "http://47.112.173.8:6806/api/v1";
|
@Value("${quanguo.url}")
|
||||||
private static final String API_KEY = "77c068fd-d5b6-4c33-97d8-db5511a09b26";
|
private String SPIDER_URL;
|
||||||
|
|
||||||
|
@Value("${quanguo.api-key}")
|
||||||
|
private String API_KEY;
|
||||||
|
|
||||||
@PostMapping("/run")
|
@PostMapping("/run")
|
||||||
public JSONObject run(@RequestBody SpiderDto dto) throws JsonProcessingException {
|
public JSONObject run(@RequestBody SpiderDto dto) throws JsonProcessingException {
|
||||||
|
@ -2,28 +2,37 @@ package com.zsc.edu.dify.modules.dify.controller;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.zsc.edu.dify.framework.mybatisplus.DataPermission;
|
import com.zsc.edu.dify.framework.mybatisplus.DataPermission;
|
||||||
|
import com.zsc.edu.dify.modules.dify.dto.WorkflowDeptDto;
|
||||||
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
||||||
|
import com.zsc.edu.dify.modules.dify.entity.WorkflowDept;
|
||||||
import com.zsc.edu.dify.modules.dify.service.AppEntityService;
|
import com.zsc.edu.dify.modules.dify.service.AppEntityService;
|
||||||
|
import com.zsc.edu.dify.modules.dify.service.WorkflowDeptService;
|
||||||
import com.zsc.edu.dify.modules.operationLog.entity.OperationLogAnnotation;
|
import com.zsc.edu.dify.modules.operationLog.entity.OperationLogAnnotation;
|
||||||
import io.github.guoshiqiufeng.dify.server.DifyServer;
|
import io.github.guoshiqiufeng.dify.server.DifyServer;
|
||||||
import io.github.guoshiqiufeng.dify.server.dto.response.ApiKeyResponseVO;
|
import io.github.guoshiqiufeng.dify.server.dto.response.ApiKeyResponseVO;
|
||||||
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
|
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
|
||||||
import io.github.guoshiqiufeng.dify.server.dto.response.DatasetApiKeyResponseVO;
|
import io.github.guoshiqiufeng.dify.server.dto.response.DatasetApiKeyResponseVO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/server")
|
@RequestMapping("/api/v1/server")
|
||||||
public class V1ServerController {
|
public class V1ServerController {
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DifyServer difyServer;
|
private DifyServer difyServer;
|
||||||
@Resource
|
|
||||||
private AppEntityService appEntityService;
|
private AppEntityService appEntityService;
|
||||||
|
|
||||||
|
private final WorkflowDeptService workflowDeptService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取应用列表
|
* 获取应用列表
|
||||||
* @param mode 模式 chat\agent-chat\completion\advanced-chat\workflow
|
* @param mode 模式 chat\agent-chat\completion\advanced-chat\workflow
|
||||||
@ -31,9 +40,8 @@ public class V1ServerController {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@GetMapping("/apps")
|
@GetMapping("/apps")
|
||||||
@DataPermission
|
public List<AppEntity> getApps(String mode, String name, Integer type) {
|
||||||
public List<AppsResponseVO> getApps(String mode, String name) {
|
return appEntityService.getApps(mode, name, type);
|
||||||
return appEntityService.getApps(mode, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,8 +122,21 @@ public class V1ServerController {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@GetMapping("/apps/type")
|
@GetMapping("/apps/type")
|
||||||
@DataPermission
|
// @DataPermission
|
||||||
public List<AppEntity> getAppsByAppType(Integer appType){
|
public List<AppEntity> getAppsByAppType(Integer appType){
|
||||||
return appEntityService.selectByAppType(appType);
|
return appEntityService.selectByAppType(appType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/link")
|
||||||
|
public ResponseEntity<String> link(@RequestBody WorkflowDeptDto workflowDeptDto) {
|
||||||
|
List<WorkflowDept> workflowDepts = new ArrayList<>();
|
||||||
|
for (Long deptId: workflowDeptDto.getDeptIds()) {
|
||||||
|
workflowDepts.add(new WorkflowDept(workflowDeptDto.getWorkflowId(), deptId));
|
||||||
|
}
|
||||||
|
// 删除旧的关联关系
|
||||||
|
workflowDeptService.remove(new LambdaQueryWrapper<WorkflowDept>().eq(WorkflowDept::getWorkflowId, workflowDeptDto.getWorkflowId()));
|
||||||
|
return workflowDeptService.saveBatch(workflowDepts) ?
|
||||||
|
ResponseEntity.ok("关联成功") :
|
||||||
|
ResponseEntity.status(HttpStatus.BAD_REQUEST).body("关联失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,10 @@ public class WordController {
|
|||||||
* 用户 id可以改为从上下文(token)获取,
|
* 用户 id可以改为从上下文(token)获取,
|
||||||
* apikey 建议在数据库进行存储,前端调用时传智能体 id,从数据库查询
|
* apikey 建议在数据库进行存储,前端调用时传智能体 id,从数据库查询
|
||||||
*/
|
*/
|
||||||
@PostMapping("/completions")
|
@PostMapping("/completions/{appId}")
|
||||||
@OperationLogAnnotation(content = "'dify对话'", operationType = "发送")
|
@OperationLogAnnotation(content = "'dify对话'", operationType = "发送")
|
||||||
public ChatMessageSendResponse sendChatMessage(@RequestBody ChatMessageSendRequest sendRequest){
|
public ChatMessageSendResponse sendChatMessage(@RequestBody ChatMessageSendRequest sendRequest, @PathVariable String appId){
|
||||||
sendRequest.setApiKey(appEntityService.getApikey("baca08c1-e92b-4dc9-a445-3584803f54d4"));
|
sendRequest.setApiKey(appEntityService.getApikey(appId));
|
||||||
sendRequest.setUserId(SecurityUtil.getUserInfo().id.toString());
|
sendRequest.setUserId(SecurityUtil.getUserInfo().id.toString());
|
||||||
return ExceptionUtil.difyException(()->difyChat.send(sendRequest));
|
return ExceptionUtil.difyException(()->difyChat.send(sendRequest));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.zsc.edu.dify.modules.dify.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WorkflowDeptDto {
|
||||||
|
@NotNull
|
||||||
|
private String workflowId;
|
||||||
|
@NotNull
|
||||||
|
private Long[] deptIds;
|
||||||
|
}
|
@ -19,7 +19,6 @@ import java.util.Map;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Data
|
|
||||||
@TableName("apps_entity")
|
@TableName("apps_entity")
|
||||||
public class AppEntity extends AppsResponseVO {
|
public class AppEntity extends AppsResponseVO {
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Data
|
|
||||||
@TableName("workflow_data")
|
@TableName("workflow_data")
|
||||||
public class WorkflowData{
|
public class WorkflowData{
|
||||||
@TableId
|
@TableId
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.zsc.edu.dify.modules.dify.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class WorkflowDept {
|
||||||
|
private String workflowId;
|
||||||
|
private Long deptId;
|
||||||
|
}
|
@ -2,10 +2,15 @@ package com.zsc.edu.dify.modules.dify.repo;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface AppEntityRepository extends BaseMapper<AppEntity> {
|
public interface AppEntityRepository extends BaseMapper<AppEntity> {
|
||||||
|
|
||||||
@Select("select api_key from apps_entity where id = #{appId}")
|
@Select("select api_key from apps_entity where id = #{appId}")
|
||||||
String selectApiKey(String appId);
|
String selectApiKey(String appId);
|
||||||
|
|
||||||
|
List<AppEntity> selectByAppType(@Param("deptId") Long deptId, @Param("appType") Integer appType);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.zsc.edu.dify.modules.dify.repo;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.zsc.edu.dify.modules.dify.entity.WorkflowDept;
|
||||||
|
|
||||||
|
public interface WorkflowDeptRepository extends BaseMapper<WorkflowDept> {
|
||||||
|
}
|
@ -2,12 +2,11 @@ package com.zsc.edu.dify.modules.dify.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
||||||
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface AppEntityService extends IService<AppEntity> {
|
public interface AppEntityService extends IService<AppEntity> {
|
||||||
List<AppsResponseVO> getApps(String mode, String name);
|
List<AppEntity> getApps(String mode, String name, Integer appType);
|
||||||
|
|
||||||
boolean enabledApp(String id);
|
boolean enabledApp(String id);
|
||||||
|
|
||||||
|
@ -3,9 +3,12 @@ package com.zsc.edu.dify.modules.dify.service.Impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.zsc.edu.dify.exception.ConstraintException;
|
import com.zsc.edu.dify.exception.ConstraintException;
|
||||||
|
import com.zsc.edu.dify.framework.security.SecurityUtil;
|
||||||
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
import com.zsc.edu.dify.modules.dify.entity.AppEntity;
|
||||||
|
import com.zsc.edu.dify.modules.dify.entity.WorkflowDept;
|
||||||
import com.zsc.edu.dify.modules.dify.mapper.AppEntityMapper;
|
import com.zsc.edu.dify.modules.dify.mapper.AppEntityMapper;
|
||||||
import com.zsc.edu.dify.modules.dify.repo.AppEntityRepository;
|
import com.zsc.edu.dify.modules.dify.repo.AppEntityRepository;
|
||||||
|
import com.zsc.edu.dify.modules.dify.repo.WorkflowDeptRepository;
|
||||||
import com.zsc.edu.dify.modules.dify.service.AppEntityService;
|
import com.zsc.edu.dify.modules.dify.service.AppEntityService;
|
||||||
import io.github.guoshiqiufeng.dify.server.DifyServer;
|
import io.github.guoshiqiufeng.dify.server.DifyServer;
|
||||||
import io.github.guoshiqiufeng.dify.server.dto.response.ApiKeyResponseVO;
|
import io.github.guoshiqiufeng.dify.server.dto.response.ApiKeyResponseVO;
|
||||||
@ -14,6 +17,7 @@ import jakarta.annotation.Resource;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -23,16 +27,23 @@ import java.util.*;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
public class AppEntityServiceImpl extends ServiceImpl<AppEntityRepository, AppEntity> implements AppEntityService {
|
public class AppEntityServiceImpl extends ServiceImpl<AppEntityRepository, AppEntity> implements AppEntityService {
|
||||||
@Resource
|
|
||||||
private AppEntityMapper appEntityMapper;
|
private final AppEntityMapper appEntityMapper;
|
||||||
@Resource
|
|
||||||
private DifyServer difyServer;
|
private final DifyServer difyServer;
|
||||||
@Resource
|
|
||||||
private AppEntityRepository appEntityRepository;
|
private final AppEntityRepository appEntityRepository;
|
||||||
|
|
||||||
|
private final WorkflowDeptRepository workflowDeptRepository;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AppsResponseVO> getApps(String mode, String name) {
|
public List<AppEntity> getApps(String mode, String name, Integer type) {
|
||||||
return addApps(difyServer.apps(mode, name));
|
return this.lambdaQuery()
|
||||||
|
.eq(StringUtils.hasText(mode), AppEntity::getMode, mode)
|
||||||
|
.eq(StringUtils.hasText(name), AppEntity::getName, name)
|
||||||
|
.eq(Objects.nonNull(type), AppEntity::getAppType, type)
|
||||||
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,17 +108,8 @@ public class AppEntityServiceImpl extends ServiceImpl<AppEntityRepository, AppEn
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<AppEntity> selectByAppType(Integer appType) {
|
public List<AppEntity> selectByAppType(Integer appType) {
|
||||||
return this.lambdaQuery()
|
Long deptId = SecurityUtil.getUserInfo().getDept().getId();
|
||||||
.eq(AppEntity::getAppType, appType)
|
return baseMapper.selectByAppType(deptId, appType);
|
||||||
.list();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.zsc.edu.dify.modules.dify.service.Impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.zsc.edu.dify.modules.dify.entity.WorkflowDept;
|
||||||
|
import com.zsc.edu.dify.modules.dify.repo.WorkflowDeptRepository;
|
||||||
|
import com.zsc.edu.dify.modules.dify.service.WorkflowDeptService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class WorkflowDeptServiceImpl extends ServiceImpl<WorkflowDeptRepository, WorkflowDept> implements WorkflowDeptService {
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.zsc.edu.dify.modules.dify.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.zsc.edu.dify.modules.dify.entity.WorkflowDept;
|
||||||
|
|
||||||
|
public interface WorkflowDeptService extends IService<WorkflowDept> {
|
||||||
|
}
|
@ -59,6 +59,10 @@ spring:
|
|||||||
socketFactoryClass: javax.net.ssl.SSLSocketFactory
|
socketFactoryClass: javax.net.ssl.SSLSocketFactory
|
||||||
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
|
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
|
||||||
debug: true
|
debug: true
|
||||||
|
http:
|
||||||
|
client:
|
||||||
|
connect-timeout: 1800000
|
||||||
|
read-timeout: 1800000
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
attachment: ./storage/attachment
|
attachment: ./storage/attachment
|
||||||
@ -70,9 +74,16 @@ jwt:
|
|||||||
|
|
||||||
dify:
|
dify:
|
||||||
url: http://47.112.173.8:6800/ # 请替换为实际的 Dify 服务地址
|
url: http://47.112.173.8:6800/ # 请替换为实际的 Dify 服务地址
|
||||||
|
# url: http://172.16.35.190 # 请替换为实际的 Dify 服务地址
|
||||||
server:
|
server:
|
||||||
email: 2913129173@qq.com # 请替换为实际的 Dify 服务邮箱,若不需要调用 server相关接口可不填
|
email: 2913129173@qq.com # 请替换为实际的 Dify 服务邮箱,若不需要调用 server相关接口可不填
|
||||||
password: tian14384, # 请替换为实际的 Dify 服务密码,若不需要调用 server相关接口可不填
|
password: tian14384, # 请替换为实际的 Dify 服务密码,若不需要调用 server相关接口可不填
|
||||||
|
# email: admin@admin.com # 请替换为实际的 Dify 服务邮箱,若不需要调用 server相关接口可不填
|
||||||
|
# password: Anheng@keji_777 # 请替换为实际的 Dify 服务密码,若不需要调用 server相关接口可不填
|
||||||
dataset:
|
dataset:
|
||||||
api-key: dataset-kN5WTJ8jR877YfN1A34JceVg # 请替换为实际的知识库api-key, 若不需要调用知识库可不填
|
api-key: dataset-kN5WTJ8jR877YfN1A34JceVg # 请替换为实际的知识库api-key, 若不需要调用知识库可不填
|
||||||
|
|
||||||
|
quanguo:
|
||||||
|
url: http://${QUANGUO_HOST:47.112.173.8:6806/api/v1}
|
||||||
|
api-key: ${QUANGUO_API_KEY:77c068fd-d5b6-4c33-97d8-db5511a09b26}
|
||||||
|
|
||||||
|
@ -3,21 +3,35 @@ server:
|
|||||||
|
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
type-aliases-package: com.zsc.edu.dify.modules.*.entity
|
type-aliases-package: com.zsc.edu.dify.modules.*.entity
|
||||||
mapper-locations: classpath:mappers/*/*.xml
|
mapper-locations: classpath*:mappers/*/*.xml
|
||||||
type-handlers-package: com.zsc.edu.dify.framework.mybatisplus
|
type-handlers-package: com.zsc.edu.dify.framework.mybatisplus
|
||||||
configuration:
|
configuration:
|
||||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
|
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://localhost:5432/gateway?ssl=false&TimeZone=Asia/Shanghai
|
url: jdbc:postgresql://${POSTGRES_HOST:postgres}:5432/dify?ssl=false&TimeZone=Asia/Shanghai
|
||||||
username: postgres
|
username: postgres
|
||||||
password: 123456
|
password: postgres
|
||||||
driver-class-name: org.postgresql.Driver
|
driver-class-name: org.postgresql.Driver
|
||||||
|
hikari:
|
||||||
|
max-lifetime: 1800000
|
||||||
|
idle-timeout: 600000
|
||||||
|
validation-timeout: 5000
|
||||||
|
data:
|
||||||
|
redis:
|
||||||
|
host: 43.139.10.64
|
||||||
|
port: 16379
|
||||||
|
password:
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 40MB
|
max-file-size: 40MB
|
||||||
max-request-size: 40MB
|
max-request-size: 40MB
|
||||||
|
jackson:
|
||||||
|
# 属性为空不序列化
|
||||||
|
default-property-inclusion: non_null
|
||||||
mail:
|
mail:
|
||||||
# 配置 SMTP 服务器地址
|
# 配置 SMTP 服务器地址
|
||||||
host: smtp.qq.com
|
host: smtp.qq.com
|
||||||
@ -33,10 +47,29 @@ spring:
|
|||||||
properties:
|
properties:
|
||||||
mail:
|
mail:
|
||||||
smtp:
|
smtp:
|
||||||
|
auth: true
|
||||||
|
starttls:
|
||||||
|
enable: true
|
||||||
socketFactoryClass: javax.net.ssl.SSLSocketFactory
|
socketFactoryClass: javax.net.ssl.SSLSocketFactory
|
||||||
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
|
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
|
||||||
debug: true
|
debug: true
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
attachment: ./storage/attachment
|
attachment: ./storage/attachment
|
||||||
temp: ./storage/temp
|
temp: ./storage/temp
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
secret: your_secret_key_here
|
||||||
|
expiration: 3600
|
||||||
|
|
||||||
|
dify:
|
||||||
|
url: http://${DIFY_HOST:localhost}/ # 请替换为实际的 Dify 服务地址
|
||||||
|
server:
|
||||||
|
email: ${DIFY_EMAIL:admin@admin.com} # 请替换为实际的 Dify 服务邮箱,若不需要调用 server相关接口可不填
|
||||||
|
password: ${DIFY_PASSWORD:Anheng@keji_777} # 请替换为实际的 Dify 服务密码,若不需要调用 server相关接口可不填
|
||||||
|
dataset:
|
||||||
|
api-key: ${DIFY_DATASET_API_KEY:dataset-kN5WTJ8jR877YfN1A34JceVg} # 请替换为实际的知识库api-key, 若不需要调用知识库可不填
|
||||||
|
|
||||||
|
guangzhou:
|
||||||
|
url: ${GUANGZHOU_HOST:http://47.112.173.8:6806/api/v1}
|
||||||
|
api-key: ${GUANGZHOU_API_KEY:ed01e58b-c537-4837-9907-8d9bec2efa55}
|
@ -1,6 +1,6 @@
|
|||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: ${PROF_ACTIVE:dev}
|
||||||
docker:
|
docker:
|
||||||
compose:
|
compose:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
20
src/main/resources/mappers/dify/AppEntityRepository.xml
Normal file
20
src/main/resources/mappers/dify/AppEntityRepository.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.zsc.edu.dify.modules.dify.repo.AppEntityRepository">
|
||||||
|
|
||||||
|
<select id="selectByAppType" resultType="com.zsc.edu.dify.modules.dify.entity.AppEntity">
|
||||||
|
select ae.* from apps_entity ae
|
||||||
|
left join workflow_dept wd on ae.id=wd.workflow_id
|
||||||
|
<where>
|
||||||
|
<if test="appType != null">
|
||||||
|
and ae.app_type=#{appType}
|
||||||
|
</if>
|
||||||
|
<if test="deptId != null">
|
||||||
|
and wd.dept_id=#{deptId}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.zsc.edu.dify.modules.dify.repo;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class AppEntityRepositoryTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AppEntityRepository appEntityRepository;
|
||||||
|
@Test
|
||||||
|
void selectByAppType() {
|
||||||
|
appEntityRepository.selectByAppType(1L, 1);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user