feat(dify): 添加 Dify应用服务模块

- 新增 DifyServeService 服务类,实现应用列表获取和持久化- 添加 DifyServeMapper 和 DifyServeRepository 接口
- 创建 AppsResponse 实体类,用于存储应用响应数据
- 新增 V1ServeController 控制器,提供应用列表接口
- 在 application-dev.yml 中添加 Dify 服务器配置信息
- 移除不必要的 SseController 和 WebConfig 类
This commit is contained in:
zhuangtianxiang 2025-04-24 01:30:22 +08:00
parent ba03edbc00
commit aeaaf046d6
11 changed files with 145 additions and 52 deletions

View File

@ -3,8 +3,10 @@ package com.zsc.edu.dify.modules.dify.controller;
import com.zsc.edu.dify.modules.dify.service.DifyChatService; import com.zsc.edu.dify.modules.dify.service.DifyChatService;
import io.github.guoshiqiufeng.dify.chat.dto.request.ChatMessageSendRequest; import io.github.guoshiqiufeng.dify.chat.dto.request.ChatMessageSendRequest;
import io.github.guoshiqiufeng.dify.chat.dto.request.MessageConversationsRequest; import io.github.guoshiqiufeng.dify.chat.dto.request.MessageConversationsRequest;
import io.github.guoshiqiufeng.dify.chat.dto.request.MessageFeedbackRequest;
import io.github.guoshiqiufeng.dify.chat.dto.response.ChatMessageSendCompletionResponse; import io.github.guoshiqiufeng.dify.chat.dto.response.ChatMessageSendCompletionResponse;
import io.github.guoshiqiufeng.dify.chat.dto.response.MessageConversationsResponse; import io.github.guoshiqiufeng.dify.chat.dto.response.MessageConversationsResponse;
import io.github.guoshiqiufeng.dify.chat.dto.response.MessageFeedbackResponse;
import io.github.guoshiqiufeng.dify.core.pojo.DifyPageResult; import io.github.guoshiqiufeng.dify.core.pojo.DifyPageResult;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -44,4 +46,5 @@ public class V1ChatController {
return difyChatService.conversations(request); return difyChatService.conversations(request);
} }
} }

View File

@ -0,0 +1,25 @@
package com.zsc.edu.dify.modules.dify.controller;
import com.zsc.edu.dify.modules.dify.service.DifyServeService;
import io.github.guoshiqiufeng.dify.autoconfigure.DifyServerAutoConfiguration;
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author zhuang
*/
@RestController
@RequestMapping("/v1/serve")
public class V1ServeController {
@Resource
private DifyServeService difyServeService;
@GetMapping("/apps")
public List<AppsResponseVO> apps(String mode, String name) {
return difyServeService.apps(mode, name);
}
}

View File

@ -0,0 +1,30 @@
package com.zsc.edu.dify.modules.dify.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zsc.edu.dify.framework.json.JsonbTypeHandler;
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@TableName("apps_response")
public class AppsResponse extends AppsResponseVO {
@TableField(typeHandler = JsonbTypeHandler.class)
public Map<String, Object> workflow;
@TableField(typeHandler = JsonbTypeHandler.class)
public List<String> tags;
@TableField(typeHandler = JsonbTypeHandler.class)
public Map<String, Object> modelConfig;
}

View File

@ -0,0 +1,12 @@
package com.zsc.edu.dify.modules.dify.mapper;
import com.zsc.edu.dify.common.mapstruct.BaseMapper;
import com.zsc.edu.dify.modules.dify.entity.AppsResponse;
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface DifyServeMapper extends BaseMapper<AppsResponseVO, AppsResponse> {
}

View File

@ -0,0 +1,8 @@
package com.zsc.edu.dify.modules.dify.repo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zsc.edu.dify.modules.dify.entity.AppsResponse;
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
public interface DifyServeRepository extends BaseMapper<AppsResponse> {
}

View File

@ -1,16 +1,21 @@
package com.zsc.edu.dify.modules.dify.service; package com.zsc.edu.dify.modules.dify.service;
import io.github.guoshiqiufeng.dify.chat.DifyChat; import io.github.guoshiqiufeng.dify.chat.DifyChat;
import io.github.guoshiqiufeng.dify.chat.dto.request.BaseChatRequest;
import io.github.guoshiqiufeng.dify.chat.dto.request.ChatMessageSendRequest; import io.github.guoshiqiufeng.dify.chat.dto.request.ChatMessageSendRequest;
import io.github.guoshiqiufeng.dify.chat.dto.request.MessageConversationsRequest; import io.github.guoshiqiufeng.dify.chat.dto.request.MessageConversationsRequest;
import io.github.guoshiqiufeng.dify.chat.dto.request.MessageFeedbackRequest;
import io.github.guoshiqiufeng.dify.chat.dto.response.ChatMessageSendCompletionResponse; import io.github.guoshiqiufeng.dify.chat.dto.response.ChatMessageSendCompletionResponse;
import io.github.guoshiqiufeng.dify.chat.dto.response.MessageConversationsResponse; import io.github.guoshiqiufeng.dify.chat.dto.response.MessageConversationsResponse;
import io.github.guoshiqiufeng.dify.chat.dto.response.MessageFeedbackResponse;
import io.github.guoshiqiufeng.dify.core.pojo.DifyPageResult; import io.github.guoshiqiufeng.dify.core.pojo.DifyPageResult;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import java.lang.reflect.Field;
/** /**
* @author yanghq * @author yanghq
* @version 1.0 * @version 1.0
@ -25,11 +30,14 @@ public class DifyChatService {
public Flux<ChatMessageSendCompletionResponse> sendChatMessageStream(ChatMessageSendRequest sendRequest) { public Flux<ChatMessageSendCompletionResponse> sendChatMessageStream(ChatMessageSendRequest sendRequest) {
// 可以进行自定义逻辑处理参数转换权限校验等 // 可以进行自定义逻辑处理参数转换权限校验等
(sendRequest).setApiKey("app-mM2UGTE5QVPLCwGvwifnV0g7");
return difyChat.sendChatMessageStream(sendRequest); return difyChat.sendChatMessageStream(sendRequest);
} }
public DifyPageResult<MessageConversationsResponse> conversations(MessageConversationsRequest request) { public DifyPageResult<MessageConversationsResponse> conversations(MessageConversationsRequest request) {
(request).setApiKey("app-mM2UGTE5QVPLCwGvwifnV0g7");
return difyChat.conversations(request); return difyChat.conversations(request);
} }
} }

View File

@ -0,0 +1,42 @@
package com.zsc.edu.dify.modules.dify.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zsc.edu.dify.modules.dify.entity.AppsResponse;
import com.zsc.edu.dify.modules.dify.mapper.DifyServeMapper;
import com.zsc.edu.dify.modules.dify.repo.DifyServeRepository;
import io.github.guoshiqiufeng.dify.server.DifyServer;
import io.github.guoshiqiufeng.dify.server.dto.response.AppsResponseVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author zhuang
*/
@Slf4j
@Service
public class DifyServeService {
@Resource
DifyServer difyServer;
@Resource
DifyServeRepository difyServeRepository;
@Resource
DifyServeMapper difyServeMapper;
public List<AppsResponseVO> apps(String mode, String name) {
return addApps(difyServer.apps(mode, name));
}
public List<AppsResponseVO> addApps(List<AppsResponseVO> apps) {
for(AppsResponseVO app : apps){
boolean isHave = difyServeRepository.exists(new LambdaQueryWrapper<AppsResponse>().eq(AppsResponse::getId, app.getId()));
if(isHave){
difyServeRepository.updateById(difyServeMapper.toEntity(app));
}else {
difyServeRepository.insert(difyServeMapper.toEntity(app));
}
}
return apps;
}
}

View File

@ -1,33 +0,0 @@
package com.zsc.edu.dify.modules.sse;
import lombok.AllArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;
import reactor.util.concurrent.Queues;
import java.time.Duration;
@AllArgsConstructor
@RestController
@RequestMapping("/api/rest/sse")
public class SseController {
private final Sinks.Many<ServerSentEvent<String>> sink = Sinks.many().multicast().onBackpressureBuffer(Queues.SMALL_BUFFER_SIZE);
@GetMapping(value = "/send", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> sendSse() {
return sink.asFlux()
.doOnSubscribe(subscription -> {
// 模拟发送事件
sink.tryEmitNext(ServerSentEvent.builder("Hello, SSE!").build());
sink.tryEmitNext(ServerSentEvent.builder("This is a Server-Sent Event.").build());
sink.tryEmitNext(ServerSentEvent.builder("SSE is working.").build());
})
.delayElements(Duration.ofSeconds(1));
}
}

View File

@ -1,19 +0,0 @@
package com.zsc.edu.dify.modules.sse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/rest/sse/**")
.allowedOrigins("http://localhost:8081")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}

View File

@ -57,3 +57,8 @@ storage:
jwt: jwt:
secret: your_secret_key_here secret: your_secret_key_here
expiration: 3600 expiration: 3600
dify:
server:
email: 2913129173@qq.com
password: tian14384,

View File

@ -0,0 +1,12 @@
create table persistent_logins
(
username varchar(64) not null,
series varchar(64) not null
primary key,
token varchar(64) not null,
last_used timestamp not null
);
alter table persistent_logins
owner to gitea;