TakaiAiServiceImpl.java 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844
  1. package com.takai.ai.service.impl;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONArray;
  4. import com.alibaba.fastjson2.JSONObject;
  5. import com.github.pagehelper.PageHelper;
  6. import com.takai.ai.domain.TakaiSysOss;
  7. import com.takai.ai.domain.dto.*;
  8. import com.takai.ai.domain.entity.*;
  9. import com.takai.ai.mapper.*;
  10. import com.takai.ai.service.IMinioConfigService;
  11. import com.takai.ai.service.ITakaiAiService;
  12. import com.takai.ai.utils.*;
  13. import com.takai.common.annotation.DataScope;
  14. import com.takai.common.annotation.DataSource;
  15. import com.takai.common.config.DeepseekConfig;
  16. import com.takai.common.constant.UserConstants;
  17. import com.takai.common.core.domain.entity.SysDictData;
  18. import com.takai.common.core.domain.entity.SysUser;
  19. import com.takai.common.core.domain.model.LoginUser;
  20. import com.takai.common.core.redis.RedisCache;
  21. import com.takai.common.enums.AppTypeEnum;
  22. import com.takai.common.enums.DataSourceType;
  23. import com.takai.common.utils.SecurityUtils;
  24. import com.takai.common.utils.StringUtils;
  25. import com.takai.common.utils.uuid.IdUtils;
  26. import com.takai.framework.web.service.SysPermissionService;
  27. import com.takai.system.domain.*;
  28. import com.takai.system.mapper.*;
  29. import com.takai.system.service.ISysUserService;
  30. import lombok.extern.slf4j.Slf4j;
  31. import okhttp3.*;
  32. import okhttp3.sse.EventSource;
  33. import okhttp3.sse.EventSourceListener;
  34. import okhttp3.sse.EventSources;
  35. import org.apache.commons.collections4.MapUtils;
  36. import org.slf4j.Logger;
  37. import org.slf4j.LoggerFactory;
  38. import org.springframework.beans.BeanUtils;
  39. import org.springframework.beans.factory.annotation.Autowired;
  40. import org.springframework.data.redis.core.RedisTemplate;
  41. import org.springframework.stereotype.Service;
  42. import org.springframework.web.multipart.MultipartFile;
  43. import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  44. import javax.validation.constraints.NotNull;
  45. import java.io.IOException;
  46. import java.nio.charset.StandardCharsets;
  47. import java.time.LocalDate;
  48. import java.time.LocalDateTime;
  49. import java.time.temporal.ChronoUnit;
  50. import java.util.*;
  51. import java.util.concurrent.TimeUnit;
  52. import java.util.stream.Collectors;
  53. /**
  54. * 高井 业务层处理
  55. *
  56. * @author takai
  57. */
  58. @Slf4j
  59. @Service
  60. @DataSource(DataSourceType.MASTER)
  61. public class TakaiAiServiceImpl implements ITakaiAiService {
  62. private static final Logger logger = LoggerFactory.getLogger(TakaiAiServiceImpl.class);
  63. @Autowired
  64. private TakaiDialogMapper takaiDialogMapper;
  65. @Autowired
  66. private TakaiApplicationMapper takaiApplicationMapper;
  67. @Autowired
  68. private TakaiQuestionMapper takaiQuestionMapper;
  69. @Autowired
  70. private TakaiKnowledgeMapper takaiKnowledgeMapper;
  71. @Autowired
  72. private TakaiDocumentMapper takaiDocumentMapper;
  73. @Autowired
  74. private TakaiSysOssConfigMapper takaiSysOssConfigMapper;
  75. @Autowired
  76. private TakaiSysOssMapper takaiSysOssMapper;
  77. @Autowired
  78. private MinioUtil minioUtil;
  79. @Autowired
  80. private TakaiDocumentSettingsMapper takaiDocumentSettingsMapper;
  81. @Autowired
  82. private DeepseekConfig deepseekConfig;
  83. @Autowired
  84. private TakaiAppInfoMapper takaiAppInfoMapper;
  85. @Autowired
  86. private TakaiMediaReplacementMapper takaiMediaReplacementMapper;
  87. @Autowired
  88. private RedisCache redisCache;
  89. @Autowired
  90. public RedisTemplate redisTemplate;
  91. @Autowired
  92. private TakaiSliceInfoMapper takaiSliceInfoMapper;
  93. @Autowired
  94. private DocumentAuditConfigMapper documentAuditConfigMapper;
  95. @Autowired
  96. private DocumentAuditInfoMapper documentAuditInfoMapper;
  97. @Autowired
  98. private SysPermissionService permissionService;
  99. @Autowired
  100. private TypeAppMapper appTypeMapper;
  101. @Autowired
  102. private TakaiAppCollectMapper appCollectMapper;
  103. @Autowired
  104. private SysDictDataMapper sysDictDataMapper;
  105. @Autowired
  106. private SysProjectAppMapper sysProjectAppMapper;
  107. @Autowired
  108. private TakaiFileInfoMapper fileInfoMapper;
  109. @Autowired
  110. private Base64DecodeUtil base64DecodeUtil;
  111. public static final String START_SIGN = "【";
  112. public static final String END_SIGN = "】";
  113. public static final String SYMBOL = "【示意图序号";
  114. public static final String USER_STR = "user";
  115. public static final String TODAY = "今日";
  116. public static final String BEFOR = "日前";
  117. private final String OSS_URL= "https://minio.jkec.info:9000";
  118. @Autowired
  119. private SysProjectMapper sysProjectMapper;
  120. @Autowired
  121. private ISysUserService userService;
  122. @Override
  123. public void initDeepseekInfo() {
  124. //获取应用列表
  125. // List<TakaiApplication> appList = takaiApplicationMapper.selectApplicationList(null);
  126. setRedisCache(null);
  127. }
  128. private void setRedisCache(String knowledgeId) {
  129. //获取知识库列表
  130. List<TakaiKnowledge> knowledgeList = null;
  131. if (StringUtils.isEmpty(knowledgeId)) {
  132. knowledgeList = takaiKnowledgeMapper.selectAllKnowledgeList(null);
  133. } else {
  134. knowledgeList = takaiKnowledgeMapper.selectAllKnowledgeList(TakaiKnowledge.builder().knowledgeId(knowledgeId).build());
  135. }
  136. //获取知识列表
  137. if (!knowledgeList.isEmpty()) {
  138. for (TakaiKnowledge bmKnowledge : knowledgeList) {
  139. TakaiDocument conditon = TakaiDocument.builder().knowledgeId(bmKnowledge.getKnowledgeId()).build();
  140. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(conditon);
  141. if (!documentList.isEmpty()) {
  142. for (TakaiDocument bmDocument : documentList) {
  143. //获取知识图片列表
  144. TakaiMediaReplacement conditonR = TakaiMediaReplacement.builder().documentId(bmDocument.getDocumentId()).build();
  145. List<TakaiMediaReplacement> imageList = takaiMediaReplacementMapper.selectMediaList(conditonR);
  146. if (!imageList.isEmpty()) {
  147. for (TakaiMediaReplacement image : imageList) {
  148. redisCache.setCacheObject(image.getOriginText(), image.getMediaUrl());
  149. }
  150. }
  151. }
  152. }
  153. }
  154. }
  155. }
  156. @Override
  157. public SseEmitter sseInvoke(TakaiSseInfoParams sseParams) {
  158. TakaiApplication appInfo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(sseParams.getAppId()).build());
  159. if (appInfo != null) {
  160. List<String> idList = Arrays.stream(appInfo.getKnowledgeIds().split(",")) // 按「逗号+空格」拆分字符串为数组
  161. .filter(str -> str != null && !str.trim().isEmpty()) // 过滤 null 和空字符串(防异常)
  162. .collect(Collectors.toList());
  163. TakaiKnowledge knowledgeParam = TakaiKnowledge.builder().knowledgeIds(idList).build();
  164. List<TakaiKnowledge> knowledgeList = takaiKnowledgeMapper.selectAllKnowledgeList(knowledgeParam);
  165. if (knowledgeList != null && !knowledgeList.isEmpty()) {
  166. SseEmitter sseEmitter = new SseEmitter(0L);
  167. String url = deepseekConfig.getBaseurl() + deepseekConfig.getChat();
  168. TakaiAppInfo info = takaiAppInfoMapper.selectAppInfoByAppId(sseParams.getAppId());
  169. JSONObject json = JSONObject.parseObject(info.getAppInfo());
  170. //重新设置knowledgeIds为数组
  171. json.put("knowledgeIds",idList);
  172. String query = null;
  173. decodeMessage(sseParams.getMessages());
  174. decodeMessage(sseParams.getPrompt());
  175. if(sseParams.getMessages() != null && !sseParams.getMessages().isEmpty() ) {
  176. query = sseParams.getMessages().get(sseParams.getMessages().size() - 1).getContent();
  177. } else {
  178. query = sseParams.getPrompt().get(sseParams.getPrompt().size() - 1).getContent();
  179. }
  180. log.info("deepseek聊天请求参数:" + query);
  181. json.put("query", query);
  182. json.put("embeddingId", knowledgeList.get(0).getEmbeddingId());
  183. if(UserConstants.YES.equals(json.getString("isDeepThink"))) {
  184. json.put("enable_think", true);
  185. } else {
  186. json.put("enable_think", false);
  187. }
  188. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toJSONString());
  189. Request request = buildPostRequest(url, requestBody);
  190. // 使用EventSourceListener处理来自服务器的SSE事件
  191. EventSourceListener listener = new EventSourceListener() {
  192. private String preData = "";
  193. //图片识别
  194. private String symbolData = "";
  195. @Override
  196. public void onOpen(@NotNull EventSource eventSource, @NotNull Response response) {
  197. log.info("deepseek Connection opened. Headers: {}", response.headers());
  198. log.info("deepseek Request URL: {}", response.request().url());
  199. }
  200. @Override
  201. public void onClosed(@NotNull EventSource eventSource) {
  202. log.info("deepseek Connection closed.");
  203. sseEmitter.complete();
  204. }
  205. @Override
  206. public void onEvent(@NotNull EventSource eventSource, String id, String type, @NotNull String data) {
  207. if (!StringUtils.isEmpty(data)) {
  208. String newData = data.substring(preData.length());
  209. logger.info("deepseek聊天返回消息:" + data);
  210. preData = data;
  211. if (newData.indexOf(START_SIGN) > -1 || symbolData.length() > 0) {
  212. symbolData = symbolData + newData;
  213. //接收到了完整的图片标识
  214. int endSignPos = symbolData.indexOf(END_SIGN);
  215. if (endSignPos > -1) {
  216. JSONObject json = new JSONObject();
  217. json.put("id", id);
  218. json.put("event", "add");
  219. //是图片
  220. if (symbolData.indexOf(SYMBOL) > -1) {
  221. //获取完整Key
  222. int startPos = symbolData.indexOf(START_SIGN);
  223. int endPos = symbolData.indexOf(END_SIGN) + 1;
  224. String key = symbolData.substring(startPos, endPos);
  225. String url = redisCache.getCacheObject(key);
  226. if (org.springframework.util.StringUtils.hasText(url)) {
  227. if(url.contains("https://10.1.28.14:9000")){
  228. //url = url.replace("https://10.1.28.14:9000", "https://minio.jkec.info:9000");
  229. url = url.replace("https://10.1.28.14:9000", OSS_URL);
  230. }
  231. //匹配markdown图片格式
  232. // symbolData = symbolData.replace(key, "![](" + url + ")");
  233. } else {
  234. logger.error("图片标识符"+key+"没有获取到对应的URL{}: " + symbolData);
  235. }
  236. //检查是否当前token包含其他图片的开始符号”【“
  237. int lastPos = symbolData.lastIndexOf(START_SIGN);
  238. if(lastPos > endSignPos){
  239. // 从'【' 开始截取
  240. newData = symbolData.substring(0, lastPos);
  241. symbolData = symbolData.substring(lastPos);
  242. logger.info("截取结果{}: " + symbolData);
  243. } else {
  244. newData = symbolData;
  245. symbolData = "";
  246. }
  247. if(!StringUtils.isEmpty(url)) {
  248. newData = newData.replace(key, " ![](" + url + ")");
  249. }
  250. } else {
  251. newData = symbolData;
  252. symbolData = "";
  253. }
  254. json.put("data", newData);
  255. log.info("获取到图片替换结束符号,返回前端信息:" + json);
  256. send(sseEmitter, json);
  257. //如果超过长度200还没收到】符号,直接返回。
  258. } else if (symbolData.length() > 200) {
  259. JSONObject json = new JSONObject();
  260. json.put("id", id);
  261. json.put("event", "add");
  262. json.put("data", symbolData);
  263. }
  264. } else {
  265. JSONObject json = new JSONObject();
  266. json.put("id", id);
  267. json.put("event", type);
  268. json.put("data", newData);
  269. log.info("deepseek返回信息:" + json);
  270. send(sseEmitter, json);
  271. }
  272. }
  273. if (com.takai.common.utils.StringUtils.isNotEmpty(type) && "finish".equals(type)) {
  274. log.info("deepseek聊天结束");
  275. JSONObject json = new JSONObject();
  276. json.put("id", id);
  277. json.put("event", type);
  278. json.put("data", data);
  279. log.info("deepseek返回信息:" + json);
  280. send(sseEmitter, json);
  281. }
  282. }
  283. @Override
  284. public void onFailure(@NotNull EventSource eventSource, Throwable t, Response response) {
  285. if (response != null) {
  286. log.error("deepseek Connection failed. Response code: {}, message: {}, body: {}",
  287. response.code(), response.message(), response.body() != null ? response.body().toString() : "null");
  288. } else {
  289. log.error("deepseek Connection failed with no response", t);
  290. }
  291. sseEmitter.completeWithError(t);
  292. }
  293. private void send(SseEmitter sseEmitter, Object obj) {
  294. try {
  295. sseEmitter.send(obj);
  296. } catch (IOException e) {
  297. log.error("deepseek 推送数据失败", e);
  298. }
  299. }
  300. };
  301. OkHttpClient client = buildOkHttpClient();
  302. EventSource.Factory factory = EventSources.createFactory(client);
  303. final EventSource eventSources = factory.newEventSource(request, listener);
  304. // 客户端主动关闭连接
  305. sseEmitter.onCompletion(() -> {
  306. logger.info("deepseek客户端主动关闭连接 -- SSE 连接关闭");
  307. });
  308. // 超时回调
  309. sseEmitter.onTimeout(() -> {
  310. logger.info("deepseek客户端连接超时 -- SSE 连接关闭");
  311. if(eventSources != null) {
  312. logger.info("deepseek超时回调 -- 成功关闭SSE连接 ");
  313. eventSources.cancel();
  314. }
  315. });
  316. // 错误回调
  317. sseEmitter.onError(e -> {
  318. logger.info("deepseek客户端回调失败 -- SSE 连接关闭");
  319. if(eventSources != null) {
  320. logger.info("deepseek错误回调 -- 成功关闭SSE连接 ");
  321. eventSources.cancel();
  322. }
  323. });
  324. return sseEmitter;
  325. }
  326. }
  327. return null;
  328. }
  329. private void decodeMessage(List<TakaiPromptInfo> messages) {
  330. if(messages == null || messages.isEmpty()) {
  331. return;
  332. }
  333. for (TakaiPromptInfo message : messages) {
  334. message.setContent(base64DecodeUtil.decodeIfNeeded(message.getContent()));
  335. }
  336. }
  337. @Override
  338. public List<String> asyncCompletions(TakaiCompletionsParams params) {
  339. List<String> list = new ArrayList<>();
  340. TakaiApplication vo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(params.getAppId()).build());
  341. if (vo != null) {
  342. TakaiPromptInfo info = new TakaiPromptInfo();
  343. info.setContent(deepseekConfig.getPrompt());
  344. info.setRole("user");
  345. decodeMessage(params.getMessages());
  346. params.getMessages().add(info);
  347. JSONObject jsonObject = new JSONObject();
  348. jsonObject.put("model", vo.getModel());
  349. jsonObject.put("messages", params.getMessages());
  350. jsonObject.put("chat_id", params.getChat_id());
  351. JSONObject result = getasyncCompletions(jsonObject);
  352. if (result != null && result.getInteger("code") == 200) {
  353. JSONArray array = result.getJSONArray("data");
  354. if(array != null){
  355. list.addAll(array.toJavaList(String.class));
  356. }
  357. }
  358. }
  359. return list;
  360. }
  361. private JSONObject getasyncCompletions(JSONObject jsonObject) {
  362. String url = deepseekConfig.getBaseurl() + deepseekConfig.getAsyncCompletions();
  363. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toJSONString());
  364. Request request = buildPostRequest(url, requestBody);
  365. OkHttpClient client = buildOkHttpClient();
  366. try {
  367. Response response = client.newCall(request).execute();
  368. if (response.isSuccessful()) {
  369. String body = response.body().string();
  370. if (isJsonObject(body)) {
  371. return JSON.parseObject(body);
  372. }
  373. }
  374. } catch (IOException e) {
  375. log.info("deepseek Request URL: {}", e.getMessage());
  376. }
  377. return null;
  378. }
  379. @Override
  380. public List<TakaiDialogRespDTO> getDialogDetail(String dialogId) {
  381. List<TakaiDialogRespDTO> detail = takaiDialogMapper.selectDialogDetail(dialogId);
  382. if(detail != null && detail.size() != 0){
  383. for(TakaiDialogRespDTO dto : detail){
  384. if(StringUtils.isNotEmpty(dto.getSliceJson())){
  385. dto.setSliceInfo(JSON.parseObject(dto.getSliceJson(), TakaiSliceInfoDTO.class));
  386. }
  387. if("user".equals(dto.getType())){
  388. List<TakaiFileInfo> fileInfoList = fileInfoMapper.getFileInfoById(null, dto.getDialog_id(), dto.getDid());
  389. if(fileInfoList != null && !fileInfoList.isEmpty()){
  390. List<TakaiDocumentDTO> documentDTOS = new ArrayList<>();
  391. for(TakaiFileInfo fileInfo : fileInfoList){
  392. TakaiDocumentDTO documentDTO = new TakaiDocumentDTO();
  393. BeanUtils.copyProperties(fileInfo, documentDTO);
  394. documentDTOS.add(documentDTO);
  395. }
  396. dto.setDocuments(documentDTOS);
  397. }
  398. }
  399. }
  400. }
  401. return detail;
  402. }
  403. @Override
  404. public void saveDialog(TakaiDialogReqDTO dialogReqDTO) {
  405. String dialogId = null;
  406. TakaiDialogRespDTO dialogVo = null;
  407. if (com.takai.common.utils.StringUtils.isNotEmpty(dialogReqDTO.getId())) {
  408. dialogVo = takaiDialogMapper.selectDialogById(dialogReqDTO.getId());
  409. }
  410. if (dialogVo == null) {
  411. takaiDialogMapper.insertDialog(dialogReqDTO);
  412. dialogId = dialogReqDTO.getId();
  413. } else {
  414. dialogId = dialogReqDTO.getId();
  415. }
  416. for (TakaiDialogDetailReqDTO dto : dialogReqDTO.getMessages()) {
  417. dto.setDialogId(dialogId);
  418. dto.setContent(base64DecodeUtil.decodeIfNeeded(dto.getContent()));
  419. TakaiDialogRespDTO detail = takaiDialogMapper.selectDialogDetailById(dto.getId());
  420. if (detail == null) {
  421. if (dto.getSliceInfo() != null) dto.setSliceJson(JSON.toJSONString(dto.getSliceInfo()));
  422. takaiDialogMapper.insertDialogDetail(dto);
  423. }
  424. if(dto.getDocuments() != null && !dto.getDocuments().isEmpty()){
  425. for(TakaiDocumentDTO documentVo : dto.getDocuments()){
  426. if(!"".equals(documentVo.getId())) {
  427. List<TakaiFileInfo> fileInfo = fileInfoMapper.getFileInfoById(documentVo.getId(), null, null);
  428. if((fileInfo == null || fileInfo.isEmpty()) && "user".equals(dto.getRole())) {
  429. TakaiFileInfo params = new TakaiFileInfo();
  430. params.setId(documentVo.getId());
  431. params.setName(documentVo.getName());
  432. params.setUrl(documentVo.getUrl());
  433. params.setDialogId(dialogId);
  434. params.setDialogDid(dto.getId());
  435. fileInfoMapper.insertFileInfo(params);
  436. }
  437. }
  438. }
  439. }
  440. }
  441. }
  442. @Override
  443. public List<Object> getDialogList(String appId, String userId) {
  444. List<TakaiDialogRespDTO> dialogRespDTOS = takaiDialogMapper.selectDialogList(appId, userId);
  445. //当前日期
  446. LocalDate today = LocalDate.now();
  447. //根据时间分组降序排序
  448. NavigableMap<LocalDateTime, List<TakaiDialogRespDTO>> groupList = dialogRespDTOS.stream().collect(Collectors.groupingBy(TakaiDialogRespDTO::getCreate_time, TreeMap::new, Collectors.toList())).descendingMap();
  449. List<Object> obj = new ArrayList();
  450. if (!groupList.isEmpty()) {
  451. for (Map.Entry<LocalDateTime, List<TakaiDialogRespDTO>> entry : groupList.entrySet()) {
  452. // 对比两个时间相差多少天
  453. long daysBetween = ChronoUnit.DAYS.between(today, entry.getKey());
  454. Map<String, Object> m = new HashMap();
  455. m.put("key", System.nanoTime());
  456. m.put("type", "group");
  457. if (daysBetween == 0l) {
  458. m.put("label", TODAY);
  459. m.put("children", setValue(entry.getValue(), appId));
  460. obj.add(m);
  461. } else {
  462. m.put("label", -daysBetween + BEFOR);
  463. m.put("children", setValue(entry.getValue(), appId));
  464. obj.add(m);
  465. }
  466. }
  467. }
  468. return obj;
  469. }
  470. @Override
  471. public void DelDialogDetail(String id) {
  472. int result = takaiDialogMapper.delDialog(id);
  473. if (result > 0) {
  474. takaiDialogMapper.delDialogDetail(id);
  475. }
  476. }
  477. @Override
  478. public void updateDialog(TakaiDialogReqDTO dialogReqDTO) {
  479. takaiDialogMapper.updateDialog(dialogReqDTO);
  480. }
  481. @Override
  482. public List<TakaiDialogRespDTO> exportExcel(String dialogId) {
  483. return takaiDialogMapper.selectDialogExport(dialogId);
  484. }
  485. @Override
  486. public int createKnowledge(TakaiKnowledgeParams knowledge) {
  487. SnowflakeDigitGenerator snowflakeDigitGenerator = new SnowflakeDigitGenerator(1, 1);
  488. long knowledgeId = snowflakeDigitGenerator.nextId();
  489. String url = deepseekConfig.getBaseurl() + deepseekConfig.getCreateKnowledge();
  490. JSONObject jsonObject = new JSONObject();
  491. jsonObject.put("knowledge_id", "a" + knowledgeId);
  492. jsonObject.put("embedding_id", knowledge.getEmbeddingId());
  493. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toJSONString());
  494. Request request = buildPostRequest(url, requestBody);
  495. OkHttpClient client = buildOkHttpClient();
  496. String createdBy = SecurityUtils.getLoginUser() == null ? "":SecurityUtils.getLoginUser().getUserId();
  497. try {
  498. Response response = client.newCall(request).execute();
  499. if (response.isSuccessful()) {
  500. String body = response.body().string();
  501. JSONObject obj = JSON.parseObject(body);
  502. Integer code = obj.getInteger("code");
  503. if (code == 200) {
  504. TakaiKnowledge params = TakaiKnowledge.builder()
  505. .knowledgeId("a" + knowledgeId)
  506. .name(knowledge.getName())
  507. .embeddingId(knowledge.getEmbeddingId())
  508. .description(knowledge.getDescription())
  509. .visible(knowledge.getVisible())
  510. .build();
  511. params.setCreateBy(createdBy);
  512. return takaiKnowledgeMapper.insertKnowledge(params);
  513. }
  514. } else {
  515. logger.error("创建知识库调用python接口失败,返回状态码:{}", response.code());
  516. }
  517. } catch (IOException e) {
  518. logger.error("创建知识库调用python接口失败", e.getMessage());
  519. }
  520. return 0;
  521. }
  522. @Override
  523. public int updateKnowledge(TakaiKnowledgeParams knowledge, String knowledgeId) {
  524. TakaiKnowledge params = TakaiKnowledge.builder().knowledgeId(knowledgeId)
  525. .name(knowledge.getName())
  526. .description(knowledge.getDescription())
  527. .embeddingId(knowledge.getEmbeddingId())
  528. .visible(knowledge.getVisible())
  529. .build();
  530. String updateBy = SecurityUtils.getLoginUser() == null ? "":SecurityUtils.getLoginUser().getUserId();
  531. params.setUpdateBy(updateBy);
  532. params.setUpdateTime(new Date());
  533. return takaiKnowledgeMapper.updateKnowledge(params);
  534. }
  535. @Override
  536. public TakaiKnowledge detailKnowledge(String knowledgeId) {
  537. TakaiKnowledge vo = TakaiKnowledge.builder().knowledgeId(knowledgeId).build();
  538. return takaiKnowledgeMapper.selectTargetKnowledge(vo);
  539. }
  540. @Override
  541. public int delKnowledge(String knowledgeId) {
  542. String url = deepseekConfig.getBaseurl() + deepseekConfig.getDeleteKnowledge() + "/" + knowledgeId;
  543. Request request = buildDeleteRequest(url);
  544. OkHttpClient client = buildOkHttpClient();
  545. Response response = null;
  546. try {
  547. response = client.newCall(request).execute();
  548. if (response.isSuccessful()) {
  549. String body = response.body().string();
  550. JSONObject obj = JSON.parseObject(body);
  551. Integer code = obj.getInteger("code");
  552. if (code == 200) {
  553. // TakaiKnowledge info = takaiKnowledgeMapper.selectTargetKnowledge(TakaiKnowledge.builder().knowledgeId(knowledgeId).build());
  554. List<TakaiMediaReplacement> list = takaiMediaReplacementMapper.selectMediaList(TakaiMediaReplacement.builder().knowledgeId(knowledgeId).build());
  555. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(TakaiDocument.builder().knowledgeId(knowledgeId).build());
  556. int knowledgeInt = takaiKnowledgeMapper.delKnowledge(knowledgeId);
  557. if (knowledgeInt > 0) {
  558. takaiDocumentMapper.delDocumentByKnowledgeId(knowledgeId);
  559. takaiDocumentSettingsMapper.deleteDocumentSettingsByKnowledgeId(knowledgeId);
  560. if(list != null && list.size() > 0){
  561. try {
  562. for(TakaiDocument document: documentList){
  563. logger.info("删除知识库->删除minio文件");
  564. minioUtil.remove("deepseek-doc", "/"+document.getName());
  565. }
  566. for (int k = 0; k < list.size(); k++ ) {
  567. logger.info("删除知识库->删除minio图片{}", k);
  568. String key = "/pdf/"+knowledgeId+"/"+list.get(k).getDocumentId()+"/【示意图序号_"+list.get(k).getDocumentId()+"_"+k+1+"】.jpg";
  569. logger.info("删除知识库->删除minio图片key{}", key);
  570. minioUtil.remove("deepseek-doc" , key);
  571. }
  572. } catch (Exception e) {
  573. logger.error("删除知识库->删除minion文件失败", e.getMessage());
  574. throw new RuntimeException(e);
  575. }
  576. }
  577. }
  578. return knowledgeInt;
  579. }
  580. }
  581. } catch (IOException e) {
  582. logger.error("删除知识库调用python接口失败", e.getMessage());
  583. }
  584. return 0;
  585. }
  586. @Override
  587. public int uploadDocument(MultipartFile[] files, String knowledgeId) {
  588. List<TakaiSysOss> result = null;
  589. try {
  590. result = minioUtil.uploadMultiple(files);
  591. } catch (Exception e) {
  592. logger.error("上传文件失败", e.getMessage());
  593. }
  594. if (result != null && result.size() > 0) {
  595. List<UploadDocumentParams> params = new ArrayList<>();
  596. for (int i = 0; i<result.size(); i++) {
  597. SnowflakeDigitGenerator documentIdGenerator = new SnowflakeDigitGenerator(i, i);
  598. long documentId = documentIdGenerator.nextId();
  599. UploadDocumentParams param = new UploadDocumentParams();
  600. param.setDocument_id("a" + documentId);
  601. param.setName(result.get(i).getOriginalName());
  602. param.setUrl(result.get(i).getUrl());
  603. params.add(param);
  604. }
  605. TakaiDocumentSettings settings = new TakaiDocumentSettings();
  606. settings.setKnowledgeId(knowledgeId);
  607. JSONObject jsonObject = analysisFile(params, settings, "upload");
  608. String updateBy = SecurityUtils.getLoginUser() == null ? "":SecurityUtils.getLoginUser().getUserId();
  609. if (jsonObject != null && jsonObject.containsKey("code") && jsonObject.getInteger("code") == 200) {
  610. for (UploadDocumentParams vo : params) {
  611. // 更新知识库文件大小,总字符数, 文件总数
  612. JSONObject docInfo = jsonObject.getJSONObject("doc_info");
  613. if(docInfo != null){
  614. Integer fileLen = docInfo.getInteger("file_size");
  615. Integer wordNum = docInfo.getInteger("total_char_len");
  616. Integer sliceTotal = docInfo.getInteger("slice_num");
  617. for (TakaiSysOss oss : result) {
  618. // oss保存到数据库
  619. takaiSysOssMapper.insertSysOss(oss);
  620. }
  621. // 保存知识信息
  622. TakaiDocument document = TakaiDocument.builder()
  623. .documentId(vo.getDocument_id())
  624. .knowledgeId(knowledgeId)
  625. .customSeparator(String.format("[\"%s\"", "\\n") + "]")
  626. .sentenceSize("300")
  627. .name(vo.getName())
  628. .url(vo.getUrl())
  629. .sliceTotal(sliceTotal)
  630. .length(fileLen)
  631. .wordNum(wordNum)
  632. .build();
  633. document.setCreateBy(updateBy);
  634. int documentIdInsert = takaiDocumentMapper.insertDocument(document);
  635. if (documentIdInsert > 0) {
  636. // 保存知识设置信息
  637. SnowflakeDigitGenerator snowflakeDigitGenerator = new SnowflakeDigitGenerator(1, 1);
  638. long id = snowflakeDigitGenerator.nextId();
  639. TakaiDocumentSettings dSettings = new TakaiDocumentSettings();
  640. dSettings.setId(String.valueOf(id));
  641. dSettings.setKnowledgeId(knowledgeId);
  642. dSettings.setDocumentId(vo.getDocument_id());
  643. dSettings.setSetSlice("0"); // 默认 按标题段落切片
  644. dSettings.setSetAnalyze("1"); // 默认 图片转换成标识符
  645. dSettings.setSetTable("0"); // 默认 ttable转图片
  646. takaiDocumentSettingsMapper.insertDocumentSettings(dSettings);
  647. }
  648. }
  649. }
  650. updateKnowledgeSize(knowledgeId);
  651. setRedisCache(knowledgeId);
  652. return 1;
  653. }
  654. }
  655. return 0;
  656. }
  657. private void updateKnowledgeSize(String knowledgeId) {
  658. TakaiKnowledge info = takaiKnowledgeMapper.selectTargetKnowledge(TakaiKnowledge.builder().knowledgeId(knowledgeId).build());
  659. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(TakaiDocument.builder().knowledgeId(knowledgeId).build());
  660. int totalLen = documentList.stream()
  661. .mapToInt(doc -> doc.getLength() != null ? doc.getLength() : 0)
  662. .sum();
  663. int totalWordNum = documentList.stream()
  664. .mapToInt(doc -> doc.getWordNum() != null ? doc.getWordNum() : 0)
  665. .sum();
  666. int docSize = documentList == null || documentList.size() == 0 ? 0 : documentList.size();
  667. String updateBy = SecurityUtils.getLoginUser() == null ? "":SecurityUtils.getLoginUser().getUserId();
  668. TakaiKnowledge paramInfo = TakaiKnowledge.builder().knowledgeId(knowledgeId)
  669. .length(totalLen) // 文件大小
  670. .wordNum(totalWordNum) // 总字符数
  671. .documentSize(docSize) // 文件总数
  672. .build();
  673. paramInfo.setUpdateBy(updateBy);
  674. paramInfo.setUpdateTime(new Date());
  675. takaiKnowledgeMapper.updateKnowledge(paramInfo);
  676. }
  677. private void updateDocumentSize(String knowledgeId,String documentId) {
  678. List<TakaiSliceInfo> sliceList = selectByDocumentId(documentId,null);
  679. //字符数
  680. int totalLen = sliceList.stream()
  681. .mapToInt(slice -> slice.getSliceText() != null ? slice.getSliceText().length() : 0)
  682. .sum();
  683. //文件大小
  684. int totalSize = sliceList.stream()
  685. .mapToInt(slice -> slice.getSliceText() != null ? slice.getSliceText().getBytes(StandardCharsets.UTF_8).length : 0)
  686. .sum();
  687. TakaiDocument doc = TakaiDocument.builder()
  688. .documentId(documentId)
  689. .length(totalSize)
  690. .wordNum(totalLen)
  691. .sliceTotal(sliceList.size())
  692. .build();
  693. String updateBy = SecurityUtils.getLoginUser() == null ? "":SecurityUtils.getLoginUser().getUserId();
  694. doc.setUpdateBy(updateBy);
  695. doc.setUpdateTime(new Date());
  696. takaiDocumentMapper.updateDocument(doc);
  697. updateKnowledgeSize(knowledgeId);
  698. }
  699. @Override
  700. public int updateDocument(TakaiDocumentParams documentParams, String documentId) {
  701. int i = takaiDocumentMapper.updateDocument(TakaiDocument.builder()
  702. .documentId(documentId)
  703. .name(documentParams.getName())
  704. .build());
  705. return i;
  706. }
  707. @Override
  708. public List<TakaiDocument> documentList(TakaiDocumentParams documentParams) {
  709. List<TakaiDocument> documentList = takaiDocumentMapper.selectDocumentList(TakaiDocument.builder().knowledgeId(documentParams.getKnowledge_id()).build());
  710. replaceOssUrl(documentList);
  711. return documentList;
  712. }
  713. private void replaceOssUrl(List<TakaiDocument> documentList) {
  714. if(documentList == null || documentList.isEmpty()) {
  715. return;
  716. }
  717. for(TakaiDocument document : documentList) {
  718. replaceDocUrl(document);
  719. }
  720. }
  721. private void replaceDocUrl(TakaiDocument document) {
  722. if(document == null) {
  723. return;
  724. }
  725. String url = document.getUrl();
  726. url = url.replace("https://10.1.28.14:9000", OSS_URL);
  727. document.setUrl(url);
  728. }
  729. @Override
  730. public TakaiDocument documentDetail(String documentId) {
  731. TakaiDocument doc = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
  732. replaceDocUrl(doc);
  733. return doc;
  734. }
  735. @Override
  736. public int delDocument(String documentId) {
  737. TakaiDocument vo = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
  738. if(vo != null){
  739. String url = deepseekConfig.getBaseurl() + deepseekConfig.getDeleteDoc() + "/" + documentId + "/" + vo.getKnowledgeId();
  740. Request request = buildDeleteRequest(url);
  741. OkHttpClient client = buildOkHttpClient();
  742. try {
  743. Response response = client.newCall(request).execute();
  744. if (response.isSuccessful()) {
  745. String body = response.body().string();
  746. logger.info("删除知识文件调用python接口返回结果:{}", body);
  747. JSONObject obj = JSON.parseObject(body);
  748. Integer code = obj.getInteger("code");
  749. if (code == 200) {
  750. List<TakaiMediaReplacement> list = takaiMediaReplacementMapper.selectMediaList(TakaiMediaReplacement.builder().documentId(documentId).build());
  751. // 删除图片
  752. takaiMediaReplacementMapper.deleteMedia(documentId);
  753. // 删除document文件
  754. int i = takaiDocumentMapper.delDocument(documentId);
  755. if(i > 0){
  756. //更新知识库
  757. updateKnowledgeSize(vo.getKnowledgeId());
  758. // 删除minio文件
  759. try {
  760. logger.info("删除minio文件");
  761. minioUtil.remove("deepseek-doc", "/"+vo.getName());
  762. if(list != null && list.size() > 0){
  763. for (int k=1; k<=list.size(); k++ ) {
  764. logger.info("删除minio图片{}", k);
  765. minioUtil.remove("deepseek-doc" , "/pdf/"+vo.getKnowledgeId()+"/"+documentId+"/【示意图序号_"+documentId+"_"+k+"】.jpg");
  766. }
  767. }
  768. } catch (Exception e) {
  769. logger.error("删除minion文件失败", e.getMessage());
  770. throw new RuntimeException(e);
  771. }
  772. return i;
  773. }
  774. }
  775. }
  776. } catch (IOException e) {
  777. logger.error("删除知识文件调用python接口失败", e.getMessage());
  778. }
  779. }
  780. return 0;
  781. }
  782. @Override
  783. public void uploadUrl(TakaiDocumentObject object) {
  784. }
  785. @Override
  786. public int createApplication(TakaiApplicationParams params, boolean isAdmin) {
  787. ApprovalNode vo = getFirstApproverNode(); // 获取第一个审批对象
  788. if(vo != null){
  789. SnowflakeDigitGenerator snowflakeDigitGenerator = new SnowflakeDigitGenerator(1, 1);
  790. long appId = snowflakeDigitGenerator.nextId();
  791. TakaiApplication info = TakaiApplication.builder().appId(String.valueOf(appId))
  792. .name(params.getName())
  793. .desc(params.getDesc())
  794. .model(params.getModel())
  795. .knowledgeIds(params.getKnowledge_ids().stream().collect(Collectors.joining(",")))
  796. .topP(params.getTop_p())
  797. .temperature(params.getTemperature())
  798. .maxToken(params.getMax_token())
  799. .prompt(base64DecodeUtil.decodeIfNeeded(params.getPrompt()))
  800. .knowledgeInfo(params.getKnowledge_info())
  801. .sliceCount(params.getSlice_count())
  802. .typeId(params.getTypeId())
  803. .visible(params.getVisible())
  804. .isDeepThink(params.getIsDeepThink())
  805. .sort(params.getSort())
  806. .build();
  807. //关联项目
  808. if(params.getAppProId() != null){
  809. SysProjectApp sysProjectApp = new SysProjectApp();
  810. sysProjectApp.setProjectId(params.getAppProId()[1]);
  811. sysProjectApp.setAppId(info.getAppId());
  812. sysProjectAppMapper.insertSysProjectApp(sysProjectApp);
  813. }
  814. //管理员,私有,项目级应用不需要审核
  815. if(isAdmin
  816. || "1".equals(params.getVisible())
  817. || AppTypeEnum.PROJECT.getCode().equals(String.valueOf(params.getTypeId()))){ // 1 私有 0 公开
  818. info.setStatus("3"); // 有直接创建权限无需审核
  819. }else{
  820. info.setStatus("5"); // 未开始审核状态
  821. info.setApprover(String.valueOf(vo.getApprover()));
  822. info.setNodeOrder(String.valueOf(vo.getNodeOrder()));
  823. }
  824. info.setCreateBy(params.getUserId());
  825. int i = takaiApplicationMapper.insertApplication(info);
  826. if (i > 0) {
  827. //添加VIP用户
  828. if(params.getVipList() != null && params.getVipList().size() > 0){
  829. for(SysUser sysUser : params.getVipList()){
  830. VipApplication vipApplication =
  831. VipApplication.builder()
  832. .appId(info.getAppId())
  833. .userId(sysUser.getUserId())
  834. .build();
  835. takaiApplicationMapper.insertVipApp(vipApplication);
  836. }
  837. }
  838. TypeApp appType = new TypeApp();
  839. appType.setTypeId(params.getTypeId() == null ? null : params.getTypeId());
  840. appType.setAppId(String.valueOf(appId));
  841. appTypeMapper.insertAppType(appType);
  842. logger.info("create application success, id:{}, name:{}", appId, params.getName());
  843. TakaiAppInfo appInfo = new TakaiAppInfo();
  844. appInfo.setAppId(String.valueOf(appId));
  845. appInfo.setAppInfo(String.valueOf(JSONObject.from(info).toJSONString()));
  846. takaiAppInfoMapper.insertAppInfo(appInfo);
  847. List<String> list = params.getQuestionList();
  848. if (!list.isEmpty() && list.size() > 0) {
  849. for (String str : list) {
  850. if (org.apache.commons.lang3.StringUtils.isNotBlank(str)) {
  851. String uuid = IdUtils.simpleUUID();
  852. TakaiQuestion question = TakaiQuestion.builder().id(uuid).question(str).appId(String.valueOf(appId)).build();
  853. takaiQuestionMapper.insertQuestion(question);
  854. }
  855. }
  856. }
  857. return i;
  858. }
  859. }else{
  860. // 没有审批人
  861. return 9;
  862. }
  863. return 0;
  864. }
  865. @Override
  866. public int updateApplication(TakaiApplicationParams params, String appId, boolean isAdmin) {
  867. ApprovalNode vo = getFirstApproverNode(); // 获取第一个审批对象
  868. if(vo != null){
  869. TakaiApplication info = TakaiApplication.builder().appId(appId)
  870. .name(params.getName())
  871. .desc(params.getDesc())
  872. .model(params.getModel())
  873. .knowledgeIds(params.getKnowledge_ids().stream().collect(Collectors.joining(",")))
  874. .topP(params.getTop_p())
  875. .temperature(params.getTemperature())
  876. .maxToken(params.getMax_token())
  877. .prompt(base64DecodeUtil.decodeIfNeeded(params.getPrompt()))
  878. .knowledgeInfo(params.getKnowledge_info())
  879. .sliceCount(params.getSlice_count())
  880. .typeId(params.getTypeId())
  881. .isDeepThink(params.getIsDeepThink())
  882. .visible(params.getVisible())
  883. .sort(params.getSort())
  884. .build();
  885. //关联项目
  886. if(params.getAppProId() != null){
  887. SysProjectApp sysProjectApp = sysProjectAppMapper.selectSysProjectAppByAppId(appId);
  888. if(sysProjectApp != null){
  889. sysProjectAppMapper.deleteSysProjectAppByAppId(appId);
  890. }
  891. sysProjectApp = new SysProjectApp();
  892. sysProjectApp.setProjectId(params.getAppProId()[1]);
  893. sysProjectApp.setAppId(appId);
  894. sysProjectAppMapper.insertSysProjectApp(sysProjectApp);
  895. }
  896. if(isAdmin
  897. || "1".equals(params.getVisible())
  898. || AppTypeEnum.PROJECT.getCode().equals(String.valueOf(params.getTypeId()))){
  899. info.setStatus("3"); // 有直接修改权限无需审核
  900. info.setApprover(null);
  901. info.setNodeOrder(null);
  902. }else{
  903. info.setStatus("2"); // 未开始审核状态
  904. info.setApprover(String.valueOf(vo.getApprover()));
  905. info.setNodeOrder(String.valueOf(vo.getNodeOrder()));
  906. }
  907. info.setUpdateBy(params.getUserId());
  908. int i = takaiApplicationMapper.updateApplication(info);
  909. if (1 > 0) {
  910. //添加VIP用户
  911. takaiApplicationMapper.deleteVipByAppId(info.getAppId());
  912. if(params.getVipList() != null && params.getVipList().size() > 0){
  913. for(SysUser sysUser : params.getVipList()){
  914. VipApplication vipApplication =
  915. VipApplication.builder()
  916. .appId(info.getAppId())
  917. .userId(sysUser.getUserId())
  918. .build();
  919. takaiApplicationMapper.insertVipApp(vipApplication);
  920. }
  921. }
  922. TakaiAppInfo appInfo = new TakaiAppInfo();
  923. appInfo.setAppId(appId);
  924. appInfo.setAppInfo(String.valueOf(JSONObject.from(info).toJSONString()));
  925. takaiAppInfoMapper.updateAppInfoByAppId(appInfo);
  926. logger.info("update application success, id:{}, name:{}", appId, params.getName());
  927. //预设问题写入数据库
  928. takaiQuestionMapper.delQuestionByAppId(appId);
  929. List<String> list = params.getQuestionList();
  930. if (!list.isEmpty() && list.size() > 0) {
  931. for (String str : list) {
  932. if (org.apache.commons.lang3.StringUtils.isNotBlank(str)) {
  933. String uuid = IdUtils.simpleUUID();
  934. TakaiQuestion question = TakaiQuestion.builder().id(uuid).question(str).appId(String.valueOf(appId)).build();
  935. takaiQuestionMapper.insertQuestion(question);
  936. }
  937. }
  938. }
  939. }
  940. return i;
  941. } else {
  942. return 9;
  943. }
  944. }
  945. @Override
  946. @DataScope(deptAlias = "u", userAlias = "u")
  947. public List<TakaiApplicationResult> getApplicationList(TakaiApplication params) {
  948. //管理员 获取所有项目
  949. Map<String,Object> userParams = getUserParams();
  950. if(userParams != null){
  951. params.getParams().putAll(userParams);
  952. }
  953. List<TakaiApplicationResult> appList = takaiApplicationMapper.selectApplicationList(params);
  954. //添加应用VIP用户
  955. // if(appList != null && appList.size() > 0){
  956. // for (TakaiApplicationResult appResult : appList) {
  957. // List<SysUser> vipList = userService.selectAppVipList(appResult.getAppId());
  958. // appResult.setVipList(vipList);
  959. // }
  960. // }
  961. return appList;
  962. }
  963. @Override
  964. public JSONObject selectApplication(String appId) {
  965. JSONObject object = new JSONObject();
  966. TakaiApplication application = TakaiApplication.builder().appId(appId).build();
  967. TakaiApplication takaiApplication = takaiApplicationMapper.selectTargetApplication(application);
  968. //项目级应用 返回['项目分类','项目id']
  969. if(takaiApplication != null) {
  970. //添加应用VIP用户
  971. List<SysUser> vipList = userService.selectAppVipList(appId);
  972. takaiApplication.setVipList(vipList);
  973. if(AppTypeEnum.PROJECT.getCode().equals(String.valueOf(takaiApplication.getTypeId()))) {
  974. SysProjectApp sysProjectApp = sysProjectAppMapper.selectSysProjectAppByAppId(application.getAppId());
  975. if (sysProjectApp != null) {
  976. SysProject sysProject = sysProjectMapper.selectSysProjectByProjectId(sysProjectApp.getProjectId());
  977. takaiApplication.setAppProId(Arrays.asList(
  978. String.valueOf(sysProject.getSourceFrom()),
  979. String.valueOf(sysProject.getProjectId())));
  980. }
  981. }
  982. List<String> idList = Arrays.stream(takaiApplication.getKnowledgeIds().split(",")) // 按「逗号+空格」拆分字符串为数组
  983. .filter(str -> str != null && !str.trim().isEmpty()) // 过滤 null 和空字符串(防异常)
  984. .collect(Collectors.toList());
  985. JSONObject detailObj = JSONObject.from(takaiApplication); // 转为JSON对象
  986. detailObj.put("knowledgeIds", idList); // 用数组替换原字符串
  987. object.put("detail", detailObj);
  988. } else {
  989. object.put("detail", takaiApplication);
  990. }
  991. List<TakaiQuestionDTO> list = takaiQuestionMapper.getQuestionList(appId);
  992. object.put("questionlist", list);
  993. return object;
  994. }
  995. @Override
  996. public int delApplication(String appId) {
  997. int i = takaiApplicationMapper.delApplication(appId);
  998. if (i > 0) {
  999. takaiAppInfoMapper.delAppInfoByAppId(appId);
  1000. takaiQuestionMapper.delQuestionByAppId(appId);
  1001. takaiApplicationMapper.delApplication(appId);
  1002. }
  1003. return i;
  1004. }
  1005. @Override
  1006. public List<TakaiQuestionDTO> selectQuestionByAppId(String appId) {
  1007. List<TakaiQuestionDTO> List = takaiQuestionMapper.getQuestionList(appId);
  1008. return List;
  1009. }
  1010. @Override
  1011. public List<TakaiKnowledge> queryKnowledgeList() {
  1012. //管理员 获取所有项目
  1013. TakaiKnowledge params = getKnowledgeUserParams();
  1014. return takaiKnowledgeMapper.selectKnowledgeList(params);
  1015. }
  1016. private TakaiKnowledge getKnowledgeUserParams() {
  1017. TakaiKnowledge params = null;
  1018. //管理员 获取所有项目
  1019. Map<String,Object> userParams = getUserParams();
  1020. if(userParams != null){
  1021. params = TakaiKnowledge.builder().build();
  1022. params.setParams(userParams);
  1023. }
  1024. return params;
  1025. }
  1026. private Map<String,Object> getUserParams() {
  1027. //管理员 获取所有项目
  1028. LoginUser user = SecurityUtils.getLoginUser();
  1029. Map<String,Object> userParams = null;
  1030. if(user != null){
  1031. userParams = new HashMap<>();
  1032. SysUser loginUser = user.getUser();
  1033. userParams.put("userType",loginUser.getUserType());
  1034. userParams.put("userId",loginUser.getUserId());
  1035. if(loginUser.getRoles().stream().anyMatch(role -> role.getRoleId() == 1)) {
  1036. userParams.put("isAdmin", true);
  1037. } else {
  1038. userParams.put("isAdmin", false);
  1039. }
  1040. }
  1041. return userParams;
  1042. }
  1043. @Override
  1044. public List<TakaiDialogRespDTO> selectDialogListByAppId(String appId, String userId) {
  1045. List<TakaiDialogRespDTO> list = takaiDialogMapper.selectDialog(appId, userId);
  1046. // List<Object> result = setDialogList(list);
  1047. return list;
  1048. }
  1049. @Override
  1050. public TakaiDocumentSettings documentSetting(String documentId) {
  1051. return takaiDocumentSettingsMapper.selectById(documentId);
  1052. }
  1053. @Override
  1054. public int updateDocumentSetting(TakaiDocumentSettings documentSettings, String documentId) {
  1055. TakaiDocumentSettings settings = new TakaiDocumentSettings();
  1056. TakaiDocumentSettings settingsVo = takaiDocumentSettingsMapper.selectById(documentId);
  1057. settings.setKnowledgeId(settingsVo.getKnowledgeId());
  1058. settings.setSetSlice(documentSettings.getSetSlice());
  1059. settings.setSliceValue(documentSettings.getSliceValue());
  1060. settings.setSetAnalyze(documentSettings.getSetAnalyze());
  1061. settings.setSetTable(documentSettings.getSetTable());
  1062. TakaiDocument document = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
  1063. List<UploadDocumentParams> listParams = new ArrayList<>();
  1064. if (document != null) {
  1065. UploadDocumentParams params = new UploadDocumentParams();
  1066. params.setDocument_id(documentId);
  1067. params.setName(document.getName());
  1068. params.setUrl(document.getUrl());
  1069. listParams.add(params);
  1070. }
  1071. JSONObject jsonObject = analysisFile(listParams, settings, "update");
  1072. if (jsonObject != null && jsonObject.containsKey("code") && jsonObject.getInteger("code") == 200) {
  1073. logger.info("update document setting success, id:{}", documentId);
  1074. documentSettings.setDocumentId(documentId);
  1075. return takaiDocumentSettingsMapper.updateDocumentSettings(documentSettings);
  1076. }
  1077. return 0;
  1078. }
  1079. @Override
  1080. public JSONObject getSliceList(TakaiSliceParams params) {
  1081. // String url = deepseekConfig.getBaseurl() + deepseekConfig.getSlicePage();
  1082. // JSONObject jsonObject = new JSONObject();
  1083. // jsonObject.put("document_id", params.getDocument_id());
  1084. // jsonObject.put("knowledge_id", params.getKnowledge_id());
  1085. // jsonObject.put("text", params.getText());
  1086. // jsonObject.put("pageNum", params.getPageNum());
  1087. // jsonObject.put("pageSize", params.getPageSize());
  1088. //
  1089. // RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.toJSONString());
  1090. // Request request = buildPostRequest(url, requestBody);
  1091. //
  1092. // OkHttpClient client = buildOkHttpClient();
  1093. // Response response = null;
  1094. // try {
  1095. // response = client.newCall(request).execute();
  1096. // if (response.isSuccessful()) {
  1097. // String body = response.body().string();
  1098. // JSONObject obj = JSON.parseObject(body);
  1099. // Integer code = obj.getInteger("code");
  1100. // if (code == 200) {
  1101. // return obj;
  1102. // }
  1103. // } else {
  1104. // logger.info("获取切片列表调用python接口失败,返回状态码:{}", response.code());
  1105. // }
  1106. // } catch (IOException e) {
  1107. // logger.error("获取切片列表调用python接口失败", e.getMessage());
  1108. // }
  1109. return null;
  1110. }
  1111. @Override
  1112. public int deleteSlice(String sliceId, String knowledgeId, String documentId) {
  1113. String url = deepseekConfig.getBaseurl() + deepseekConfig.getDeleteSlice() + "/" + sliceId + "/" + knowledgeId + "/" + documentId;
  1114. Request request = buildDeleteRequest(url);
  1115. OkHttpClient client = buildOkHttpClient();
  1116. Response response = null;
  1117. try {
  1118. response = client.newCall(request).execute();
  1119. if (response.isSuccessful()) {
  1120. String body = response.body().string();
  1121. JSONObject obj = JSON.parseObject(body);
  1122. Integer code = obj.getInteger("code");
  1123. logger.info("删除切片调用python接口成功,返回结果:{}", body);
  1124. if (code == 200) {
  1125. updateDocumentSize(knowledgeId,documentId);
  1126. return 1;
  1127. }
  1128. }
  1129. } catch (IOException e) {
  1130. logger.error("删除切片调用python接口失败", e.getMessage());
  1131. }
  1132. return 0;
  1133. }
  1134. @Override
  1135. public JSONObject getSliceDetail(String sliceId, String knowledgeId) {
  1136. String url = deepseekConfig.getBaseurl() + deepseekConfig.getSliceDetail() + "/" + knowledgeId + "/" + sliceId;
  1137. Request request = buildGetRequest(url);
  1138. OkHttpClient client = buildOkHttpClient();
  1139. try {
  1140. Response response = client.newCall(request).execute();
  1141. if (response.isSuccessful()) {
  1142. String body = response.body().string();
  1143. log.info("查询切片详情返回:" + body);
  1144. JSONObject jsonObject = JSON.parseObject(body);
  1145. JSONObject dataObject = jsonObject.getJSONObject("data");
  1146. String docId = dataObject.getString("document_id");
  1147. String sliceText = dataObject.getString("slice_text");
  1148. TakaiMediaReplacement conditonR = TakaiMediaReplacement.builder().documentId(docId).build();
  1149. List<TakaiMediaReplacement> imageList = takaiMediaReplacementMapper.selectMediaList(conditonR);
  1150. //替换【示意图序号_XXXXX】为超链接
  1151. List<TakaiSliceImage> sliceImageList = SchematicNumberParser.extractImageUrlMappings(sliceText,imageList);
  1152. // String replaceText = SchematicNumberParser.replaceWithImageLinks(sliceText,imageList);
  1153. // dataObject.put("slice_text",replaceText);
  1154. dataObject.put("imageList",sliceImageList);
  1155. return jsonObject;
  1156. } else {
  1157. logger.info("获取切片详情调用python接口失败,返回状态码:{}", response.code());
  1158. }
  1159. } catch (IOException e) {
  1160. log.error("查询切片详情调用python接口失败", e.getMessage());
  1161. }
  1162. return null;
  1163. }
  1164. @Override
  1165. public List<TakaiSliceImage> uploadSliceImage(MultipartFile[] files, String knowledgeId, String documentId) {
  1166. List<TakaiSysOss> resultList = null;
  1167. try {
  1168. resultList = minioUtil.uploadSliceImages(files,knowledgeId,documentId);
  1169. } catch (Exception e) {
  1170. logger.error("上传文件失败", e.getMessage());
  1171. }
  1172. //保存图片信息
  1173. List<TakaiSliceImage> originTextList = new ArrayList<>();
  1174. for (TakaiSysOss result : resultList) {
  1175. TakaiMediaReplacement takaiMediaReplacement =
  1176. TakaiMediaReplacement.builder()
  1177. .knowledgeId(knowledgeId)
  1178. .documentId(documentId)
  1179. .originText(result.getOriginText())
  1180. .mediaType("image")
  1181. .mediaUrl(result.getUrl())
  1182. .build();
  1183. Date currentDate = new Date();
  1184. takaiMediaReplacement.setCreateTime(currentDate);
  1185. takaiMediaReplacement.setUpdateTime(currentDate);
  1186. takaiMediaReplacementMapper.insertMedia(takaiMediaReplacement);
  1187. TakaiSliceImage sliceImage = TakaiSliceImage.builder().name(result.getOriginText()).url(result.getUrl()).build();
  1188. originTextList.add(sliceImage);
  1189. }
  1190. return originTextList;
  1191. }
  1192. @Override
  1193. public int updateSliceInfo(TakaiSliceUpdateParams params) {
  1194. String url = deepseekConfig.getBaseurl() + deepseekConfig.getUpdateSlice();
  1195. JSONObject object = new JSONObject();
  1196. object.put("knowledge_id", params.getKnowledgeId());
  1197. object.put("slice_id", params.getSliceId());
  1198. object.put("slice_text", base64DecodeUtil.decodeIfNeeded(params.getSliceText()));
  1199. object.put("document_id", params.getDocumentId());
  1200. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), object.toJSONString());
  1201. Request request = buildPutRequest(url, requestBody);
  1202. OkHttpClient client = buildOkHttpClient();
  1203. try {
  1204. Response response = client.newCall(request).execute();
  1205. if (response.isSuccessful()) {
  1206. String body = response.body().string();
  1207. JSONObject obj = JSON.parseObject(body);
  1208. Integer code = obj.getInteger("code");
  1209. if (code == 200) {
  1210. updateDocumentSize(params.getKnowledgeId(),params.getDocumentId());
  1211. return 1;
  1212. }
  1213. }
  1214. } catch (Exception e) {
  1215. logger.error("更新切片信息调用python接口失败", e.getMessage());
  1216. }
  1217. return 0;
  1218. }
  1219. @Override
  1220. public TakaiMediaReplacement getTakaiMediaReplacement() {
  1221. TakaiMediaReplacement mrParams = TakaiMediaReplacement.builder()
  1222. .documentId("a2912832435041734656")
  1223. .originText("【示意图序号_a2912832435041734656_1】")
  1224. .mediaType("image").build();
  1225. TakaiMediaReplacement mrVo = takaiMediaReplacementMapper.selectTargetMedia(mrParams);
  1226. return mrVo;
  1227. }
  1228. @Override
  1229. public int addSlice(TakaiSliceUpdateParams params) {
  1230. String url = deepseekConfig.getBaseurl() + deepseekConfig.getAddSlice();
  1231. TakaiDocument info = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(params.getDocumentId()).build());
  1232. if(info != null){
  1233. JSONObject json = new JSONObject();
  1234. json.put("knowledge_id", params.getKnowledgeId());
  1235. json.put("document_id", params.getDocumentId());
  1236. json.put("slice_text", base64DecodeUtil.decodeIfNeeded(params.getSliceText()));
  1237. json.put("doc_name", info.getName());
  1238. RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toJSONString());
  1239. Request request = buildPostRequest(url, requestBody);
  1240. OkHttpClient client = buildOkHttpClient();
  1241. try {
  1242. Response response = client.newCall(request).execute();
  1243. if (response.isSuccessful()) {
  1244. String body = response.body().string();
  1245. JSONObject obj = JSON.parseObject(body);
  1246. Integer code = obj.getInteger("code");
  1247. if (code == 200) {
  1248. updateDocumentSize(params.getKnowledgeId(),params.getDocumentId());
  1249. return 1;
  1250. }
  1251. }
  1252. }catch (Exception e) {
  1253. logger.error("新增切片调用python接口失败", e.getMessage());
  1254. }
  1255. }
  1256. return 0;
  1257. }
  1258. @Override
  1259. public List<TakaiSliceInfo> selectByDocumentId(String documentId,String sliceText) {
  1260. return takaiSliceInfoMapper.selectByDocumentId(documentId,sliceText);
  1261. }
  1262. @Override
  1263. public TakaiSliceInfo selectBySliceId(String sliceId) {
  1264. return takaiSliceInfoMapper.selectBySliceId(sliceId);
  1265. }
  1266. @Override
  1267. public List<SliceInfo> slicePageInfoList(List<String> list) {
  1268. return takaiSliceInfoMapper.slicePageInfoList(list);
  1269. }
  1270. @Override
  1271. public JSONObject searchSlice(String id) {
  1272. String url = deepseekConfig.getBaseurl() + deepseekConfig.getSearchSlice() + "/" + id;
  1273. Request request = buildGetRequest(url);
  1274. OkHttpClient client = buildOkHttpClient();
  1275. try {
  1276. Response response = client.newCall(request).execute();
  1277. if (response.isSuccessful()) {
  1278. String body = response.body().string();
  1279. JSONObject obj = JSON.parseObject(body);
  1280. Integer code = obj.getInteger("code");
  1281. if (code == 200) {
  1282. return obj;
  1283. }
  1284. }
  1285. }catch (Exception e) {
  1286. logger.error("切片得分调用python接口失败", e.getMessage());
  1287. }
  1288. return null;
  1289. }
  1290. @Override
  1291. public List<Object> searchAppTypeGroupList(List<SysDictData> dictDataList, String userId) {
  1292. List<Object> result = new ArrayList();
  1293. if (dictDataList!= null && dictDataList.size() > 0) {
  1294. for (SysDictData dictData : dictDataList){
  1295. // PageHelper.startPage(1, 3, "sort is null asc,sort");
  1296. PageHelper.orderBy("sort is null asc, sort");
  1297. Map<String, Object> map = new HashMap();
  1298. TakaiApplication paramsVo = TakaiApplication.builder().approver(userId).flag("0").addOrderBy("0").build();
  1299. //项目应用
  1300. if(dictData.getDictCode() == 41){
  1301. Map<String, Object> l = searchAppProjectGroupList(paramsVo, dictData);
  1302. if(!MapUtils.isEmpty(l)){
  1303. result.add(l);
  1304. }
  1305. //其他分类应用
  1306. }else{
  1307. paramsVo.setTypeId(Long.valueOf(dictData.getDictCode()));
  1308. List<TakaiApplicationResult> list = takaiApplicationMapper.selectApplicationList(paramsVo);
  1309. if(list != null && list.size() > 0){
  1310. List<Object> appInfoList = new ArrayList();
  1311. map.put("title", dictData.getDictLabel());
  1312. for (TakaiApplicationResult application : list){
  1313. Map<String, Object> infoMap = new HashMap();
  1314. infoMap.put("title", application.getName());
  1315. infoMap.put("appId", application.getAppId());
  1316. infoMap.put("showMenu", "false");
  1317. infoMap.put("chatMode", "LOCAL");
  1318. appInfoList.add(infoMap);
  1319. }
  1320. map.put("children", appInfoList);
  1321. result.add(map);
  1322. }
  1323. }
  1324. }
  1325. }
  1326. return result;
  1327. }
  1328. private Map<String, Object> searchAppProjectGroupList(TakaiApplication paramsVo, SysDictData dictData) {
  1329. paramsVo.setTypeId(dictData.getDictCode());
  1330. List<TakaiApplicationResult> list = takaiApplicationMapper.selectApplicationList(paramsVo);
  1331. //项目级应用
  1332. Map<String, Object> projectLevelMap = new HashMap();
  1333. projectLevelMap.put("title", dictData.getDictLabel());
  1334. List<Object> projectAppList = new ArrayList();
  1335. if (list!= null && list.size() > 0) {
  1336. // 按项目分组
  1337. Map<String, List<TakaiApplicationResult>> projectAppMap = list
  1338. .stream().collect(Collectors.groupingBy(TakaiApplicationResult::getProjectName));
  1339. for (Iterator<String> iterator = projectAppMap.keySet().iterator(); iterator.hasNext();) {
  1340. String projectName = iterator.next();
  1341. Map<String,Object> newProjectAppMap = new HashMap();
  1342. List<TakaiApplicationResult> appList = projectAppMap.get(projectName);
  1343. List<Object> newAppList = new ArrayList();
  1344. for (TakaiApplicationResult application : appList) {
  1345. Map<String, Object> appMap = new HashMap();
  1346. appMap.put("appId", application.getAppId());
  1347. appMap.put("showMenu", "false");
  1348. appMap.put("chatMode", "LOCAL");
  1349. appMap.put("title", application.getName());
  1350. newAppList.add(appMap);
  1351. }
  1352. newProjectAppMap.put("title", projectName);
  1353. newProjectAppMap.put("children",newAppList);
  1354. projectAppList.add(newProjectAppMap);
  1355. }
  1356. }
  1357. projectLevelMap.put("children",projectAppList);
  1358. return projectLevelMap;
  1359. };
  1360. private Map<String, Object> searchAppTypeGroupList(TakaiApplication paramsVo, SysDictData dictData) {
  1361. //慧监理
  1362. paramsVo.setTypeId(Long.valueOf(42));
  1363. List<TakaiApplicationResult> list1 = takaiApplicationMapper.selectApplicationList(paramsVo);
  1364. //慧项管
  1365. paramsVo.setTypeId(Long.valueOf(43));
  1366. List<TakaiApplicationResult> list2 = takaiApplicationMapper.selectApplicationList(paramsVo);
  1367. List<TakaiApplicationResult> list3 = new ArrayList();
  1368. list3.addAll(list1);
  1369. list3.addAll(list2);
  1370. Map<String, Object> map = new HashMap();
  1371. if (list3!= null && list3.size() > 0) {
  1372. List<Object> l = new ArrayList<>();
  1373. map.put("title", dictData.getDictLabel());
  1374. // 分组
  1375. Map<String, List<TakaiApplicationResult>> map1 = list3.stream().collect(Collectors.groupingBy(TakaiApplicationResult::getTypeId));
  1376. for (Map.Entry<String, List<TakaiApplicationResult>> entry : map1.entrySet()) {
  1377. List<TakaiApplicationResult> mp = entry.getValue();
  1378. Map<String, Object> infoProjectMap = new HashMap();
  1379. List<Object> projectInfoList = new ArrayList();
  1380. for (TakaiApplicationResult application : mp){
  1381. SysDictData vo = sysDictDataMapper.selectDictDataById(Long.valueOf(application.getTypeId()));
  1382. infoProjectMap.put("title", vo.getDictLabel());
  1383. Map<String, Object> projectMap = new HashMap();
  1384. projectMap.put("appId", application.getAppId());
  1385. projectMap.put("showMenu", "false");
  1386. projectMap.put("chatMode", "LOCAL");
  1387. projectMap.put("title", application.getName());
  1388. projectInfoList.add(projectMap);
  1389. }
  1390. infoProjectMap.put("children", projectInfoList);
  1391. l.add(infoProjectMap);
  1392. }
  1393. map.put("children", l);
  1394. }
  1395. return map;
  1396. }
  1397. @Override
  1398. public List<TakaiApplication> applicationListByApprover(TakaiApplicationParams takaiApplicationParams) {
  1399. TakaiApplication vo = TakaiApplication.builder().approver(takaiApplicationParams.getApprover())
  1400. .build();
  1401. return takaiApplicationMapper.selectAppListByApprover(vo);
  1402. }
  1403. @Override
  1404. public int startAudit(String appId, String userId) {
  1405. List<DocumentAuditConfig> list = documentAuditConfigMapper.selectDocumentAuditConfigListByBo(null);
  1406. if(list != null && list.size() > 0) {
  1407. ApprovalFlowManager flowManager = new ApprovalFlowManager();
  1408. logger.info("开启审核");
  1409. for (DocumentAuditConfig config : list) {
  1410. // 添加审核节点
  1411. flowManager.addNode(new ApprovalNode(config.getId(), config.getNodeOrder(), config.getApprover(), config.getChain()));
  1412. }
  1413. ApprovalNode vo = flowManager.getFirstApprover();
  1414. TakaiApplication appVo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(appId).build());
  1415. appVo.setApprover(String.valueOf(vo.getApprover()));
  1416. appVo.setNodeOrder(String.valueOf(vo.getNodeOrder()));
  1417. appVo.setStatus("1");
  1418. int i = takaiApplicationMapper.updateApplication(appVo);
  1419. if(i > 0){
  1420. DocumentAuditInfo info = new DocumentAuditInfo();
  1421. info.setAppId(appId);
  1422. info.setApprover(userId);
  1423. info.setStatus("5");
  1424. info.setNodeOrder(Integer.valueOf("0"));
  1425. info.setCreateBy(userId);
  1426. info.setCreateTime(new Date());
  1427. documentAuditInfoMapper.insertDocumentAuditInfo(info); // 审核记录
  1428. }
  1429. return i;
  1430. }else{
  1431. return 9;
  1432. }
  1433. }
  1434. @Override
  1435. public int updateAuditApplication(TakaiApplicationParams appParams, String appId) {
  1436. // 获取审核配置信息 (人员,节点)
  1437. List<DocumentAuditConfig> list = documentAuditConfigMapper.selectDocumentAuditConfigListByBo(null);
  1438. if(list != null && list.size() > 0){
  1439. if(("Y").equals(appParams.getStatus())){
  1440. ApprovalFlowManager flowManager = new ApprovalFlowManager();
  1441. logger.info("审核通过,开始审批流程");
  1442. for (DocumentAuditConfig config: list){
  1443. // 添加审核节点
  1444. flowManager.addNode(new ApprovalNode(config.getId(), config.getNodeOrder(), config.getApprover(), config.getChain()));
  1445. }
  1446. // 根据审核节点获取下一个审核节点
  1447. ApprovalNode nextNode = flowManager.getNextApproverByOrder(Integer.valueOf(appParams.getNodeOrder()));
  1448. if (nextNode == null) {
  1449. // 审核通过,更新文档状态
  1450. logger.info("审核通过,到最后节点");
  1451. return saveAuditInfo(appParams, "3", appId);
  1452. }else{
  1453. // 审核通过,下一个节点
  1454. TakaiApplication appVo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(appId).build());
  1455. appVo.setApprover(String.valueOf(nextNode.getApprover()));
  1456. appVo.setNodeOrder(String.valueOf(nextNode.getNodeOrder()));
  1457. appVo.setStatus("2");
  1458. appVo.setComment(appParams.getComment());
  1459. int successI = takaiApplicationMapper.updateApplication(appVo);
  1460. if(successI > 0){
  1461. DocumentAuditInfo info = new DocumentAuditInfo();
  1462. info.setAppId(appId);
  1463. info.setApprover(appParams.getApprover());
  1464. info.setComment(appParams.getComment());
  1465. info.setStatus("2");
  1466. info.setNodeOrder(Integer.valueOf(appParams.getNodeOrder()));
  1467. info.setCreateBy(appParams.getApprover());
  1468. info.setCreateTime(new Date());
  1469. documentAuditInfoMapper.insertDocumentAuditInfo(info); // 审核记录
  1470. }
  1471. return successI;
  1472. }
  1473. }else{
  1474. // 审核拒绝,更新文档状态
  1475. logger.info("审核拒绝,更新状态");
  1476. return saveAuditInfo(appParams, "5", appId);
  1477. }
  1478. }
  1479. return 0;
  1480. }
  1481. private int saveAuditInfo(TakaiApplicationParams appParams, String status, String appId){
  1482. TakaiApplication appVo = takaiApplicationMapper.selectTargetApplication(TakaiApplication.builder().appId(appId).build());
  1483. appVo.setApprover(appParams.getApprover());
  1484. appVo.setNodeOrder(appParams.getNodeOrder());
  1485. appVo.setStatus(status);
  1486. appVo.setComment(appParams.getComment());
  1487. int successI = takaiApplicationMapper.updateApplication(appVo);
  1488. if(successI > 0){
  1489. DocumentAuditInfo info = new DocumentAuditInfo();
  1490. info.setAppId(appId);
  1491. info.setApprover(appParams.getApprover());
  1492. info.setComment(appParams.getComment());
  1493. if("5".equals(status)){
  1494. info.setStatus("4");
  1495. }else{
  1496. info.setStatus(status);
  1497. }
  1498. info.setNodeOrder(Integer.valueOf(appParams.getNodeOrder()));
  1499. info.setCreateBy(appParams.getApprover());
  1500. info.setCreateTime(new Date());
  1501. documentAuditInfoMapper.insertDocumentAuditInfo(info); // 审核记录
  1502. }
  1503. return successI;
  1504. }
  1505. @Override
  1506. public List<TakaiApplicationResult> selectAppByUserId(String userId) {
  1507. return takaiApplicationMapper.selectAppByUserId(userId);
  1508. }
  1509. @Override
  1510. public List<String> selectAppCollectList(String userId) {
  1511. return appCollectMapper.selectAppCollectList(userId);
  1512. }
  1513. @Override
  1514. public int insertAppCollect(AppCollect appCollect) {
  1515. AppCollect collect = appCollectMapper.selectAppCollectDetail(appCollect.getAppId(), appCollect.getUserId());
  1516. if (collect == null) {
  1517. return appCollectMapper.insertAppCollect(appCollect);
  1518. }
  1519. return 0;
  1520. }
  1521. @Override
  1522. public int deleteAppCollect(String userId, String appId) {
  1523. return appCollectMapper.delAppCollect(userId, appId);
  1524. }
  1525. @Override
  1526. public List<TakaiApplicationResult> selectRoleApp() {
  1527. return takaiApplicationMapper.selectRoleApp();
  1528. }
  1529. @Override
  1530. public List<TakaiApplicationResult> getChatAppList(List<TakaiApplicationResult> params, String userId) {
  1531. List<TakaiApplicationResult> list = new ArrayList();
  1532. for (TakaiApplicationResult app : params) {
  1533. AppCollect appCollect = appCollectMapper.selectAppCollectDetail(app.getAppId(), userId);
  1534. SysDictData dictData = null;
  1535. if(app.getTypeId() != null && !"".equals(app.getTypeId())){
  1536. dictData = sysDictDataMapper.selectDictDataById(Long.valueOf(app.getTypeId()));
  1537. }
  1538. TakaiApplicationResult appResult = new TakaiApplicationResult();
  1539. appResult.setAppId(app.getAppId());
  1540. appResult.setName(app.getName());
  1541. appResult.setDesc(app.getDesc());
  1542. appResult.setTypeId(app.getTypeId());
  1543. appResult.setCreateTime(app.getCreateTime());
  1544. appResult.setChatMode("LOCAL");
  1545. appResult.setIsCollect(appCollect != null ? true : false);
  1546. appResult.setTypeName(dictData != null ? dictData.getDictLabel() : "");
  1547. list.add(appResult);
  1548. }
  1549. return list;
  1550. }
  1551. private ApprovalNode getFirstApproverNode() {
  1552. List<DocumentAuditConfig> list = documentAuditConfigMapper.selectDocumentAuditConfigListByBo(null);
  1553. if(list != null && list.size() > 0) {
  1554. ApprovalFlowManager flowManager = new ApprovalFlowManager();
  1555. logger.info("开启审核");
  1556. for (DocumentAuditConfig config : list) {
  1557. // 添加审核节点
  1558. flowManager.addNode(new ApprovalNode(config.getId(), config.getNodeOrder(), config.getApprover(), config.getChain()));
  1559. }
  1560. return flowManager.getFirstApprover();
  1561. }
  1562. return null;
  1563. }
  1564. private JSONObject analysisFile(List<UploadDocumentParams> result, TakaiDocumentSettings settings, String flag) {
  1565. String url = deepseekConfig.getBaseurl() + deepseekConfig.getUploadKnowledge();
  1566. JSONObject json = new JSONObject();
  1567. json.put("knowledge_id", settings.getKnowledgeId());
  1568. json.put("docs", result);
  1569. if ("upload".equals(flag)) {
  1570. json.put("set_slice", "0");
  1571. json.put("slice_value", null);
  1572. json.put("set_analyze", "1");
  1573. json.put("set_table", "0");
  1574. json.put("flag", "upload");
  1575. } else {
  1576. json.put("set_slice", settings.getSetSlice());
  1577. json.put("slice_value", settings.getSliceValue());
  1578. json.put("set_analyze", settings.getSetAnalyze());
  1579. json.put("set_table", settings.getSetTable());
  1580. json.put("flag", "update");
  1581. }
  1582. RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), json.toJSONString());
  1583. Request request = buildPostRequest(url, requestBody);
  1584. OkHttpClient client = buildOkHttpClient();
  1585. Response response = null;
  1586. try {
  1587. response = client.newCall(request).execute();
  1588. if (response.isSuccessful()) {
  1589. String body = response.body().string();
  1590. JSONObject obj = JSON.parseObject(body);
  1591. Integer code = obj.getInteger("code");
  1592. if (code == 200) {
  1593. logger.info("上传文档调用python接口成功,返回内容:{}", body);
  1594. } else {
  1595. logger.info("上传文档调用python接口失败,返回内容:{}", body);
  1596. }
  1597. return obj;
  1598. } else {
  1599. logger.error("上传文档调用python接口失败返回code:{}", response.code());
  1600. return null;
  1601. }
  1602. } catch (IOException e) {
  1603. logger.error("上传文档调用python接口失败", e.getMessage());
  1604. return null;
  1605. }
  1606. }
  1607. @Override
  1608. public List<Object> setDialogList(List<TakaiDialogRespDTO> list) {
  1609. //根据时间分组降序排序
  1610. NavigableMap<LocalDateTime, List<TakaiDialogRespDTO>> groupList = list.stream().collect(Collectors.groupingBy(TakaiDialogRespDTO::getCreate_time, TreeMap::new, Collectors.toList())).descendingMap();
  1611. List<Object> obj = new ArrayList();
  1612. if (!groupList.isEmpty()) {
  1613. for (Map.Entry<LocalDateTime, List<TakaiDialogRespDTO>> entry : groupList.entrySet()) {
  1614. List<TakaiDialogRespDTO> aList = entry.getValue();
  1615. List<TakaiDialogRespDTO> detailList = takaiDialogMapper.selectDialogExport(aList.get(0).getId());
  1616. Map<String, Object> map = new HashMap();
  1617. map.put("dialog_name", aList.get(0).getDialog_name());
  1618. map.put("length", detailList.size());
  1619. map.put("create_time", aList.get(0).getCreate_time());
  1620. map.put("did", aList.get(0).getDid());
  1621. map.put("id", aList.get(0).getId());
  1622. obj.add(map);
  1623. }
  1624. }
  1625. return obj;
  1626. }
  1627. private List<Map<String, Object>> setValue(List<TakaiDialogRespDTO> list, String appId) {
  1628. List<Map<String, Object>> l = new ArrayList();
  1629. for (TakaiDialogRespDTO vo : list) {
  1630. Map<String, Object> map = new HashMap();
  1631. map.put("key", vo.getId());
  1632. map.put("label", vo.getDialog_name());
  1633. map.put("appId", appId);
  1634. map.put("showMenu", "false");
  1635. map.put("chatMode", "LOCAL");
  1636. l.add(map);
  1637. }
  1638. return l;
  1639. }
  1640. private OkHttpClient buildOkHttpClient() {
  1641. return new OkHttpClient.Builder()
  1642. .connectTimeout(10, TimeUnit.SECONDS)
  1643. .writeTimeout(50, TimeUnit.SECONDS)
  1644. .readTimeout(20, TimeUnit.MINUTES)
  1645. .build();
  1646. }
  1647. private Request buildGetRequest(String url) {
  1648. return new Request.Builder()
  1649. .addHeader("User-Agent", "insomnia/10.3.1")
  1650. .url(url).get().build();
  1651. }
  1652. private Request buildPostRequest(String url, RequestBody requestBody) {
  1653. return new Request.Builder()
  1654. .addHeader("User-Agent", "insomnia/10.3.1")
  1655. .addHeader("Content-Type", "application/json")
  1656. .url(url).post(requestBody).build();
  1657. }
  1658. private Request buildPutRequest(String url, RequestBody requestBody) {
  1659. return new Request.Builder()
  1660. .addHeader("User-Agent", "insomnia/10.3.1")
  1661. .url(url).put(requestBody).build();
  1662. }
  1663. private Request buildDeleteRequest(String url) {
  1664. return new Request.Builder()
  1665. .addHeader("Content-Type", "multipart/form-data")
  1666. .addHeader("User-Agent", "insomnia/10.3.1")
  1667. .url(url).delete().build();
  1668. }
  1669. private Request buildUploadPostRequest(String url, RequestBody requestBody) {
  1670. return new Request.Builder()
  1671. .addHeader("User-Agent", "insomnia/10.3.1")
  1672. .addHeader("Content-Type", "application/json")
  1673. .url(url).post(requestBody).build();
  1674. }
  1675. private boolean isJsonObject(String data) {
  1676. try {
  1677. JSON.parseObject(data);
  1678. return true;
  1679. } catch (Exception e) {
  1680. return false;
  1681. }
  1682. }
  1683. }