Explorar el Código

Merge branch 'master' into test

# Conflicts:
#	src/main/resources/props/config_local.properties
#	src/main/webapp/WEB-INF/views/portal/index.html
anderx hace 2 años
padre
commit
6c840f718d
Se han modificado 39 ficheros con 1679 adiciones y 191 borrados
  1. 77 69
      pom.xml
  2. 83 0
      src/main/java/com/goafanti/baiduAI/BaiduChatErrorEnums.java
  3. 53 0
      src/main/java/com/goafanti/baiduAI/bo/InputSendChat.java
  4. 38 0
      src/main/java/com/goafanti/baiduAI/bo/Messages.java
  5. 23 0
      src/main/java/com/goafanti/baiduAI/bo/OutChatER.java
  6. 4 0
      src/main/java/com/goafanti/baiduAI/bo/OutSendChat.java
  7. 44 0
      src/main/java/com/goafanti/baiduAI/bo/OutSendChatOK.java
  8. 90 0
      src/main/java/com/goafanti/baiduAI/bo/SseEventBo.java
  9. 9 0
      src/main/java/com/goafanti/baiduAI/bo/SseMap.java
  10. 42 0
      src/main/java/com/goafanti/baiduAI/bo/SseResult.java
  11. 101 0
      src/main/java/com/goafanti/baiduAI/controller/BaiduAiController.java
  12. 16 0
      src/main/java/com/goafanti/baiduAI/service/BaiduAiService.java
  13. 63 0
      src/main/java/com/goafanti/baiduAI/service/impl/BaiduAiServiceImpl.java
  14. 27 0
      src/main/java/com/goafanti/common/bo/SseEmitterUTF8.java
  15. 13 15
      src/main/java/com/goafanti/common/controller/BaseApiController.java
  16. 9 6
      src/main/java/com/goafanti/common/controller/BaseController.java
  17. 1 7
      src/main/java/com/goafanti/common/controller/CertifyApiController.java
  18. 21 6
      src/main/java/com/goafanti/common/controller/PublicController.java
  19. 19 0
      src/main/java/com/goafanti/common/controller/WebpageController.java
  20. 21 0
      src/main/java/com/goafanti/common/dao/ErnieBotCommonDao.java
  21. 72 0
      src/main/java/com/goafanti/common/mapper/ErnieBotCommonDao.xml
  22. 48 0
      src/main/java/com/goafanti/common/model/ErnieBotCommon.java
  23. 25 0
      src/main/java/com/goafanti/common/utils/AsyncUtils.java
  24. 195 0
      src/main/java/com/goafanti/common/utils/BaiduChatUtils.java
  25. 12 6
      src/main/java/com/goafanti/common/utils/DateUtils.java
  26. 59 1
      src/main/java/com/goafanti/common/utils/HttpUtils.java
  27. 6 6
      src/main/java/com/goafanti/common/utils/PasswordUtil.java
  28. 210 0
      src/main/java/com/goafanti/common/utils/RedisUtil.java
  29. 1 0
      src/main/java/com/goafanti/core/cache/serializer/FastJsonRedisSerializer.java
  30. 74 0
      src/main/java/com/goafanti/core/cache/template/ExtendedRedisCacheManager.java
  31. 22 22
      src/main/java/com/goafanti/core/shiro/token/TokenManager.java
  32. 1 1
      src/main/resources/props/config_local.properties
  33. 1 0
      src/main/resources/shiro_base_auth.ini
  34. 26 23
      src/main/resources/spring/spring-mvc.xml
  35. 44 19
      src/main/resources/spring/spring-shiro.xml
  36. 64 0
      src/main/webapp/WEB-INF/views/portal/answers.html
  37. 2 2
      src/main/webapp/WEB-INF/views/portal/index.html
  38. 54 0
      src/main/webapp/WEB-INF/views/portal/test.html
  39. 9 8
      src/main/webapp/WEB-INF/web.xml

+ 77 - 69
pom.xml

@@ -20,35 +20,35 @@
 		<org.aspectj-version>1.6.10</org.aspectj-version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 	</properties>
-	<profiles>  
-        <profile>  
-            <id>aft_local</id>  
-            <activation>  
-                <activeByDefault>true</activeByDefault>  
-            </activation>  
-            <properties>  
-                <profiles.activation>local</profiles.activation>  
-            </properties>  
-        </profile>  
-        <profile>  
-            <id>aft_dev</id>  
-            <properties>  
-                <profiles.activation>dev</profiles.activation>  
-            </properties>  
-        </profile>  
-        <profile>  
-            <id>aft_prod</id>  
-            <properties>  
-                <profiles.activation>prod</profiles.activation>  
-            </properties>  
-        </profile>  
-        <profile>  
-            <id>aft_test</id>  
-            <properties>  
-                <profiles.activation>test</profiles.activation>  
-            </properties>  
-        </profile>  
-	</profiles> 
+	<profiles>
+        <profile>
+            <id>aft_local</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <properties>
+                <profiles.activation>local</profiles.activation>
+            </properties>
+        </profile>
+        <profile>
+            <id>aft_dev</id>
+            <properties>
+                <profiles.activation>dev</profiles.activation>
+            </properties>
+        </profile>
+        <profile>
+            <id>aft_prod</id>
+            <properties>
+                <profiles.activation>prod</profiles.activation>
+            </properties>
+        </profile>
+        <profile>
+            <id>aft_test</id>
+            <properties>
+                <profiles.activation>test</profiles.activation>
+            </properties>
+        </profile>
+	</profiles>
 
 	<dependencies>
 		<!-- spring -->
@@ -95,13 +95,13 @@
 			<artifactId>spring-messaging</artifactId>
 			<version>${org.springframework-version}</version>
 		</dependency>
-		
+
 		<dependency>
 		    <groupId>org.springframework.data</groupId>
 		    <artifactId>spring-data-redis</artifactId>
 		    <version>1.8.3.RELEASE</version>
 		</dependency>
-		
+
 		<dependency>
 		    <groupId>org.thymeleaf</groupId>
 		    <artifactId>thymeleaf-spring4</artifactId>
@@ -364,7 +364,7 @@
 			<artifactId>httpasyncclient</artifactId>
 			<version>4.1.3</version>
 		</dependency>
-        
+
         <!-- jpush -->
 		<dependency>
 			<groupId>cn.jpush.api</groupId>
@@ -382,20 +382,28 @@
 			<artifactId>Gson</artifactId>
 			<version>2.5</version>
 		</dependency>
-		
+
 		<!-- ffmpeg -->
 		<dependency>
 		  <groupId>net.bramp.ffmpeg</groupId>
 		  <artifactId>ffmpeg</artifactId>
 		  <version>0.6.2</version>
 		</dependency>
-		
+
 		<!-- commons -->
 		<dependency>
 		    <groupId>commons-net</groupId>
 		    <artifactId>commons-net</artifactId>
 		    <version>3.6</version>
 		</dependency>
+		<!--chatAi输出-->
+		<dependency>
+			<groupId>com.github.plexpt</groupId>
+			<artifactId>chatgpt</artifactId>
+			<version>4.0.7</version>
+		</dependency>
+
+
 	</dependencies>
 	<build>
 		<resources>
@@ -431,45 +439,45 @@
 					<skip>true</skip>
 				</configuration>
 			</plugin>
-			<plugin>    
-			    <groupId>org.apache.maven.plugins</groupId>    
-			    <artifactId>maven-surefire-plugin</artifactId>    
-			    <version>2.5</version>    
-			    <configuration>    
-			        <skip>true</skip>    
-			    </configuration>    
-			</plugin> 
-			<plugin>  
-                <groupId>org.apache.maven.plugins</groupId>  
-                <artifactId>maven-war-plugin</artifactId>  
-                <version>3.1.0</version>  
-                <configuration>  
-                    <warName>${profiles.activation}</warName>  
-                    <!-- 激活spring profile -->  
-                    <webResources>  
-                        <resource>  
-                            <filtering>true</filtering>  
-                            <directory>src/main/webapp</directory>  
-                            <includes>  
-                                <include>**/**</include>  
-                            </includes>  
-                        </resource>  
-                        <resource>  
-                            <filtering>true</filtering>  
+			<plugin>
+			    <groupId>org.apache.maven.plugins</groupId>
+			    <artifactId>maven-surefire-plugin</artifactId>
+			    <version>2.5</version>
+			    <configuration>
+			        <skip>true</skip>
+			    </configuration>
+			</plugin>
+			<plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <warName>${profiles.activation}</warName>
+                    <!-- 激活spring profile -->
+                    <webResources>
+                        <resource>
+                            <filtering>true</filtering>
+                            <directory>src/main/webapp</directory>
+                            <includes>
+                                <include>**/**</include>
+                            </includes>
+                        </resource>
+                        <resource>
+                            <filtering>true</filtering>
                             <directory>src/main/resources</directory>
                             <targetPath>WEB-INF/classes</targetPath>
-                            <includes>  
-                                <include>**/**</include>  
-                            </includes>  
-                        </resource>  
-                    </webResources>  
-                    <warSourceDirectory>src/main/webapp</warSourceDirectory>  
-                    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>  
-                </configuration>  
+                            <includes>
+                                <include>**/**</include>
+                            </includes>
+                        </resource>
+                    </webResources>
+                    <warSourceDirectory>src/main/webapp</warSourceDirectory>
+                    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
+                </configuration>
 			</plugin>
 		</plugins>
 	</build>
-	
+
 	<repositories>
 		<repository>
 			<id>aliyun-repos</id>
@@ -489,4 +497,4 @@
 			</snapshots>
 		</pluginRepository>
 	</pluginRepositories>
-</project>
+</project>

+ 83 - 0
src/main/java/com/goafanti/baiduAI/BaiduChatErrorEnums.java

@@ -0,0 +1,83 @@
+package com.goafanti.baiduAI;
+
+import com.goafanti.common.enums.AchievementAuditStatus;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum BaiduChatErrorEnums {
+
+    FWQCW(1,"服务器内部错误"),
+    FWQBKY(2,"服务暂不可用"),
+    APINOT(3,"调用的API不存在"),
+    JQCCX(4,"集群超限额。"),
+    WFWQX(6,"无权限访问该用户数据"),
+    TKER(13,"获取token失败。"),
+    IAMNOT(14,"IAM鉴权失败。"),
+    APPNOT(15,"应用不存在或者创建失败。"),
+    MAXER(17,"每天请求量超限额"),
+    QPSER(18,"QPS超限额"),
+    TKCXWX(19,"无效的access_token参数"),
+    TKWX(100,"access_token验证无效"),
+    TKGQ(110,"access token验证过期"),
+    FWQNCW(111,"服务内部错误。"),
+    RCER(336000,"入参格式有误"),
+    BODYER(336002,"入参body不是标准的JSON格式。"),
+    PRAMER(336003,"参数校验不合法"),
+    RSGDER(336100,"互动的人过多,请您稍后重新向我提问。"),
+    OTHER(0,"未知错误");
+
+
+    private Integer code;
+    private String msg;
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    private BaiduChatErrorEnums(Integer code, String msg){
+        this.code=code;
+        this.msg=msg;
+    }
+
+    private static Map<String, BaiduChatErrorEnums> status = new HashMap<String, BaiduChatErrorEnums>();
+
+    static {
+        for (BaiduChatErrorEnums value : BaiduChatErrorEnums.values()) {
+            status.put(value.getMsg(), value);
+        }
+    }
+
+    public static BaiduChatErrorEnums getStatus(String code) {
+        if (containsType(code)) {
+            return status.get(code);
+        }
+        return OTHER;
+    }
+    public static boolean containsType(String code) {
+        return status.containsKey(code);
+    }
+
+    public static String BycodeGetMsg(Integer code){
+        for (BaiduChatErrorEnums value : status.values()) {
+            if (code.equals(value.getCode())){
+                return value.msg;
+            }
+        }
+        return OTHER.msg;
+    }
+
+}

+ 53 - 0
src/main/java/com/goafanti/baiduAI/bo/InputSendChat.java

@@ -0,0 +1,53 @@
+package com.goafanti.baiduAI.bo;
+
+import java.util.List;
+
+public class InputSendChat {
+
+    /**
+     * 聊天上下文信息。说明:
+     * (1)messages成员不能为空,1个成员表示单轮对话,多个成员表示多轮对话。
+     * (2)最后一个message为当前请求的信息,前面的message为历史对话信息。
+     * (3)必须为奇数个成员,成员中message的role必须依次为user、assistant。
+     * (4)最后一个message的content长度(即此轮对话的问题)不能超过2000个字符;如果messages中content总长度大于2000字符,系统会依次遗忘最早的历史会话,直到content的总长度不超过2000个字符。
+     */
+    private List<Messages> messages;
+
+    /**
+     * 是否以流式接口的形式返回数据,默认false。
+     */
+    private boolean stream;
+
+    /**
+     * 表示最终用户的唯一标识符,可以监视和检测滥用行为,防止接口恶意调用。
+     */
+    private String userId;
+
+
+    public List<Messages> getMessages() {
+        return messages;
+    }
+
+    public void setMessages(List<Messages> messages) {
+        this.messages = messages;
+    }
+
+    public boolean isStream() {
+        return stream;
+    }
+
+    public void setStream(boolean stream) {
+        this.stream = stream;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+
+
+}

+ 38 - 0
src/main/java/com/goafanti/baiduAI/bo/Messages.java

@@ -0,0 +1,38 @@
+package com.goafanti.baiduAI.bo;
+
+public class Messages {
+    /**
+     * 当前支持以下:
+     * user: 表示用户
+     * assistant: 表示对话助手
+     */
+    private String role;
+    /**
+     * 对话内容,不能为空。
+     */
+    private String content;
+
+    public Messages(String role, String content) {
+        this.role = role;
+        this.content = content;
+    }
+
+    public Messages() {
+    }
+
+    public String getRole() {
+        return role;
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+}

+ 23 - 0
src/main/java/com/goafanti/baiduAI/bo/OutChatER.java

@@ -0,0 +1,23 @@
+package com.goafanti.baiduAI.bo;
+
+public class OutChatER extends OutSendChat{
+    private Integer error_code;
+    private String error_msg;
+
+
+    public Integer getError_code() {
+        return error_code;
+    }
+
+    public void setError_code(Integer error_code) {
+        this.error_code = error_code;
+    }
+
+    public String getError_msg() {
+        return error_msg;
+    }
+
+    public void setError_msg(String error_msg) {
+        this.error_msg = error_msg;
+    }
+}

+ 4 - 0
src/main/java/com/goafanti/baiduAI/bo/OutSendChat.java

@@ -0,0 +1,4 @@
+package com.goafanti.baiduAI.bo;
+
+public class OutSendChat {
+}

+ 44 - 0
src/main/java/com/goafanti/baiduAI/bo/OutSendChatOK.java

@@ -0,0 +1,44 @@
+package com.goafanti.baiduAI.bo;
+
+public class OutSendChatOK extends  OutSendChat {
+    private String id;
+    private String object;
+    private String created;
+    private String sentence_id;
+    private String is_end;
+    private String result;
+    private String need_clear_history;
+    private Usage usage;
+
+
+
+    private class Usage {
+        private Integer prompt_tokens;
+        private Integer completion_tokens;
+        private Integer total_tokens;
+
+        public Integer getPrompt_tokens() {
+            return prompt_tokens;
+        }
+
+        public void setPrompt_tokens(Integer prompt_tokens) {
+            this.prompt_tokens = prompt_tokens;
+        }
+
+        public Integer getCompletion_tokens() {
+            return completion_tokens;
+        }
+
+        public void setCompletion_tokens(Integer completion_tokens) {
+            this.completion_tokens = completion_tokens;
+        }
+
+        public Integer getTotal_tokens() {
+            return total_tokens;
+        }
+
+        public void setTotal_tokens(Integer total_tokens) {
+            this.total_tokens = total_tokens;
+        }
+    }
+}

+ 90 - 0
src/main/java/com/goafanti/baiduAI/bo/SseEventBo.java

@@ -0,0 +1,90 @@
+package com.goafanti.baiduAI.bo;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import java.util.Set;
+
+public class SseEventBo implements SseEmitter.SseEventBuilder {
+    private String id;
+    private String comment;
+    private String name;
+    private Long reconnectTime;
+    private Object data;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getReconnectTime() {
+        return reconnectTime;
+    }
+
+    public void setReconnectTime(Long reconnectTime) {
+        this.reconnectTime = reconnectTime;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+
+    @Override
+    public SseEmitter.SseEventBuilder comment(String s) {
+        return null;
+    }
+
+    @Override
+    public SseEmitter.SseEventBuilder name(String s) {
+        return null;
+    }
+
+    @Override
+    public SseEmitter.SseEventBuilder id(String s) {
+        return null;
+    }
+
+    @Override
+    public SseEmitter.SseEventBuilder reconnectTime(long l) {
+        return null;
+    }
+
+    @Override
+    public SseEmitter.SseEventBuilder data(Object o) {
+        return null;
+    }
+
+    @Override
+    public SseEmitter.SseEventBuilder data(Object o, MediaType mediaType) {
+        return null;
+    }
+
+    @Override
+    public Set<ResponseBodyEmitter.DataWithMediaType> build() {
+        return null;
+    }
+}

+ 9 - 0
src/main/java/com/goafanti/baiduAI/bo/SseMap.java

@@ -0,0 +1,9 @@
+package com.goafanti.baiduAI.bo;
+
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SseMap {
+    public static final Map<String, SseResult> sseEmitterMap = new ConcurrentHashMap<>();
+}

+ 42 - 0
src/main/java/com/goafanti/baiduAI/bo/SseResult.java

@@ -0,0 +1,42 @@
+package com.goafanti.baiduAI.bo;
+
+import com.goafanti.common.bo.SseEmitterUTF8;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+public class SseResult {
+
+        public String clientId;
+        public long timestamp;
+        public SseEmitterUTF8 sseEmitter;
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public SseEmitter getSseEmitter() {
+        return sseEmitter;
+    }
+
+    public SseResult(String clientId, long timestamp, SseEmitterUTF8 sseEmitter) {
+        this.clientId = clientId;
+        this.timestamp = timestamp;
+        this.sseEmitter = sseEmitter;
+    }
+
+    public SseResult() {
+    }
+}
+
+

+ 101 - 0
src/main/java/com/goafanti/baiduAI/controller/BaiduAiController.java

@@ -0,0 +1,101 @@
+package com.goafanti.baiduAI.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.goafanti.baiduAI.bo.InputSendChat;
+import com.goafanti.baiduAI.bo.Messages;
+import com.goafanti.baiduAI.bo.SseMap;
+import com.goafanti.baiduAI.bo.SseResult;
+import com.goafanti.baiduAI.service.BaiduAiService;
+import com.goafanti.common.bo.Result;
+import com.goafanti.common.bo.SseEmitterUTF8;
+import com.goafanti.common.constant.ErrorConstants;
+import com.goafanti.common.controller.BaseController;
+import com.goafanti.common.controller.CertifyApiController;
+import com.goafanti.common.error.BusinessException;
+import com.goafanti.common.model.AftUser;
+import com.goafanti.common.utils.LoggerUtils;
+import com.goafanti.common.utils.StringUtils;
+import com.goafanti.core.shiro.token.TokenManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import java.io.IOException;
+import java.util.*;
+
+@RestController
+@RequestMapping(value = "/chat")
+public class BaiduAiController extends CertifyApiController{
+
+    @Autowired
+    private BaiduAiService baiduAiService;
+
+    @RequestMapping(value = "/send")
+    public Object sendChat(@RequestBody InputSendChat in){
+        if (in.getUserId()==null ){
+            in.setUserId(UUID.randomUUID().toString());
+            in.setStream(true);
+        }
+        if (in.getMessages()==null||in.getMessages().isEmpty()){
+            Result res= new Result();
+            res.getError().add(buildError(ErrorConstants.PARAM_ERROR,"访问参数"));
+            return res;
+        }
+        return baiduAiService.sendChat(in);
+    }
+
+
+
+    @RequestMapping("/start")
+    public SseEmitter testSseEmitter(String clientId) {
+        // 默认30秒超时,设置为0L则永不超时
+        SseEmitterUTF8 sseEmitter = new SseEmitterUTF8(3600_000L);
+//        if (clientId==null)clientId=UUID.randomUUID().toString();
+        SseMap.sseEmitterMap.put(clientId, new SseResult(clientId, System.currentTimeMillis(), sseEmitter));
+        return sseEmitter;
+    }
+
+
+    /**
+     * 向SseEmitter对象发送数据
+     *
+     * @param clientId
+     * @return
+     */
+    @RequestMapping("/send2")
+    public String setSseEmitter(String clientId) {
+        try {
+            SseResult result =  SseMap.sseEmitterMap.get(clientId);
+            if (result != null && result.sseEmitter != null) {
+                long timeInMillis = Calendar.getInstance().getTimeInMillis();
+                String re = "{\"success\":true,\"message\":\"操作成功!\",\"code\":200,\"result\":{\"id\":1018},\"timestamp\":"+timeInMillis+"}";
+                Map<String,Object> map= JSON.parseObject(re);
+                  result.sseEmitter.send(map);
+            }
+        } catch (IOException e) {
+            LoggerUtils.error(getClass(),"IOException");
+            return "error";
+        }
+        return "Succeed!";
+    }
+
+
+    /**
+     * 将SseEmitter对象设置成完成
+     *
+     * @param clientId
+     * @return
+     */
+    @RequestMapping("/end")
+    public String completeSseEmitter(String clientId) {
+        SseResult result =  SseMap.sseEmitterMap.get(clientId);
+        if (result != null) {
+            SseMap.sseEmitterMap.remove(clientId);
+            result.sseEmitter.complete();
+        }
+        return "Succeed!";
+    }
+
+
+
+}

+ 16 - 0
src/main/java/com/goafanti/baiduAI/service/BaiduAiService.java

@@ -0,0 +1,16 @@
+package com.goafanti.baiduAI.service;
+
+import com.goafanti.baiduAI.bo.InputSendChat;
+import com.goafanti.common.bo.SseEmitterUTF8;
+import com.goafanti.common.model.ErnieBotCommon;
+
+import java.util.List;
+
+public interface BaiduAiService {
+
+
+    SseEmitterUTF8 sendChat(InputSendChat in);
+
+
+    List<ErnieBotCommon> selectErnieBotCommonAll(Integer count);
+}

+ 63 - 0
src/main/java/com/goafanti/baiduAI/service/impl/BaiduAiServiceImpl.java

@@ -0,0 +1,63 @@
+package com.goafanti.baiduAI.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.goafanti.baiduAI.BaiduChatErrorEnums;
+import com.goafanti.baiduAI.bo.*;
+import com.goafanti.baiduAI.service.BaiduAiService;
+import com.goafanti.common.bo.SseEmitterUTF8;
+import com.goafanti.common.dao.ErnieBotCommonDao;
+import com.goafanti.common.error.BusinessException;
+import com.goafanti.common.model.ErnieBotCommon;
+import com.goafanti.common.utils.BaiduChatUtils;
+import com.goafanti.common.utils.HttpUtils;
+import com.goafanti.common.utils.LoggerUtils;
+import com.goafanti.common.utils.RedisUtil;
+import com.goafanti.core.shiro.cache.ShiroRedisCache;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class BaiduAiServiceImpl implements BaiduAiService {
+
+
+    @Autowired
+    private ErnieBotCommonDao ernieBotCommonDao;
+
+
+    @Autowired
+    private BaiduChatUtils baiduChatUtils;
+
+
+    @Override
+    public SseEmitterUTF8 sendChat(InputSendChat in) {
+        SseEmitterUTF8 sseEmitter = new SseEmitterUTF8(3600_000L);
+//        if (clientId==null)clientId=UUID.randomUUID().toString();
+        SseMap.sseEmitterMap.put(in.getUserId(), new SseResult(in.getUserId(), System.currentTimeMillis(), sseEmitter));
+        try {
+//            先将数据返回,异步调用返回数据
+            baiduChatUtils.sendBaiduAiStream(in);
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new BusinessException("文言一心调用失败"+e.getLocalizedMessage());
+        }
+            return sseEmitter;
+    }
+
+    @Override
+    @Cacheable(value = "selectErnieBotCommonAll#300",key = "'page:'+'All'")
+    public List<ErnieBotCommon> selectErnieBotCommonAll(Integer count) {
+        return ernieBotCommonDao.selectAll(count);
+    }
+
+
+}

+ 27 - 0
src/main/java/com/goafanti/common/bo/SseEmitterUTF8.java

@@ -0,0 +1,27 @@
+package com.goafanti.common.bo;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import java.nio.charset.Charset;
+
+/**
+ * 直接使用会有乱码问题,继承一下,重写下修改后就没有问题了
+ */
+public class SseEmitterUTF8 extends SseEmitter {
+
+        public SseEmitterUTF8(Long timeout) {
+            super(timeout);
+        }
+
+        @Override
+        protected void extendResponse(ServerHttpResponse outputMessage) {
+            super.extendResponse(outputMessage);
+
+            HttpHeaders headers = outputMessage.getHeaders();
+            headers.setContentType( new MediaType("text", "event-stream", Charset.forName("UTF-8")));
+        }
+    }
+

+ 13 - 15
src/main/java/com/goafanti/common/controller/BaseApiController.java

@@ -34,7 +34,7 @@ public class BaseApiController extends BaseController {
 	private String	uploadPrivatePath	= null;
 
 	/**
-	 * 
+	 *
 	 * @param request
 	 * @return
 	 */
@@ -51,7 +51,7 @@ public class BaseApiController extends BaseController {
 	}
 
 	/**
-	 * 
+	 *
 	 * @param res
 	 * @param path
 	 * @param isPrivate
@@ -77,15 +77,13 @@ public class BaseApiController extends BaseController {
 		}
 		return fileName;
 	}
-	
+
 
 	/**
-	 * 
+	 *
 	 * @param res
-	 * @param path
 	 * @param isPrivate
 	 * @param req
-	 * @param sign
 	 * @return
 	 */
 	protected String handleFile(Result res, boolean isPrivate, HttpServletRequest req, String... fileName) {
@@ -109,7 +107,7 @@ public class BaseApiController extends BaseController {
 	}
 
 	/**
-	 * 
+	 *
 	 * @param res
 	 * @param fileName
 	 * @param filePath
@@ -129,7 +127,7 @@ public class BaseApiController extends BaseController {
 	}
 
 	/**
-	 * 
+	 *
 	 * @param fileName
 	 * @return
 	 */
@@ -138,7 +136,7 @@ public class BaseApiController extends BaseController {
 	}
 
 	/**
-	 * 
+	 *
 	 * @param fileName
 	 * @return
 	 */
@@ -147,7 +145,7 @@ public class BaseApiController extends BaseController {
 	}
 
 	/**
-	 * 
+	 *
 	 * @param fileName
 	 * @return
 	 */
@@ -218,8 +216,8 @@ public class BaseApiController extends BaseController {
 	protected Result res() {
 		return new Result();
 	}
-	
-	
+
+
 	@SuppressWarnings("resource")
 	protected String handleBaseFiles(Result res, String path, boolean isPrivate, byte[] bs, String sign,
 			String uid,String fn) {
@@ -232,7 +230,7 @@ public class BaseApiController extends BaseController {
 					if(!filePath.exists()){
 						filePath.mkdirs();
 					}
-					fileName += "/"+ fn; 
+					fileName += "/"+ fn;
 					System.out.println("------------"+ uploadPrivatePath + fileName);
 					fos = new FileOutputStream(new File(uploadPrivatePath + fileName));
 				} else {
@@ -240,7 +238,7 @@ public class BaseApiController extends BaseController {
 					if(!filePath.exists()){
 						filePath.mkdirs();
 					}
-					fileName += "/" + fn; 
+					fileName += "/" + fn;
 					System.out.println("------------"+ uploadPath + fileName);
 					fos = new FileOutputStream(new File(uploadPath + fileName));
 				}
@@ -257,7 +255,7 @@ public class BaseApiController extends BaseController {
 		}
 		return fileName;
 	}
-	
+
 	protected String handleVideoFiles(Result res, HttpServletRequest req,String local) {
 		List<MultipartFile> files = getFiles(req);
 		MultipartFile mf = files.get(0);

+ 9 - 6
src/main/java/com/goafanti/common/controller/BaseController.java

@@ -33,7 +33,7 @@ public class BaseController {
 
 	@Value(value = "${static.host}")
 	private String					staticHost			= null;
-	
+
 	@Value(value = "${skjt.host}")
 	private String					skjtHost			= null;
 
@@ -57,7 +57,7 @@ public class BaseController {
 
 	@Value(value = "${avatar.upload.host}")
 	private String					avatarUploadHost	= null;
-	
+
 	@Value(value = "${video.server}")
 	private String					videoServer	= null;
 
@@ -69,13 +69,15 @@ public class BaseController {
 		String msg = (String) errorResource.getProperty(key);
 		if (StringUtils.isEmpty(msg)) {
 			msg = message;
+		}else {
+			msg=MessageFormat.format(msg, message);
 		}
 		return new Error(key, msg);
 	}
 
 	/**
 	 * 带参数的error message
-	 * 
+	 *
 	 * @param key
 	 * @param message
 	 * @param object
@@ -122,9 +124,7 @@ public class BaseController {
 		model.addAttribute("avatarUploadHost", avatarUploadHost);
 		model.addAttribute("portalHost", portalHost);
 		model.addAttribute("basePath", request.getContextPath());
-		model.addAttribute("shiro", SecurityUtils.getSubject());
-		model.addAttribute("isLogin", TokenManager.isLogin());
-		model.addAttribute("csrf", TokenManager.getCSRF());
+
 		model.addAttribute("videoServer", videoServer);
 		model.addAttribute("isAdmin", false);
 		int yearCount=0;
@@ -134,6 +134,9 @@ public class BaseController {
 		if (TokenManager.isLogin() && TokenManager.getToken() instanceof User) {
 			model.addAttribute("userData", TokenManager.getUserToken());
 			model.addAttribute("userName", TokenManager.getUserToken().getNickname());
+			model.addAttribute("shiro", SecurityUtils.getSubject());
+			model.addAttribute("isLogin", TokenManager.isLogin());
+			model.addAttribute("csrf", TokenManager.getCSRF());
 		}
 
 		if (TokenManager.isLogin() && TokenManager.getToken() instanceof Admin) {

+ 1 - 7
src/main/java/com/goafanti/common/controller/CertifyApiController.java

@@ -1,20 +1,14 @@
 package com.goafanti.common.controller;
 
-import javax.annotation.Resource;
 
 import com.goafanti.common.bo.Result;
 import com.goafanti.common.constant.ErrorConstants;
 import com.goafanti.common.enums.UserLevel;
 import com.goafanti.common.model.User;
 import com.goafanti.core.shiro.token.TokenManager;
-import com.goafanti.user.service.OrganizationIdentityService;
-import com.goafanti.user.service.UserIdentityService;
 
 public class CertifyApiController extends BaseApiController {
-	@Resource
-	private OrganizationIdentityService	organizationIdentityService;
-	@Resource
-	private UserIdentityService			userIdentityService;
+
 
 	public boolean checkCertify(Result res, User user) {
 		if (user == null) {

+ 21 - 6
src/main/java/com/goafanti/common/controller/PublicController.java

@@ -13,7 +13,9 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import com.alibaba.fastjson.JSONObject;
 import com.goafanti.common.model.JtNews;
+import com.goafanti.common.utils.*;
 import com.goafanti.news.bo.InputJtNews;
 import com.goafanti.news.bo.OutJtNews;
 import com.goafanti.news.service.EventPlanningService;
@@ -41,12 +43,6 @@ import com.goafanti.common.model.User;
 import com.goafanti.common.service.DistrictGlossoryService;
 import com.goafanti.common.service.FieldGlossoryService;
 import com.goafanti.common.service.IndustryCategoryService;
-import com.goafanti.common.utils.LoggerUtils;
-import com.goafanti.common.utils.MobileMessageUtils;
-import com.goafanti.common.utils.PasswordUtil;
-import com.goafanti.common.utils.PictureUtils;
-import com.goafanti.common.utils.TimeUtils;
-import com.goafanti.common.utils.VerifyCodeUtils;
 import com.goafanti.core.mybatis.JDBCIdGenerator;
 import com.goafanti.core.mybatis.page.Pagination;
 import com.goafanti.core.shiro.token.TokenManager;
@@ -902,6 +898,25 @@ public class PublicController extends BaseController {
 		return  res;
 	}
 
+
+
+	@RequestMapping(value = "/selectChat",method = RequestMethod.GET)
+	@ResponseBody
+	public Result  selectChat (String text){
+		Result res=new Result();
+		Map<String,Object> params=new HashMap();
+		List<String> list =new ArrayList<>();
+		params.put("priors",list);
+		params.put("text",text);
+		String str = HttpUtils.httpPostToStr("https://www.sciradar.com/gw/chat/chat/stream", params);
+		return res.data(str);
+	}
+
+
+
+
+
+
 	/**
 	 * 删除Html标签
 	 */

+ 19 - 0
src/main/java/com/goafanti/common/controller/WebpageController.java

@@ -11,6 +11,8 @@ import java.util.Map;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 
+import com.goafanti.baiduAI.service.BaiduAiService;
+import com.goafanti.common.dao.ErnieBotCommonDao;
 import com.goafanti.common.model.*;
 import com.goafanti.news.bo.InputJtNews;
 import com.goafanti.news.bo.OutJtNews;
@@ -111,6 +113,9 @@ public class WebpageController extends BaseController {
 	@Resource
 	private EventPlanningService eventPlanningService;
 
+	@Resource
+	private BaiduAiService baiduAiService;
+
 	@RequestMapping(value = "/user/account/index", method = RequestMethod.GET)
 	public ModelAndView index(HttpServletRequest request, ModelAndView modelview) {
 		modelview.setViewName("/user/account/index");
@@ -1610,6 +1615,20 @@ public class WebpageController extends BaseController {
 		return modelAndView;
 	}
 
+	@RequestMapping("/portal/answers")
+	public ModelAndView answers(ModelAndView modelAndView){
+		modelAndView.setViewName("/portal/answers");
+		List<ErnieBotCommon> list = baiduAiService.selectErnieBotCommonAll(6);
+		modelAndView.addObject("list",list);
+		return modelAndView;
+	}
+
+	@RequestMapping("/portal/test")
+	public ModelAndView test(ModelAndView modelAndView){
+		modelAndView.setViewName("/portal/test");
+		return modelAndView;
+	}
+
 	/**
 	 * 新闻详情
 	 * @param modelview

+ 21 - 0
src/main/java/com/goafanti/common/dao/ErnieBotCommonDao.java

@@ -0,0 +1,21 @@
+package com.goafanti.common.dao;
+
+import com.goafanti.common.model.ErnieBotCommon;
+
+import java.util.List;
+
+public interface ErnieBotCommonDao {
+    int deleteByPrimaryKey(Integer id);
+
+    int insert(ErnieBotCommon record);
+
+    int insertSelective(ErnieBotCommon record);
+
+    ErnieBotCommon selectByPrimaryKey(Integer id);
+
+    int updateByPrimaryKeySelective(ErnieBotCommon record);
+
+    int updateByPrimaryKey(ErnieBotCommon record);
+
+    List<ErnieBotCommon> selectAll(Integer count);
+}

+ 72 - 0
src/main/java/com/goafanti/common/mapper/ErnieBotCommonDao.xml

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.goafanti.common.dao.ErnieBotCommonDao">
+  <resultMap id="BaseResultMap" type="com.goafanti.common.model.ErnieBotCommon">
+    <id column="id" jdbcType="INTEGER" property="id" />
+    <result column="content" jdbcType="VARCHAR" property="content" />
+    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    id, content, create_time
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List" />
+    from ernie_bot_common
+    where id = #{id,jdbcType=INTEGER}
+  </select>
+
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
+    delete from ernie_bot_common
+    where id = #{id,jdbcType=INTEGER}
+  </delete>
+  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.goafanti.common.model.ErnieBotCommon" useGeneratedKeys="true">
+    insert into ernie_bot_common (content, create_time)
+    values (#{content,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP})
+  </insert>
+  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.goafanti.common.model.ErnieBotCommon" useGeneratedKeys="true">
+    insert into ernie_bot_common
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="content != null">
+        content,
+      </if>
+      <if test="createTime != null">
+        create_time,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="content != null">
+        #{content,jdbcType=VARCHAR},
+      </if>
+      <if test="createTime != null">
+        #{createTime,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.goafanti.common.model.ErnieBotCommon">
+    update ernie_bot_common
+    <set>
+      <if test="content != null">
+        content = #{content,jdbcType=VARCHAR},
+      </if>
+      <if test="createTime != null">
+        create_time = #{createTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.goafanti.common.model.ErnieBotCommon">
+    update ernie_bot_common
+    set content = #{content,jdbcType=VARCHAR},
+      create_time = #{createTime,jdbcType=TIMESTAMP}
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+
+
+  <select id="selectAll"  resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List" />
+    from ernie_bot_common
+    limit #{count}
+  </select>
+</mapper>

+ 48 - 0
src/main/java/com/goafanti/common/model/ErnieBotCommon.java

@@ -0,0 +1,48 @@
+package com.goafanti.common.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * ernie_bot_common
+ * @author 
+ */
+public class ErnieBotCommon implements Serializable {
+    private Integer id;
+
+    /**
+     * 帐号名称
+     */
+    private String content;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    private static final long serialVersionUID = 1L;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+}

+ 25 - 0
src/main/java/com/goafanti/common/utils/AsyncUtils.java

@@ -0,0 +1,25 @@
+package com.goafanti.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.goafanti.baiduAI.bo.OutSendChatOK;
+import com.goafanti.baiduAI.bo.SseMap;
+import com.goafanti.baiduAI.bo.SseResult;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+@Component
+@Async
+public class AsyncUtils {
+
+
+
+}

+ 195 - 0
src/main/java/com/goafanti/common/utils/BaiduChatUtils.java

@@ -0,0 +1,195 @@
+package com.goafanti.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.goafanti.baiduAI.BaiduChatErrorEnums;
+import com.goafanti.baiduAI.bo.*;
+import com.goafanti.common.error.BusinessException;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+
+
+public class BaiduChatUtils {
+
+    @Value(value = "${baidu.ApiKey}")
+    private   String baiduApiKey=null;
+
+    @Value(value = "${baidu.SecretKey}")
+    private   String baiduSecretKey=null;
+    @Autowired
+    private RedisUtil redisUtil;
+
+    /*文心一言地址*/
+    private static final String BAIDU_CHAT_WXYY_URL="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=";
+    /*Ernie-Lite地址*/
+    private static final String BAIDU_CHAT_ERNIE_LITE_URL="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=";
+    /*accessToken获取地址*/
+    private static final String BAIDU_ACCESSTOKEN_URL="https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&";
+
+
+    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().connectTimeout(120000, TimeUnit.MILLISECONDS)
+            .readTimeout(120000, TimeUnit.MILLISECONDS)
+            .build();
+
+
+    @Async
+    public void sendBaiduAiStream(InputSendChat inputSendChat) throws IOException {
+        SseResult res = null;
+        BufferedReader reader=null;
+        InputStreamReader inputStreamReader=null;
+        OutputStream outputStream=null;
+        try {
+            String baidu_url=BAIDU_CHAT_WXYY_URL+getRedisBaiduAccessToken();
+            URL url = new URL(baidu_url);
+            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+            connection.setRequestMethod("POST");
+            connection.setRequestProperty("Content-Type", "application/json");
+            connection.setDoInput(true);
+            connection.setDoOutput(true);
+            // 构造请求体
+//            String requestBody = "{\"messages\":[{\"role\":\"user\",\"content\":\"给我介绍一条从四川自驾到拉萨的路线\"}],\"stream\":true}";
+            String requestBody=JSON.toJSONString(inputSendChat);
+            byte[] postData = requestBody.getBytes(StandardCharsets.UTF_8);
+            connection.setRequestProperty("Content-Length", String.valueOf(postData.length));
+            outputStream =connection.getOutputStream();
+            outputStream.write(postData);
+            InputStream responseStream = connection.getInputStream();
+            inputStreamReader = new InputStreamReader(responseStream, "UTF-8");
+            reader = new BufferedReader(inputStreamReader);
+            String line;
+            res =  SseMap.sseEmitterMap.get(inputSendChat.getUserId());
+            while ((line = reader.readLine())!= null) {
+                // 每行数据中以 "data:" 开头的部分即为实际的响应数据
+                if (StringUtils.isNotBlank(line)){
+                    if (line.startsWith("data:")) {
+                        String data = line.substring("data:".length()).trim();
+                        JSONObject jsonObject = JSONObject.parseObject(data);
+                        Boolean isEnd = jsonObject.getBoolean("is_end");
+                        res.sseEmitter.send(data);
+                        if(isEnd){
+                            break;
+                        }
+                        //错误返回格式{"error_code":110,"error_msg":"Access token invalid or no longer valid"}
+                    }else if(line.startsWith("{")) {
+                        JSONObject jsonObject = JSONObject.parseObject(line);
+                        Integer errorCode = jsonObject.getInteger("error_code");
+                        OutChatER out=new OutChatER();
+                        if (errorCode!=null){
+                            out.setError_code(errorCode);
+                            if (errorCode.equals("336003")){
+                                out.setError_msg(BaiduChatErrorEnums.BycodeGetMsg(errorCode)+jsonObject.getString("error_msg"));
+                            }else {
+                                out.setError_msg(BaiduChatErrorEnums.BycodeGetMsg(errorCode));
+                            }
+                        }
+                        String errorStr=JSON.toJSONString(out);
+                        LoggerUtils.debug(getClass(),errorStr);
+                        res.sseEmitter.send(errorStr);
+                    }
+                }
+            }
+            res.sseEmitter.complete();
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+            sendJitaoBaiWen(inputSendChat.getUserId(),"data:{\"error_code\":\"2\",\"error_msg\":\"域名解析异常\"}");
+        } catch (ProtocolException e) {
+            e.printStackTrace();
+        }catch (IllegalStateException e){
+            LoggerUtils.debug(getClass(),"前端网页已关闭");
+        }finally {
+            inputStreamReader.close();
+            outputStream.close();
+            reader.close();
+            res.sseEmitter.complete();
+            SseMap.sseEmitterMap.remove(inputSendChat.getUserId());
+        }
+
+    }
+
+
+
+
+    public  String  getBaiduAccessToken() throws IOException {
+        MediaType mediaType = MediaType.parse("application/json");
+        RequestBody body = RequestBody.create(mediaType, "");
+        StringBuffer url= new StringBuffer(BAIDU_ACCESSTOKEN_URL)
+                .append("client_id=").append(baiduApiKey).append("&client_secret=").append(baiduSecretKey);
+        Request request = new Request.Builder()
+                .url(url.toString())
+                .method("POST", body)
+                .addHeader("Content-Type", "application/json")
+                .addHeader("Accept", "application/json")
+                .build();
+        Response response = HTTP_CLIENT.newCall(request).execute();
+        String result=response.body().string();
+        HashMap<String,Object> map = JSON.parseObject(result, HashMap.class);
+        String  accessToken = map.get("access_token").toString();
+        LoggerUtils.debug(getClass(),"获取accessToken="+accessToken);
+        return accessToken;
+    }
+
+
+
+
+
+    private void sendJitaoBaiWen(String userId, String s) throws IOException {
+        SseResult res =  SseMap.sseEmitterMap.get(userId);
+        res.sseEmitter.send(s);
+    }
+
+
+    private String  getRedisBaiduAccessToken() {
+        String redisAccessToken;
+        String redisTime=redisUtil.getString("baiduAccessTime");
+        if (redisTime !=null){
+            Calendar cal = Calendar.getInstance();
+            Long redisAccessTime=Long.valueOf(redisTime);
+            if (cal.getTimeInMillis()>redisAccessTime){
+                redisUtil.deleteString("baiduAccessToken");
+                redisUtil.deleteString("baiduAccessTime");
+                redisAccessToken=pushRedisBaiduAccessToken();
+                LoggerUtils.debug(getClass(),"accessToken过期,重新获取!");
+            }else {
+                redisAccessToken=  redisUtil.getString("baiduAccessToken");
+            }
+        }else {
+            redisAccessToken=pushRedisBaiduAccessToken();
+            LoggerUtils.debug(getClass(),"accessToken不存在,从百度获取!");
+        }
+        return redisAccessToken;
+    }
+
+    private String pushRedisBaiduAccessToken() {
+        String baiduAccessToken;
+        try {
+            baiduAccessToken = getBaiduAccessToken();
+        } catch (IOException e) {
+            throw new BusinessException("baiduAccessToken获取失败");
+        }
+        //获取当前系统时间
+        Calendar cal = Calendar.getInstance();
+        //将时间增加三十天
+        cal.add(Calendar.DATE, 30);
+        //获取改变后的时间
+        Long baiduAccessTime= cal.getTimeInMillis();
+        redisUtil.deleteString("baiduAccessToken");
+        redisUtil.deleteString("baiduAccessTime");
+        redisUtil.setString("baiduAccessToken",baiduAccessToken);
+        redisUtil.setString("baiduAccessTime",baiduAccessTime.toString());
+        return baiduAccessToken;
+    }
+
+
+}

+ 12 - 6
src/main/java/com/goafanti/common/utils/DateUtils.java

@@ -20,7 +20,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 	/**
 	 * Determines how two dates compare up to no more than the specified most
 	 * significant field.
-	 * 
+	 *
 	 * @param date1
 	 *            the first date, not <code>null</code>
 	 * @param date2
@@ -45,7 +45,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 	/**
 	 * Determines how two dates compare up to no more than the specified most
 	 * significant field.
-	 * 
+	 *
 	 * @param date1
 	 *            the first date, not <code>null</code>
 	 * @param date2
@@ -66,7 +66,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 	/**
 	 * Determines how two dates compare up to no more than the specified most
 	 * significant field.
-	 * 
+	 *
 	 * @param date1
 	 *            the first date, not <code>null</code>
 	 * @param date2
@@ -386,7 +386,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 		return calendar.getTime();
 	}
 
-	/** 
+	/**
 	 *  返回前一年最后一天
 	 * @param date
 	 * @return
@@ -420,12 +420,18 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 		return format.format(date);
 	}
 
+	public static String formatDate(Calendar calendar, String pattern) {
+		Date date=calendar.getTime();
+		SimpleDateFormat format = new SimpleDateFormat(pattern);
+		return format.format(date);
+	}
+
 	/**
 	 * 解析日期
 	 * @param source
 	 * @param pattern
 	 * @return
-	 * @throws ParseException 
+	 * @throws ParseException
 	 */
 	public static Date parseDate(String source, String pattern) throws ParseException {
 		SimpleDateFormat format = new SimpleDateFormat(pattern);
@@ -460,7 +466,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 		ca.setTime(date);
 		ca.add(Calendar.DATE, a);
 		return ca.getTime();
-		
+
 	}
 
 }

+ 59 - 1
src/main/java/com/goafanti/common/utils/HttpUtils.java

@@ -2,6 +2,11 @@ package com.goafanti.common.utils;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.goafanti.baiduAI.bo.InputSendChat;
+import com.goafanti.baiduAI.bo.Messages;
+import com.goafanti.common.error.BusinessException;
+import com.plexpt.chatgpt.listener.SseStreamListener;
+import okhttp3.*;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.ParseException;
@@ -12,15 +17,25 @@ import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.util.EntityUtils;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
 
+import javax.crypto.SecretKey;
 import java.io.IOException;
 import java.nio.charset.Charset;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
 
+@Component
 public class HttpUtils {
 
 
 
+
+
 	 public static JSONObject httpGet(String url) {
 			JSONObject jsonResult = null;
 			try {
@@ -51,6 +66,7 @@ public class HttpUtils {
 			httpPost.addHeader("Content-type", "application/json");
 			httpPost.setHeader("Accept", "application/json");
 			httpPost.setEntity(new StringEntity(JSON.toJSONString(map), Charset.forName("UTF-8")));
+
 			HttpResponse response = null;
 			try {
 				response = httpClient.execute(httpPost);
@@ -79,4 +95,46 @@ public class HttpUtils {
 
 
 
+	/**
+	 *
+	 * @param url 地址
+	 * @param map 参数
+	 * @return
+	 */
+	public static String httpPostToStr(String url,Map<String, Object>map){
+		HttpClient httpClient = HttpClientBuilder.create().build();
+		HttpPost httpPost = new HttpPost(url);
+		httpPost.addHeader("Content-type", "application/json");
+		httpPost.setHeader("Accept", "application/json");
+		httpPost.setEntity(new StringEntity(JSON.toJSONString(map), Charset.forName("UTF-8")));
+		httpPost.setHeader("Authorization","26a418106d92a32ea713f4fcec9e0ce6");
+		HttpResponse response = null;
+		try {
+			response = httpClient.execute(httpPost);
+			if (null == response || response.getStatusLine() == null) {
+				throw new Exception("Post Request For Url[{}] is not ok. Response is null");
+			} else if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+				throw new Exception("Post Request For Url[{}] is not ok. Response Status Code is {"+response.getStatusLine().getStatusCode()+"}");
+			}
+		} catch (ClientProtocolException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		String resultString=null;
+		try {
+			resultString = EntityUtils.toString(response.getEntity(),"UTF-8");
+		} catch (ParseException | IOException e) {
+			e.printStackTrace();
+		}
+		return resultString;
+	}
+
+
+
+
+
+
 }

+ 6 - 6
src/main/java/com/goafanti/common/utils/PasswordUtil.java

@@ -11,7 +11,7 @@ import com.goafanti.common.model.SkjtUser;
 import com.goafanti.common.model.User;
 
 public class PasswordUtil {
-	private String algorithmName = "md5";
+	private String algorithmName = null;
 	private int hashIterations = 2;
 
 	public void setAlgorithmName(String algorithmName) {
@@ -25,7 +25,7 @@ public class PasswordUtil {
 	public void encryptPassword(User user) {
 		user.setPassword(getEncryptPwd(user));
 	}
-	
+
 	public void encryptPassword(Admin admin){
 		admin.setPassword(getEncryptPwd(admin));
 	}
@@ -33,11 +33,11 @@ public class PasswordUtil {
 	public String getEncryptPwd(User user) {
 		return new SimpleHash(algorithmName, user.getPassword(), getSalt(user), hashIterations).toHex();
 	}
-	
+
 	public String getEncryptPwd(SkjtUser user) {
 		return new SimpleHash(algorithmName, user.getPassword(), getSkjtSalt(user), hashIterations).toHex();
 	}
-	
+
 	public String getEncryptPwd(Admin admin) {
 		return new SimpleHash(algorithmName, admin.getPassword(), getManageSalt(admin), hashIterations).toHex();
 	}
@@ -49,14 +49,14 @@ public class PasswordUtil {
 	public ByteSource getSalt(User user) {
 		return ByteSource.Util.bytes(String.valueOf(user.getCreateTime().getTime()));
 	}
-	
+
 	public ByteSource getManageSalt(Admin admin) {
 		return ByteSource.Util.bytes(String.valueOf(admin.getCreateTime().getTime()));
 	}
 	public ByteSource getSkjtSalt(SkjtUser user) {
 		return ByteSource.Util.bytes(String.valueOf(user.getCreateTime().getTime()));
 	}
-	
+
 	public ByteSource getAftSalt(AftUser aftUser) {
 		return ByteSource.Util.bytes(String.valueOf(aftUser.getCreateTime().getTime()));
 	}

+ 210 - 0
src/main/java/com/goafanti/common/utils/RedisUtil.java

@@ -0,0 +1,210 @@
+package com.goafanti.common.utils;
+
+
+import com.alibaba.fastjson.JSON;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+
+import java.io.*;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * redis辅助类
+ * @author
+ *
+ */
+@Component
+public class RedisUtil {
+
+	@Autowired
+	private  JedisPool pool;//创建代理对象
+
+
+	public static String SHIRO_SESSION="SHIRO_SESSION:";
+
+//	 /**
+//     * 初始化Redis连接池
+//     */
+//    public RedisUtil() {
+//    	if (pool==null) {
+//    		try {
+//    			JedisPoolConfig config = new JedisPoolConfig();
+//    			config.setBlockWhenExhausted(false);
+//    			config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy");
+//    			config.setJmxEnabled(true);
+//    			config.setJmxNamePrefix("pool");
+//    			config.setLifo(true);
+//    			config.setMaxIdle(8);
+//    			config.setMaxTotal(8);
+//    			config.setMaxWaitMillis(-1);
+//    			config.setMinEvictableIdleTimeMillis(1800000L);
+//    			config.setMinIdle(0);
+//    			config.setNumTestsPerEvictionRun(3);
+//    			config.setSoftMinEvictableIdleTimeMillis(1800000L);
+//    			config.setTestOnBorrow(false);
+//    			config.setTestWhileIdle(false);
+//    			config.setTimeBetweenEvictionRunsMillis(-1);
+//    			pool = new JedisPool(config, host, 6379, 10000, pwd);
+//    		} catch (Exception e) {
+//    			e.printStackTrace();
+//    		}
+//		}
+//    }
+
+
+
+	public  boolean presence(String key){
+		Jedis jedis = pool.getResource();
+		boolean bool=true;
+		try {
+			bool =jedis.exists(key);//进行判断
+		}catch(Exception e){
+			e.printStackTrace();//输出错误信息
+		}finally {
+			jedis.close();//释放资源
+		}
+		return bool;
+	}
+	/**
+	 * 将缓存中数据进行反序列化
+	 * @param key
+	 * @param clazz
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	public <T>List<T> getObject(String key,Class<T> clazz){
+		Jedis jedis = pool.getResource();
+		ByteArrayInputStream is=null;
+		ObjectInputStream ois=null;
+		try {
+			//将缓存中数据存入byte数组中
+			byte[] b = jedis.get(key.getBytes());
+			is= new ByteArrayInputStream(b);
+			ois = new ObjectInputStream(is);
+			return(List<T>)ois.readObject();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}finally{
+			try {
+				is.close();
+				ois.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			jedis.close();
+		}
+		return null;
+	}
+	/**
+	 * 将对象进行序列化存入redis中
+	 * @param object
+	 * @param key
+	 */
+	public void saveObject(Object object,String key){
+		Jedis jedis=pool.getResource();
+		ByteArrayOutputStream os=null;
+		ObjectOutputStream oos=null;
+		try {
+			os=new ByteArrayOutputStream();
+			oos =new ObjectOutputStream(os);
+			byte[] b=os.toByteArray();
+			JSON.toJSONString(b);
+			jedis.set(key.getBytes(), b);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}finally{
+			try {
+				os.close();
+				oos.close();
+			} catch (Exception e2) {
+				e2.printStackTrace();
+			}
+			jedis.close();
+		}
+	}
+	// 把List集合对象转换成json格式保存到指定的键中
+	public void saveJsonArray(Object object, String key) {
+		Jedis jedis = pool.getResource();
+		try {
+			// 格式化成Json字符串
+			String array = JSON.toJSONString(object);
+			jedis.set(key, array.toString()); // 存入缓存
+		} finally {
+			jedis.close();
+		}
+	}
+
+		public void setString(String key, String value) {
+			Jedis jedis = pool.getResource();
+			try {
+				jedis.set(key,value); // 存入缓存
+			} finally {
+				jedis.close();
+			}
+		}
+
+		public Set<String> keys(String key){
+			Jedis jedis = pool.getResource();
+			try {
+				return  jedis.keys(key);
+			} finally {
+				jedis.close();
+			}
+		}
+
+		public void deleteString(String key) {
+			Jedis jedis = pool.getResource();
+			try {
+				jedis.del(key);
+			} finally {
+				jedis.close();
+			}
+		}
+
+
+	public void deleteAid(String id) {
+		Jedis jedis = pool.getResource();
+		String str=new String();
+		try {
+			Set<String> set=jedis.keys(SHIRO_SESSION+"*");
+			for (String s : set) {
+				String value=getString(s);
+				if (value.contains(id)){
+					deleteString(s);
+					LoggerUtils.debug(this.getClass(),"清除缓存{%s,aid=%s}",s,id);
+				}
+			}
+		} finally {
+			jedis.close();
+		}
+	}
+
+		public String getString(String key) {
+			Jedis jedis = pool.getResource();
+			String str=new String();
+			try {
+				str=jedis.get(key);
+			} finally {
+				jedis.close();
+			}
+			return str;
+		}
+
+	// 通过键取出Json字符串并转换成 <T>这个T所指定的类型
+	public  <T> T getJsonArray(String key, Class<T> clazz) {
+		Jedis jedis = pool.getResource();
+		try {
+			String str = jedis.get(key);
+			// 把字符串转换回集合对象 clazz是指定的类型
+			return JSON.parseObject(str, clazz);
+		} finally {
+			jedis.close();
+		}
+	}
+
+}
+
+

+ 1 - 0
src/main/java/com/goafanti/core/cache/serializer/FastJsonRedisSerializer.java

@@ -24,6 +24,7 @@ public class FastJsonRedisSerializer implements RedisSerializer<Object> {
 		pc.addAccept("com.goafanti.common.model.Activity");
 		pc.addAccept("com.goafanti.portal.bo.InternationalListBo");
 		pc.addAccept("com.goafanti.easemob.bo.EasemobInfo");
+		pc.addAccept("com.goafanti.common.model.ErnieBotCommon");
 	}
 
 	@Override

+ 74 - 0
src/main/java/com/goafanti/core/cache/template/ExtendedRedisCacheManager.java

@@ -0,0 +1,74 @@
+package com.goafanti.core.cache.template;
+
+import com.goafanti.common.utils.LoggerUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.data.redis.cache.RedisCache;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.core.RedisOperations;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+public class ExtendedRedisCacheManager extends RedisCacheManager {
+
+    private static final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
+
+    private static final Pattern pattern = Pattern.compile("[+\\-*/%]");
+
+    /**
+     * 分隔符
+     */
+    private char separator = '#';
+
+    public ExtendedRedisCacheManager(RedisOperations redisOperations) {
+        super(redisOperations);
+    }
+
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected RedisCache createCache(String cacheName) {
+        // 获取默认时间
+        long expiration = computeExpiration(cacheName);
+        int index = cacheName.indexOf(this.getSeparator());
+        if (index > 0) {
+            expiration = getExpiration(cacheName, index, expiration);
+        }
+        LoggerUtils.debug(this.getClass(),cacheName+",缓存时间="+expiration);
+        return new RedisCache(cacheName, (isUsePrefix() ? getCachePrefix().prefix(cacheName) : null),
+                getRedisOperations(), expiration);
+    }
+
+    /**
+     * 计算缓存时间
+     * @param name 缓存名字 cache#60*60
+     * @param separatorIndex 分隔符位置
+     * @param defalutExp 默认缓存时间
+     * @return
+     */
+    protected long getExpiration(final String name, final int separatorIndex, final long defalutExp) {
+        Long expiration = null;
+        String expirationAsString = name.substring(separatorIndex + 1);
+        try {
+            if (pattern.matcher(expirationAsString).find()) {
+                expiration = NumberUtils.toLong(scriptEngine.eval(expirationAsString).toString(), defalutExp);
+            } else {
+                expiration = NumberUtils.toLong(expirationAsString, defalutExp);
+            }
+        } catch (ScriptException e) {
+            LoggerUtils.fmtError(this.getClass(),e,"缓存时间转换错误:{%s},异常:{%s}",name,e.getMessage());
+        }
+        return Objects.nonNull(expiration) ? expiration.longValue() : defalutExp;
+    }
+
+    public char getSeparator() {
+        return separator;
+    }
+
+    public void setSeparator(char separator) {
+        this.separator = separator;
+    }
+}

+ 22 - 22
src/main/java/com/goafanti/core/shiro/token/TokenManager.java

@@ -19,7 +19,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前登录的用户User对象
-	 * 
+	 *
 	 * @return
 	 */
 	public static AftUser getToken() {
@@ -28,7 +28,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前登录的用户User对象Role
-	 * 
+	 *
 	 * @return
 	 */
 	public static boolean hasRole(String role) {
@@ -37,7 +37,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前登录的用户User对象Permission
-	 * 
+	 *
 	 * @return
 	 */
 	public static boolean hasPermission(String permission) {
@@ -46,7 +46,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前用户的Session
-	 * 
+	 *
 	 * @return
 	 */
 	public static Session getSession() {
@@ -55,7 +55,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前用户ID
-	 * 
+	 *
 	 * @return
 	 */
 	public static String getUserId() {
@@ -64,7 +64,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前用户WebSocketID
-	 * 
+	 *
 	 * @return
 	 */
 	public static String getWebSocketKey() {
@@ -73,7 +73,7 @@ public class TokenManager {
 
 	/**
 	 * 把值放入到当前登录用户的Session里
-	 * 
+	 *
 	 * @param key
 	 * @param value
 	 */
@@ -83,7 +83,7 @@ public class TokenManager {
 
 	/**
 	 * 从当前登录用户的Session里取值
-	 * 
+	 *
 	 * @param key
 	 * @return
 	 */
@@ -93,7 +93,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前登录的普通用户对象
-	 * 
+	 *
 	 * @return
 	 */
 	public static User getUserToken() {
@@ -107,7 +107,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前登录的管理员对象
-	 * 
+	 *
 	 * @return
 	 */
 	public static Admin getAdminToken() {
@@ -121,7 +121,7 @@ public class TokenManager {
 
 	/**
 	 * 获取当前管理员ID
-	 * 
+	 *
 	 * @return
 	 */
 	public static String getAdminId() {
@@ -129,9 +129,9 @@ public class TokenManager {
 	}
 
 	/**
-	 * 
+	 *
 	 * 获取当前管理员所在省份
-	 * 
+	 *
 	 * @return
 	 */
 	/*
@@ -141,7 +141,7 @@ public class TokenManager {
 
 	/**
 	 * 获取验证码,获取一次后删除
-	 * 
+	 *
 	 * @return
 	 */
 	public static String getYZM() {
@@ -152,7 +152,7 @@ public class TokenManager {
 
 	/**
 	 * 获取CSRF TOKEN
-	 * 
+	 *
 	 * @return
 	 */
 	public static String getCSRF() {
@@ -161,7 +161,7 @@ public class TokenManager {
 
 	/**
 	 * 用户登录
-	 * 
+	 *
 	 * @param user
 	 * @param rememberMe
 	 * @return
@@ -173,10 +173,10 @@ public class TokenManager {
 		setVal2Session(CSRF_TOKEN, UUID.randomUUID().toString().replace("-", ""));
 		return (User) getToken();
 	}
-	
+
 	/**
 	 * skjt用户登录
-	 * 
+	 *
 	 * @param user
 	 * @param rememberMe
 	 * @return
@@ -191,7 +191,7 @@ public class TokenManager {
 
 	/**
 	 * 管理员登录
-	 * 
+	 *
 	 * @param admin
 	 * @param rememberMe
 	 * @return
@@ -205,7 +205,7 @@ public class TokenManager {
 
 	/**
 	 * 判断是否登录
-	 * 
+	 *
 	 * @return
 	 */
 	public static boolean isLogin() {
@@ -231,14 +231,14 @@ public class TokenManager {
 
 	/**
 	 * 根据UserIds 清空权限信息。
-	 * 
+	 *
 	 * @param id
 	 *            用户ID
 	 */
 	public static void clearUserAuthByUserId(String... userIds) {
 		realm.clearCachedAuthorizationInfo(userIds);
 	}
-	
+
 	/**
 	 * 获取UserType
 	 */

+ 1 - 1
src/main/resources/props/config_local.properties

@@ -39,7 +39,7 @@ app.mobile.website=http://m.jishutao.com/1.0/template/index.html
 template.cacheable=false
 
 static.host=//ss.jishutao.com/client/1.2.11
-portal.host=//ss.jishutao.com/portal/2.2.20
+portal.host=//ss.jishutao.com/portal/2.2.21
 skjt.host=//ss.jishutao.com/skjt/1.3
 
 

+ 1 - 0
src/main/resources/shiro_base_auth.ini

@@ -19,6 +19,7 @@
 /open/**=anon
 /favicon.ico=anon
 /static/**=anon
+/chat/**=anon
 /portal/**=device
 /api/portal/**=anon
 /api/admin/**=admin

+ 26 - 23
src/main/resources/spring/spring-mvc.xml

@@ -3,32 +3,35 @@
 	xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
 	xmlns:context="http://www.springframework.org/schema/context"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans 
-	http://www.springframework.org/schema/beans/spring-beans.xsd 
-	http://www.springframework.org/schema/context 
-	http://www.springframework.org/schema/context/spring-context-4.0.xsd 
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+	http://www.springframework.org/schema/beans/spring-beans.xsd
+	http://www.springframework.org/schema/context
+	http://www.springframework.org/schema/context/spring-context-4.0.xsd
 	http://www.springframework.org/schema/task
 	http://www.springframework.org/schema/task/spring-task-4.0.xsd
-	http://www.springframework.org/schema/mvc 
+	http://www.springframework.org/schema/mvc
 	http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
 
 	<!-- Scan controller -->
-		
+
 	<context:component-scan
-		base-package="com.goafanti.*.controller;com.goafanti.*.*.controller;com.goafanti.common.task;com.goafanti.core.websocket" />
+		base-package="com.goafanti.*.controller;com.goafanti.common.task;com.goafanti.core.websocket" />
 
 	<bean name="springContextUtils" class="com.goafanti.common.utils.SpringContextUtils" scope="singleton"></bean>
-	
+
 	<bean id="passwordUtil" class="com.goafanti.common.utils.PasswordUtil">
-		<property name="algorithmName" value="${pwd.hash_algorithm_name}"/>  
-	    <property name="hashIterations" value="${pwd.hash_iterations}"/> 
+		<property name="algorithmName" value="${pwd.hash_algorithm_name}"/>
+	    <property name="hashIterations" value="${pwd.hash_iterations}"/>
+	</bean>
+	<bean id="redisUtils" class="com.goafanti.common.utils.RedisUtil">
+
 	</bean>
-	
+
 	<!-- spring bean validator -->
-	
+
 <!-- 配置注解驱动 -->
 	<mvc:annotation-driven validator="validator"></mvc:annotation-driven>
-	
+
 	<!-- 校验器 -->
 	<bean id="validator"
 		class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
@@ -36,8 +39,8 @@
 		<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
 		<!-- 指定校验使用的资源文件,在文件中配置校验错误信息,如果不指定则默认使用classpath下的ValidationMessages.properties -->
 		<property name="validationMessageSource" ref="messageSource" />
-	</bean>	
-	
+	</bean>
+
 	<!-- 校验错误信息配置文件 -->
 	<bean id="messageSource"
 		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
@@ -50,15 +53,15 @@
 	</bean>
 
 
-	<!-- Handles HTTP GET requests for /assets/** by efficiently serving up 
+	<!-- Handles HTTP GET requests for /assets/** by efficiently serving up
 		static resources in the ${webappRoot}/assets directory -->
 	<mvc:resources mapping="/static/images/**" location="/WEB-INF/images/" />
 	<mvc:resources mapping="/static/html/**" location="/WEB-INF/html/" />
 	<mvc:resources mapping="/static/**" location="/WEB-INF/build/" />
 	<mvc:resources mapping="/favicon.ico" location="/WEB-INF/assets/favicon.ico" />
 	<mvc:resources mapping="/robots.txt" location="/WEB-INF/assets/robots.txt" />
-	
-	<bean id="templateResolver" 
+
+	<bean id="templateResolver"
         class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
         <property name="prefix" value="/WEB-INF/views/" />
         <property name="suffix" value=".html" />
@@ -71,13 +74,13 @@
     <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
         <property name="templateResolver" ref="templateResolver" />
     </bean>
-    
+
     <!-- Simple strategy: only path extension is taken into account -->
     <bean id="cnManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
         <property name="favorPathExtension" value="true"/>
         <property name="ignoreAcceptHeader" value="true"/>
         <property name="defaultContentType" value="text/html"/>
-        
+
         <property name="mediaTypes">
             <map>
                 <entry key="html" value="text/html" />
@@ -86,7 +89,7 @@
             </map>
         </property>
     </bean>
-    
+
     <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
         <property name="contentNegotiationManager" ref="cnManager"/>
         <property name="viewResolvers">
@@ -143,5 +146,5 @@
 		<property name="appName" value="${app.name}" />
 	</bean>
 	<bean id="systemWebSocketHandler" class="com.goafanti.core.websocket.SystemWebSocketHandler" scope="singleton"></bean>
-	
-</beans>
+
+</beans>

+ 44 - 19
src/main/resources/spring/spring-shiro.xml

@@ -15,6 +15,20 @@
 		<property name="minIdle" value="10" />
 		<property name="testOnBorrow" value="true" />
 	</bean>
+	<bean id="poolConfig" class="org.apache.commons.pool2.impl.GenericObjectPoolConfig">
+		<property name="minIdle" value="5"/>
+		<property name="maxIdle" value="20"/>
+		<property name="maxWaitMillis" value="100000"/>
+		<property name="maxTotal" value="10000"/>
+	</bean>
+
+	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
+		<constructor-arg name="poolConfig" ref="poolConfig"/>
+		<constructor-arg name="host" value="${jedis.host}"/>
+		<constructor-arg name="port" value="${jedis.port}"/>
+		<constructor-arg name="password" value="${jedis.password}"/>
+		<constructor-arg name="timeout" value="1000000"/>
+	</bean>
 
 	<bean id="redisConnectionFactory"
 		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
@@ -32,33 +46,42 @@
 	<bean id="sessionRedisTemplate" class="com.goafanti.core.shiro.cache.template.SessionRedisTemplate">
 		<constructor-arg index="0" ref="redisConnectionFactory" />
 	</bean>
-	
-	<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
+
+<!--	<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">-->
+<!--		<constructor-arg index="0" ref="redisTemplate" />-->
+<!--		<property name="defaultExpiration" value="86400" />-->
+<!--	</bean>-->
+
+	<bean id="cacheManager"
+		  class="com.goafanti.core.cache.template.ExtendedRedisCacheManager">
 		<constructor-arg index="0" ref="redisTemplate" />
-		<property name="defaultExpiration" value="86400" />		
+		<property name="defaultExpiration" value="1800" />
 	</bean>
-	
+
 	<bean id="shrioRedisCacheManager" class="com.goafanti.core.shiro.cache.ShiroRedisCacheManager">
 		<property name="redisTemplate" ref="sessionRedisTemplate" />
 		<property name="expire" value="2592000" />
 	</bean>
-	
+
 	<!-- 环信 -->
-    <bean id="jedisQueueListener" class="com.goafanti.easemob.queue.EasemobRedisQueueListener"/>  
-    <bean id="jedisQueue" class="com.goafanti.easemob.queue.EasemobRedisQueue" destroy-method="destroy">  
-        <property name="redisTemplate" ref="redisTemplate"></property>  
-        <property name="key" value="easemob:queue"></property>  
-        <property name="listener" ref="jedisQueueListener"></property>  
-    </bean> 
+    <bean id="jedisQueueListener" class="com.goafanti.easemob.queue.EasemobRedisQueueListener"/>
+    <bean id="jedisQueue" class="com.goafanti.easemob.queue.EasemobRedisQueue" destroy-method="destroy">
+        <property name="redisTemplate" ref="redisTemplate"></property>
+        <property name="key" value="easemob:queue"></property>
+        <property name="listener" ref="jedisQueueListener"></property>
+    </bean>
+	<bean id="HttpUtils" class="com.goafanti.common.utils.HttpUtils"/>
+	<bean id="BaiduChatUtils" class="com.goafanti.common.utils.BaiduChatUtils"/>
     <bean id="easemobUtils" class="com.goafanti.easemob.EasemobUtils"/>
-      
+
+
 	<!-- 极光 -->
-    <bean id="messageQueueListener" class="com.goafanti.message.queue.MessageRedisQueueListener"/>  
-    <bean id="messageQueue" class="com.goafanti.message.queue.MessageRedisQueue" destroy-method="destroy">  
-        <property name="redisTemplate" ref="redisTemplate"></property>  
-        <property name="key" value="jgpush:queue"></property>  
-        <property name="listener" ref="messageQueueListener"></property>  
-    </bean> 
+    <bean id="messageQueueListener" class="com.goafanti.message.queue.MessageRedisQueueListener"/>
+    <bean id="messageQueue" class="com.goafanti.message.queue.MessageRedisQueue" destroy-method="destroy">
+        <property name="redisTemplate" ref="redisTemplate"></property>
+        <property name="key" value="jgpush:queue"></property>
+        <property name="listener" ref="messageQueueListener"></property>
+    </bean>
     <bean id="jgMessageHelper" class="com.goafanti.message.JGMessageHelper"/>
 
 	<bean id="sessionIdGenerator"
@@ -71,6 +94,8 @@
 		<!-- <property name="domain" value=""/> -->
 	</bean>
 
+
+
 	<bean id="customSessionListener" class="com.goafanti.core.shiro.listener.CustomSessionListener">
 		<property name="redisTemplate" ref="sessionRedisTemplate" />
 	</bean>
@@ -168,4 +193,4 @@
 	</bean>
 	<!-- -->
 	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
-</beans>
+</beans>

+ 64 - 0
src/main/webapp/WEB-INF/views/portal/answers.html

@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
+      xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+
+<head th:replace="common::header(~{::title},~{::link})">
+  <meta charset="utf-8" />
+  <title>技淘网-技淘百问</title>
+  <link th:href="${portalHost+'/dll/dll.css'}" rel="stylesheet">
+  <link th:href="${portalHost+'/vendors.css'}" rel="stylesheet">
+  <link rel="stylesheet" th:href="${portalHost+'/answers.css'}">
+  <!-- <link th:href="${portalHost+'/evaluation/evaluate.css'}" rel="stylesheet"></head> -->
+</head>
+
+<body>
+<!--<div th:replace="common::nav('','serviceIndex')"></div>-->
+
+<div class="container basic_info">
+  <div class="title">
+    <img class="logo" th:src="${portalHost + '/img/bwlogo.jpg'}">
+    <div>
+      <div>我是技淘百问</div>
+      <div>科德全新一代知识增强大语言模型</div>
+      <div>助您高效获取科研领域专业信息</div>
+    </div>
+  </div>
+
+  <div class="contentCenter">
+    <div class="basic_list" >
+      <div class="basic_ltit">
+        <div class="basic_icon"></div>
+        <span class="basic_tips">看看大家都在问什么?</span>
+      </div>
+      <div class="basic_items" th:each="e :${list}"   th:text="${e.content}">实用新型专利主要应用哪些领域?</div>
+    </div>
+    <div class="basic_chat">
+      <div class="chat_item">
+
+      </div>
+    </div>
+  </div>
+</div>
+<div class="basic_content">
+  <div class="basic_bottom">
+    <textarea id="textarea" placeholder="在这里输入问题..." size="large" maxlength="500" class="ant-input"></textarea>
+    <button type="button" class="ant-but">
+      <img th:src="${portalHost + '/img/send.svg'}">
+    </button>
+  </div>
+</div>
+<div class="smg"><input type="text" name="msg" value="" id="msg" /></div>
+<!-- 中间内容结束 -->
+<!--<footer>-->
+<!--  <div th:replace="common::copyright"></div>-->
+<!--  <div th:replace="common::login"></div>-->
+<!--</footer>-->
+<div th:replace="common::footer(~{::script})">
+  <script type="text/javascript" th:src="${portalHost + '/dll/dll.js'}"></script>
+  <script type="text/javascript" th:src="${portalHost + '/vendors.js'}"></script>
+  <script type="text/javascript" th:src="${portalHost+'/answers.js'}"></script>
+</div>
+</body>
+
+</html>
+

+ 2 - 2
src/main/webapp/WEB-INF/views/portal/index.html

@@ -150,10 +150,10 @@
 							<span class="newapply_ltxt">高企在线评估</span>
 						</div>
 					</a>
-					<a th:href="@{/user/signIn}" target="_blank">
+					<a th:href="@{portal/answers}" target="_blank">
 						<div class="newapply_listitem">
 							<img class="newapply_licon" th:src="${portalHost+'/img/newapply/rzffs.png'}" alt="" />
-							<span class="newapply_ltxt">入驻为服务商</span>
+							<span class="newapply_ltxt">技淘百问</span>
 						</div>
 					</a>
 					<a th:href="@{/portal/technologyTrading/achievementList}" target="_blank">

+ 54 - 0
src/main/webapp/WEB-INF/views/portal/test.html

@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<head>
+    <meta charset="UTF-8">
+    <title>测试</title>
+</head>
+<body>
+<div>服务器端推送测试</div>
+<div id="serverSendEventDiv"></div>
+</body>
+<script type="text/javascript">
+    if(window.EventSource) {
+        const source = new EventSource("//172.16.0.255:8080/chat/start?clientId=123");
+        let s = '';
+        // 监听打开连接
+        source.addEventListener('open', function (e) {
+            console.log("连接打开")
+        }, false);
+        source.addEventListener('message', function (e) {
+            s += e.data + '<br/>';
+            document.getElementById("serverSendEventDiv").innerHTML = s;
+        })
+        // 监听关闭连接
+        source.addEventListener('close', function (e) {
+            if (e.readyState === EventSource.CLOSED) {
+                console.log("连接关闭")
+            } else {
+                console.log(e.readyState)
+            }
+        }, false);
+        source.addEventListener("error", function(err) {
+            console.log(JSON.stringify(err))
+            console.log(err)
+            // 类似的返回信息验证,这里是实例
+            err && err.status === 401 && console.log('not authorized')
+        })
+    } else {
+        alert("你的浏览器不支持sse")
+    }
+</script>
+
+
+<!--<script>-->
+<!--    const evtSource = new EventSource("//172.16.0.255:8080//chat/start",{ withCredentials: true });-->
+
+<!--    evtSource.onmessage=function (event) {-->
+<!--        const newElement=document.createElement("li");-->
+<!--        const eventList=document.getElementById("list");-->
+
+<!--        newElement.innerHTML="message:"+event.data;-->
+<!--        eventList.append(newElement);-->
+<!--    }-->
+<!--</script>-->
+
+

+ 9 - 8
src/main/webapp/WEB-INF/web.xml

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee  
+	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                              http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
 	version="3.1">
 
 	<display-name>AFT</display-name>
 
-	<!-- The definition of the Root Spring Container shared by all Servlets 
+	<!-- The definition of the Root Spring Container shared by all Servlets
 		and Filters -->
 	<context-param>
 		<param-name>spring.profiles.active</param-name>
@@ -17,7 +17,7 @@
 	<listener>
 		<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
 	</listener>
-	
+
 	<filter>
 		<filter-name>CorsFilter</filter-name>
 		<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
@@ -78,22 +78,23 @@
 		<load-on-startup>1</load-on-startup>
 		<async-supported>true</async-supported>
 	</servlet>
-	
+
+
 	<!-- <servlet>
 		<servlet-name>DruidStatView</servlet-name>
 		<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
 		<init-param>
-			
+
 			<param-name>resetEnable</param-name>
 			<param-value>true</param-value>
 		</init-param>
 		<init-param>
-			
+
 			<param-name>loginUsername</param-name>
 			<param-value>druid</param-value>
 		</init-param>
 		<init-param>
-			
+
 			<param-name>loginPassword</param-name>
 			<param-value>aft@2016</param-value>
 		</init-param>
@@ -123,5 +124,5 @@
 		<error-code>500</error-code>
 		<location>/WEB-INF/views/error.jsp</location>
 	</error-page>
-	
+
 </web-app>