Browse Source

yinruoxi:

新增
    1.NLT模块代码上传
tags/B.1.1.0.0_20230818_base^2
kira 2 years ago
parent
commit
0cc3500ef5
50 changed files with 2399 additions and 5 deletions
  1. +7
    -5
      Jenkinsfile
  2. +67
    -0
      Jenkinsfile1
  3. +11
    -0
      pom.xml
  4. +1
    -0
      xueyi-api/pom.xml
  5. +33
    -0
      xueyi-api/xueyi-api-nlt/pom.xml
  6. +13
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/netty/domain/vo/DmWebSocketMessageVo.java
  7. +20
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/netty/feign/RemoteWebsocketService.java
  8. +16
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmIntentVo.java
  9. +13
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/domain/vo/DmRecognitionVo.java
  10. +24
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/RemoteIntentService.java
  11. +15
    -0
      xueyi-api/xueyi-api-nlt/src/main/java/com/xueyi/nlt/api/nlt/feign/factory/RemoteIntentFallbackFactory.java
  12. +1
    -0
      xueyi-api/xueyi-api-nlt/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  13. +3
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/meeting/feign/RemoteMeetingService.java
  14. +5
    -0
      xueyi-api/xueyi-api-system/src/main/java/com/xueyi/system/api/meeting/feign/factory/RemoteMeetingFallbackFactory.java
  15. +1
    -0
      xueyi-common/xueyi-common-core/src/main/java/com/xueyi/common/core/constant/basic/ServiceConstants.java
  16. +15
    -0
      xueyi-common/xueyi-common-mqtt/src/main/java/com/xueyi/common/mqtt/constant/MqttTopicConstant.java
  17. +1
    -0
      xueyi-modules/pom.xml
  18. +17
    -0
      xueyi-modules/xueyi-nlt/Dockerfile
  19. +117
    -0
      xueyi-modules/xueyi-nlt/pom.xml
  20. +15
    -0
      xueyi-modules/xueyi-nlt/sonar-project.properties
  21. +29
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/XueYiNltApplication.java
  22. +195
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/NettyClient.java
  23. +313
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebSocketClient.java
  24. +202
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/WebsocketConfig.java
  25. +46
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/codec/WsChannelInitializer.java
  26. +66
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/MockClientHandler.java
  27. +108
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/NettyClientHandler.java
  28. +196
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/NettyWebsocketClientHandler.java
  29. +23
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/handler/WsClientHandler.java
  30. +13
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/client/message/ReceiveMessage.java
  31. +66
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/netty/controller/DmWebsocketController.java
  32. +296
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/controller/DmIntentController.java
  33. +14
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/dto/DmIntentDto.java
  34. +13
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/model/DmIntentConverter.java
  35. +61
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/po/DmIntentPo.java
  36. +13
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/query/DmIntentQuery.java
  37. +16
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/domain/vo/IntentTemplateVo.java
  38. +8
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/manager/IDmIntentManager.java
  39. +15
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/manager/impl/DmIntentManager.java
  40. +11
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/mapper/DmIntentMapper.java
  41. +8
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/IDmIntentService.java
  42. +12
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/service/impl/DmIntentServiceImpl.java
  43. +7
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/BaseTemplate.java
  44. +93
    -0
      xueyi-modules/xueyi-nlt/src/main/java/com/xueyi/nlt/nlt/template/MeetingOrderTemplate.java
  45. +10
    -0
      xueyi-modules/xueyi-nlt/src/main/resources/banner.txt
  46. +34
    -0
      xueyi-modules/xueyi-nlt/src/main/resources/bootstrap.yml
  47. +74
    -0
      xueyi-modules/xueyi-nlt/src/main/resources/logback.xml
  48. +9
    -0
      xueyi-modules/xueyi-system/pom.xml
  49. +12
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/api/DmMeetingApiController.java
  50. +41
    -0
      xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/api/DmMeetingInnerApiController.java

+ 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 "镜像推送成功"
//}
}
}

+ 11
- 0
pom.xml View File

@@ -163,6 +163,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 +306,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>


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


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

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

@@ -0,0 +1,13 @@
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;
}

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

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

@@ -0,0 +1,16 @@
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;
}

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

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

@@ -0,0 +1,24 @@
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);
}

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

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

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

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

@@ -56,4 +56,7 @@ public interface RemoteMeetingService {
@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(value = "/meeting/api/recent/{devId}/{dateStr}")
R<List<JSONObject>> ableOrderList(@PathVariable(value = "devId") String devId, @PathVariable(value = "dateStr") String dateStr, @RequestParam(value = "roomId", required = false) Long roomId, @RequestParam(value = "startTime", required = false) String startTime);
}

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

@@ -71,6 +71,11 @@ public class RemoteMeetingFallbackFactory implements FallbackFactory<RemoteMeeti
public List<JSONObject> recent(Long deptId, String dateStr, Long roomId, String startTime, Long enterpriseId, String sourceName, String source) {
return null;
}

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

+ 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";


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


+ 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"]

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

@@ -0,0 +1,117 @@
<?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>

<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>-->
<!-- <version>3.1.2</version>-->
<!-- </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();

}
}

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

@@ -0,0 +1,313 @@
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.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import okhttp3.*;
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 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.Base64;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

@Component
public class WebSocketClient extends WebSocketListener {

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

public final static Object LOCK = new Object();
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 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 String answer = "";

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

public static void main(String[] args) {
synchronized (LOCK) {
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 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();
}
}
//鉴权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",APPID);
header.addProperty("uid","123456789");
//填充parameter
chat.addProperty("domain","general");
chat.addProperty("random_threshold",0);
chat.addProperty("max_tokens",1024);
chat.addProperty("auditing","default");
parameter.add("chat",chat);
//填充payload
text.addProperty("role","user");
text.addProperty("content",question);
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");
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);
}

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

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

import com.alibaba.fastjson2.JSONObject;
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");
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();
}
}

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

@@ -0,0 +1,296 @@
package com.xueyi.nlt.nlt.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.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.web.entity.controller.BaseController;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.nlt.domain.vo.DmRecognitionVo;
import com.xueyi.nlt.api.nlt.feign.RemoteIntentService;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.netty.client.handler.NettyClientHandler;
import com.xueyi.nlt.nlt.domain.dto.DmIntentDto;
import com.xueyi.nlt.nlt.domain.query.DmIntentQuery;
import com.xueyi.nlt.api.nlt.domain.vo.DmIntentVo;
import com.xueyi.nlt.nlt.domain.vo.IntentTemplateVo;
import com.xueyi.nlt.nlt.service.IDmIntentService;
import com.xueyi.nlt.nlt.template.BaseTemplate;
import com.xueyi.nlt.nlt.template.MeetingOrderTemplate;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.digitalmans.feign.RemoteBroadcastService;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.meeting.feign.RemoteMeetingService;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

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

/**
* 意图请求
列表
*/
@PostMapping("/api/conversation")
@ResponseBody
public AjaxResult conversationApi(@RequestBody DmIntentVo intent) {
redisTemplate.opsForValue().increment("dashboard:server", 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) {
voResult.setTarget(1);
} else {
voResult.setTarget(0);
}
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);
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");
break;
} else if (Double.valueOf(String.valueOf(jo.get("timestamp"))) - System.currentTimeMillis() < 0) {
redisTemplate.opsForHash().delete("group:nlp" + ":" + recognition.getPersonId(), "meeting");
}
} else {
joResult.put("msg",value);
joResult.put("target",1);
redisTemplate.opsForHash().delete("group:nlp" + ":" + recognition.getPersonId(),key);
break;
}
}
}
return AjaxResult.success(joResult);
}

/**
* 意图请求列表
*/
@PostMapping("/inner/conversation")
@ResponseBody
public R<JSONObject> conversationInner(@RequestBody DmIntentVo intent) {
JSONObject joResult = null;
// 判断skill code的值
switch (intent.getSkillCode()) {
case "1":
// 获取名称为"meeting-order"的BaseTemplate的实例
joResult = meetingOrderTemplate.handle(intent.getDevId(),intent.getContent());
break;
default:
break;
}
return R.ok(joResult);
}

/**
* 意图请求
列表
*/
@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");
Date date = new Date(timestamp.longValue());
if (message.getSkillCode().equals("1")) {
String prefix = "假设你是一名公司前台,你看到在你们公司工作的\\"+ jo.getString("orderName")+ "\\,请你从个人角度提醒他参加\\" +
dateFormat3.format(timestamp) + "\\在\\" + meetingRoom + "\\的会,要求语气友好。输出只包含你要对他说的话,在20字左右。";
webSocketClient.sendMsg(prefix);
// 设置缓存
redisTemplate2.opsForValue().set("gpt:websocket" + ":" + "1", message);
}
return R.ok();
}

/**
* 查询意图管理
列表
*/
@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();
}



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

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

@@ -0,0 +1,16 @@
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;
}

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

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

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

import com.alibaba.fastjson2.JSONObject;

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

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

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

import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.core.web.result.R;
import com.xueyi.nlt.netty.client.WebSocketClient;
import com.xueyi.nlt.nlt.controller.DmIntentController;
import com.xueyi.system.api.meeting.feign.RemoteMeetingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;


@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 StringRedisTemplate redisTemplate;

@Override
public JSONObject handle(String devId, String content) {
synchronized (WebSocketClient.LOCK) {
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00");
DateTimeFormatter scheduleFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
// 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 = "我想请你充当[SQL数据库],我需要的数据格式为{date:,start_time:,location:,meeting_theme:},没有数据不返回字段,数据只能来自于如下文段:\"已知现在是" +
// date.format(formatter) + ",";
// String suffix = "\",只输出最后的JSON结果。不要输出任何解释说明或者代码。";
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字符串
result = result.substring(result.indexOf("{"), result.lastIndexOf("}") + 1);
System.out.println(result);
JSONObject jo = JSONObject.parseObject(result);
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"));
}
}

return jo;
} catch (JSONException je) {
// 返回结果错误,计日志,存log,返回空结果
log.error(je.getMessage(),je);
return null;
}

} catch (InterruptedException e) {
log.warn(e.getMessage());
}
}
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}
_______ _________ _ _________
|\ /||\ /|( ____ \|\ /|\__ __/ ( ( /||\ \__ __/
( \ / )| ) ( || ( \/( \ / ) ) ( | \ ( || ) ) (
\ (_) / | | | || (__ \ (_) / | | _____ | \ | || | | |
) _ ( | | | || __) \ / | |(_____)| (\ \) || | | |
/ ( ) \ | | | || ( ) ( | | | | \ || | | |
( / \ )| (___) || (____/\ | | ___) (___ | ) \ || (____/\ | |
|/ \|(_______)(_______/ \_/ \_______/ |/ )_)(_______/ )_(

+ 34
- 0
xueyi-modules/xueyi-nlt/src/main/resources/bootstrap.yml View File

@@ -0,0 +1,34 @@
# Tomcat
server:
port: 9901

# Spring
spring:
application:
# 应用名称
name: xueyi-nlt
profiles:
# 环境配置
active: @activatedProperties@
servlet:
multipart:
max-request-size: 20MB
max-file-size: 100MB
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: @nacos.host@:@nacos.port@
namespace: @nacos.namespace@

config:
# 配置中心地址
server-addr: @nacos.host@:@nacos.port@
namespace: @nacos.namespace@
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
- application-secret-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
- application-datasource-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

+ 74
- 0
xueyi-modules/xueyi-nlt/src/main/resources/logback.xml View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/xueyi-nlt" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 系统模块日志级别控制 -->
<logger name="com.xueyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />

<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

+ 9
- 0
xueyi-modules/xueyi-system/pom.xml View File

@@ -41,6 +41,11 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- SpringBoot Mock -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- XueYi Common Log -->
<dependency>
<groupId>com.xueyi</groupId>
@@ -103,6 +108,10 @@
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>com.xueyi</groupId>
<artifactId>xueyi-api-nlt</artifactId>
</dependency>


</dependencies>


+ 12
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/api/DmMeetingApiController.java View File

@@ -15,6 +15,7 @@ import com.xueyi.system.api.pass.feign.RemoteRecognizedRecordsService;
import com.xueyi.system.resource.controller.api.BaseApiController;
import com.xueyi.system.utils.common.ImageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@@ -46,6 +47,9 @@ public class DmMeetingApiController extends BaseApiController {
@Autowired
private SmsService smsService;

@Autowired
private StringRedisTemplate redisTemplate;

@GetMapping(value = "/room-lists/{devId}")
public List<DmMeetingRoomsDto> roomList(@PathVariable(value = "devId") String devId){
DeviceTenantSourceMergeVo vo = super.getDeviceTenantSourceMergeVo(devId);
@@ -91,6 +95,14 @@ public class DmMeetingApiController extends BaseApiController {
return remoteMeetingService.delInner(id, vo.getTenantId(),vo.getSourceSlave(), SecurityConstants.INNER);
}

@ResponseBody
@PostMapping(value = "/cancel-order")
public JSONObject cancel(@RequestParam(required = true) String devId) {
redisTemplate.delete("group:websocket" + ":" + devId);

return outputSuccess().toJSON();
}

@ResponseBody
@PostMapping(value = "/lists")
public JSONObject list(String dateStr, Long spaceId, String devId) {


+ 41
- 0
xueyi-modules/xueyi-system/src/main/java/com/xueyi/system/meeting/controller/api/DmMeetingInnerApiController.java View File

@@ -5,18 +5,26 @@ import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.SqlConstants;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.security.annotation.InnerAuth;
import com.xueyi.common.sms.configure.SmsProperties;
import com.xueyi.common.web.constant.ResponseCode;
import com.xueyi.common.web.utils.DateUtils;
import com.xueyi.nlt.api.netty.domain.vo.DmWebSocketMessageVo;
import com.xueyi.nlt.api.netty.feign.RemoteWebsocketService;
import com.xueyi.nlt.api.nlt.feign.RemoteIntentService;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo;
import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.meeting.domain.dto.DmMeetingOrdersDto;
import com.xueyi.system.api.meeting.domain.dto.DmMeetingRoomsDto;
import com.xueyi.system.api.meeting.domain.po.DmMeetingOrdersPo;
import com.xueyi.system.api.meeting.domain.po.DmMeetingRoomsPo;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.sms.domain.vo.SmsReqEntity;
import com.xueyi.system.api.sms.feign.RemoteSmsService;
import com.xueyi.system.api.staff.domain.po.DmStaffPo;
@@ -31,6 +39,7 @@ import com.xueyi.system.meeting.service.impl.DmMeetingRoomsServiceImpl;
import com.xueyi.system.resource.controller.api.BaseApiController;
import com.xueyi.system.staff.mapper.DmStaffMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@@ -94,6 +103,17 @@ public class DmMeetingInnerApiController extends BaseApiController {
@Autowired
private DmMeetingRoomsConverter dmMeetingRoomsConverter;

@Autowired
private StringRedisTemplate redisTemplate;

@Autowired
private RemoteWebsocketService remoteWebsocketService;

@Autowired
private RemoteIntentService remoteIntentService;
@Autowired
private RemoteManDeviceService manDeviceService;


@InnerAuth
@GetMapping("/rooms/{deptId}")
@@ -189,6 +209,27 @@ public class DmMeetingInnerApiController extends BaseApiController {
System.err.println(e.getMessage());
e.printStackTrace();
}
// 埋点 预定会议室
redisTemplate.opsForValue().increment("dashboard:meeting", 1);
// 创建会议提醒
// 创建json
JSONObject jsonObject = new JSONObject();
jsonObject.put("meetingRoom", meetingRoom.getName());
jsonObject.put("orderName", dmStaffPo.getUserName());
jsonObject.put("orderId", dmStaffPo.getId());
jsonObject.put("timestamp", list.get(0).getStartTime().getTime());
// redisTemplate.opsForValue().set("group:nlp" + ":" + dmStaffPo.getId() + ":" + "meeting",jsonObject.toString());
// 将创建临时信息添加进缓存:用户会议提醒

DmWebSocketMessageVo vo = new DmWebSocketMessageVo();
vo.setDevId(order.getDevId());
vo.setSkillCode("1");
vo.setFormat(jsonObject);
R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(order.getDevId());
Source source = SourceUtil.getSourceCache(manDeviceDtoR.getData().getStrategyId());
remoteIntentService.sendMessage(vo, manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
// 清除设备会议室模版session信息
redisTemplate.delete("group:websocket" + ":" + order.getDevId());
return outputSuccess().toJSON();
}



Loading…
Cancel
Save