Browse Source

yinruoxi:

修改
    1.test代码合并请求
tags/B.1.2.4.0_20230908_alpha
kira 2 years ago
parent
commit
1027fc8d3f
100 changed files with 4087 additions and 33 deletions
  1. +7
    -5
      Jenkinsfile
  2. +67
    -0
      Jenkinsfile1
  3. +14
    -0
      docker-compose.yml
  4. +24
    -0
      pom.xml
  5. +1
    -0
      xueyi-api/pom.xml
  6. +16
    -0
      xueyi-api/xueyi-api-message/src/main/java/com/xueyi/message/api/transfer/domain/vo/Message.java
  7. +10
    -5
      xueyi-api/xueyi-api-message/src/main/java/com/xueyi/message/api/transfer/feign/RemoteTransferService.java
  8. +1
    -1
      xueyi-api/xueyi-api-modules-auth/src/main/java/com/xueyi/modules/auth/api/domain/vo/IntentionReqDto.java
  9. +33
    -0
      xueyi-api/xueyi-api-nlt/pom.xml
  10. +15
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/netty/domain/vo/DmWebSocketMessageVo.java
  11. +20
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/netty/feign/RemoteWebsocketService.java
  12. +13
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/CoversationSessionVo.java
  13. +18
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmIntentVo.java
  14. +29
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmLandingLlmVo.java
  15. +13
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmRecognitionVo.java
  16. +13
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/KnowledgeVo.java
  17. +17
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/TaskKnowledgeVo.java
  18. +27
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteIntentService.java
  19. +28
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteLandingLlmService.java
  20. +30
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteQAService.java
  21. +15
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteIntentFallbackFactory.java
  22. +42
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteLandingLlmFallbackFactory.java
  23. +34
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteQAFallbackFactory.java
  24. +3
    -0
      xueyi-api/xueyi-api-nlt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  25. +2
    -1
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/dto/DmSyncDigitalmanDto.java
  26. +2
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/dto/DmVisitorsDto.java
  27. +14
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/vo/DmBatchQuestionsVo.java
  28. +1
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/vo/DmBroadcastVo.java
  29. +4
    -2
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/feign/RemoteBroadcastService.java
  30. +13
    -1
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/feign/RemoteDigitalmanService.java
  31. +22
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/feign/RemoteQuestionanswersService.java
  32. +16
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/meeting/feign/RemoteMeetingService.java
  33. +25
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/meeting/feign/factory/RemoteMeetingFallbackFactory.java
  34. +28
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/organize/feign/RemoteEnterpriseService.java
  35. +31
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/organize/feign/factory/RemoteEnterpriseFallbackFactory.java
  36. +14
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/resource/feign/RemoteH5ConfigService.java
  37. +21
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/resource/feign/factory/RemoteH5ConfigFallbackFactory.java
  38. +8
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/staff/domain/po/DmStaffPo.java
  39. +3
    -0
      xueyi-api/xueyi-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  40. +13
    -0
      xueyi-common/xueyi-common-core/pom.xml
  41. +1
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/basic/ServiceConstants.java
  42. +8
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/digitalman/MessageConstants.java
  43. +29
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/digitalman/SkillConstants.java
  44. +6
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/nacos/NacosConstants.java
  45. +9
    -1
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/DateUtil.java
  46. +54
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/InetAddressUtils.java
  47. +23
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/core/StrUtil.java
  48. +40
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/sql/EsClient.java
  49. +30
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/time/LocalDateTimeSerializer.java
  50. +30
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/time/LocalDatetimeDeserializer.java
  51. +13
    -1
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/web/entity/base/BaseEntity.java
  52. +2
    -1
      xueyi-common/xueyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  53. +15
    -0
      xueyi-common/xueyi-common-mqtt/src/main/java/com/xueyi/common/mqtt/constant/MqttTopicConstant.java
  54. +1
    -0
      xueyi-common/xueyi-common-sms/src/main/java/com/xueyi/common/sms/configure/SmsProperties.java
  55. +5
    -0
      xueyi-common/xueyi-common-web/pom.xml
  56. +2
    -2
      xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/constant/ResponseCode.java
  57. +4
    -0
      xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/entity/service/IBaseService.java
  58. +57
    -0
      xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/entity/service/impl/BaseServiceImpl.java
  59. +12
    -0
      xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/utils/DateUtils.java
  60. +1
    -0
      xueyi-modules/pom.xml
  61. +28
    -2
      xueyi-modules/xueyi-file/src/main/java/com/xueyi/file/utils/PdfToImageUtil.java
  62. +5
    -0
      xueyi-modules/xueyi-job/pom.xml
  63. +23
    -0
      xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DmBroadDataTask.java
  64. +24
    -0
      xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DmGenerativeKnowledgeTask.java
  65. +25
    -0
      xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DmRecognizedRecordsCleanTask.java
  66. +2
    -1
      xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/util/AbstractQuartzJob.java
  67. +11
    -1
      xueyi-modules/xueyi-message/pom.xml
  68. +99
    -9
      xueyi-modules/xueyi-message/src/main/java/com/xueyi/message/transfer/controller/ApiController.java
  69. +19
    -0
      xueyi-modules/xueyi-message/src/main/java/com/xueyi/message/transfer/service/IMessageQueueService.java
  70. +167
    -0
      xueyi-modules/xueyi-message/src/main/java/com/xueyi/message/transfer/service/impl/MessageQueueServiceImpl.java
  71. +17
    -0
      xueyi-modules/xueyi-nlt/Dockerfile
  72. +112
    -0
      xueyi-modules/xueyi-nlt/pom.xml
  73. +15
    -0
      xueyi-modules/xueyi-nlt/sonar-project.properties
  74. +29
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/XueYiNltApplication.java
  75. +195
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/NettyClient.java
  76. +374
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClient.java
  77. +202
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebsocketConfig.java
  78. +46
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/codec/WsChannelInitializer.java
  79. +66
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/MockClientHandler.java
  80. +108
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/NettyClientHandler.java
  81. +196
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/NettyWebsocketClientHandler.java
  82. +23
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/WsClientHandler.java
  83. +13
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/message/ReceiveMessage.java
  84. +79
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/controller/DmWebsocketController.java
  85. +603
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/controller/DmIntentController.java
  86. +14
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/dto/DmIntentDto.java
  87. +13
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/model/DmIntentConverter.java
  88. +61
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/po/DmIntentPo.java
  89. +13
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/query/DmIntentQuery.java
  90. +19
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/vo/IntentTemplateVo.java
  91. +8
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/manager/IDmIntentManager.java
  92. +15
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/manager/impl/DmIntentManager.java
  93. +11
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/mapper/DmIntentMapper.java
  94. +8
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/IDmIntentService.java
  95. +12
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/impl/DmIntentServiceImpl.java
  96. +8
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/BaseTemplate.java
  97. +61
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/FreeChatTemplate.java
  98. +59
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/GenerativeKnowledgeTemplate.java
  99. +245
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MeetingOrderTemplate.java
  100. +10
    -0
      xueyi-modules/xueyi-nlt/src/main/resources/banner.txt

+ 7
- 5
Jenkinsfile View File

@@ -19,7 +19,7 @@ pipeline {
sh "which java"
echo "打包子目录并进行代码检查 ${project_name}"
sh "mvn clean install"
sh "mvn -f ${project_name} clean package -e -U -Dmaven.test.skip=true -Dsonar.login=admin -Dsonar.password=Digimeta@2023 sonar:sonar"
sh "mvn -f ${project_name} clean package -e -U -Dmaven.test.skip=true -P${build_env} -Dsonar.login=admin -Dsonar.password=Digimeta@2023 sonar:sonar"
}
}
}
@@ -31,8 +31,10 @@ pipeline {
def workspace=pwd()
// 删除所有report报告
sh "find ${workspace} -name report-task.txt | xargs rm -f"
// 删除所有sonar锁
sh "find ${workspace} -name .sonar_lock | xargs rm -f"
}
timeout(time: 15, unit: 'MINUTES') {
timeout(time: 5, unit: 'MINUTES') {
// Parameter indicates whether to set pipeline to UNSTABLE if Quality Gate fails
// true = set pipeline to UNSTABLE, false = don't waitForQualityGates abortPipeline: true
waitForQualityGate abortPipeline: true
@@ -55,9 +57,9 @@ pipeline {
sh """
cd ${workspace}/${project_name}
docker login --username=缔智元2023 --password=digimeta@2023 ${ali_registry}
docker build --tag ${ali_registry}/digitalman-multisaas/${module_name}:${version} .
docker push ${ali_registry}/digitalman-multisaas/${module_name}:${version}
docker rmi ${ali_registry}/digitalman-multisaas/${module_name}:${version}
docker build --tag ${ali_registry}/digitalman-multisaas/${module_name}:${git_version}-${build_env} .
docker push ${ali_registry}/digitalman-multisaas/${module_name}:${git_version}-${build_env}
docker rmi ${ali_registry}/digitalman-multisaas/${module_name}:${git_version}-${build_env}
"""
}
}


+ 67
- 0
Jenkinsfile1 View File

@@ -0,0 +1,67 @@
node {
def workspace=pwd()
// 版本
def tag = "0.8"
def ali_registry = "registry.cn-beijing.aliyuncs.com"
// 镜像仓库的地址
// def harbor_url = "192.168.81.102:85"
// 镜像仓库的项目,这里建议项目名称和jenkins的item项目名称、以及harbor的项目名称保持一致,否则用一下脚本会出问题
// def harbor_project = "demo"
def mavenPath="/usr/share/maven"
// 拉取代码
stage('pull code') {
checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: '0f6d6eaa8754e735262afa495fe2828d611fca17', url: 'http://39.105.23.186:3000/develop/digimeta-MultiSaas.git']]])
}
// 代码静态检查
stage('Maven Package and Sonar') {
if ("${project_name}" == 'digimeta-MultiSaas' ) {
echo '打包根目录'
sh 'mvn clean package sonar:sonar'
} else {
echo "打包子目录并进行代码检查 ${project_name}"
sh "mvn clean install"
sh "mvn -f ${project_name} clean package -e -U -Dmaven.test.skip=true sonar:sonar"
}

//script {
//引入Jenkins SonarQube-Scanner全局工具 "全局配置中以SonarQube-Scanner命名的工具"
// scannerHome = tool 'SonarQube-Scanner'
//}
//引用SonarQube环境 "系统配置中配置的SonarQube servers的name值 "
//withSonarQubeEnv('Sonar') {
//执行sonar-scanner命令
//sh "${scannerHome}/bin/sonar-scanner"
// $mavenPath/bin/mvn sonar:sonar
//}
}
// build Docker并推送镜像仓库
stage('build project') {
if ("${project_name}" == 'digimeta-MultiSaas' ) {
echo '仅做代码检查,不打包目录'
} else {
echo "构件微服务 ${project_name},并推送到镜像仓库"
sh """
cd ${workspace}/${project_name}
docker login --username=缔智元2023 ${ali_registry}
docker build --tag ${ali_registry}/digitalman-multisaas/${project_name}:${version}
docker push ${ali_registry}/digitalman-multisaas/${project_name}:${version}
"""

}
//echo "把jar上传镜像仓库"
//def oldImageName = "${project_name}:latest"
//def newImageName = "${harbor_url}/${harbor_project}/${project_name}:${tag}"
// 改名称 做规范
//sh "docker tag ${oldImageName} ${newImageName}"
// 删除之前的 镜像
//sh "docker rmi ${oldImageName}"
// 推送到 dockers仓库
//withCredentials([usernamePassword(credentialsId: '8a3d7ab1-4cd6-482c-86c9-a12aa6404d98', passwordVariable: 'harbor_password', usernameVariable: 'harbor_account')]) {
// 登录
//sh "docker login -u ${harbor_account} -p ${harbor_password} ${harbor_url}"
// 上传
//sh "docker push ${newImageName}"
//echo "镜像推送成功"
//}
}
}

+ 14
- 0
docker-compose.yml View File

@@ -180,6 +180,20 @@ services:
depends_on:
- xueyi-nacos
- xueyi-redis
links:
- xueyi-nacos
- xueyi-redis
-
xueyi-nlt:
container_name: xueyi-nlt
build:
context: xueyi-modules/xueyi-nlt
dockerfile: ./Dockerfile
ports:
- "9910:9910"
depends_on:
- xueyi-nacos
- xueyi-redis
links:
- xueyi-nacos
- xueyi-redis

+ 24
- 0
pom.xml View File

@@ -46,6 +46,8 @@
<sonar.java.checkstyle.reportPaths>./target/checkstyle-result.xml</sonar.java.checkstyle.reportPaths>
<sonar.login>admin</sonar.login>
<sonar.password>Digimeta@2023</sonar.password>
<jakarta-json.version>2.0.1</jakarta-json.version>
<elasticsearch.version>8.3.3</elasticsearch.version>
</properties>

<!-- 依赖声明 -->
@@ -163,6 +165,11 @@
<version>${fastjson2.version}</version>
</dependency>

<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
@@ -301,6 +308,12 @@
<version>${xueyi.version}</version>
</dependency>

<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api-nlt</artifactId>
<version>${xueyi.version}</version>
</dependency>

<!-- huTool 工具类库 -->
<dependency>
<groupId>cn.hutool</groupId>
@@ -310,6 +323,17 @@
<scope>import</scope>
</dependency>

<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>${jakarta-json.version}</version>
</dependency>

</dependencies>
</dependencyManagement>



+ 1
- 0
xueyi-api/pom.xml View File

@@ -14,6 +14,7 @@
<module>xueyi-api-tenant</module>
<module>xueyi-api-file</module>
<module>xueyi-api-job</module>
<module>xueyi-api-nlt</module>
<module>xueyi-api-modules-auth</module>

</modules>


+ 16
- 0
xueyi-api/xueyi-api-message/src/main/java/com/xueyi/message/api/transfer/domain/vo/Message.java View File

@@ -0,0 +1,16 @@
package com.xueyi.message.api.transfer.domain.vo;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;

import java.io.Serializable;

@Data
@ToString
@Builder
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Message implements Serializable,Cloneable{


}

+ 10
- 5
xueyi-api/xueyi-api-message/src/main/java/com/xueyi/message/api/transfer/feign/RemoteTransferService.java View File

@@ -1,15 +1,14 @@
package com.xueyi.message.api.transfer.feign;

import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;

import com.xueyi.message.api.transfer.feign.factory.RemoteTransferFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
* 数据源服务
@@ -21,4 +20,10 @@ public interface RemoteTransferService {
@RequestMapping(value = "/api/device_online_status/{devId}", method = {RequestMethod.GET})
@ResponseBody
public AjaxResult getDeviceOnlineStatus(@RequestParam(value = "devId") String devId);

@RequestMapping(value = "/api/broadcast", method = {RequestMethod.GET})
@ResponseBody
public R broadcast(@RequestParam(value = "channel") String channel);


}

+ 1
- 1
xueyi-api/xueyi-api-modules-auth/src/main/java/com/xueyi/modules/auth/api/domain/vo/IntentionReqDto.java View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
public class IntentionReqDto {
@NotNull(message = "staffId不能为空")
private String staffId;
@NotNull(message = "staffType不能为空")
private String staffType;
@NotNull(message = "skillCode不能为空")
private String skillCode;


+ 33
- 0
xueyi-api/xueyi-api-nlt/pom.xml View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api</artifactId>
<version>2.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>xueyi-api-nlt</artifactId>

<description>
xueyi-api-nlt模型接入管理模块
</description>

<dependencies>

<!-- XueYi Common Core -->
<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-common-core</artifactId>
</dependency>


<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api-system</artifactId>
</dependency>
</dependencies>

</project>

+ 15
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/netty/domain/vo/DmWebSocketMessageVo.java View File

@@ -0,0 +1,15 @@
package com.xueyi.nlt.api.netty.domain.vo;

import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class DmWebSocketMessageVo {
String devId;
String skillCode;
JSONObject format;
String template;
String operator;
}

+ 20
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/netty/feign/RemoteWebsocketService.java View File

@@ -0,0 +1,20 @@
package com.xueyi.nlt.api.netty.feign;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.nlt.domain.vo.DmIntentVo;
import com.xueyi.nlt.api.nlt.feign.factory.RemoteIntentFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;

@FeignClient(contextId = "remoteWebsocketService", value = ServiceConstants.NLT_SERVICE, fallbackFactory = RemoteIntentFallbackFactory.class)
public interface RemoteWebsocketService {

@PostMapping("websocket/inner/sendMessage")
R sendMessage(@RequestBody DmWebSocketMessageVo message, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

+ 13
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/CoversationSessionVo.java View File

@@ -0,0 +1,13 @@
package com.xueyi.nlt.api.nlt.domain.vo;

import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class CoversationSessionVo {
protected String category;
protected String id;
protected JSONObject format;
}

+ 18
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmIntentVo.java View File

@@ -0,0 +1,18 @@
package com.xueyi.nlt.api.nlt.domain.vo;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class DmIntentVo {
String devId;
Long operator;
String skillCode;
String content;
String preIntent;
String sign;
String requestId;
/** 模式类型 1:工作模式 2:接待模式 3:闲聊模式 */
String mode;
}

+ 29
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmLandingLlmVo.java View File

@@ -0,0 +1,29 @@
package com.xueyi.nlt.api.nlt.domain.vo;


import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Data
@NoArgsConstructor
public class DmLandingLlmVo {
private String category;
private List<DmLlm> message = new ArrayList<>();
@Data
@NoArgsConstructor
class DmLlm {
private String role;
private String content;
}

// 定义创建DmLlm的对象方法,并添加到message中
public void addDmLlm(String role, String content) {
DmLlm dmLlm = new DmLlm();
dmLlm.setRole(role);
dmLlm.setContent(content);
message.add(dmLlm);
}
}

+ 13
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmRecognitionVo.java View File

@@ -0,0 +1,13 @@
package com.xueyi.nlt.api.nlt.domain.vo;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class DmRecognitionVo {
String devId;
Long personId;
String registered;
String sign;
}

+ 13
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/KnowledgeVo.java View File

@@ -0,0 +1,13 @@
package com.xueyi.nlt.api.nlt.domain.vo;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class KnowledgeVo {
private String man_code;
private String question;
private Long tenant_id;
private String trace_id;
}

+ 17
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/TaskKnowledgeVo.java View File

@@ -0,0 +1,17 @@
package com.xueyi.nlt.api.nlt.domain.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class TaskKnowledgeVo {
private Long knowledgeId;
private String content;
private Integer count;
private Long manId;
private Long tenantId;
private int split;
private Long createBy;
}

+ 27
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteIntentService.java View File

@@ -0,0 +1,27 @@
package com.xueyi.nlt.api.nlt.feign;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.nlt.domain.vo.DmIntentVo;
import com.xueyi.nlt.api.nlt.feign.factory.RemoteIntentFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.ResponseBody;

@FeignClient(contextId = "remoteIntentService", value = ServiceConstants.NLT_SERVICE, fallbackFactory = RemoteIntentFallbackFactory.class)
public interface RemoteIntentService {

@PostMapping("/intent/inner/conversation")
R<JSONObject> conversationInner(@RequestBody DmIntentVo intent, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

@PostMapping("/intent/inner/sendMessage")
R sendMessage(@RequestBody DmWebSocketMessageVo message, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

@PostMapping("/intent/inner/taskGenerativeKnowledge")
public R taskGenerativeKnowledge();
}

+ 28
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteLandingLlmService.java View File

@@ -0,0 +1,28 @@
package com.xueyi.nlt.api.nlt.feign;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.nlt.api.nlt.domain.vo.DmLandingLlmVo;
import com.xueyi.nlt.api.nlt.feign.factory.RemoteLandingLlmFallbackFactory;
import com.xueyi.nlt.api.nlt.feign.factory.RemoteQAFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

/**
* 问答服务
* @Param man_id 机器人id
* @Param question 问题
* @Param tenant_id 租户id
* @author yrx
*/
@FeignClient(url = "${notification.landing-llm.url}",name = "landing-llm", fallbackFactory = RemoteLandingLlmFallbackFactory.class)
public interface RemoteLandingLlmService {

@PostMapping("/search/questionAnswer")
@ResponseBody
JSONObject query(@RequestBody DmLandingLlmVo vo);
@PostMapping("/search/questionAnswer")
@ResponseBody
JSONObject query(@RequestBody JSONObject jsonObject);

}

+ 30
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteQAService.java View File

@@ -0,0 +1,30 @@
package com.xueyi.nlt.api.nlt.feign;

import com.alibaba.fastjson.JSONObject;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.nlt.api.nlt.domain.vo.KnowledgeVo;
import com.xueyi.nlt.api.nlt.feign.factory.RemoteQAFallbackFactory;
import com.xueyi.system.api.sms.domain.vo.SmsReqEntity;
import com.xueyi.system.api.sms.feign.factory.RemoteSmsFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

/**
* 问答服务
* @Param man_id 机器人id
* @Param question 问题
* @Param tenant_id 租户id
* @author yrx
*/
@FeignClient(url = "${notification.qa.url}",name = "qa", fallbackFactory = RemoteQAFallbackFactory.class)
public interface RemoteQAService {

@GetMapping("/knowledge")
AjaxResult query(@RequestParam(value = "man_code") String manCode, @RequestParam(value = "question") String question, @RequestParam(value = "tenant_id") Long tenantId);
@PostMapping ("/knowledge")
AjaxResult query(@RequestBody KnowledgeVo vo);

}

+ 15
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteIntentFallbackFactory.java View File

@@ -0,0 +1,15 @@
package com.xueyi.nlt.api.nlt.feign.factory;

import com.xueyi.nlt.api.nlt.feign.RemoteIntentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class RemoteIntentFallbackFactory implements FallbackFactory<RemoteIntentService> {
@Override
public RemoteIntentService create(Throwable cause) {
return null;
}
}

+ 42
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteLandingLlmFallbackFactory.java View File

@@ -0,0 +1,42 @@
package com.xueyi.nlt.api.nlt.feign.factory;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.nlt.api.nlt.domain.vo.DmLandingLlmVo;
import com.xueyi.nlt.api.nlt.feign.RemoteLandingLlmService;
import com.xueyi.nlt.api.nlt.feign.RemoteQAService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

/**
* 会议室服务 降级处理
*
* @author xueyi
*/
@Slf4j
@Component
public class RemoteLandingLlmFallbackFactory implements FallbackFactory<RemoteLandingLlmService> {

@Override
public RemoteLandingLlmService create(Throwable throwable) {
log.error("短信服务调用失败:{}", throwable.getMessage());
return new RemoteLandingLlmService() {
@Override
public JSONObject query(DmLandingLlmVo vo) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("status","fail");
jsonObject.put("data","");
return jsonObject;
}

@Override
public JSONObject query(JSONObject jsonObject) {
JSONObject jResult = new JSONObject();
jResult.put("status","fail2");
jResult.put("data","");
return jResult;
}
};
}
}

+ 34
- 0
xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteQAFallbackFactory.java View File

@@ -0,0 +1,34 @@
package com.xueyi.nlt.api.nlt.feign.factory;

import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.nlt.api.nlt.domain.vo.KnowledgeVo;
import com.xueyi.nlt.api.nlt.feign.RemoteQAService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

/**
* 会议室服务 降级处理
*
* @author xueyi
*/
@Slf4j
@Component
public class RemoteQAFallbackFactory implements FallbackFactory<RemoteQAService> {

@Override
public RemoteQAService create(Throwable throwable) {
log.error("短信服务调用失败:{}", throwable.getMessage());
return new RemoteQAService() {
@Override
public AjaxResult query(String manCode, String question, Long tenantId) {
return AjaxResult.error("查询失败");
}

@Override
public AjaxResult query(KnowledgeVo vo) {
return AjaxResult.error("查询失败");
}
};
}
}

+ 3
- 0
xueyi-api/xueyi-api-nlt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports View File

@@ -0,0 +1,3 @@
com.xueyi.nlt.api.nlt.feign.factory.RemoteIntentFallbackFactory
com.xueyi.nlt.api.nlt.feign.factory.RemoteQAFallbackFactory
com.xueyi.nlt.api.nlt.feign.factory.RemoteLandingLlmFallbackFactory

+ 2
- 1
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/dto/DmSyncDigitalmanDto.java View File

@@ -9,6 +9,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serial;
import java.util.List;

@Data
@EqualsAndHashCode(callSuper = true)
@@ -23,6 +24,6 @@ public class DmSyncDigitalmanDto extends DmDigitalmanPo {
protected DmDigitalmanWorktimePo worktime;
protected SysDeptExt workdayHour;
protected String iconPos;
protected DmBroadcastVo broadcast;
protected List<DmBroadcastVo> broadcast;

}

+ 2
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/dto/DmVisitorsDto.java View File

@@ -22,4 +22,6 @@ public class DmVisitorsDto extends DmVisitorsPo {
public static final Long TYPE_VIP_VISITOR = 9L;
public static final Long TYPE_SPECIAL_VISITOR = 10L;

public String imgUrl;

}

+ 14
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/vo/DmBatchQuestionsVo.java View File

@@ -0,0 +1,14 @@
package com.xueyi.system.api.digitalmans.domain.vo;

import com.alibaba.fastjson2.JSONArray;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.bind.annotation.RequestParam;

@Data
@NoArgsConstructor
public class DmBatchQuestionsVo {
private Long knowledgeId;
private JSONArray questions;
private Long createId;
}

+ 1
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/domain/vo/DmBroadcastVo.java View File

@@ -11,5 +11,6 @@ import java.util.List;
public class DmBroadcastVo {
Integer recycle;
Integer speed;
Long id;
List<JSONObject> resource;
}

+ 4
- 2
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/feign/RemoteBroadcastService.java View File

@@ -11,12 +11,14 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@FeignClient(contextId = "remoteBroadcastService", value = ServiceConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteBroadcastService {


@GetMapping("/broadcast/inner/list")
public R<DmBroadcastVo> innerlist(@RequestParam("manCode") String manCode,
@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
public R<List<DmBroadcastVo>> innerlist(@RequestParam("manCode") String manCode,
@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

}

+ 13
- 1
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/feign/RemoteDigitalmanService.java View File

@@ -1,5 +1,6 @@
package com.xueyi.system.api.digitalmans.feign;

import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.R;
@@ -8,7 +9,11 @@ import com.xueyi.system.api.digitalmans.domain.dto.DmSyncDigitalmanDto;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo;
import com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@@ -44,4 +49,11 @@ public interface RemoteDigitalmanService {
@GetMapping("/man/inner-api/devInfo/{devId}")
public R<DmDigitalmanExtPo> devInfo(@RequestParam(value = "devId") String devId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);


@GetMapping("/man/api/mansInfo")
public R<JSONObject> mansInfo();

@GetMapping("/man/delRecognizedRecords")
public R<JSONObject> delRecognizedRecords(@RequestParam(value = "day") Integer days);

}

+ 22
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/digitalmans/feign/RemoteQuestionanswersService.java View File

@@ -0,0 +1,22 @@
package com.xueyi.system.api.digitalmans.feign;

import com.alibaba.fastjson2.JSONArray;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.system.api.digitalmans.domain.vo.DmBatchQuestionsVo;
import com.xueyi.system.api.digitalmans.domain.vo.DmReceptionVo;
import com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

@FeignClient(contextId = "remoteQuestionanswersService", value = ServiceConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteQuestionanswersService {


@PostMapping("/questionanswers/inner/batch_insert")
@ResponseBody
public R<DmReceptionVo> batchInsertInner(@RequestBody DmBatchQuestionsVo dmBatchQuestionsVo,
@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

}

+ 16
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/meeting/feign/RemoteMeetingService.java View File

@@ -9,10 +9,12 @@ import com.xueyi.system.api.meeting.domain.dto.DmMeetingRoomsDto;
import com.xueyi.system.api.meeting.feign.factory.RemoteMeetingFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@@ -50,4 +52,18 @@ public interface RemoteMeetingService {

@PostMapping(value = "/meeting/inner-api/lists-all")
JSONObject listAllInner(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

@GetMapping("/meeting/inner-api/recent/{deptId}/{dateStr}")
@ResponseBody
public List<JSONObject> recent(@PathVariable(value = "deptId") Long deptId, @PathVariable(value = "dateStr") String dateStr, @RequestParam(value = "roomId", required = false) Long roomId,@RequestParam(value = "startTime", required = false) String startTime, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) ;

@GetMapping("/meeting/inner-api/recent/{deptId}")
@ResponseBody
public List<JSONObject> recent(@PathVariable(value = "deptId") Long deptId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source) ;

@GetMapping(value = "/meeting/api/recent/{devId}/{dateStr}")
R<List<JSONObject>> ableOrderList(@PathVariable(value = "devId") String devId, @PathVariable(value = "dateStr",required = false) String dateStr, @RequestParam(value = "roomId", required = false) Long roomId, @RequestParam(value = "startTime", required = false) String startTime);

@GetMapping(value = "/meeting/inner-api/enableOrder/{roomId}/{dateStr}/{startTime}")
JSONObject queryExist(@PathVariable(name = "roomId") Long roomId, @PathVariable(name = "dateStr") String dateStr, @PathVariable(name = "startTime") String startTime, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

+ 25
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/meeting/feign/factory/RemoteMeetingFallbackFactory.java View File

@@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
@@ -66,6 +67,30 @@ public class RemoteMeetingFallbackFactory implements FallbackFactory<RemoteMeeti
public JSONObject listAllInner(String dateStr, Long spaceId, Long enterpriseId, String sourceName, String source) {
return R.fail("获取会议室预约列表失败:" + throwable.getMessage()).toJson();
}

@Override
public List<JSONObject> recent(Long deptId, String dateStr, Long roomId, String startTime, Long enterpriseId, String sourceName, String source) {
List js = new ArrayList<>();
js.add(R.fail("获取会议室可预约列表失败:" + throwable.getMessage()).toJson());
return js;
}

@Override
public List<JSONObject> recent(Long deptId, Long enterpriseId, String sourceName, String source) {
List js = new ArrayList<>();
js.add(R.fail("获取会议室可预约列表失败:" + throwable.getMessage()).toJson());
return js;
}

@Override
public R<List<JSONObject>> ableOrderList(String devId, String dateStr, Long roomId, String startTime) {
return null;
}

@Override
public JSONObject queryExist(Long roomId, String dateStr, String startTime, Long enterpriseId, String sourceName, String source) {
return null;
}
};
}
}

+ 28
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/organize/feign/RemoteEnterpriseService.java View File

@@ -0,0 +1,28 @@
package com.xueyi.system.api.organize.feign;

import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.system.api.organize.domain.dto.SysDeptDto;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.feign.factory.RemoteDeptFallbackFactory;
import com.xueyi.system.api.organize.feign.factory.RemoteEnterpriseFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

/**
* 部门服务
*
* @author xueyi
*/
@FeignClient(contextId = "remoteEnterpriseService", value = ServiceConstants.SYSTEM_SERVICE, fallbackFactory = RemoteEnterpriseFallbackFactory.class)
public interface RemoteEnterpriseService {

/**
* 新增部门
*
* @return 结果
*/
@GetMapping("/enterprise/info")
R<SysEnterpriseDto> getInfo(@RequestParam(value = "enterpriseId") Long enterpriseId);
}

+ 31
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/organize/feign/factory/RemoteEnterpriseFallbackFactory.java View File

@@ -0,0 +1,31 @@
package com.xueyi.system.api.organize.feign.factory;

import com.xueyi.common.core.web.result.R;
import com.xueyi.system.api.organize.domain.dto.SysDeptDto;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.feign.RemoteDeptService;
import com.xueyi.system.api.organize.feign.RemoteEnterpriseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

/**
* 部门服务 降级处理
*
* @author xueyi
*/
@Slf4j
@Component
public class RemoteEnterpriseFallbackFactory implements FallbackFactory<RemoteEnterpriseService> {

@Override
public RemoteEnterpriseService create(Throwable throwable) {
log.error("部门服务调用失败:{}", throwable.getMessage());
return new RemoteEnterpriseService() {
@Override
public R<SysEnterpriseDto> getInfo(Long enterpriseId) {
return R.fail("获取企业信息失败:" + throwable.getMessage());
}
};
}
}

+ 14
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/resource/feign/RemoteH5ConfigService.java View File

@@ -0,0 +1,14 @@
package com.xueyi.system.api.resource.feign;

import com.xueyi.common.core.constant.basic.ServiceConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.system.api.resource.feign.factory.RemoteH5ConfigFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

@FeignClient(contextId = "remoteH5ConfigService", value = ServiceConstants.SYSTEM_SERVICE, fallbackFactory = RemoteH5ConfigFallbackFactory.class)
public interface RemoteH5ConfigService {

@GetMapping("/h5config/inner/syncH5Config")
R<String> syncH5Config(@RequestParam(value = "tId",required = false) String tId);
}

+ 21
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/resource/feign/factory/RemoteH5ConfigFallbackFactory.java View File

@@ -0,0 +1,21 @@
package com.xueyi.system.api.resource.feign.factory;

import com.xueyi.common.core.web.result.R;
import com.xueyi.system.api.resource.feign.RemoteH5ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class RemoteH5ConfigFallbackFactory implements FallbackFactory<RemoteH5ConfigService> {
@Override
public RemoteH5ConfigService create(Throwable cause) {
return new RemoteH5ConfigService() {
@Override
public R<String> syncH5Config(String tId) {
return R.fail("同步配置文件失败");
}
};
}
}

+ 8
- 0
xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/staff/domain/po/DmStaffPo.java View File

@@ -87,4 +87,12 @@ public class DmStaffPo extends TBaseEntity {
@Excel(name = "所属组织ID")
protected Long resourceId;

/** 生日日期 */
@Excel(name = "生日日期")
protected Date birthDate;

/** 入职日期 */
@Excel(name = "入职日期")
protected Date hireDate;

}

+ 3
- 0
xueyi-api/xueyi-api-system/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports View File

@@ -1,8 +1,11 @@
com.xueyi.system.api.organize.feign.factory.RemoteDeptFallbackFactory
com.xueyi.system.api.organize.feign.factory.RemotePostFallbackFactory
com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory
com.xueyi.system.api.organize.feign.factory.RemoteEnterpriseFallbackFactory
com.xueyi.system.api.authority.feign.factory.RemoteLoginFallbackFactory
com.xueyi.system.api.authority.feign.factory.RemoteMenuFallbackFactory
com.xueyi.system.api.authority.feign.factory.RemoteAuthFallbackFactory
com.xueyi.system.api.dict.feign.factory.RemoteConfigFallbackFactory
com.xueyi.system.api.log.feign.factory.RemoteLogFallbackFactory
com.xueyi.system.api.meeting.feign.factory.RemoteMeetingFallbackFactory
com.xueyi.system.api.resource.feign.factory.RemoteH5ConfigFallbackFactory

+ 13
- 0
xueyi-common/xueyi-common-core/pom.xml View File

@@ -77,6 +77,12 @@
<artifactId>jackson-databind</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.0</version>
</dependency>

<!-- Alibaba Fastjson -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
@@ -149,6 +155,13 @@
<artifactId>hutool-crypto</artifactId>
</dependency>

<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.3.3</version>
</dependency>


</dependencies>

</project>

+ 1
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/basic/ServiceConstants.java View File

@@ -26,6 +26,7 @@ public class ServiceConstants {
public static final String MESSAGE_SERVICE = "xueyi-message";

public static final String MODULES_AUTH_SERVICE = "xueyi-modules-auth";
public static final String NLT_SERVICE = "xueyi-nlt";

/** 定时任务模块的serviceId */
public static final String JOB_SERVICE = "xueyi-job";


+ 8
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/digitalman/MessageConstants.java View File

@@ -16,6 +16,13 @@ public class MessageConstants {
/** 数字人同步 */
public static final Long MODEL_SYNC = 2L;

public static final Long H5_CONFIG_SYNC = 4L;

/** 数字人场景 */
public static final String MODE_WORK = "1"; // 工作模式
public static final String MODE_RECEPTION = "2"; // 接待模式
public static final String MODE_FREE_CHAT = "3"; // 闲聊模式

/** 缓存数据头 */
public static final String REDIS_GROUP_HEADER = "group:dgman:";
public static final String REDIS_GROUP_DEVICE_HEADER = "group:dgman:device:";
@@ -32,6 +39,7 @@ public class MessageConstants {
public static final Integer SYS_DICT_DATA_RELEASE_UPDATE_UPDATING = 7;
public static final Integer SYS_DICT_DATA_RESTART_DEVICE = 0;
public static final Integer SYS_DICT_DATA_RESTART_APP = 1;
public static final Integer SYS_DICT_DATA_SPLITED = 1;

public enum RestartEnum {
RESTART_DEVICE(0, "重启设备"),


+ 29
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/digitalman/SkillConstants.java View File

@@ -0,0 +1,29 @@
package com.xueyi.common.core.constant.digitalman;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* 技能配置通用常量
*
* @author yinruoxi
*/
public class SkillConstants {

/** 技能配置 */
@Getter
@AllArgsConstructor
public enum SkillType {
GENERATION("0", "通用问答"),
BOOK_MEETING_ROOM("1", "会议室预定"),
CREATE_VISITOR_INFO("2", "访客预约登记"),
REGISTER_VISITOR("3", "访客到访登记"),
INTRODUCE_STRANGER("24", "熟人介绍生人"),
BROADCAST_DISPLAY("25", "播报展示"),
OPEN_DOOR("26", "开门");

private final String code;
private final String info;

}
}

+ 6
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/nacos/NacosConstants.java View File

@@ -0,0 +1,6 @@
package com.xueyi.common.core.constant.nacos;

public class NacosConstants {
public static final String DEFAULT_CONFIG_PATH = "config.json";
public static final String DEFAULT_GROUP = "DEFAULT_GROUP";
}

+ 9
- 1
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/DateUtil.java View File

@@ -5,7 +5,12 @@ import org.apache.commons.lang3.time.DateFormatUtils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
@@ -25,11 +30,14 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils {

public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";


private static final String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

public static final DateTimeFormatter DEFAULT_DATETIME_PATTERN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

/**
* 获取当前Date型日期
*


+ 54
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/InetAddressUtils.java View File

@@ -0,0 +1,54 @@
package com.xueyi.common.core.utils;


import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;

/**
* @author yinruoxi
* @version V1.0
* @className InetAddressUtils
* @description TO DO
* @Date 2023/8/10 14:19 PM
*/
public class InetAddressUtils {

public static InetAddress getLocalHostLANAddress() throws UnknownHostException {
try {
InetAddress candidateAddress = null;
// 遍历所有的网络接口
for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
// 在所有的接口下再遍历IP
for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
if (inetAddr.isSiteLocalAddress()) {
// 如果是site-local地址,就是它了
return inetAddr;
} else if (candidateAddress == null) {
// site-local类型的地址未被发现,先记录候选地址
candidateAddress = inetAddr;
}
}
}
}
if (candidateAddress != null) {
return candidateAddress;
}
// 如果没有发现 non-loopback地址.只能用最次选的方案
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
if (jdkSuppliedAddress == null) {
throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
}
return jdkSuppliedAddress;
} catch (Exception e) {
UnknownHostException unknownHostException = new UnknownHostException(
"Failed to determine LAN address: " + e);
unknownHostException.initCause(e);
throw unknownHostException;
}
}
}

+ 23
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/core/StrUtil.java View File

@@ -167,4 +167,27 @@ public class StrUtil extends cn.hutool.core.util.StrUtil implements StrPool {
return matcher.match(pattern, url);
}

/**
* @Author yangkai
* @Description 驼峰转下划线形式,如 helloWorldTest->hello_world_test
* @Date 2023/9/4
* @Param
* @return
**/
public static String camelCaseToUnderscore(String input) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char currentChar = input.charAt(i);
if (Character.isUpperCase(currentChar)) {
if (i > 0) {
result.append("_");
}
result.append(Character.toLowerCase(currentChar));
} else {
result.append(currentChar);
}
}
return result.toString();
}

}

+ 40
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/sql/EsClient.java View File

@@ -0,0 +1,40 @@
package com.xueyi.common.core.utils.sql;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import lombok.Data;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author yk
* @description
* @date 2023-08-29 15:55
*/
@Data
@Configuration
public class EsClient {
@Value("${spring.elasticsearch.host}")
public String esHost;

@Value("${spring.elasticsearch.port}")
public String esPort;


@Bean
public ElasticsearchClient getEsClient() {
RestClient restClient = RestClient.builder(
new HttpHost(esHost, Integer.valueOf(esPort))).build();

ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
return client;
}

}

+ 30
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/time/LocalDateTimeSerializer.java View File

@@ -0,0 +1,30 @@
package com.xueyi.common.core.utils.time;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.xueyi.common.core.utils.DateUtil;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;

/**
* @author yk
* @description
* @date 2023-08-26 16:19
*/
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
try {
String s = value.format(DateUtil.DEFAULT_DATETIME_PATTERN);
gen.writeString(s);
} catch (DateTimeParseException e) {
System.err.println(e);
gen.writeString("");
}
}
}

+ 30
- 0
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/utils/time/LocalDatetimeDeserializer.java View File

@@ -0,0 +1,30 @@
package com.xueyi.common.core.utils.time;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.xueyi.common.core.utils.DateUtil;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;

/**
* @author yk
* @description
* @date 2023-08-26 16:05
*/
public class LocalDatetimeDeserializer extends JsonDeserializer<LocalDateTime> {

@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
String str = p.getText();
try {
return LocalDateTime.parse(str, DateUtil.DEFAULT_DATETIME_PATTERN);
} catch (DateTimeParseException e) {
System.err.println(e);
return null;
}
}
}

+ 13
- 1
xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/web/entity/base/BaseEntity.java View File

@@ -1,8 +1,16 @@
package com.xueyi.common.core.web.entity.base;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.xueyi.common.core.utils.time.LocalDateTimeSerializer;
import com.xueyi.common.core.utils.time.LocalDatetimeDeserializer;
import lombok.Data;
import lombok.EqualsAndHashCode;

@@ -46,6 +54,8 @@ public class BaseEntity extends BasisEntity {
@OrderBy(sort = 20)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField(insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
@JsonDeserialize(using = LocalDatetimeDeserializer.class) // 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class)
protected LocalDateTime createTime;

/** 更新者Id */
@@ -55,6 +65,8 @@ public class BaseEntity extends BasisEntity {
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField(insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)
@JsonDeserialize(using = LocalDatetimeDeserializer.class) // 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class)
protected LocalDateTime updateTime;

/** 删除标志 */


+ 2
- 1
xueyi-common/xueyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports View File

@@ -1,2 +1,3 @@
com.xueyi.common.core.utils.core.SpringUtil
com.xueyi.common.core.utils.core.SpringUtils
com.xueyi.common.core.utils.core.SpringUtils
com.xueyi.common.core.utils.sql.EsClient

+ 15
- 0
xueyi-common/xueyi-common-mqtt/src/main/java/com/xueyi/common/mqtt/constant/MqttTopicConstant.java View File

@@ -0,0 +1,15 @@
package com.xueyi.common.mqtt.constant;

public class MqttTopicConstant {

/**
* 数字人常量
*/
public static final String TOPIC_DIGITALMAN = "/digitalman";
/**
* 通知重启
*/
public static final String TOPIC_NOTIFY_RESTART = "notify/restart";


}

+ 1
- 0
xueyi-common/xueyi-common-sms/src/main/java/com/xueyi/common/sms/configure/SmsProperties.java View File

@@ -26,6 +26,7 @@ public class SmsProperties {
private String meetingQuitTemplate;
private String meetingRemindTemplate;
private String defaultRemindTemplate;
private String warningTemplate;
private String visitorTemplate;
private String robotName;
private String receptionPhones;


+ 5
- 0
xueyi-common/xueyi-common-web/pom.xml View File

@@ -40,6 +40,11 @@
<artifactId>xueyi-common-datasource</artifactId>
</dependency>

<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-common-core</artifactId>
</dependency>

<!-- XueYi Common DataSource -->
<dependency>
<groupId>com.xueyi</groupId>


+ 2
- 2
xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/constant/ResponseCode.java View File

@@ -457,12 +457,12 @@ public class ResponseCode {
public static final Integer NOT_FOUND_VISITOR = 5404;

@ResponseMessage(
msg = {"预订失败,会议室预订时间点有冲突"}
msg = {"会议室预订时间点有冲突"}
)
public static final Integer MEETING_ORDER_CONFLICT = 5501;

@ResponseMessage(
msg = {"预订失败,会议室预订时间错误"}
msg = {"会议室预订时间错误"}
)
public static final Integer MEETING_ORDER_TIME_ERROR = 5502;



+ 4
- 0
xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/entity/service/IBaseService.java View File

@@ -123,4 +123,8 @@ public interface IBaseService<Q extends BaseEntity, D extends BaseEntity> {
* 更新缓存数据
*/
void refreshCache();

void createEsIndex(D dto);

void saveToEs(D dto);
}

+ 57
- 0
xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/entity/service/impl/BaseServiceImpl.java View File

@@ -1,5 +1,7 @@
package com.xueyi.common.web.entity.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.xueyi.common.core.constant.basic.BaseConstants;
import com.xueyi.common.core.constant.basic.OperateConstants;
@@ -11,7 +13,12 @@ import com.xueyi.common.redis.constant.RedisConstants;
import com.xueyi.common.web.entity.manager.IBaseManager;
import com.xueyi.common.web.entity.service.IBaseService;
import com.xueyi.common.web.entity.service.impl.handle.BaseHandleServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
@@ -27,6 +34,7 @@ import java.util.stream.Collectors;
*/
public class BaseServiceImpl<Q extends BaseEntity, D extends BaseEntity, IDG extends IBaseManager<Q, D>> extends BaseHandleServiceImpl<Q, D, IDG> implements IBaseService<Q, D> {

private Logger log = LoggerFactory.getLogger(BaseServiceImpl.class);
/**
* 查询数据对象列表
*
@@ -214,4 +222,53 @@ public class BaseServiceImpl<Q extends BaseEntity, D extends BaseEntity, IDG ext
throw new UtilException("未正常配置缓存,无法使用!");
refreshCache(null, RedisConstants.OperateType.REFRESH_ALL, null, null);
}

@Autowired
private ElasticsearchClient client;

@Value("${spring.profiles.active}")
private String activeProfile;
@Override
public void createEsIndex(D dto) {
boolean exists = false;
String indexName = activeProfile+"_"+StrUtil.camelCaseToUnderscore(dto.getClass().getSimpleName());

try {
String finalIndexName = indexName;
log.info("indexName:{}", indexName);
exists = client.indices().exists(query -> query.index(finalIndexName)).value();
System.out.println(exists);
if (exists) {
log.info("索引已存在");
} else {
String finalIndexName1 = indexName;
log.info("exists:false, indexName:{}", indexName);
final CreateIndexResponse products = client.indices().create(builder -> builder.index(finalIndexName1));
log.info(products.acknowledged()?"索引创建成功" : "索引创建失败");
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}


@Override
public void saveToEs(BaseEntity dto) {
try {
if (null != dto.getId()) {
String indexName = activeProfile+"_"+StrUtil.camelCaseToUnderscore(dto.getClass().getSimpleName());
log.info("indexName:{}", indexName);
createEsIndex((D)dto);
String finalIndexName = indexName;
client.index(i -> i
.index(finalIndexName)
.id(dto.getId().toString())
.document(dto));
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

+ 12
- 0
xueyi-common/xueyi-common-web/src/main/java/com/xueyi/common/web/utils/DateUtils.java View File

@@ -8,6 +8,7 @@ import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
@@ -334,4 +335,15 @@ public class DateUtils extends org.apache.commons.lang.time.DateUtils {

return ldt;
}

public static String isAmPm(){
//判断当前时间是上午还是下午,上午返回am,下午返回pm
LocalTime currentTime = LocalTime.now();

if (currentTime.isBefore(LocalTime.NOON)) {
return "am";
} else {
return "pm";
}
}
}

+ 1
- 0
xueyi-modules/pom.xml View File

@@ -16,6 +16,7 @@
<module>xueyi-file</module>
<module>xueyi-message</module>
<module>xueyi-modules-auth</module>
<module>xueyi-nlt</module>
</modules>

<artifactId>xueyi-modules</artifactId>


+ 28
- 2
xueyi-modules/xueyi-file/src/main/java/com/xueyi/file/utils/PdfToImageUtil.java View File

@@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
@@ -18,6 +20,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -70,8 +73,11 @@ public class PdfToImageUtil {
BufferedImage image = pdfRenderer.renderImageWithDPI(pageIdx, 300); // Set the DPI as needed

// 保存图像到本地临时目录
String imageName = "page_" + (pageIdx + 1) + ".png";
File imageFile = saveImageToFile(image, imageName);
/*String imageName = "page_" + (pageIdx + 1) + ".png";
File imageFile = saveImageToFile(image, imageName);*/
String imageName = "page_" + (pageIdx + 1) + ".jpg";
File imageFile = saveCompressedImage(image, imageName, 0.8f);

imageFiles.add(imageFile);
}
}
@@ -131,6 +137,26 @@ public class PdfToImageUtil {
}


private static File saveCompressedImage(BufferedImage image, String imageName, float compressionQuality) throws IOException {
File tempDir = new File(TEMP_DIR);
if (!tempDir.exists()) {
tempDir.mkdirs();
}

File imageFile = new File(tempDir, imageName);

Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = writers.next();

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(compressionQuality);

ImageIO.write(image, "jpg", imageFile);

return imageFile;
}



/**


+ 5
- 0
xueyi-modules/xueyi-job/pom.xml View File

@@ -65,6 +65,11 @@
<artifactId>xueyi-api-job</artifactId>
</dependency>

<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api-nlt</artifactId>
</dependency>

</dependencies>

<build>


+ 23
- 0
xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DmBroadDataTask.java View File

@@ -0,0 +1,23 @@
package com.xueyi.job.task;

import com.xueyi.message.api.transfer.feign.RemoteTransferService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* 定时任务调度测试
*
* @author xueyi
*/
@Component("dmBroadDataTask")
public class DmBroadDataTask {
@Autowired
RemoteTransferService remoteTransferService;
/**
* 触发条件:* 0/1 * * * *
* 每分钟执行一次
*/
public void syncData() {
remoteTransferService.broadcast("broadData");
}
}

+ 24
- 0
xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DmGenerativeKnowledgeTask.java View File

@@ -0,0 +1,24 @@
package com.xueyi.job.task;

import com.xueyi.message.api.transfer.feign.RemoteTransferService;
import com.xueyi.nlt.api.nlt.feign.RemoteIntentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* 定时任务调度测试
*
* @author xueyi
*/
@Component("dmGenerativeKnowledgeTask")
public class DmGenerativeKnowledgeTask {
@Autowired
RemoteIntentService remoteIntentService;
/**
* 触发条件:* 0/1 * * * *
* 每分钟执行一次
*/
public void generativeKnowledge() {
remoteIntentService.taskGenerativeKnowledge();
}
}

+ 25
- 0
xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/task/DmRecognizedRecordsCleanTask.java View File

@@ -0,0 +1,25 @@
package com.xueyi.job.task;

import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* 定时任务调度测试
*
* @author xueyi
*/
@Component("dmRecognizedRecordsCleanTask")
public class DmRecognizedRecordsCleanTask {
@Autowired
RemoteDigitalmanService remoteDigitalmanService;
/**
* 触发条件:* 0/1 * * * *
* 每分钟执行一次
*/


public void delOutDays() {
remoteDigitalmanService.delRecognizedRecords(5);
}
}

+ 2
- 1
xueyi-modules/xueyi-job/src/main/java/com/xueyi/job/util/AbstractQuartzJob.java View File

@@ -43,7 +43,8 @@ public abstract class AbstractQuartzJob implements Job {
doExecute(context, sysJob);
after(context, sysJob, null);
} catch (Exception e) {
log.error("任务执行异常 - :", e);
log.error("任务执行异常 - :", e.getMessage());
e.printStackTrace();
after(context, sysJob, e);
}
}


+ 11
- 1
xueyi-modules/xueyi-message/pom.xml View File

@@ -47,7 +47,16 @@
<artifactId>spring-integration-mqtt</artifactId>
<version>5.5.14</version>
</dependency>

<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.13</version>
</dependency>
<dependency>
<groupId>io.socket</groupId>
<artifactId>socket.io-client</artifactId>
<version>1.0.0</version>
</dependency>

<!-- XueYi Common Log -->
<dependency>
@@ -55,6 +64,7 @@
<artifactId>xueyi-common-log</artifactId>
</dependency>


<!-- XueYi Common Web -->
<dependency>
<groupId>com.xueyi</groupId>


+ 99
- 9
xueyi-modules/xueyi-message/src/main/java/com/xueyi/message/transfer/controller/ApiController.java View File

@@ -1,7 +1,6 @@
package com.xueyi.message.transfer.controller;


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
@@ -11,27 +10,34 @@ import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.message.api.transfer.domain.vo.DmActiveVo;
import com.xueyi.message.api.transfer.domain.vo.DmDeviceVo;
import com.xueyi.message.transfer.service.impl.MessageQueueServiceImpl;
import com.xueyi.system.api.authority.feign.RemoteLoginService;
import com.xueyi.system.api.device.domain.vo.DeviceTenantSourceMergeVo;
import com.xueyi.system.api.device.feign.RemoteDeviceTenantMergeService;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmSkillDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmSyncDigitalmanDto;
import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo;
import com.xueyi.system.api.digitalmans.domain.vo.DmBroadcastVo;
import com.xueyi.system.api.digitalmans.domain.vo.DmReceptionVo;
import com.xueyi.system.api.digitalmans.feign.*;
import com.xueyi.system.api.digitalmans.feign.RemoteBroadcastService;
import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.digitalmans.feign.RemoteReceptionService;
import com.xueyi.system.api.digitalmans.feign.RemoteSkillService;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.resource.feign.RemoteH5ConfigService;
import com.xueyi.system.api.staff.domain.vo.DmStaffFeature;
import com.xueyi.system.api.staff.feign.RemoteStaffService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
@@ -70,6 +76,13 @@ public class ApiController {
@Autowired
RemoteBroadcastService remoteBroadcastService;

@Autowired
MessageQueueServiceImpl messageQueueService;

@Autowired
RemoteH5ConfigService remoteH5ConfigService;



@RequestMapping(value = "/heartbeat", method = {RequestMethod.POST})
@ResponseBody
@@ -105,6 +118,10 @@ public class ApiController {
if (timestamp != null && !timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
dex_res += 0x100;
}
timestamp = redisTemplate.opsForValue().get("group:dgman:" + enterpriseDto.getData().getId() + ":" + MessageConstants.H5_CONFIG_SYNC);
if (timestamp != null && !timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
dex_res += 0x10000;
}
// if (!timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
// dex_res += 0x10;
// }
@@ -169,7 +186,7 @@ public class ApiController {
if (syncDmDto.isFail())
return AjaxResult.warn("新增失败,请检查");
// 添加播报信息
R<DmBroadcastVo> broadcastVoR = remoteBroadcastService.innerlist(manDeviceDtoR.getData().getManCode(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
R<List<DmBroadcastVo>> broadcastVoR = remoteBroadcastService.innerlist(manDeviceDtoR.getData().getManCode(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
if (!broadcastVoR.isFail()) {
syncDmDto.getData().setBroadcast(broadcastVoR.getData());
}
@@ -180,6 +197,8 @@ public class ApiController {
if (receptionVo.isFail()){
return AjaxResult.warn("接待模式任务获取失败,请检查");
}


// JSONObject jsObject = new JSONObject();
// jsObject.put("code",200);
// JSONObject data = new JSONObject();
@@ -199,6 +218,12 @@ public class ApiController {
// jsObject.put("data",data);
// jsObject.put("msg","success");
return AjaxResult.success(receptionVo.getData());
case 4:
R<String> propertyR = remoteH5ConfigService.syncH5Config(manDeviceDtoR.getData().getTId().toString());
if (propertyR.isFail()) {
return AjaxResult.warn("配置同步失败,请检查");
}
return AjaxResult.success(propertyR.getData());
}
}
return AjaxResult.success();
@@ -264,6 +289,55 @@ public class ApiController {
return AjaxResult.success(System.currentTimeMillis() - Long.parseLong(timestamp) >10 * 60 * 1000 ? InitConstants.DEVICE_ACTIVATE_STATUS_OFFLINE : InitConstants.DEVICE_ACTIVATE_STATUS_ONLINE);
}

/**
* @Author yangkai
* @Description //TODO
* @Date 2023/8/11
* @Param
* @return
*
*
* manCount
* serviceTimeCount
* chatTimes
* chatDurationCount
* skillExecuteTimes
*
* recognizedPersonCount
* servicePerCount
*
* receptionServiceCount
* meetingServiceCount
* visitServiceCount
* largeModelKnowledgeBaseGroupChangeNum
* largeModelKnowledgeBaseChangeNum
**/
@RequestMapping(value = "/broadcast", method = {RequestMethod.GET})
@ResponseBody
public R broadcast(@RequestParam(value = "channel") String channel){
try {
JSONObject json = new JSONObject();
/*json.put("chatTimes", 865531);
json.put("chatDurationCount", 10068);
// json.put("skillExecuteTimes", 10);
json.put("recognizedPersonCount", 13899);
json.put("receptionServiceCount", 1824);
json.put("meetingServiceCount", 1762);
json.put("visitServiceCount", 523);*/

R<JSONObject> objectR = remoteDigitalmanService.mansInfo();
JSONObject jsonObj = objectR.getData();
jsonObj.keySet().forEach(key -> json.put(key, jsonObj.get(key)));
String str = json.toJSONString();

messageQueueService.broadcast(channel, str);
return R.ok(str);
}catch (Exception e){
e.printStackTrace();
return R.fail(e.getMessage());
}
}

@RequestMapping(value = "/get_activate/{snCode}", method = {RequestMethod.GET})
@ResponseBody
public AjaxResult activate(@PathVariable(value = "snCode") String snCode, HttpServletResponse response) {
@@ -275,4 +349,20 @@ public class ApiController {
System.out.println(manDeviceDtR.getData().toString());
return AjaxResult.success("true");
}

@RequestMapping(value = "/get_config_info/{deviceId}", method = {RequestMethod.GET})
@ResponseBody
public AjaxResult getConfigInfo(@PathVariable(value = "deviceId") String deviceId, HttpServletResponse response) {
// 根据设备id获取租户信息
R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(deviceId);
String tenantId = null;
if (manDeviceDtoR.isOk() && manDeviceDtoR.getData() != null) {
tenantId = manDeviceDtoR.getData().getTId().toString();
}
R<String> propertyR = remoteH5ConfigService.syncH5Config(tenantId);
if (propertyR.isFail()) {
return AjaxResult.warn("配置同步失败,请检查");
}
return AjaxResult.success(propertyR.getData());
}
}

+ 19
- 0
xueyi-modules/xueyi-message/src/main/java/com/xueyi/message/transfer/service/IMessageQueueService.java View File

@@ -0,0 +1,19 @@
package com.xueyi.message.transfer.service;

import com.corundumstudio.socketio.SocketIOClient;
import com.xueyi.message.api.transfer.domain.vo.Message;

import java.util.Collection;
import java.util.List;

public interface IMessageQueueService {

// public List<Message> getAll();
//
// public boolean add(Message message);

public void broadcast(String channel, String message);

public Collection<SocketIOClient> getAllClients();

}

+ 167
- 0
xueyi-modules/xueyi-message/src/main/java/com/xueyi/message/transfer/service/impl/MessageQueueServiceImpl.java View File

@@ -0,0 +1,167 @@
package com.xueyi.message.transfer.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import com.corundumstudio.socketio.listener.ExceptionListener;
import com.xueyi.common.core.utils.InetAddressUtils;
import com.xueyi.message.api.transfer.domain.vo.Message;
import com.xueyi.message.transfer.service.IMessageQueueService;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class MessageQueueServiceImpl implements IMessageQueueService {

@Autowired
RedisTemplate<String, Serializable> redisTemplate;
private Integer port = 9901;

private SocketIOServer server;
private ConcurrentHashMap<String, Message> messageMap = new ConcurrentHashMap<>();

MessageQueueServiceImpl(){
startServer(port);
}

// @Override
// public List<Message> getAll(){
// List<Message> list = new ArrayList<Message>();
// Iterator<Map.Entry<String, Message>> entries = messageMap.entrySet().iterator();
// while(entries.hasNext()){
// Map.Entry<String, Message> entry = entries.next();
// Message value = entry.getValue();
// if(System.currentTimeMillis()- value.getTimestamp() > 10000){
// messageMap.remove(entry.getKey());
// }else{
// list.add(value);
// }
// }
// if(list.size()>0){
// return list;
// }
// return null;
// }
//
// @Override
// public boolean add(Message message){
//
// messageMap.put(message.getVid(),message);
// return true;
// }

@Override
public void broadcast(String channel, String message){
server.getBroadcastOperations().sendEvent(channel,message);
}

@Override
public Collection<SocketIOClient> getAllClients(){
return server.getAllClients();
}


private void startServer(int port){
Configuration config = new Configuration();
ExceptionListener exceptionListener = new ExceptionListener() {
@Override
public void onEventException(Exception e, List<Object> list, SocketIOClient socketIOClient) {

}

@Override
public void onDisconnectException(Exception e, SocketIOClient socketIOClient) {

}

@Override
public void onConnectException(Exception e, SocketIOClient socketIOClient) {

}

@Override
public boolean exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable throwable) throws Exception {
channelHandlerContext.close();
return true;
}
};
try {
System.out.println("启动");
config.setHostname(InetAddressUtils.getLocalHostLANAddress().getHostAddress());

} catch (Exception e) {
e.printStackTrace();
}
config.setPort(port);
config.setExceptionListener(exceptionListener);
server = new SocketIOServer(config);
server.addConnectListener(new ConnectListener() {
// 添加客户端连接监听器
@Override
public void onConnect(SocketIOClient client) {
System.out.println(client.getRemoteAddress().toString());
if(client.getRemoteAddress().toString().contains("100.117") || client.getRemoteAddress().toString().contains("100.171")){
client.disconnect();
return;
}
client.sendEvent("connected", "hello");
}
});

server.addEventListener("client_info", String.class, new DataListener<String>(){
@Override
public void onData(SocketIOClient client, String data, AckRequest ackRequest) throws ClassNotFoundException {
//客户端推送advert_info事件时,onData接受数据,这里是string类型的json数据,还可以为Byte[],object其他类型
String sa = client.getRemoteAddress().toString();
String clientIp = sa.substring(1,sa.indexOf(":"));//获取客户端连接的ip
Map params = client.getHandshakeData().getUrlParams();//获取客户端url参数
System.out.println(clientIp+":客户端:************"+data);
}
});
// server.addEventListener("remove_vinfromrsu", String.class, new DataListener<String>() {
// @Override
// public void onData(SocketIOClient socketIOClient, String s, AckRequest ackRequest) throws Exception {
// System.out.println("remove_vinfromrsu : " + s);
// List<RsuEventSimulatorMessage> list = JSON.parseArray(s, RsuEventSimulatorMessage.class);
// for (RsuEventSimulatorMessage item : list) {
// for (String vout : item.getVinouts()) {
// redisTemplate.opsForSet().remove("rsu_" + item.getRsuId(),vout);
// }
// }
// }
// });
// server.addEventListener("screen_info", String.class, new DataListener<String>(){
// @Override
// public void onData(SocketIOClient client, String data, AckRequest ackRequest) throws ClassNotFoundException {
// VehicleGridCountItem item = ((JSONObject)JSON.parse(data)).toJavaObject(VehicleGridCountItem.class);
// gridCountItemMap.put(client,item);
// }
// });
//添加客户端断开连接事件
server.addDisconnectListener(new DisconnectListener(){
@Override
public void onDisconnect(SocketIOClient client) {
String sa = client.getRemoteAddress().toString();
String clientIp = sa.substring(1,sa.indexOf(":"));//获取设备ip
System.out.println(clientIp+"-------------------------"+"客户端已断开连接");
//给客户端发送消息
client.sendEvent("advert_info",clientIp+"客户端你好,我是服务端,期待下次和你见面");
}
});
server.start();
}

}

+ 17
- 0
xueyi-modules/xueyi-nlt/Dockerfile View File

@@ -0,0 +1,17 @@
# 基础镜像
FROM openjdk:17-oracle
# author
MAINTAINER xueyi

# 挂载目录
VOLUME /home/xueyi
# 创建目录
RUN mkdir -p /home/xueyi
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 指定路径
WORKDIR /home/xueyi
# 复制jar文件到路径
COPY ./target/xueyi-modules-nlt.jar /home/xueyi/xueyi-modules-nlt.jar

# 启动系统服务
ENTRYPOINT ["java","-jar","xueyi-modules-nlt.jar"]

+ 112
- 0
xueyi-modules/xueyi-nlt/pom.xml View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-modules</artifactId>
<version>2.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>xueyi-modules-nlt</artifactId>

<description>
xueyi-modules-nlt大模型处理模块
</description>

<dependencies>

<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/com.squareup.okhttp/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>

<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- XueYi Common Log -->
<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-common-log</artifactId>
</dependency>

<!-- XueYi Common Web -->
<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-common-web</artifactId>
</dependency>

<!-- XueYi Common Swagger -->
<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-common-swagger</artifactId>
</dependency>

<!-- XueYi Api File -->
<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api-nlt</artifactId>
</dependency>

<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api-system</artifactId>
</dependency>

</dependencies>

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
<delimiters>@</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

+ 15
- 0
xueyi-modules/xueyi-nlt/sonar-project.properties View File

@@ -0,0 +1,15 @@
sonar.projectKey=digimeta-MultiSaas-nlt

sonar.projectName=digimeta-MultiSaas-nlt
sonar.sourceEncoding=UTF-8
sonar.projectVersion=0.8



sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.

sonar.java.source=1.8
sonar.java.target=1.8


+ 29
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/XueYiNltApplication.java View File

@@ -0,0 +1,29 @@
package com.xueyi.nlt;


import com.xueyi.common.security.annotation.EnableCustomConfig;
import com.xueyi.common.security.annotation.EnableRyFeignClients;
import com.xueyi.common.swagger.annotation.EnableCustomSwagger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableCustomConfig
@EnableCustomSwagger
@EnableRyFeignClients
@SpringBootApplication
public class XueYiNltApplication {
public static void main(String[] args) {
SpringApplication.run(XueYiNltApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ NLT模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" _____ __ ____ __ \n" +
" \\ _\\ / / \\ \\ / / \n" +
" .-./ ). / ' \\ _. / ' \n" +
" \\ '_ .') .' _( )_ .' \n" +
" (_ (_) _) ' ___(_ o _)' \n" +
" / \\ \\ | |(_,_)' \n" +
" `-'`-' \\| `-' / \n" +
" / / \\ \\\\ / \n" +
" '--' '----'`-..-' ");
}

}

+ 195
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/NettyClient.java View File

@@ -0,0 +1,195 @@
package com.xueyi.nlt.netty.client;

import com.xueyi.nlt.netty.client.codec.WsChannelInitializer;
import com.xueyi.nlt.netty.client.handler.MockClientHandler;
import com.xueyi.nlt.netty.client.handler.NettyClientHandler;
import com.xueyi.nlt.netty.client.handler.NettyWebsocketClientHandler;
import com.xueyi.nlt.netty.client.message.ReceiveMessage;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.timeout.IdleStateHandler;
import okhttp3.HttpUrl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

@Component
public class NettyClient {
private static final Logger log = LoggerFactory.getLogger(NettyClient.class);
private final int PORT = 8000;


public static String hostUrl = "https://spark-api.xf-yun.com/v1.1/chat";
public static String APPID = "3d9282da";//从开放平台控制台中获取
public static String APIKEY = "7c217b3a313f4b66fcc14a8e97f85103";//从开放平台控制台中获取
public static String APISecret = "ZTRiNDQwMTRlOTlmZDQwMDUwYTdjMDM0";//从开放平台控制台中获取
public static NettyClient nettyClient;

private String mHost;

private int mPort;

private NettyClientHandler mClientHandler;

private ChannelFuture mChannelFuture;

/**
* websocket配置
*/
private WebsocketConfig websocketConfig;

private Channel channel;

/**
* 接口消息的接口
*/
private ReceiveMessage receiveMessage;


public void connect() {


EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
HttpUrl authUrl = getAuthorizationUrl(hostUrl, APIKEY, APISecret);
String url = authUrl.toString().replace("https://","wss://").replace("http://","ws://");
URI uri = new URI(url);
final boolean ssl = "wss".equalsIgnoreCase(url);
final SslContext sslCtx;
if (ssl) {
sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
} else {
sslCtx = null;
}
NettyClientHandler webSocketClientHandler = new NettyClientHandler(
WebSocketClientHandshakerFactory.newHandshaker(authUrl.uri()
, WebSocketVersion.V07
, null
, false
, new DefaultHttpHeaders()));

final NettyWebsocketClientHandler handler =
new NettyWebsocketClientHandler(
WebSocketClientHandshakerFactory.newHandshaker(
authUrl.uri(), WebSocketVersion.V13, null, true, new DefaultHttpHeaders()), receiveMessage);

handler.setWebsocketConfig(websocketConfig);

Bootstrap b = new Bootstrap();
// mClientHandler = new NettyClientHandler(webSocketClientHandler);
// b.group(workerGroup).channel(NioSocketChannel.class)
// // KeepAlive
// .option(ChannelOption.SO_KEEPALIVE, true)
// // Handler
// .handler(new WsChannelInitializer(webSocketClientHandler));


b.group(workerGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
//wss 连接
if (sslCtx != null) {
pipeline.addLast(sslCtx.newHandler(ch.alloc(), authUrl.host(), authUrl.port()));
}
pipeline.addLast(
new HttpServerCodec(),
new HttpObjectAggregator(65536),
WebSocketClientCompressionHandler.INSTANCE,
//new LoggingHandler(LogLevel.INFO), // only for debug
// new IdleStateHandler(websocketConfig.getReaderIdleTimeSeconds(),
// websocketConfig.getWriterIdleTimeSeconds(),
// websocketConfig.getAllIdleTimeSeconds()),
handler);
}
}).option(ChannelOption.SO_KEEPALIVE, true)

;

// mChannelFuture = b.connect(authUrl.host(),authUrl.port()).sync();
mChannelFuture = b.connect("spark-api.xf-yun.com",443).sync();
channel = mChannelFuture.channel();
handler.handshakeFuture().sync();
if (mChannelFuture.isSuccess()) {
log.info("Client,连接服务端成功");
}
channel.writeAndFlush("介绍下自己");
// mChannelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
}
}

//鉴权url
public static HttpUrl getAuthorizationUrl(String hostUrl , String apikey ,String apisecret) throws Exception {
//获取host
URL url = new URL(hostUrl);
//获取鉴权时间 date
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
System.out.println("format:\n" + format );
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
//获取signature_origin字段
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").
// append("date: ").append(date).append("\n").
append("date: ").append("Wed, 02 Aug 2023 05:35:33 GMT").append("\n").
append("GET ").append(url.getPath()).append(" HTTP/1.1");
System.out.println("signature_origin:\n" + builder);
//获得signatue
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec sp = new SecretKeySpec(apisecret.getBytes(charset),"hmacsha256");
mac.init(sp);
byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset));
String signature = Base64.getEncoder().encodeToString(basebefore);
//获得 authorization_origin
String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"",apikey,"hmac-sha256","host date request-line",signature);
//获得authorization
String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset));
//获取httpurl
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", authorization).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();
System.out.println("httpUrl:\n" + httpUrl);
return httpUrl;
}

public static void main(String[] args) {
nettyClient = new NettyClient();
nettyClient.connect();

}
}

+ 374
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClient.java View File

@@ -0,0 +1,374 @@
package com.xueyi.nlt.netty.client;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.alibaba.nacos.shaded.com.google.gson.JsonArray;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class WebSocketClient extends WebSocketListener {

public static WebSocketClient INSTANCE;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;

@Value("${secret.spark.appId}")
private String appId;

@Value("${secret.spark.apiSecret}")
private String apiSecret;

@Value("${secret.spark.apiKey}")
private String apiKey;

public final static Object LOCK = new Object();
public static String hostUrl = "https://spark-api.xf-yun.com/v2.1/chat";
// public static String APPID = "3d9282da";//从开放平台控制台中获取
// public static String APIKEY = "7c217b3a313f4b66fcc14a8e97f85103";//从开放平台控制台中获取
// public static String APISecret = "ZTRiNDQwMTRlOTlmZDQwMDUwYTdjMDM0";//从开放平台控制台中获取

public static WebSocket webSocket;
public static String APPID = "948cf4b6";//从开放平台控制台中获取
public static String APIKEY = "54f6e81f40a31d66d976496de895a7a4";//从开放平台控制台中获取
public static String APISecret = "ZDYyMjNmMTlkYTE0YWRmOWUwZTYxNjYz";//从开放平台控制台中获取
public static final Gson json = new Gson();
// public static String question = "假设你是一位前台,你需要通过与其他人对话来获取会议相关信息,已知今天是2023-7-19,你需要获取会议日期,开始时间,持续时间,会议地点,会议主题。时间用类似00:00的格式输出。对方的话中可能不包含全部信息,对于未知的信息填充为none。如果所有信息都已知那么commit为true。否则为false。将你获得的信息输出为json格式。对方的话是:“明天下午开个会。从两点开到下午三点,在大会议室开,主题是访客接待”,只输出最后的json。输出只有一行,输出格式为{date:,start_time:,duration:,location:,theme:commit:}。";//可以修改question 内容,来向模型提问
public static String question = "请帮我安排五一出行计划";//可以修改question 内容,来向模型提问
public static List<String> questions = new ArrayList<>();//可以修改question 内容,来向模型提问
public String answer = "";

@PostConstruct
public void init() {
INSTANCE = this;
INSTANCE.redisTemplate = this.redisTemplate;
INSTANCE.stringRedisTemplate = this.stringRedisTemplate;
INSTANCE.appId = this.appId;
}

public static void main(String[] args) {
synchronized (LOCK) {
try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl(hostUrl, INSTANCE.apiKey, INSTANCE.apiSecret);
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
WebSocket webSocket = okHttpClient.newWebSocket(request,new WebSocketClient());
LOCK.wait();
System.out.println("查询完成");
} catch (Exception e) {
e.printStackTrace();
}
}



// write your code here

}

public void sendMsg(String message){
question = message;

try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl(hostUrl,apiKey,apiSecret);
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
webSocket = okHttpClient.newWebSocket(request,new WebSocketClient());

} catch (Exception e) {
e.printStackTrace();
}
}

public void sendMsg(List<String> messages){
questions = messages;
question = null;

try {
//构建鉴权httpurl
String authUrl = getAuthorizationUrl(hostUrl,apiKey,apiSecret);
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
String url = authUrl.replace("https://","wss://").replace("http://","ws://");
Request request = new Request.Builder().url(url).build();
webSocket = okHttpClient.newWebSocket(request,new WebSocketClient());

} catch (Exception e) {
e.printStackTrace();
}
}
//鉴权url
public static String getAuthorizationUrl(String hostUrl , String apikey ,String apisecret) throws Exception {
//获取host
URL url = new URL(hostUrl);
//获取鉴权时间 date
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
System.out.println("format:\n" + format );
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
//获取signature_origin字段
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").
append("date: ").append(date).append("\n").
append("GET ").append(url.getPath()).append(" HTTP/1.1");
System.out.println("signature_origin:\n" + builder);
//获得signatue
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec sp = new SecretKeySpec(apisecret.getBytes(charset),"hmacsha256");
mac.init(sp);
byte[] basebefore = mac.doFinal(builder.toString().getBytes(charset));
String signature = Base64.getEncoder().encodeToString(basebefore);
//获得 authorization_origin
String authorization_origin = String.format("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"",apikey,"hmac-sha256","host date request-line",signature);
//获得authorization
String authorization = Base64.getEncoder().encodeToString(authorization_origin.getBytes(charset));
//获取httpurl
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", authorization).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();

return httpUrl.toString();
}

//重写onopen
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
new Thread(()->{
JsonObject frame = new JsonObject();
JsonObject header = new JsonObject();
JsonObject chat = new JsonObject();
JsonObject parameter = new JsonObject();
JsonObject payload = new JsonObject();
JsonObject message = new JsonObject();
JsonObject text = new JsonObject();
JsonArray ja = new JsonArray();

//填充header
header.addProperty("app_id",INSTANCE.appId);
header.addProperty("uid","123456789");
//填充parameter
// chat.addProperty("domain","general"); //1.0版本
chat.addProperty("domain","generalv2"); // 2.0版本
chat.addProperty("random_threshold",0.5);
chat.addProperty("max_tokens",1024);
chat.addProperty("auditing","default");
parameter.add("chat",chat);
if (!StringUtils.isEmpty(question)) {
text = new JsonObject();
//填充payload
text.addProperty("role","user");
text.addProperty("content",question);
ja.add(text);
}else {
for (int i = 0;i < questions.size();i++) {

text = new JsonObject();
if (i % 2 == 0) {
text.addProperty("role","user");

} else {
text.addProperty("role","assistant");
}
text.addProperty("content",questions.get(i));
System.out.println(text.toString());
ja.add(text);
}
}
// message.addProperty("text",ja.getAsString());
message.add("text",ja);
payload.add("message",message);
frame.add("header",header);
frame.add("parameter",parameter);
frame.add("payload",payload);
System.out.println("frame:\n" + frame.toString());
webSocket.send(frame.toString());


}


).start();
}

//重写onmessage

@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
System.out.println("text:\n" + text);
ResponseData responseData = json.fromJson(text,ResponseData.class);
synchronized (LOCK) {
try {
// System.out.println("code:\n" + responseData.getHeader().get("code"));
if (0 == responseData.getHeader().get("code").getAsInt()) {
System.out.println("###########");
System.out.println("getStatus: " + responseData.getHeader().get("status").getAsInt());
if (2 != responseData.getHeader().get("status").getAsInt()) {
System.out.println("****************");
Payload pl = json.fromJson(responseData.getPayload(), Payload.class);
JsonArray temp = (JsonArray) pl.getChoices().get("text");
JsonObject jo = (JsonObject) temp.get(0);
answer += jo.get("content").getAsString();
// System.out.println(answer);
} else {
Payload pl1 = json.fromJson(responseData.getPayload(), Payload.class);
JsonObject jsonObject = (JsonObject) pl1.getUsage().get("text");
int prompt_tokens = jsonObject.get("prompt_tokens").getAsInt();
JsonArray temp1 = (JsonArray) pl1.getChoices().get("text");
JsonObject jo = (JsonObject) temp1.get(0);
answer += jo.get("content").getAsString();
System.out.println("返回结果为:\n" + answer);

if (INSTANCE.redisTemplate.hasKey("gpt:websocket:1")) {
DmWebSocketMessageVo message = (DmWebSocketMessageVo) INSTANCE.redisTemplate.opsForValue().get("gpt:websocket:1");
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("birthday")) {
JSONObject birthdayJo = new JSONObject();
birthdayJo.put("content", answer);
birthdayJo.put("timestamp", message.getFormat().get("timestamp"));
INSTANCE.stringRedisTemplate.opsForHash().put("group:nlp" + ":" + message.getFormat().getString("orderId"), "birthday", birthdayJo.toString());
INSTANCE.redisTemplate.delete("gpt:websocket:1");
return;
}
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("hireDate")) {
JSONObject birthdayJo = new JSONObject();
birthdayJo.put("content", answer);
birthdayJo.put("timestamp", message.getFormat().get("timestamp"));
INSTANCE.stringRedisTemplate.opsForHash().put("group:nlp" + ":" + message.getFormat().getString("orderId"), "hireDate", birthdayJo.toString());
INSTANCE.redisTemplate.delete("gpt:websocket:1");
return;
}
JSONObject preWebsocketJo = message.getFormat();
JSONObject meetingJo = new JSONObject();
meetingJo.put("timestamp",preWebsocketJo.get("timestamp"));
meetingJo.put("content",answer);
INSTANCE.stringRedisTemplate.opsForHash().put("group:nlp" + ":" + preWebsocketJo.getString("orderId"), "meeting", meetingJo.toString());
INSTANCE.redisTemplate.delete("gpt:websocket:1");

}else {
// 添加缓存
INSTANCE.stringRedisTemplate.opsForValue().set("group:websocket:content", answer);
LOCK.notifyAll();
}

// webSocket.close(3,"客户端主动断开链接");
//webSocket.close(1000,"客户端主动断开链接");

}

} else {
System.out.println("返回结果错误:\n" + responseData.getHeader().get("code") + responseData.getHeader().get("message"));
LOCK.notifyAll();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}


//重写onFailure

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
System.out.println(response);
}



class ResponseData{
private JsonObject header;
private JsonObject payload;

public JsonObject getHeader() {
return header;
}

public JsonObject getPayload() {
return payload;
}
}

class Header{
private int code ;
private String message;
private String sid;
private String status;

public int getCode() {
return code;
}

public String getMessage() {
return message;
}

public String getSid() {
return sid;
}

public String getStatus() {
return status;
}
}

class Payload{
private JsonObject choices;
private JsonObject usage;

public JsonObject getChoices() {
return choices;
}

public JsonObject getUsage() {
return usage;
}
}

class Choices{
private int status;
private int seq;
private JsonArray text;

public int getStatus() {
return status;
}

public int getSeq() {
return seq;
}

public JsonArray getText() {
return text;
}
}






}

+ 202
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebsocketConfig.java View File

@@ -0,0 +1,202 @@
package com.xueyi.nlt.netty.client;

import java.util.Map;

public class WebsocketConfig {

/**
* websocket url-------------(如果存在则以url为主)
*/
private String url;


/**
* websocket前缀
*/
private String scheme = "ws";

/**
* 服务器IP
*/
private String host;

/**
* 服务器端口
*/
private int port;

/**
* 默认的websocket地址
*/
private String path = "websocket";

/**
* url参数
*/
private Map<String, Object> suffixParams;


// Optional settings below
/**
* 检查
*/
private Long checkLiveDuration;

/**
* 自动重启客户端
*/
private Boolean autoRebootClient;

/**
* 保持连接状态
*/
private Boolean keepAlive;

/**
* 读空闲超时时间
*/
private Integer readerIdleTimeSeconds = 60;

/**
* 写空闲超时时间
*/
private Integer writerIdleTimeSeconds = 60;

/**
* 所有空闲超时时间
*/
private Integer allIdleTimeSeconds = 0;

/**
* 心跳实现
*/
// private HeartBeat heartBeat;

public WebsocketConfig(){
}

public WebsocketConfig(String host, int port){
this.host = host;
this.port = port;
}


public WebsocketConfig(String host, int port, String path){
this.host = host;
this.port = port;
this.path = path;
}

public WebsocketConfig(String scheme, String host, int port, String path){
this.scheme = scheme;
this.host = host;
this.port = port;
this.path = path;
}


public String getScheme() {
return scheme;
}

public void setScheme(String scheme) {
this.scheme = scheme;
}

public String getHost() {
return host;
}

public void setHost(String host) {
this.host = host;
}

public int getPort() {
return port;
}

public void setPort(int port) {
this.port = port;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public Map<String, Object> getSuffixParams() {
return suffixParams;
}

public void setSuffixParams(Map<String, Object> suffixParams) {
this.suffixParams = suffixParams;
}

public Long getCheckLiveDuration() {
return checkLiveDuration;
}

public void setCheckLiveDuration(Long checkLiveDuration) {
this.checkLiveDuration = checkLiveDuration;
}

public Boolean getAutoRebootClient() {
return autoRebootClient;
}

public void setAutoRebootClient(Boolean autoRebootClient) {
this.autoRebootClient = autoRebootClient;
}


public Boolean getKeepAlive() {
return keepAlive;
}

public void setKeepAlive(Boolean keepAlive) {
this.keepAlive = keepAlive;
}

public Integer getReaderIdleTimeSeconds() {
return readerIdleTimeSeconds;
}

public void setReaderIdleTimeSeconds(Integer readerIdleTimeSeconds) {
this.readerIdleTimeSeconds = readerIdleTimeSeconds;
}

public Integer getWriterIdleTimeSeconds() {
return writerIdleTimeSeconds;
}

public void setWriterIdleTimeSeconds(Integer writerIdleTimeSeconds) {
this.writerIdleTimeSeconds = writerIdleTimeSeconds;
}

public Integer getAllIdleTimeSeconds() {
return allIdleTimeSeconds;
}

public void setAllIdleTimeSeconds(Integer allIdleTimeSeconds) {
this.allIdleTimeSeconds = allIdleTimeSeconds;
}

// public HeartBeat getHeartBeat() {
// return heartBeat;
// }

// public void setHeartBeat(HeartBeat heartBeat) {
// this.heartBeat = heartBeat;
// }

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}
}

+ 46
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/codec/WsChannelInitializer.java View File

@@ -0,0 +1,46 @@
package com.xueyi.nlt.netty.client.codec;

import com.xueyi.nlt.netty.client.handler.MockClientHandler;
import com.xueyi.nlt.netty.client.handler.NettyClientHandler;
import com.xueyi.nlt.netty.client.handler.WsClientHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

public class WsChannelInitializer extends ChannelInitializer {

private NettyClientHandler nettyClientHandler;

public WsChannelInitializer(NettyClientHandler nettyClientHandler) {
this.nettyClientHandler = nettyClientHandler;
}

@Override
protected void initChannel(Channel ch) {
ChannelPipeline pipeline = ch.pipeline();
// websocket是基于http协议的,所以需要使用http编解码器
pipeline.addLast(new HttpClientCodec());
pipeline.addLast(new LoggingHandler(LogLevel.INFO));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// 以上三个处理器是对http协议的支持

// websocket 服务器处理的协议,并用于指定客户端连接的路由(这里指定的是 /ws)
// 这里的URL就是 ws://ip:port/ws
// 该处理器为运行websocket服务器承担了所有繁重的工作
// 它会负责websocket的握手以及处理控制帧
// websocket的数据传输都是以frames进行的
pipeline.addLast(new WebSocketServerProtocolHandler("/wss"));
// 自定义的处理器
pipeline.addLast("handler", nettyClientHandler);
}
}

+ 66
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/MockClientHandler.java View File

@@ -0,0 +1,66 @@
package com.xueyi.nlt.netty.client.handler;

import com.xueyi.nlt.netty.client.NettyClient;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Slf4j
public class MockClientHandler extends SimpleChannelInboundHandler<String> {

// private MsgHandleService msgHandleService;
private static final Logger log = LoggerFactory.getLogger(NettyClient.class);
private final WebSocketClientHandshaker webSocketClientHandshaker;

public MockClientHandler(WebSocketClientHandshaker webSocketClientHandshaker) {
this.webSocketClientHandshaker = webSocketClientHandshaker;
// this.msgHandleService = SpringContextHolder.getBean(MsgHandleService.class);
}

/**
* 当客户端主动链接服务端的链接后,调用此方法
*
* @param channelHandlerContext ChannelHandlerContext
*/
@Override
public void channelActive(ChannelHandlerContext channelHandlerContext) {
log.info("\n\t⌜⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓\n" +
"\t├ [Mock 建立连接]\n" +
"\t⌞⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓");

Channel channel = channelHandlerContext.channel();
// 握手
webSocketClientHandshaker.handshake(channel);
}


@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, String data) {
log.info("接收到客户端的响应为:{}", data);
//自定义处理消息
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.info("\n\t⌜⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓\n" +
"\t├ [exception]: {}\n" +
"\t⌞⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓⎓", cause.getMessage());
ctx.close();
}

@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
System.out.println("与服务器端断开连接");
}

@Override
public void channelReadComplete(ChannelHandlerContext channelHandlerContext) {
channelHandlerContext.flush();
}
}



+ 108
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/NettyClientHandler.java View File

@@ -0,0 +1,108 @@
package com.xueyi.nlt.netty.client.handler;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.websocketx.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;

import static com.xueyi.nlt.netty.client.NettyClient.APPID;

public class NettyClientHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {



// 定义log
private static final Logger log = LoggerFactory.getLogger(NettyClientHandler.class);

private final WebSocketClientHandshaker webSocketClientHandshaker;

public NettyClientHandler(WebSocketClientHandshaker webSocketClientHandshaker) {
this.webSocketClientHandshaker = webSocketClientHandshaker;
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {

Channel channel = ctx.channel();
// 握手
webSocketClientHandshaker.handshake(channel);

String question = "你是能帮我指定一个五一出行的计划么?";
log.info("Client,channelActive");
JSONObject frame = new JSONObject();
JSONObject header = new JSONObject();
JSONObject chat = new JSONObject();
JSONObject parameter = new JSONObject();
JSONObject payload = new JSONObject();
JSONObject message = new JSONObject();
JSONObject text = new JSONObject();
JSONArray ja = new JSONArray();

//填充header
header.put("app_id",APPID);
header.put("uid","123456789");
//填充parameter
chat.put("domain","general");
chat.put("random_threshold",0);
chat.put("max_tokens",1024);
chat.put("auditing","default");
parameter.put("chat",chat);
//填充payload
text.put("role","user");
text.put("content",question);
ja.add(text);
// message.addProperty("text",ja.getAsString());
message.put("text",ja);
payload.put("message",message);
frame.put("header",header);
frame.put("parameter",parameter);
frame.put("payload",payload);
System.out.println("frame:\n" + frame.toString());
ByteBuf byteBuf = Unpooled.copiedBuffer(frame.toString(), Charset.forName("utf-8"));
ctx.writeAndFlush(frame.toString());
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// log.info("Client,接收到服务端发来的消息:" + msg);
// ByteBuf buf = (ByteBuf) msg;
// byte[] buffer = new byte[buf.readableBytes()];
// buf.readBytes(buffer);
// String message = new String(buffer, "utf-8");
// log.info("Client,接收到服务端发来的消息:" + message);

Channel ch = ctx.channel();
DefaultHttpResponse response = (DefaultHttpResponse) msg;
log.info(response.toString());
}

@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
// 获取客户端传输来的文本消息
String text = textWebSocketFrame.text();
// 这个是自定义的日志工具类,可见其它文章
log.info("收到的文本消息:[{}]", text);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.info("Client,exceptionCaught");
cause.printStackTrace();
}

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("Client,channelInactive");
}

}

+ 196
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/NettyWebsocketClientHandler.java View File

@@ -0,0 +1,196 @@
package com.xueyi.nlt.netty.client.handler;

import com.xueyi.nlt.netty.client.message.ReceiveMessage;
import com.xueyi.nlt.netty.client.WebsocketConfig;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.HandshakeComplete;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class NettyWebsocketClientHandler extends SimpleChannelInboundHandler<Object> {
private Logger logger = LoggerFactory.getLogger(NettyWebsocketClientHandler.class);

private WebsocketConfig websocketConfig;

private final WebSocketClientHandshaker handshaker;

private ChannelPromise handshakeFuture;

private ReceiveMessage receiveMessage;

// private HeartBeat heartBeat;

public NettyWebsocketClientHandler(WebSocketClientHandshaker handshaker) {
this.handshaker = handshaker;
}

public NettyWebsocketClientHandler(WebSocketClientHandshaker handshaker, ReceiveMessage receiveMessage) {
this.handshaker = handshaker;
this.receiveMessage = receiveMessage;
}

public ChannelFuture handshakeFuture() {
return handshakeFuture;
}

@Override
public void handlerAdded(ChannelHandlerContext ctx) {
handshakeFuture = ctx.newPromise();
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception{
super.channelActive(ctx);
handshaker.handshake(ctx.channel());
logger.info("channelActive");
}

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception{
super.channelInactive(ctx);
logger.info("WebSocket Client disconnected!");
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
}

@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
Channel ch = ctx.channel();
if (!handshaker.isHandshakeComplete()) {
try {
handshaker.finishHandshake(ch, (FullHttpResponse) msg);
logger.info("WebSocket Client connected!");
handshakeFuture.setSuccess();
} catch (WebSocketHandshakeException e) {
logger.info("WebSocket Client failed to connect, " + e.getMessage());
handshakeFuture.setFailure(e);
}
return;
}

if (msg instanceof FullHttpResponse) {
FullHttpResponse response = (FullHttpResponse) msg;
throw new IllegalStateException(
"Unexpected FullHttpResponse (getStatus=" + response.getStatus() +
", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
}

WebSocketFrame frame = (WebSocketFrame) msg;
if (frame instanceof TextWebSocketFrame) {
/**
* 我们主要是用TextWebSocketFrame
*/
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
receiveMessage.onMessage(ch, textFrame.text());
} else if (frame instanceof PongWebSocketFrame) {
logger.info("WebSocket Client received pong");
receiveMessage.onMessage(ch, frame);
} else if (frame instanceof CloseWebSocketFrame) {
logger.info("WebSocket Client received close Frame");
//执行后将关闭
receiveMessage.onMessage(ch, frame);
//receive a closing frame to shutdown the event loop
ch.eventLoop().shutdownGracefully();
ch.close().sync();
}else if(frame instanceof BinaryWebSocketFrame){
BinaryWebSocketFrame binaryFrame = (BinaryWebSocketFrame)msg;
ByteBuf buf = binaryFrame.content();
if (buf.isReadable()){
int availableBytesNumber = buf.readableBytes();
byte[] receivedBytes = new byte[availableBytesNumber];
buf.readBytes(receivedBytes);
receiveMessage.onMessage(ch, receivedBytes);
}
//buf.release();
// byte [] bytes = receivedBytes;
}
}

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// if (evt instanceof IdleStateEvent) {
// IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
// switch (idleStateEvent.state()) {
// case WRITER_IDLE:
// handlerWriterIdleEvent(ctx);
// break;
// case READER_IDLE:
// handlerReaderIdleEvent(ctx);
// break;
// case ALL_IDLE:
// handlerAllIdleEvent(ctx);
// break;
// default:
// break;
// }
// } else {
// super.userEventTriggered(ctx, evt);
// }
if(evt instanceof HandshakeComplete) {
HandshakeComplete handshake = (WebSocketServerProtocolHandler.HandshakeComplete)evt;
//http request header
HttpHeaders headers = handshake.requestHeaders();

//http request uri: /chat?accesskey=hello
String uri = handshake.requestUri();

//TODO: parse uri parameters to map ...
Map<String, String> params ;

//put to channel context
// ctx.channel().attr(RequestParams).set(params);
}

}


// protected void handlerWriterIdleEvent(ChannelHandlerContext ctx){
// heartBeat.ping(ctx);
// }
//
// protected void handlerReaderIdleEvent(ChannelHandlerContext ctx){
// heartBeat.ping(ctx);
// }
//
// protected void handlerAllIdleEvent(ChannelHandlerContext ctx){
// heartBeat.ping(ctx);
// }


@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
if (!handshakeFuture.isDone()) {
handshakeFuture.setFailure(cause);
}
logger.info("exceptionCaught "+ cause.getMessage());
}


public WebsocketConfig getWebsocketConfig() {
return websocketConfig;
}

public void setWebsocketConfig(WebsocketConfig websocketConfig) {
this.websocketConfig = websocketConfig;
}

// public HeartBeat getHeartBeat() {
// return heartBeat;
// }

// public void setHeartBeat(HeartBeat heartBeat) {
// this.heartBeat = heartBeat;
// }
}

+ 23
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/WsClientHandler.java View File

@@ -0,0 +1,23 @@
package com.xueyi.nlt.netty.client.handler;

import com.xueyi.nlt.netty.client.NettyClient;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WsClientHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

private static final Logger log = LoggerFactory.getLogger(WsClientHandler.class);
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
// 获取客户端传输来的文本消息
String text = msg.text();
// 这个是自定义的日志工具类,可见其它文章
log.info("收到的文本消息:[{}]", text);
// 在这里可以判断消息类型(比如初始化连接、消息在客户端间传输等)
// 然后可以将客户端Channel与对应的唯一标识用Map关联起来,就可以做定向推送,而不是广播

}
}

+ 13
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/message/ReceiveMessage.java View File

@@ -0,0 +1,13 @@
package com.xueyi.nlt.netty.client.message;

import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;

public interface ReceiveMessage {

public void onMessage(Channel channel, String text);

public void onMessage(Channel channel, byte[] bytes);

public void onMessage(Channel channel, WebSocketFrame frame);
}

+ 79
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/controller/DmWebsocketController.java View File

@@ -0,0 +1,79 @@
package com.xueyi.nlt.netty.controller;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.nlt.domain.vo.DmIntentVo;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.nlt.domain.vo.IntentTemplateVo;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.model.Source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;

@RestController
@RequestMapping("/websocket")
public class DmWebsocketController {

private static final Logger log = LoggerFactory.getLogger(DmWebsocketController.class);

@Autowired
WebSocketClient webSocketClient;

@Autowired
StringRedisTemplate stringRedisTemplate;

@Autowired
RedisTemplate redisTemplate;


/**
* 意图请求
列表
*/
@PostMapping("/inner/sendMessage")
@ResponseBody
public R sendMessage(@RequestBody DmWebSocketMessageVo message) {

log.info("websocket sendMessage:{}", message);
if (message == null || message.getFormat() == null) {
return R.fail("参数为空");
}
JSONObject jo = message.getFormat();
SimpleDateFormat dateFormat3 = new SimpleDateFormat("MM-dd");
Double timestamp = Double.valueOf((String)jo.get("timestamp"));
String meetingRoom = jo.getString("meetingRoom");
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("birthday")) {
String prefix = "假设你是一名公司前台,你看到" + message.getFormat().get("name")+ "已知今天是他的生日。请你从个人角度输出给他的生日贺词。要求待人平和,具有人情味,用词正式,内容与工作无关。输出只包含你要对他说的话,在20字以内。";
webSocketClient.sendMsg(prefix);
redisTemplate.opsForValue().set("gpt:websocket" + ":" + "1", message);
return R.ok();
}
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("hiredate")) {
String prefix = "假设你是一名公司前台,你看到"+ message.getFormat().get("name")+ ",已知今天是他入职1周年,请你从个人角度说出对他入职周年的祝贺。要求具有人情味,有特色,字数在25字左右,不要提到生日,要带人名。输出只包含你要对他说的话。";
webSocketClient.sendMsg(prefix);
redisTemplate.opsForValue().set("gpt:websocket" + ":" + "1", message);
return R.ok();
}
Date date = new Date(timestamp.longValue());
if (message.getSkillCode().equals("1")) {
String prefix = "假设你是一名公司前台,你看到在你们公司工作的\\"+ jo.getString("orderName")+ "\\,请你从个人角度提醒他参加\\" +
dateFormat3.format(timestamp) + "\\在\\" + meetingRoom + "\\的会,要求语气友好。输出只包含你要对他说的话,在20字左右。";
webSocketClient.sendMsg(prefix);
// 设置缓存
redisTemplate.opsForValue().set("gpt:websocket" + ":" + "1", message);
}
return R.ok();
}
}

+ 603
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/controller/DmIntentController.java View File

@@ -0,0 +1,603 @@
package com.xueyi.nlt.nlt.controller;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchAllQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.digitalman.MessageConstants;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.core.web.validate.V_A;
import com.xueyi.common.core.web.validate.V_E;
import com.xueyi.common.log.annotation.Log;
import com.xueyi.common.log.enums.BusinessType;
import com.xueyi.common.security.annotation.Logical;
import com.xueyi.common.security.annotation.RequiresPermissions;
import com.xueyi.common.security.utils.SecurityUtils;
import com.xueyi.common.web.entity.controller.BaseController;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.nlt.domain.vo.*;
import com.xueyi.nlt.api.nlt.feign.RemoteIntentService;
import com.xueyi.nlt.api.nlt.feign.RemoteLandingLlmService;
import com.xueyi.nlt.api.nlt.feign.RemoteQAService;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;
import com.xueyi.nlt.nlt.domain.vo.IntentTemplateVo;
import com.xueyi.nlt.nlt.service.IDmIntentService;
import com.xueyi.nlt.nlt.template.FreeChatTemplate;
import com.xueyi.nlt.nlt.template.GenerativeKnowledgeTemplate;
import com.xueyi.nlt.nlt.template.MeetingOrderTemplate;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.digitalmans.domain.vo.DmBatchQuestionsVo;
import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.digitalmans.feign.RemoteQuestionanswersService;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.feign.RemoteEnterpriseService;
import com.xueyi.tenant.api.tenant.domain.dto.TeTenantDto;
import com.xueyi.tenant.api.tenant.feign.RemoteTenantService;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.xueyi.common.core.constant.digitalman.SkillConstants.SkillType;

import java.io.IOException;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.xueyi.common.core.constant.digitalman.MessageConstants.SYS_DICT_DATA_SPLITED;

@RestController
@RequestMapping("/intent")
public class DmIntentController extends BaseController<DmIntentQuery, DmIntentDto, IDmIntentService> {

private static final Logger log = LoggerFactory.getLogger(DmIntentController.class);
@Autowired
IDmIntentService dmIntentService;

@Autowired
WebSocketClient webSocketClient;

/** 定义节点名称 */
@Override
protected String getNodeName() {
return "意图管理 ";
}


@Autowired
private StringRedisTemplate redisTemplate;

@Autowired
private RedisTemplate<Object,Object> redisTemplate2;



@Autowired
private RemoteManDeviceService manDeviceService;

@Autowired
private RemoteIntentService remoteIntentService;
@Autowired
private MeetingOrderTemplate meetingOrderTemplate;

@Autowired
private GenerativeKnowledgeTemplate generativeKnowledgeTemplate;

@Autowired
private FreeChatTemplate freeChatTemplate;

@Autowired
private RemoteQuestionanswersService questionanswersService;

@Autowired
RemoteEnterpriseService enterpriseService;

@Autowired
RemoteLandingLlmService remoteLandingLlmService;

@Autowired
RemoteQAService remoteQAService;

@Autowired
RemoteDigitalmanService remoteDigitalmanService;

@Autowired
private ElasticsearchClient esClient;
/**
* 意图请求
列表
*/
@PostMapping("/api/conversation")
@ResponseBody
public AjaxResult conversationApi(@RequestBody DmIntentVo intent) {
log.info("对话详情:{}", intent.toString());
log.info("交互对象:{}", intent.toString());
redisTemplate.opsForValue().increment("dashboard:server", 1);
// 获取今天日期,并格式化成yyyy-MM-dd
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String today = sdf.format(new Date());
redisTemplate.opsForValue().increment(("dashboard:server-chart:" + today), 1);
R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(intent.getDevId());
Source source = SourceUtil.getSourceCache(manDeviceDtoR.getData().getStrategyId());
R<JSONObject> jsonObjectR = remoteIntentService.conversationInner(intent, manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
IntentTemplateVo voResult = new IntentTemplateVo();
voResult.setMsg("");
if (jsonObjectR.getData() != null) {
if (jsonObjectR.getData().containsKey("result") && StringUtils.isEmpty(jsonObjectR.getData().getString("result")) ) {
voResult.setTarget(0);
} else {
voResult.setTarget(1);
}
} else {
voResult.setTarget(0);
}
if (intent.getMode() != null && intent.getMode().equals(MessageConstants.MODE_FREE_CHAT)) {
voResult.setMsg(jsonObjectR.getData().get("msg").toString());
}
else {
voResult.setFormat(jsonObjectR.getData());
}
return AjaxResult.success(voResult);
}

@PostMapping("/api/skill-intent")
@ResponseBody
public AjaxResult skillIntentApi(@RequestBody DmIntentVo intent) {
log.info("交互对象:{}", intent.toString());
redisTemplate.opsForValue().increment("dashboard:server", 1);
R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(intent.getDevId());
Source source = SourceUtil.getSourceCache(manDeviceDtoR.getData().getStrategyId());
IntentTemplateVo voResult = new IntentTemplateVo();
//查询es,将满足条件的数据调用后续处理,不满足条件的返回原始数据
SearchResponse<JSONObject> dateResponse = null;
List<Hit<JSONObject>> question_list = null;
try {
MatchQuery byName = MatchQuery.of(m->m.field("name").query(intent.getContent()));
dateResponse = esClient.search(builder -> builder
.index("regular_expression").query(q->q.match(byName)),
JSONObject.class);
question_list = dateResponse.hits().hits();
log.info("esClient search result: {}", dateResponse);
}catch (IOException ie) {
log.error("esClient search error", ie);
return null;
}
for (Hit<JSONObject> jsonObjectHit : question_list) {
JSONObject jo = jsonObjectHit.source();
Pattern pat = Pattern.compile(jo.get("name").toString());
Matcher m = pat.matcher(intent.getContent());
if (m.find()) {
// R<JSONObject> jsonObjectR = remoteIntentService.conversationInner(intent, manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);

voResult.setMsg(jo.get("answer").toString());
// 如果包含Json数据并且json的skillCode字段不等于空
if (jo.containsKey("json") && StringUtils.isNotEmpty(jo.getString("json"))) {
String skillCode = jo.getJSONObject("json").getString("skillCode");
intent.setSkillCode(skillCode);
voResult.setJsonFormat(jo.getJSONObject("json"));
voResult.setType("1");
}

// return AjaxResult.success(voResult);
}
}

//走知识库
R<JSONObject> jsonObjectR = remoteIntentService.conversationInner(intent, manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
if (jsonObjectR.getData() != null) {
if (jsonObjectR.getData().containsKey("result") && StringUtils.isEmpty(jsonObjectR.getData().getString("result")) ) {
voResult.setTarget(0);
} else {
voResult.setTarget(1);
}
} else {
voResult.setTarget(0);
}
if (intent.getMode() != null && intent.getMode().equals(MessageConstants.MODE_FREE_CHAT)) {
voResult.setMsg(jsonObjectR.getData().get("msg").toString());
}
else {
voResult.setFormat(jsonObjectR.getData());
}
return AjaxResult.success(voResult);
}

/**
* 意图请求
列表
*/
@PostMapping("/api/say_hello")
@ResponseBody
public AjaxResult sayHelloApi(@RequestBody DmRecognitionVo recognition) {
log.info(recognition.toString());
redisTemplate.opsForValue().increment("dashboard:recognition", 1);

redisTemplate.opsForValue().increment("dashboard:conversation-times", 1);
JSONObject joResult = new JSONObject();
joResult.put("msg","");
joResult.put("target",0);
if (StringUtils.isNotEmpty(recognition.getRegistered()) && recognition.getRegistered().equals("1")) {

Map cntMap = redisTemplate.opsForHash().entries("group:nlp" + ":" + recognition.getPersonId());
//遍历key和value
for (Object key : cntMap.keySet()) {
String value = (String) cntMap.get(key);
if (String.valueOf(key).equals("meeting")) {
JSONObject jo = JSONObject.parseObject(value);
// 判断是否在30分钟内
System.out.println("timestamp:" + jo.get("timestamp"));
System.out.println("currenttime:" + System.currentTimeMillis());
if(jo.containsKey("timestamp") &&
Double.valueOf(String.valueOf(jo.get("timestamp"))) - System.currentTimeMillis() < 1800000) {
joResult.put("msg",jo.get("content"));
joResult.put("target",1);
redisTemplate.opsForHash().delete("group:nlp" + ":" + recognition.getPersonId(), "meeting");
redisTemplate.opsForValue().increment("dashboard:conversation-duration", jo.get("content").toString().length() / 4);
return AjaxResult.success(joResult);
} else if (Double.valueOf(String.valueOf(jo.get("timestamp"))) - System.currentTimeMillis() < 0) {
redisTemplate.opsForHash().delete("group:nlp" + ":" + recognition.getPersonId(), "meeting");
}
} else {
JSONObject jo = JSONObject.parseObject(value);
JSONObject joresult = addNotificaion(String.valueOf(key),recognition.getPersonId(),jo);
if (joresult!= null) {
return AjaxResult.success(joresult);
}
joResult.put("msg",value);
redisTemplate.opsForValue().increment("dashboard:conversation-duration", value.toString().length() / 4);
joResult.put("target",1);
redisTemplate.opsForHash().delete("group:nlp" + ":" + recognition.getPersonId(),key);
return AjaxResult.success(joResult);
}
}
}
redisTemplate.opsForValue().increment("dashboard:conversation-duration", 3);
return AjaxResult.success(joResult);
}

/**
* 知识库问答请求
*/
@PostMapping("/api/searchQA")
@ResponseBody
public AjaxResult searchQA(@RequestBody DmIntentVo intent) {
log.info("交互对象:{}",intent.toString());

R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(intent.getDevId());
Source source = SourceUtil.getSourceCache(manDeviceDtoR.getData().getStrategyId());
KnowledgeVo knowledgeVo = new KnowledgeVo();
knowledgeVo.setMan_code(manDeviceDtoR.getData().getManCode());
knowledgeVo.setTenant_id(manDeviceDtoR.getData().getTId());
knowledgeVo.setQuestion(intent.getContent());
// return remoteQAService.query(manDeviceDtoR.getData().getManCode(),intent.getContent(),manDeviceDtoR.getData().getTId());
return remoteQAService.query(knowledgeVo);

}

/**
* 联动北方大模型请求
*/
@PostMapping("/api/searchQuestionAnswer")
@ResponseBody
public AjaxResult searchQuestionAnswer(@RequestBody DmIntentVo intent) {
log.info("交互对象:{}",intent.toString());
redisTemplate.opsForValue().increment("dashboard:recognition", 1);
JSONObject joResult = new JSONObject();
joResult.put("msg","");
joResult.put("target",0);
DmLandingLlmVo vo = new DmLandingLlmVo();
vo.setCategory("bj_unicom");
vo.addDmLlm("user", intent.getContent());
JSONObject testJ = new JSONObject();
testJ.put("category","bj_unicom");
JSONArray ja1 = new JSONArray();
JSONObject jo = new JSONObject();
jo.put("role","user");
jo.put("content",intent.getContent());
ja1.add(jo);
testJ.put("messages",ja1);
JSONObject resultJson = remoteLandingLlmService.query(testJ);
JSONArray ja = resultJson.getJSONArray("data");

if (ja.size() > 0) {
joResult.put("msg",ja.getJSONObject(0).get("text"));
joResult.put("target",1);
}
return AjaxResult.success(joResult);
}


/**
* 意图请求列表
*/
@PostMapping("/inner/conversation")
@ResponseBody
public R<JSONObject> conversationInner(@RequestBody DmIntentVo intent) {
JSONObject joResult = null;
if (intent.getMode() !=null && intent.getMode().equals(MessageConstants.MODE_FREE_CHAT)) {
// 闲聊
joResult = freeChatTemplate.handle(intent.getDevId(),intent.getContent());
return R.ok(joResult);
}
// 获取设备号对应缓存
CoversationSessionVo sessionObject = (CoversationSessionVo) redisTemplate2.opsForValue().get("group:device" + ":" + intent.getDevId() + ":" +"session"); //category
if (sessionObject != null) {
switch (sessionObject.getCategory()) {
case "meeting":
joResult = meetingOrderTemplate.handle(intent.getDevId(),intent.getContent(), Long.parseLong(SecurityContextHolder.getLocalMap().get("enterprise_id").toString()));
return R.ok(joResult);
}
}
if (StringUtils.isEmpty(intent.getSkillCode())) {
// 调用知识库问答
AjaxResult qaAjax = searchQA(intent);
return R.ok(JSONObject.from(qaAjax.get("data")));
}
SkillType.BOOK_MEETING_ROOM.getCode();
// 判断skill code的值
if (SkillType.BOOK_MEETING_ROOM.getCode().equals(intent.getSkillCode())) {

// 获取名称为"meeting-order"的BaseTemplate的实例
redisTemplate.opsForValue().increment("dashboard:meeting", 1);

joResult = meetingOrderTemplate.handle(intent.getDevId(),intent.getContent(), Long.parseLong(SecurityContextHolder.getLocalMap().get("enterprise_id").toString()));
} else if (SkillType.CREATE_VISITOR_INFO.getCode().equals(intent.getSkillCode())) {
// 访客预定
redisTemplate.opsForValue().increment("dashboard:create_visitor_info", 1);
} else if (SkillType.REGISTER_VISITOR.getCode().equals(intent.getSkillCode())) {
// 访客登记
redisTemplate.opsForValue().increment("dashboard:register_visitor", 1);
} else if (SkillType.BROADCAST_DISPLAY.getCode().equals(intent.getSkillCode())) {
// 播报展示
redisTemplate.opsForValue().increment("dashboard:broadcast_display", 1);
} else if (SkillType.OPEN_DOOR.getCode().equals(intent.getSkillCode())) {
// 开门记录
redisTemplate.opsForValue().increment("dashboard:open_door", 1);
}
return R.ok(joResult);
}

/**
* 意图请求
列表
*/
@PostMapping("/inner/sendMessage")
@ResponseBody
public R<Object> sendMessage(@RequestBody DmWebSocketMessageVo message) {

log.info("websocket sendMessage:{}", message);
if (message == null || message.getFormat() == null) {
return R.fail("参数为空");
}
JSONObject jo = message.getFormat();
//SimpleDateFormat dateFormat3 = new SimpleDateFormat("MM-dd");
SimpleDateFormat dateFormat4 = new SimpleDateFormat("M月d日");
Double timestamp = Double.valueOf((String)jo.get("timestamp"));
String meetingRoom = jo.getString("meetingRoom");
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("birthday")) {
String prefix = "假设你是一名公司前台,你看到" + message.getFormat().get("name")+ "已知今天是他的生日。请你从个人角度输出给他的生日贺词。要求待人平和,具有人情味,用词正式,内容与工作无关。输出只包含你要对他说的话,在20字以内。";
webSocketClient.sendMsg(prefix);
redisTemplate2.opsForValue().set("gpt:websocket" + ":" + "1", message);
return R.ok();
}
if (StringUtils.isNotEmpty(message.getTemplate()) && message.getTemplate().equals("hireDate")) {
String prefix = "假设你是一名公司前台,你看到"+ message.getFormat().get("name")+ ",已知今天是他入职" + message.getFormat().get("years")+"周年,请你从个人角度说出对他入职周年的祝贺。要求具有人情味,有特色,字数在25字左右,不要提到生日,要带人名。输出只包含你要对他说的话。";
webSocketClient.sendMsg(prefix);
redisTemplate2.opsForValue().set("gpt:websocket" + ":" + "1", message);
return R.ok();
}
Date date = new Date(timestamp.longValue());
if (message.getSkillCode().equals("1")) {
String prefix = "假设你是一名公司前台,你看到在你们公司工作的\\"+ jo.getString("orderName")+ "\\,请你从个人角度提醒他参加\\" +
dateFormat4.format(timestamp) + "\\在\\" + meetingRoom + "\\的会,要求语气友好。输出只包含你要对他说的话,在20字左右。";
webSocketClient.sendMsg(prefix);
// 设置缓存
redisTemplate2.opsForValue().set("gpt:websocket" + ":" + "1", message);
}
return R.ok();
}

/**
* 意图请求
列表
*/
@PostMapping("/inner/taskGenerativeKnowledge")
@ResponseBody
public R<Object> taskGenerativeKnowledge() {

// 从列表中获取知识库任务
TaskKnowledgeVo vo = (TaskKnowledgeVo) redisTemplate2.opsForList().leftPop("group:task");

log.info("从缓存中获取对象:{}",vo.toString());
if (vo == null) {
return R.ok(null,"没有任务");
}

if (vo.getSplit() != SYS_DICT_DATA_SPLITED) {
// 请开始你的表演
String contents = vo.getContent();

List<String> results = Arrays.stream(contents.split("\n")).filter(StringUtils::isNotBlank).collect(Collectors.toList());
results.forEach(item->{
TaskKnowledgeVo temp = new TaskKnowledgeVo();
temp.setContent(item);
temp.setCount(item.length());
temp.setManId(vo.getManId());
temp.setKnowledgeId(vo.getKnowledgeId());
temp.setTenantId(vo.getTenantId());
temp.setSplit(SYS_DICT_DATA_SPLITED);
temp.setCreateBy(vo.getCreateBy());
redisTemplate2.opsForList().rightPush("group:task", temp);
});
return R.ok(null,"处理成功");
}
log.info("交互对象:{}",vo.toString());
JSONObject joResult = generativeKnowledgeTemplate.handle(null,vo.getContent());

if (joResult == null) {
redisTemplate2.opsForList().rightPush("group:task", vo);
return R.ok(null,"任务处理失败,重新放入队列");
}

R<SysEnterpriseDto> enterpriseDtoR = enterpriseService.getInfo(vo.getTenantId());
if (enterpriseDtoR.isFail()) {
log.warn("任务执行失败:{}",vo);
}
Source source = SourceUtil.getSourceCache(enterpriseDtoR.getData().getStrategyId());
DmBatchQuestionsVo batchQuestionsVo = new DmBatchQuestionsVo();
batchQuestionsVo.setKnowledgeId(vo.getKnowledgeId());
batchQuestionsVo.setQuestions(JSONArray.from(joResult.get("questions")));
batchQuestionsVo.setCreateId(vo.getCreateBy());
questionanswersService.batchInsertInner(batchQuestionsVo,vo.getTenantId(),source.getMaster(),SecurityConstants.INNER);

return R.ok(null,"处理成功");
}

/**
* 查询意图管理
列表
*/
@Override
@GetMapping("/list")
@RequiresPermissions(Auth.DM_INTENT_LIST)
public AjaxResult list(DmIntentQuery intent) {
return super.list(intent);
}

/**
* 查询意图管理
详细
*/
@Override
@GetMapping(value = "/{id}")
@RequiresPermissions(Auth.DM_INTENT_SINGLE)
public AjaxResult getInfo(@PathVariable Serializable id) {
return super.getInfo(id);
}

/**
* 意图管理
新增
*/
@Override
@PostMapping
@RequiresPermissions(Auth.DM_INTENT_ADD)
@Log(title = "意图管理", businessType = BusinessType.INSERT)
public AjaxResult add(@Validated({V_A.class}) @RequestBody DmIntentDto intent) {
return super.add(intent);
}

/**
* 意图管理
修改
*/
@Override
@PutMapping
@RequiresPermissions(Auth.DM_INTENT_EDIT)
@Log(title = "意图管理", businessType = BusinessType.UPDATE)
public AjaxResult edit(@Validated({V_E.class}) @RequestBody DmIntentDto intent) {
return super.edit(intent);
}

/**
* 意图管理
修改状态
*/
@Override
@PutMapping("/status")
@RequiresPermissions(value = {Auth.DM_INTENT_EDIT, Auth.DM_INTENT_ES}, logical = Logical.OR)
@Log(title = "意图管理", businessType = BusinessType.UPDATE_STATUS)
public AjaxResult editStatus(@RequestBody DmIntentDto intent) {
return super.editStatus(intent);
}

/**
* 意图管理
批量删除
*/
@Override
@DeleteMapping("/batch/{idList}")
@RequiresPermissions(Auth.DM_INTENT_DEL)
@Log(title = "意图管理", businessType = BusinessType.DELETE)
public AjaxResult batchRemove(@PathVariable List<Long> idList) {
return super.batchRemove(idList);
}

/**
* 获取意图管理
选择框列表
*/
@Override
@GetMapping("/option")
public AjaxResult option() {
return super.option();
}


private JSONObject addNotificaion(String key,Long personId,JSONObject jo) {
JSONObject joResult = new JSONObject();
if (String.valueOf(key).equals("birthday") || String.valueOf(key).equals("hireDate")) {
// 获取value中的timestamp,判断是否是当天
if (jo.containsKey("timestamp")) {
// 判断jo.get("timestamp")的月份是否与当天相同
DateFormat dateFormat = new SimpleDateFormat("MM-dd");
if (dateFormat.format(new Date(Long.valueOf(String.valueOf(jo.get("timestamp"))))).equals(dateFormat.format(new Date()))) {
joResult.put("msg", jo.get("content"));
joResult.put("target", 1);
redisTemplate.opsForHash().delete("group:nlp" + ":" + personId, key);
redisTemplate.opsForValue().increment("dashboard:conversation-duration", jo.get("content").toString().length() / 4);
return joResult;
}
}
}
return joResult;
}

interface Auth {
/** 系统 - 意图管理
管理 - 列表 */
String DM_INTENT_LIST = "nlt:intent:list";
/** 系统 - 意图管理
管理 - 详情 */
String DM_INTENT_SINGLE = "nlt:intent:single";
/** 系统 - 意图管理
管理 - 新增 */
String DM_INTENT_ADD = "nlt:intent:add";
/** 系统 - 意图管理
管理 - 修改 */
String DM_INTENT_EDIT = "nlt:intent:edit";
/** 系统 - 意图管理
管理 - 修改状态 */
String DM_INTENT_ES = "nlt:intent:es";
/** 系统 - 意图管理
管理 - 删除 */
String DM_INTENT_DEL = "nlt:intent:delete";
}
}

+ 14
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/dto/DmIntentDto.java View File

@@ -0,0 +1,14 @@
package com.xueyi.nlt.nlt.domain.dto;


import com.xueyi.nlt.nlt.domain.po.DmIntentPo;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = true)
public class DmIntentDto extends DmIntentPo {

private static final long serialVersionUID = 1L;

}

+ 13
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/model/DmIntentConverter.java View File

@@ -0,0 +1,13 @@
package com.xueyi.nlt.nlt.domain.model;

import com.xueyi.common.core.web.entity.model.BaseConverter;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.po.DmIntentPo;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;


@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface DmIntentConverter extends BaseConverter<DmIntentQuery, DmIntentDto, DmIntentPo> {
}

+ 61
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/po/DmIntentPo.java View File

@@ -0,0 +1,61 @@
package com.xueyi.nlt.nlt.domain.po;

import com.baomidou.mybatisplus.annotation.TableName;
import com.xueyi.common.core.annotation.Excel;
import com.xueyi.common.core.web.tenant.base.TBaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serial;

import static com.xueyi.common.core.constant.basic.EntityConstants.REMARK;
import static com.xueyi.common.core.constant.basic.EntityConstants.SORT;

/**
* 访客 持久化对象
*
* @author xueyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "dm_skills", excludeProperty = { SORT, REMARK })
public class DmIntentPo extends TBaseEntity {

@Serial
private static final long serialVersionUID = 1L;

/** 数字人id */
@Excel(name = "数字人id")
protected Long manId;

/** 技能id */
@Excel(name = "技能id")
protected String skillCode;

/** 技能名称 */
@Excel(name = "技能名称")
protected String name;

/** 技能信息 */
@Excel(name = "技能信息")
protected String info;

/** 访客公司 */
@Excel(name = "访客公司")
protected String resp;

/** 访客称呼 */
@Excel(name = "访客称呼")
protected Long motionId;

protected String motionName;

protected Integer firstCall;

protected String auth;

protected String intent;

protected String template;

}

+ 13
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/query/DmIntentQuery.java View File

@@ -0,0 +1,13 @@
package com.xueyi.nlt.nlt.domain.query;


import com.xueyi.nlt.nlt.domain.po.DmIntentPo;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = true)
public class DmIntentQuery extends DmIntentPo {

private static final long serialVersionUID = 1L;
}

+ 19
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/vo/IntentTemplateVo.java View File

@@ -0,0 +1,19 @@
package com.xueyi.nlt.nlt.domain.vo;

import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class IntentTemplateVo {
private String msg;
private JSONObject format;
/**
* 是否触发技能
*/
private Integer target;
private String skillCode;
private JSONObject jsonFormat;
private String type ="0";
}

+ 8
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/manager/IDmIntentManager.java View File

@@ -0,0 +1,8 @@
package com.xueyi.nlt.nlt.manager;

import com.xueyi.common.web.entity.manager.IBaseManager;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;

public interface IDmIntentManager extends IBaseManager<DmIntentQuery, DmIntentDto> {
}

+ 15
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/manager/impl/DmIntentManager.java View File

@@ -0,0 +1,15 @@
package com.xueyi.nlt.nlt.manager.impl;

import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.model.DmIntentConverter;
import com.xueyi.nlt.nlt.domain.po.DmIntentPo;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;
import com.xueyi.nlt.nlt.manager.IDmIntentManager;
import com.xueyi.nlt.nlt.mapper.DmIntentMapper;
import org.springframework.stereotype.Component;

@Component
public class DmIntentManager extends BaseManagerImpl<DmIntentQuery, DmIntentDto, DmIntentPo, DmIntentMapper, DmIntentConverter> implements IDmIntentManager {

}

+ 11
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/mapper/DmIntentMapper.java View File

@@ -0,0 +1,11 @@
package com.xueyi.nlt.nlt.mapper;

import com.xueyi.common.datasource.annotation.Isolate;
import com.xueyi.common.web.entity.mapper.BaseMapper;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.po.DmIntentPo;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;

@Isolate
public interface DmIntentMapper extends BaseMapper<DmIntentQuery, DmIntentDto, DmIntentPo> {
}

+ 8
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/IDmIntentService.java View File

@@ -0,0 +1,8 @@
package com.xueyi.nlt.nlt.service;

import com.xueyi.common.web.entity.service.IBaseService;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;

public interface IDmIntentService extends IBaseService<DmIntentQuery, DmIntentDto> {
}

+ 12
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/impl/DmIntentServiceImpl.java View File

@@ -0,0 +1,12 @@
package com.xueyi.nlt.nlt.service.impl;

import com.xueyi.common.web.entity.service.impl.BaseServiceImpl;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;
import com.xueyi.nlt.nlt.manager.IDmIntentManager;
import com.xueyi.nlt.nlt.service.IDmIntentService;
import org.springframework.stereotype.Service;

@Service
public class DmIntentServiceImpl extends BaseServiceImpl<DmIntentQuery, DmIntentDto, IDmIntentManager> implements IDmIntentService {
}

+ 8
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/BaseTemplate.java View File

@@ -0,0 +1,8 @@
package com.xueyi.nlt.nlt.template;

import com.alibaba.fastjson2.JSONObject;

public interface BaseTemplate {
JSONObject handle(String dev, String content);
JSONObject handle(String dev, String content,Long tenantId);
}

+ 61
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/FreeChatTemplate.java View File

@@ -0,0 +1,61 @@
package com.xueyi.nlt.nlt.template;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.nlt.netty.client.WebSocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;


@Service("free-chat")
public class FreeChatTemplate implements BaseTemplate{

private static final Logger log = LoggerFactory.getLogger(FreeChatTemplate.class);
@Autowired
WebSocketClient webSocketClient;

@Autowired
private RedisTemplate<String,String> redisTemplate;

@Override
public JSONObject handle(String devId, String content) {

// 根据content内容调用模版并返回结果
synchronized (WebSocketClient.LOCK) {
// 通过redis获取数字人上下文信息
Long size = redisTemplate.opsForList().size("group:device:" + devId);
if (size > 8) {
redisTemplate.opsForList().leftPop("group:device:" + devId,2);
}
redisTemplate.opsForList().rightPush("group:device:" + devId,content);
List<String> context = redisTemplate.opsForList().range("group:device:" + devId,0,size);
String prefix = "你的任务是[针对给定的文段提出" + (content.length() /100 + 1 ) + "个问题并回答]。文段为:[\"";
String suffix = "\"]。输出为一个JSON数组[{}],每个元素是一个JSON:{“question”:,”answer”:}。不要给出任何解释说明。";
log.info(prefix + content + suffix);
// webSocketClient.sendMsg(prefix + content + suffix);
webSocketClient.sendMsg(context);
try {
WebSocketClient.LOCK.wait();
String result = (String)redisTemplate.opsForValue().get("group:websocket:content");
redisTemplate.opsForList().rightPush("group:device:" + devId,result);
JSONObject resultJson = new JSONObject();
resultJson.put("msg",result);
return resultJson;
} catch (InterruptedException e) {
log.warn(e.getMessage());
}
}
return null;
}

@Override
public JSONObject handle(String dev, String content, Long tenantId) {
return null;
}
}

+ 59
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/GenerativeKnowledgeTemplate.java View File

@@ -0,0 +1,59 @@
package com.xueyi.nlt.nlt.template;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.nlt.netty.client.WebSocketClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


@Service("generative-knowledge")
public class GenerativeKnowledgeTemplate implements BaseTemplate{

private static final Logger log = LoggerFactory.getLogger(GenerativeKnowledgeTemplate.class);
@Autowired
WebSocketClient webSocketClient;

@Autowired
private RedisTemplate<String,String> redisTemplate;

@Override
public JSONObject handle(String devId, String content) {

// 根据content内容调用模版并返回结果
synchronized (WebSocketClient.LOCK) {

String prefix = "你的任务是[针对给定的文段提出" + (content.length() /100 + 1 ) + "个问题并回答]。文段为:[\"";
String suffix = "\"]。输出为一个JSON数组[{}],每个元素是一个JSON:{“question”:,”answer”:}。不要给出任何解释说明。";
log.info(prefix + content + suffix);
webSocketClient.sendMsg(prefix + content + suffix);
try {
WebSocketClient.LOCK.wait();
String result = (String)redisTemplate.opsForValue().get("group:websocket:content");
try {
JSONArray jsonArray = JSONArray.parseArray(result);
JSONObject jsonObject = new JSONObject();
jsonObject.put("questions",jsonArray);
return jsonObject;
} catch (JSONException je) {
// 返回结果错误,计日志,存log,返回空结果
log.error(je.getMessage(),je);
return new JSONObject();
}

} catch (InterruptedException e) {
log.warn(e.getMessage());
}
}
return new JSONObject();
}

@Override
public JSONObject handle(String dev, String content, Long tenantId) {
return null;
}
}

+ 245
- 0
xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MeetingOrderTemplate.java View File

@@ -0,0 +1,245 @@
package com.xueyi.nlt.nlt.template;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.digitalman.SkillConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.api.nlt.domain.vo.CoversationSessionVo;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.nlt.controller.DmIntentController;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo;
import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import com.xueyi.system.api.meeting.domain.dto.DmMeetingRoomsDto;
import com.xueyi.system.api.meeting.feign.RemoteMeetingService;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.organize.feign.RemoteEnterpriseService;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service("meeting-order")
public class MeetingOrderTemplate implements BaseTemplate {

private static final Logger log = LoggerFactory.getLogger(MeetingOrderTemplate.class);
@Autowired
WebSocketClient webSocketClient;

// @Autowired
// RemoteMeetingService remoteMeetingService;

@Autowired
private RemoteMeetingService remoteMeetingService;

@Autowired
private RemoteDigitalmanService digitalmanService;
@Autowired
RemoteEnterpriseService enterpriseService;
@Autowired
private StringRedisTemplate redisTemplate;

@Autowired
private RedisTemplate<Object,Object> objectRedisTemplate;
@Autowired
private ElasticsearchClient esClient;

@Override
public JSONObject handle(String devId, String content,Long tenantId) {
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00");
DateTimeFormatter scheduleFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
R<SysEnterpriseDto> enterpriseDtoR = enterpriseService.getInfo(tenantId);
Source source = SourceUtil.getSourceCache(enterpriseDtoR.getData().getStrategyId());
R<DmDigitalmanExtPo> extR = digitalmanService.selectExtByDeviceId(devId,tenantId,source.getMaster(), SecurityConstants.INNER);
DmDigitalmanExtPo extPo = null;
if (null != extR) {
extPo = extR.getData();
}


// 获取房间号
R<List<DmMeetingRoomsDto>> roomListR = remoteMeetingService.roomListInner(extPo.getDeptId(),tenantId,source.getMaster(), SecurityConstants.INNER);
// 缓存获取会议室session信息
CoversationSessionVo session = (CoversationSessionVo) objectRedisTemplate.opsForValue().get("group:device" + ":" + devId + ":" +"session");
if (session == null) {
session = new CoversationSessionVo();
session.setCategory("meeting");
session.setFormat(new JSONObject());
session.getFormat().put("skillCode",SkillConstants.SkillType.BOOK_MEETING_ROOM.getCode());
}

synchronized (WebSocketClient.LOCK) {

// String prefix = "假设你是一位前台,你需要通过与其他人对话来获取会议相关信息,已知今天是" +
// date.format(formatter) + ",你需要获取会议日期,开始时间,持续时间,会议地点,会议主题。时间用类似00:00的格式输出。对方的话中可能不包含全部信息,对于未知的信息填充为none。如果所有信息都已知那么commit为true。否则为false。将你获得的信息输出为json格式。对方的话是:“";
// String suffix = "”,只输出最后的json。输出只有一行,输出格式为{date:,start_time:,duration:,location:,theme:commit:}。";
// remoteMeetingService.roomListInner()
// String prefix = "我想请你充当[企业前台], 已知现在是" +
// date.format(formatter) + "。我对你说:”";
// String suffix = "”。会议地点:{" + "大会议室,小会议室" + "}。会议内容:{其他会议,例会,访客接待,面试}。未知的项目输出null。输出为{date:,start_time:,duration_hours:,location:,meeting_content:}";
String prefix = "当前时间是"+ dateFormatter.format(date)+ " 00:00。我将提供一些用户输入的信息,请提取输入的内容进行结构化转换并输出对应 json 格式的代码。下面是结构的描述:date(格式为YYYY-MM-DD);start_time(格式HH:MM);location; 下面是用户的输入信息:开个会";
String suffix = "\"。请开始信息提取,你回复的内容必须是一个json结构,如果没提取到的信息赋值为null,我不需要代码。";
log.info(prefix + content + suffix);

// String prefix = "当前时间是" +
// date.format(formatter) + " " + date.getDayOfWeek() + "。我将提供一些用户输入的信息,请提取输入的内容进行结构化转换并输出对应 json 格式的代码。下面是结构的描述:会议日期date(格式为YYYY-MM-DD);具体时间start_time(格式HH:MM);会议室地点location; 下面是用户的输入信息:\"";
// String suffix = "\"。请开始信息提取,你回复的内容必须是一个json结构,我只要json结果,不需要代码。";
// log.info(prefix + content + suffix);
webSocketClient.sendMsg(prefix + content + suffix);
try {
WebSocketClient.LOCK.wait();
String result = redisTemplate.opsForValue().get("group:websocket:content");
try {
//对result进行解析,获取字符串第一个与'{'和最后一个'}'之间的字符串,即为json字符串
if (!result.contains("{") || !result.contains("}")) {
// 生成内容无效
return session.getFormat();
}
result = result.substring(result.indexOf("{"), result.lastIndexOf("}") + 1);
System.out.println(result);
JSONObject jo = JSONObject.parseObject(result);
String dateStr = jo.getString("date");
String timeStr = jo.getString("start_time");
String locationStr = jo.getString("location");

if (StringUtils.isNotEmpty(locationStr)) {
roomListR.getData().forEach(item -> {
if(item.getName().equals(jo.get("location"))){
jo.put("locationId",item.getId());
}
});
if (jo.get("locationId") != null) {
session.getFormat().put("location",locationStr);
session.getFormat().put("locationId",jo.get("locationId"));
}
}
//设置时间参数
if (StringUtils.isNotEmpty(dateStr) && dateStr.split(":").length == 3) {
if (!jo.containsKey("locationId") || !session.getFormat().containsKey("date")) {
session.getFormat().put("date",dateStr);
}

}
if (StringUtils.isNotEmpty(timeStr) && !timeStr.equals("00:00")) {
//判断timeStr的格式是否是HH:mm
if (timeStr.split(":").length == 2) {
session.getFormat().put("start_time",timeStr);
}

}

// R<List<JSONObject>> recentListR = null;
// if (jo.get("start_time") != null ) {
// if (jo.get("start_time").equals("00:00")) {
// recentListR = remoteMeetingService.ableOrderList(devId, jo.getString("date"), null, null);
// } else {
// recentListR = remoteMeetingService.ableOrderList(devId, jo.getString("date"), null, jo.getString("start_time"));
// }
// if (recentListR.isOk()) {
// jo.put("start_time",recentListR.getData().get(0).get("startTime"));
// jo.put("location",recentListR.getData().get(0).get("roomId"));
// }
// }
// 判断内容是否击中es
CoversationSessionVo dateSession = processEsDate(content,session);
if (dateSession != null ){
session = dateSession;
}
//判断会议室是否冲突,如果冲突,删除时间
JSONObject checkObject = session.getFormat();
if (checkObject.containsKey("date") && checkObject.containsKey("time") && checkObject.containsKey("location")) {
JSONObject ret = remoteMeetingService.queryExist(checkObject.getLong("locationId"), checkObject.getString("date"), checkObject.getString("time"),tenantId,source.getMaster(), SecurityConstants.INNER);
if (StringUtils.isNotEmpty(ret.getString("err"))) {
// 会议室冲突,删除时间
session.getFormat().remove("time");
}
}
// redis缓存更新session
objectRedisTemplate.opsForValue().set("group:device" + ":" + devId + ":" +"session", session, 1,TimeUnit.MINUTES);
session.getFormat().put("skillCode", SkillConstants.SkillType.BOOK_MEETING_ROOM.getCode());
return session.getFormat();
} catch (JSONException je) {
// 返回结果错误,计日志,存log,返回空结果
log.error(je.getMessage(),je);
return null;
}

} catch (InterruptedException e) {
log.warn(e.getMessage());
Thread.currentThread().interrupt();
}
// JSONArray ja = new JSONArray();
// R<List<JSONObject>> recentListR = null;
// recentListR = remoteMeetingService.ableOrderList(devId,null,null,null);
// if (recentListR.isOk()) {
// recentListR.getData().forEach(item->{
// JSONObject tJson = new JSONObject();
// tJson.put("start_time",item.get("startTime"));
// tJson.put("location",item.get("roomId"));
// tJson.put("date",item.get(("orderDate")));
// tJson.put("duration_hours",0.5);
// ja.add(tJson);
// });
// JSONObject result = new JSONObject();
// result.put("data",ja);
// return result;
// }
}
return null;
}
private CoversationSessionVo processEsDate(String content,CoversationSessionVo session) {
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
SearchResponse<JSONObject> dateResponse = null;
try {
MatchQuery byName = MatchQuery.of(m->m.field("name").query(content));
dateResponse = esClient.search(builder -> builder
.index("meeting_date").query(q->q.match(byName)).minScore(3.0),
JSONObject.class);
log.info("esClient search result: {}", dateResponse);
}catch (IOException ie) {
log.error("esClient search error", ie);
return null;
}
List<JSONObject> dates = dateResponse.hits().hits().stream().map(f->f.source()).collect(
Collectors.toList()
);
if (dates.size() > 0) {
Integer dateInt = date.getDayOfWeek().getValue();
date = dates.get(0).get("type").equals("week")? date.plusDays(dates.get(0).getLong("content") - (long)dateInt) : date.plusDays(dates.get(0).getLong("content"));
session.getFormat().put("date",dateFormatter.format(date));

}
return session;
}

@Override
public JSONObject handle(String dev, String content) {
return null;
}
}

+ 10
- 0
xueyi-modules/xueyi-nlt/src/main/resources/banner.txt View File

@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_______ _________ _ _________
|\ /||\ /|( ____ \|\ /|\__ __/ ( ( /||\ \__ __/
( \ / )| ) ( || ( \/( \ / ) ) ( | \ ( || ) ) (
\ (_) / | | | || (__ \ (_) / | | _____ | \ | || | | |
) _ ( | | | || __) \ / | |(_____)| (\ \) || | | |
/ ( ) \ | | | || ( ) ( | | | | \ || | | |
( / \ )| (___) || (____/\ | | ___) (___ | ) \ || (____/\ | |
|/ \|(_______)(_______/ \_/ \_______/ |/ )_)(_______/ )_(

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save