feat(dify): 实现工作流与部门关联功能

- 新增 WorkflowDept 实体类和相关 DTO
- 实现 AppEntityRepository 中的 selectByAppType 方法
- 更新 AppEntityService 接口,添加按类型获取应用列表的方法- 实现 V1ServerController 中的 link 方法,用于关联工作流和部门
- 新增 WorkflowDeptRepository 和 WorkflowDeptService 接口
- 更新 SpringSecurityConfig,添加并发会话控制策略
-调整应用配置文件,增加全局和广州 API 配置
This commit is contained in:
vertoryao 2025-06-12 16:43:49 +08:00
parent 0d30f40f0e
commit 2ea43b840c
26 changed files with 265 additions and 82 deletions

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
} }
} }

View File

@ -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

View File

@ -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();
} }
} }

View File

@ -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));
} }
/** /**

View File

@ -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));
} }
/** /**

View File

@ -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 {

View File

@ -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("关联失败");
}
} }

View File

@ -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));
} }

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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;
}

View File

@ -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);
} }

View File

@ -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> {
}

View File

@ -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);

View File

@ -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();
} }
} }

View File

@ -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 {
}

View File

@ -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> {
}

View File

@ -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}

View File

@ -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}

View File

@ -1,6 +1,6 @@
spring: spring:
profiles: profiles:
active: dev active: ${PROF_ACTIVE:dev}
docker: docker:
compose: compose:
enabled: false enabled: false

View 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>

View File

@ -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);
}
}