diff --git a/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/Base64Api.java b/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/Base64Api.java index 390cde1..c81af0a 100644 --- a/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/Base64Api.java +++ b/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/Base64Api.java @@ -4,7 +4,11 @@ import com.alibaba.fastjson2.JSONObject; import com.dc.app.domain.enums.PlatformTypeEnum; import com.dc.app.domain.request.GetDcTypeRequest; import com.dc.app.domain.response.NearbyDriverResponse; +import com.dc.common.config.DCConfig; import com.dc.common.core.domain.AjaxResult; +import com.dc.common.utils.file.FileUploadUtils; +import com.dc.common.utils.file.FileUtils; +import com.dc.framework.config.ServerConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -12,10 +16,14 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import javax.validation.Valid; +import java.io.File; import java.util.List; +import static com.dc.system.until.AsrV2.loadAsBase64; + @Slf4j @RestController @RequestMapping("/base64Api") @@ -24,6 +32,9 @@ public class Base64Api { @Autowired private RedisTemplate redisTemplate; + @Autowired + private ServerConfig serverConfig; + @PostMapping("inputBase64") public AjaxResult inputBase64(@RequestBody JSONObject query) { //创建uuid作为key存储 query中的base64 @@ -31,4 +42,32 @@ public class Base64Api { redisTemplate.opsForValue().set(uuid,query.getString("base64")); return AjaxResult.success("success",uuid); } + + /** + * 通用上传请求(单个) + */ + @PostMapping("/upload") + public AjaxResult uploadFile(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = DCConfig.getUploadPath(); + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + fileName = fileName.replace("/profile/upload", ""); + String url = serverConfig.getUrl() + fileName; + // 获取文件的 Base64 编码 + String path = filePath + File.separator + fileName; + path = path.replace("profile", ""); + String base64 = loadAsBase64(path); + AjaxResult ajax = AjaxResult.success(); + ajax.put("base64", base64); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } } diff --git a/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/ChatHttpApi.java b/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/ChatHttpApi.java new file mode 100644 index 0000000..60ac6f4 --- /dev/null +++ b/dc-Vue/dc-admin/src/main/java/com/dc/app/controller/ChatHttpApi.java @@ -0,0 +1,48 @@ +package com.dc.app.controller; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.dc.app.service.ChatService; +import com.dc.common.core.domain.AjaxResult; +import com.dc.system.mapper.SysConfigMapper; +import com.dc.system.until.AuthV3Util; +import com.dc.system.until.HttpUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: 聊天界面 + * @Author: 86187 + * @Date: 2025/03/06 15:37 + * @Version: 1.0 + */ +@RestController +@RequestMapping("/chatHttpApi") +public class ChatHttpApi { + @Autowired + private ChatService chatService; + + /** + * 翻译 + * @param requestData + * @return + * @throws Exception + */ + @PostMapping("/getChatInfo") + public AjaxResult getChatInfo(@RequestBody Map requestData) throws Exception { + if ("Chinese".equals(requestData.get("lang").toString())) { + return AjaxResult.success(requestData.get("q").toString()); + } + requestData.put("to", "zh-CHS"); + return AjaxResult.success(chatService.textTranslators(requestData)); + } +} diff --git a/dc-Vue/dc-admin/src/main/java/com/dc/app/service/ChatService.java b/dc-Vue/dc-admin/src/main/java/com/dc/app/service/ChatService.java index c8db41c..f381b16 100644 --- a/dc-Vue/dc-admin/src/main/java/com/dc/app/service/ChatService.java +++ b/dc-Vue/dc-admin/src/main/java/com/dc/app/service/ChatService.java @@ -1,18 +1,20 @@ package com.dc.app.service; -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.TimeUnit; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.dc.app.controller.ChatApi; +import com.dc.common.core.domain.AjaxResult; import com.dc.system.mapper.SysConfigMapper; +import com.dc.system.until.AuthV3Util; +import com.dc.system.until.HttpUtil; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Autowired; @@ -68,9 +70,10 @@ public class ChatService { put("Swedish", "sv"); put("Thai", "th"); put("Turkish", "tr"); + put("Chinese", "zh-CHS"); }}; - private static Map sendFlagMap =new HashMap<>(); + private static Map sendFlagMap = new HashMap<>(); @Autowired private RedisTemplate redisTemplate; private final OkHttpClient client = new OkHttpClient.Builder() @@ -80,44 +83,102 @@ public class ChatService { public void sendChatRequest(JSONObject requestData) { try { - if (requestData.getJSONObject("inputs").getString("type").equals("image")||requestData.getJSONObject("inputs").getString("type").equals("voice")){ - requestData.put("query",redisTemplate.opsForValue().get(requestData.getString("query"))); - } - if (requestData.getJSONObject("inputs").getString("type").equals("voice")){ - String appKey = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_KEY"); - String appSecret = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_SECRET"); - //如果是语言则直接走有道自己进行翻译 不需要走大模型 - Map params = new HashMap(); - String langType = langMap.get(requestData.getJSONObject("inputs").getString("lang")); - params.put("appKey", appKey); - String q = requestData.getString("query"); - params.put("q", q); - params.put("format", "wav"); - params.put("rate", "16000"); - params.put("channel", "1"); - params.put("docType", "json"); - params.put("type", "1"); - String salt = UUID.randomUUID().toString(); - params.put("salt", salt); - params.put("langType", langType); - String curtime = String.valueOf(System.currentTimeMillis() / 1000); - params.put("curtime", curtime); - String signStr = appKey + truncate(q) + salt + curtime + appSecret; - String sign = getDigest(signStr); - params.put("sign", sign); - params.put("signType", "v2"); - JSONObject res = JSONObject.parseObject(doRequest("https://openapi.youdao.com/asrapi", params)); - if(res.getString("errorCode").equals("0")){ - JSONArray jsonArray = res.getJSONArray("result"); - requestData.put("query",jsonArray.get(0)); - JSONObject temp =new JSONObject(); - temp.put("type","text"); - requestData.put("inputs",temp); - } + Map requestMap = new HashMap<>(); + requestMap.put("q", requestData.getString("query")); + requestMap.put("lang", requestData.getJSONObject("inputs").getString("sayLang")); + requestMap.put("to", langMap.get(requestData.getJSONObject("inputs").getString("lang"))); + if ("Bearer app-EcJaT2EkUjHNJsax9SwESQuK".equals(requestData.getString("token"))) { + if (requestData.getJSONObject("inputs").getString("type").equals("image")) {// || requestData.getJSONObject("inputs").getString("type").equals("voice") +// requestData.put("query", redisTemplate.opsForValue().get(requestData.getString("query"))); + requestMap.put("q", redisTemplate.opsForValue().get(requestData.getString("query"))); + JSONObject jsonObject = imageTranslators(requestMap); + String answer = jsonObject.getString("render_image"); + JSONArray resRegionsArray = jsonObject.getJSONArray("resRegions"); + List javaList = resRegionsArray.toJavaList(String.class); + String tranContent = ""; + for (String s : javaList) { + JSONObject jsonObject1 = JSONObject.parseObject(s); + String string = jsonObject1.getString("tranContent"); + tranContent = string + "\n" + tranContent; + } + Map map = new HashMap(); + map.put("answer", answer); + map.put("tranContent", tranContent); + // 将 Map 转换为 JSON + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(map); + chatApi.sendMessage(jsonString, requestData.getString("socketId")); + return; + } + if (requestData.getJSONObject("inputs").getString("type").equals("voice")) { + String sayLang = requestData.getJSONObject("inputs").getString("sayLang"); + String lang = requestData.getJSONObject("inputs").getString("lang"); + String appKey = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_KEY"); + String appSecret = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_SECRET"); + //如果是语言则直接走有道自己进行翻译 不需要走大模型 + Map params = new HashMap(); + params.put("appKey", appKey); + String q = redisTemplate.opsForValue().get(requestData.getString("query")); + params.put("q", q); + params.put("format", "mp3"); + params.put("rate", "16000"); + params.put("channel", "1"); + params.put("docType", "json"); + params.put("type", "1"); + String salt = UUID.randomUUID().toString(); + params.put("salt", salt); + params.put("langType", requestData.getJSONObject("inputs").getString("sayLang")); + String curtime = String.valueOf(System.currentTimeMillis() / 1000); + params.put("curtime", curtime); + String signStr = appKey + truncate(q) + salt + curtime + appSecret; + String sign = getDigest(signStr); + params.put("sign", sign); + params.put("signType", "v2"); + JSONObject res = JSONObject.parseObject(doRequest("https://openapi.youdao.com/asrapi", params)); + if (res.getString("errorCode").equals("0")) { + JSONArray result = res.getJSONArray("result"); + if (result != null && !result.isEmpty()) { + String resultStr = String.join(",", result.toJavaList(String.class)); + JSONArray jsonArray = res.getJSONArray("result"); + requestData.put("query", resultStr); + JSONObject temp = new JSONObject(); + temp.put("type", "text"); + temp.put("lang", requestData.getJSONObject("inputs").getString("lang")); + requestData.put("inputs", temp); + //翻译 + Map data = new HashMap<>(); + data.put("q", new String[]{resultStr}); + data.put("from", new String[]{sayLang}); + data.put("to", new String[]{langMap.get(lang).toString()}); + AuthV3Util.addAuthParams(appKey, appSecret, data); + byte[] result1 = HttpUtil.doPost("https://openapi.youdao.com/api", null, data, "application/json"); + // 打印返回结果 + if (result != null) { + JSONObject jsonObject = JSONObject.parseObject(new String(result1, StandardCharsets.UTF_8)); + // 获取translation数组 + JSONArray translationArray = jsonObject.getJSONArray("translation"); + String join = String.join(",", translationArray.toJavaList(String.class)); + chatApi.sendMessage(join, requestData.getString("socketId")); + } + } + } + return; + } else if (requestData.getJSONObject("inputs").getString("type").equals("text")) { + try { + String result = textTranslators(requestMap); + chatApi.sendMessage(result, requestData.getString("socketId")); + } catch (Exception e) { + e.printStackTrace(); + } finally { + return; + } + } + return; } String url = "http://flintown.cn:8080/v1/chat-messages"; MediaType mediaType = MediaType.parse("application/json; charset=utf-8"); + log.info("Request body: {}", requestData.toJSONString()); RequestBody body = RequestBody.create(mediaType, requestData.toJSONString()); Request request = new Request.Builder() @@ -168,8 +229,20 @@ public class ChatService { showToast("Request failed"); } } + + public static boolean base64ToFile(String base64, String filePath) { + try (FileOutputStream fos = new FileOutputStream(filePath)) { + byte[] decodedBytes = Base64.getDecoder().decode(base64); + fos.write(decodedBytes); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + // 处理 SSE 事件 - private void processSseEvent(String event,String socketId) { + private void processSseEvent(String event, String socketId) { if (event.startsWith("data: ")) { String data = event.substring("data: ".length()).trim(); if (!data.isEmpty()) { @@ -181,16 +254,16 @@ public class ChatService { chatApi.sendMessage(answer, socketId); } - if (jsonData.containsKey("conversation_id")&&sendFlagMap.get(socketId).equals("0")) { + if (jsonData.containsKey("conversation_id") && sendFlagMap.get(socketId).equals("0")) { String conversation_id = jsonData.getString("conversation_id"); System.out.println("New conversation_id: " + conversation_id); - JSONObject res =new JSONObject(); - res.put("conversation_id",conversation_id); + JSONObject res = new JSONObject(); + res.put("conversation_id", conversation_id); chatApi.sendMessage(JSONObject.toJSONString(res), socketId); - sendFlagMap.put(socketId,"1"); + sendFlagMap.put(socketId, "1"); } - if (jsonData.containsKey("event")&&jsonData.getString("event").equals("workflow_finished")) { - String answer ="workflow_finished"; + if (jsonData.containsKey("event") && jsonData.getString("event").equals("workflow_finished")) { + String answer = "workflow_finished"; System.out.println("end answer: " + answer); chatApi.sendMessage(answer, socketId); @@ -199,18 +272,17 @@ public class ChatService { System.out.println("Parse error: " + e.getMessage()); } } - }else{ + } else { try { JSONObject jsonObject = JSONObject.parseObject(event); - if (jsonObject.getString("event").equals("message")){ + if (jsonObject.getString("event").equals("message")) { JSONObject answer1 = jsonObject.getJSONObject("answer"); String response = answer1.getString("response"); System.out.println("New answer: " + response); chatApi.sendMessage(response, socketId); - } - }catch (Exception e){ + } catch (Exception e) { } } @@ -222,6 +294,66 @@ public class ChatService { System.out.println("Toast: " + message); } + /** + * 有道翻译(文本) + * + * @param requestData + * @return + * @throws Exception + */ + public String textTranslators(Map requestData) throws Exception { + requestData.put("url", "https://openapi.youdao.com/api"); + JSONObject jsonObject = translatorsCommon(requestData); + // 获取translation数组 + JSONArray translationArray = jsonObject.getJSONArray("translation"); + return String.join(",", translationArray.toJavaList(String.class)); + } + + /** + * 有道翻译(图片) + * + * @param requestData + * @return + * @throws Exception + */ + public JSONObject imageTranslators(Map requestData) throws Exception { + requestData.put("url", "https://openapi.youdao.com/ocrtransapi"); + requestData.put("render", "1"); + JSONObject jsonObject = translatorsCommon(requestData); + return jsonObject; + } + + + /** + * 有道通用调用接口 + * + * @param requestData 请求数据 + * @return + * @throws Exception + */ + public JSONObject translatorsCommon(Map requestData) throws Exception { + String appKey = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_KEY"); + String appSecret = sysConfigMapper.getcheckConfigKeyUnique("YOUDAO_APP_SECRET"); + //翻译 + Map data = new HashMap<>(); + data.put("q", new String[]{requestData.get("q")}); + data.put("from", new String[]{requestData.get("lang")}); + if (requestData.get("to") != null) { + data.put("to", new String[]{requestData.get("to")}); + } + // 图片翻译时需要的参数 + if (requestData.get("render") != null) { + data.put("render", new String[]{requestData.get("render")}); + } + AuthV3Util.addAuthParams(appKey, appSecret, data); + byte[] result1 = HttpUtil.doPost(requestData.get("url"), null, data, "application/json"); + // 打印返回结果 + if (result1 != null) { + return JSONObject.parseObject(new String(result1, StandardCharsets.UTF_8)); + } + return null; + } + public static void main(String[] args) { ChatService chatService = new ChatService(); diff --git a/dc-Vue/dc-admin/src/main/java/com/dc/system/until/AuthV3Util.java b/dc-Vue/dc-admin/src/main/java/com/dc/system/until/AuthV3Util.java new file mode 100644 index 0000000..87ac33b --- /dev/null +++ b/dc-Vue/dc-admin/src/main/java/com/dc/system/until/AuthV3Util.java @@ -0,0 +1,90 @@ +package com.dc.system.until; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.UUID; + +public class AuthV3Util { + + /** + * 添加鉴权相关参数 - + * appKey : 应用ID + * salt : 随机值 + * curtime : 当前时间戳(秒) + * signType : 签名版本 + * sign : 请求签名 + * + * @param appKey 您的应用ID + * @param appSecret 您的应用密钥 + * @param paramsMap 请求参数表 + */ + public static void addAuthParams(String appKey, String appSecret, Map paramsMap) + throws NoSuchAlgorithmException { + String[] qArray = paramsMap.get("q"); + if (qArray == null) { + qArray = paramsMap.get("img"); + } + StringBuilder q = new StringBuilder(); + for (String item : qArray) { + q.append(item); + } + String salt = UUID.randomUUID().toString(); + String curtime = String.valueOf(System.currentTimeMillis() / 1000); + String sign = calculateSign(appKey, appSecret, q.toString(), salt, curtime); + paramsMap.put("appKey", new String[]{appKey}); + paramsMap.put("salt", new String[]{salt}); + paramsMap.put("curtime", new String[]{curtime}); + paramsMap.put("signType", new String[]{"v3"}); + paramsMap.put("sign", new String[]{sign}); + } + + /** + * 计算鉴权签名 - + * 计算方式 : sign = sha256(appKey + input(q) + salt + curtime + appSecret) + * + * @param appKey 您的应用ID + * @param appSecret 您的应用密钥 + * @param q 请求内容 + * @param salt 随机值 + * @param curtime 当前时间戳(秒) + * @return 鉴权签名sign + */ + public static String calculateSign(String appKey, String appSecret, String q, String salt, String curtime) + throws NoSuchAlgorithmException { + String strSrc = appKey + getInput(q) + salt + curtime + appSecret; + return encrypt(strSrc); + } + + private static String encrypt(String strSrc) throws NoSuchAlgorithmException { + byte[] bt = strSrc.getBytes(); + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(bt); + byte[] bts = md.digest(); + StringBuilder des = new StringBuilder(); + for (byte b : bts) { + String tmp = (Integer.toHexString(b & 0xFF)); + if (tmp.length() == 1) { + des.append("0"); + } + des.append(tmp); + } + return des.toString(); + } + + private static String getInput(String input) { + if (input == null) { + return null; + } + String result; + int len = input.length(); + if (len <= 20) { + result = input; + } else { + String startStr = input.substring(0, 10); + String endStr = input.substring(len - 10, len); + result = startStr + len + endStr; + } + return result; + } +} diff --git a/dc-Vue/dc-admin/src/main/java/com/dc/system/until/HttpUtil.java b/dc-Vue/dc-admin/src/main/java/com/dc/system/until/HttpUtil.java new file mode 100644 index 0000000..abc1d1b --- /dev/null +++ b/dc-Vue/dc-admin/src/main/java/com/dc/system/until/HttpUtil.java @@ -0,0 +1,103 @@ +package com.dc.system.until; + +import okhttp3.FormBody; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Objects; + +public class HttpUtil { + + private static OkHttpClient httpClient = new OkHttpClient.Builder().build(); + + public static byte[] doGet(String url, Map header, Map params, String expectContentType) { + Request.Builder builder = new Request.Builder(); + addHeader(builder, header); + addUrlParam(builder, url, params); + return requestExec(builder.build(), expectContentType); + } + + public static byte[] doPost(String url, Map header, Map body, String expectContentType) { + Request.Builder builder = new Request.Builder().url(url); + addHeader(builder, header); + addBodyParam(builder, body, "POST"); + return requestExec(builder.build(), expectContentType); + } + + private static void addHeader(Request.Builder builder, Map header) { + if (header == null) { + return; + } + for (String key : header.keySet()) { + String[] values = header.get(key); + if (values != null) { + for (String value : values) { + builder.addHeader(key, value); + } + } + } + } + + private static void addUrlParam(Request.Builder builder, String url, Map params) { + if (params == null) { + return; + } + HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder(); + for (String key : params.keySet()) { + String[] values = params.get(key); + if (values != null) { + for (String value : values) { + urlBuilder.addQueryParameter(key, value); + } + } + } + builder.url(urlBuilder.build()); + } + + private static void addBodyParam(Request.Builder builder, Map body, String method) { + if (body == null) { + return; + } + FormBody.Builder formBodyBuilder = new FormBody.Builder(StandardCharsets.UTF_8); + for (String key : body.keySet()) { + String[] values = body.get(key); + if (values != null) { + for (String value : values) { + formBodyBuilder.add(key, value); + } + } + } + builder.method(method, formBodyBuilder.build()); + } + + private static byte[] requestExec(Request request, String expectContentType) { + Objects.requireNonNull(request, "okHttp request is null"); + + try (Response response = httpClient.newCall(request).execute()) { + if (response.code() == 200) { + ResponseBody body = response.body(); + if (body != null) { + String contentType = response.header("Content-Type"); + if (contentType != null && !contentType.contains(expectContentType)) { + String res = new String(body.bytes(), StandardCharsets.UTF_8); + System.out.println(res); + return null; + } + return body.bytes(); + } + System.out.println("response body is null"); + } else { + System.out.println("request failed, http code: " + response.code()); + } + } catch (IOException ioException) { + System.out.println("request exec error: " + ioException.getMessage()); + } + return null; + } +} diff --git a/dc-Vue/dc-common/src/main/java/com/dc/common/utils/file/MimeTypeUtils.java b/dc-Vue/dc-common/src/main/java/com/dc/common/utils/file/MimeTypeUtils.java index ca15022..5e91350 100644 --- a/dc-Vue/dc-common/src/main/java/com/dc/common/utils/file/MimeTypeUtils.java +++ b/dc-Vue/dc-common/src/main/java/com/dc/common/utils/file/MimeTypeUtils.java @@ -36,7 +36,8 @@ public class MimeTypeUtils // 视频格式 "mp4", "avi", "rmvb", // pdf - "pdf" }; + "pdf", + "mp3"}; public static String getExtension(String prefix) {