|
|
@@ -0,0 +1,385 @@
|
|
|
+package cn.cslg.pas.service.dify;
|
|
|
+
|
|
|
+import cn.cslg.pas.common.model.cronModel.SystemFile;
|
|
|
+import cn.cslg.pas.common.model.dify.*;
|
|
|
+import cn.cslg.pas.common.model.dify.generateDiscoveryResult.DiscoryResultVO;
|
|
|
+import cn.cslg.pas.common.model.dify.generateDiscoveryResult.QueryDiscoveryPictureDTO;
|
|
|
+import cn.cslg.pas.common.model.dify.generateDiscoveryResult.UpdateDiscoveryPictureDTO;
|
|
|
+import cn.cslg.pas.common.model.dify.generateRejection.GenerateRejectionDTO;
|
|
|
+import cn.cslg.pas.common.utils.*;
|
|
|
+import cn.cslg.pas.common.utils.commonUtils.HoliDayUtils;
|
|
|
+import cn.cslg.pas.common.vo.StarPatentVO;
|
|
|
+import cn.cslg.pas.domain.business.ReportTemple;
|
|
|
+import cn.cslg.pas.domain.dify.AssoConfessionSessionFile;
|
|
|
+import cn.cslg.pas.domain.dify.ConfessionSession;
|
|
|
+import cn.cslg.pas.exception.ExceptionEnum;
|
|
|
+import cn.cslg.pas.exception.XiaoShiException;
|
|
|
+import cn.cslg.pas.mapper.dify.ConfessionSessionMapper;
|
|
|
+import cn.cslg.pas.service.TemplateExportService;
|
|
|
+import cn.cslg.pas.service.business.ReportTempleService;
|
|
|
+import cn.cslg.pas.service.common.DifyService;
|
|
|
+import cn.cslg.pas.service.common.FileManagerService;
|
|
|
+import cn.cslg.pas.service.common.WordService;
|
|
|
+import cn.cslg.pas.service.common.XwpfTemplateService;
|
|
|
+import cn.cslg.pas.service.importPatent.ImportSinglePatentService;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.deepoove.poi.XWPFTemplate;
|
|
|
+import com.google.gson.Gson;
|
|
|
+import jakarta.json.Json;
|
|
|
+import okhttp3.*;
|
|
|
+import okhttp3.Response;
|
|
|
+import org.apache.commons.lang3.ObjectUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import reactor.core.publisher.Flux;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.Duration;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class GenerateRejectionService {
|
|
|
+ @Autowired
|
|
|
+ private DifyService difyService;
|
|
|
+ @Value("${FileDownloadUrl}")
|
|
|
+ private String fileDownloadUrl;
|
|
|
+ @Value("${DIFY.url}")
|
|
|
+ private String url;
|
|
|
+ @Autowired
|
|
|
+ private ConfessionSessionService confessionSessionService;
|
|
|
+ @Autowired
|
|
|
+ private LoginUtils loginUtils;
|
|
|
+ @Value("${DIFY.generateRejectionKey}")
|
|
|
+ private String generateRejectionKey;
|
|
|
+ @Autowired
|
|
|
+ private FileManagerService fileManagerService;
|
|
|
+ @Autowired
|
|
|
+ private WordService wordService;
|
|
|
+ @Autowired
|
|
|
+ private AssoConfessionSessionFileService assoConfessionSessionFileService;
|
|
|
+ @Autowired
|
|
|
+ private ConfessionSessionMapper confessionSessionMapper;
|
|
|
+ @Autowired
|
|
|
+ private ReportTempleService reportTempleService;
|
|
|
+ @Autowired
|
|
|
+ private FileUtils fileUtils;
|
|
|
+ @Autowired
|
|
|
+ private XwpfTemplateService xwpfTemplateService;
|
|
|
+ @Autowired
|
|
|
+ private ImportSinglePatentService importSinglePatentService;
|
|
|
+ @Autowired
|
|
|
+ private HoliDayUtils holiDayUtils;
|
|
|
+
|
|
|
+ public Flux<String> GenerateRejectionDTO(GenerateRejectionDTO generateRejectionDTO) throws Exception {
|
|
|
+ DiscoryResultVO discoryResultVO = null;
|
|
|
+ Integer confessionSessionId = generateRejectionDTO.getConfessionSessionId();
|
|
|
+ String rejectionDecision = generateRejectionDTO.getRejectionDecision();
|
|
|
+ String reviewFiles = generateRejectionDTO.getReviewFiles();
|
|
|
+ String reviewSuggest = generateRejectionDTO.getReviewSuggest();
|
|
|
+ ConfessionSession confessionSession = confessionSessionService.getById(confessionSessionId);
|
|
|
+ String conversionId = confessionSession.getConversationId();
|
|
|
+ String createId = confessionSession.getCreateId();
|
|
|
+
|
|
|
+ OkHttpClient client = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+
|
|
|
+
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("rejection_decision", rejectionDecision);
|
|
|
+ map.put("review_files", reviewFiles);
|
|
|
+ map.put("review_suggest", reviewSuggest);
|
|
|
+
|
|
|
+ OAMessageDTO oaMessageDTO = new OAMessageDTO();
|
|
|
+ oaMessageDTO.setInputs(map);
|
|
|
+ oaMessageDTO.setResponseMode("streaming");
|
|
|
+ oaMessageDTO.setUser(createId);
|
|
|
+ oaMessageDTO.setQuery("生成驳回指导函");
|
|
|
+ oaMessageDTO.setConversationId(conversionId);
|
|
|
+ oaMessageDTO.setFiles(new ArrayList<>());
|
|
|
+
|
|
|
+ String param = new Gson().toJson(oaMessageDTO);
|
|
|
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(url + "chat-messages")
|
|
|
+ .addHeader("Authorization", "Bearer " + generateRejectionKey)
|
|
|
+ .addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
|
|
|
+ .post(requestBody)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ AtomicBoolean businessCompleted = new AtomicBoolean(false);
|
|
|
+
|
|
|
+
|
|
|
+ Flux<String> businessFlux = Flux.create(emitter -> {
|
|
|
+ client.newCall(request).enqueue(new Callback() {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onFailure(Call call, IOException e) {
|
|
|
+ emitter.error(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onResponse(Call call, Response response) throws IOException {
|
|
|
+
|
|
|
+ if (!response.isSuccessful()) {
|
|
|
+ emitter.error(new IOException("Unexpected code: " + response));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try (Reader reader = response.body().charStream()) {
|
|
|
+ BufferedReader bufferedReader = new BufferedReader(reader);
|
|
|
+ String line;
|
|
|
+ String prefixToRemove = "data: ";
|
|
|
+ String runId = conversionId;
|
|
|
+ while ((line = bufferedReader.readLine()) != null) {
|
|
|
+ if (line.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (line.startsWith(prefixToRemove)) {
|
|
|
+ line = line.substring(prefixToRemove.length());
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ JSONObject jsonObject = JSON.parseObject(line);
|
|
|
+ String sessionConversationId = jsonObject.get("conversation_id").toString();
|
|
|
+ String event = jsonObject.get("event").toString();
|
|
|
+ if (StringUtils.isEmpty(runId)) {
|
|
|
+ if (StringUtils.isNotEmpty(sessionConversationId)) {
|
|
|
+ runId = sessionConversationId;
|
|
|
+ confessionSessionMapper.updateSingleField(confessionSessionId, "conversation_id", sessionConversationId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (event.equals("message")) {
|
|
|
+ String data = jsonObject.get("answer").toString();
|
|
|
+ JSONObject dataObject = null;
|
|
|
+ if (StringUtils.isNotEmpty(data)) {
|
|
|
+ try {
|
|
|
+ dataObject = JSON.parseObject(data);
|
|
|
+ String code = dataObject.get("code").toString();
|
|
|
+ if (StringUtils.equals(code, "200")) {
|
|
|
+ JSONObject object = dataObject.getJSONObject("data");
|
|
|
+ List<JSONObject> publicNos = getPubilcNos(object);
|
|
|
+ saveContent(confessionSession, publicNos);
|
|
|
+ generateDoc(generateRejectionDTO, confessionSessionId, object, publicNos);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ emitter.next(line); // 将每行数据发送到 Flux
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ emitter.error(e);
|
|
|
+ } finally {
|
|
|
+ businessCompleted.set(true);
|
|
|
+ emitter.complete();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ return businessFlux;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public Map<String, Object> loadMap(GenerateRejectionDTO generateRejectionDTO, JSONObject object, List<JSONObject> allPublicNos) {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("case_volume", generateRejectionDTO.getCaseVolume());
|
|
|
+ map.put("review_count", generateRejectionDTO.getReviewCount());
|
|
|
+ map.put("review_suggest", generateRejectionDTO.getReviewSuggest());
|
|
|
+ JSONObject rejectionDecision = object.getJSONObject("rejection_decision");
|
|
|
+ String appNo = rejectionDecision.getString("appNo").replace(" ", "");
|
|
|
+ map.put("appNo", appNo);
|
|
|
+ rejectionDecision.put("appNo", appNo);
|
|
|
+ String title = rejectionDecision.getString("title").replace(" ", "");
|
|
|
+ map.put("title", title);
|
|
|
+ rejectionDecision.put("title", title);
|
|
|
+ String issuance = rejectionDecision.getString("issuance").replace(" ", "");
|
|
|
+ rejectionDecision.put("issuance", issuance);
|
|
|
+
|
|
|
+ try {
|
|
|
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
|
|
|
+ Date issuanceDate = simpleDateFormat.parse(issuance);
|
|
|
+ Date reviewPeriod = DateUtils.getPlusMonthDate(issuanceDate, 3);
|
|
|
+ reviewPeriod = holiDayUtils.getWorkingDay(reviewPeriod);
|
|
|
+ String reviewPeriodStr = simpleDateFormat.format(reviewPeriod);
|
|
|
+ map.put("review_period", reviewPeriodStr);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> rejectionAnalysis = new ArrayList<>();
|
|
|
+ String rejectionAnalysisStr = object.getString("rejection_analysis");
|
|
|
+ List<String> rejectionAnalysisList = JSONArray.parseArray(rejectionAnalysisStr, String.class);
|
|
|
+ for (String item : rejectionAnalysisList) {
|
|
|
+ List<String> tem = cn.cslg.pas.common.utils.StringUtils.changeStringToString(item, "\r?\n+|<br>+");
|
|
|
+ rejectionAnalysis.addAll(tem);
|
|
|
+ }
|
|
|
+ map.put("rejection_analysis",rejectionAnalysis);
|
|
|
+ List<JSONObject> reviewFileList = new ArrayList<>();
|
|
|
+ List<JSONObject> reviewFiles = object.getJSONArray("review_files");
|
|
|
+ for (JSONObject jsonObject : reviewFiles) {
|
|
|
+ JSONObject stateOpinions = jsonObject.getJSONObject("state_opinions");
|
|
|
+ JSONObject examinationOpinion = jsonObject.getJSONObject("examination_opinion");
|
|
|
+ List<JSONObject> publicNos = examinationOpinion.getJSONArray("publicNos");
|
|
|
+ String itemPublicNosStr = null;
|
|
|
+ for (Integer i = 0; i < publicNos.size(); i++) {
|
|
|
+ JSONObject publicNo = publicNos.get(i);
|
|
|
+ Integer pIndex = publicNo.getInteger("index");
|
|
|
+ String pPublicNo = publicNo.getString("publicNo");
|
|
|
+ String sign = "、";
|
|
|
+ if (i == publicNos.size() - 1) {
|
|
|
+ sign = "和";
|
|
|
+ }
|
|
|
+ if (itemPublicNosStr != null) {
|
|
|
+ itemPublicNosStr = itemPublicNosStr + sign + "对比文件" + pIndex + "("+pPublicNo+")";
|
|
|
+ } else {
|
|
|
+ itemPublicNosStr = "对比文件" + pIndex + "("+pPublicNo+")";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ JSONObject obj = new JSONObject();
|
|
|
+ Integer num = jsonObject.getInteger("num");
|
|
|
+ obj.put("num", DataUtils.numberToChinese(num));
|
|
|
+
|
|
|
+ if (stateOpinions.getString("claimChange") != null) {
|
|
|
+ stateOpinions.put("claimChange", stateOpinions.getString("claimChange").replace(" ", ""));
|
|
|
+ }
|
|
|
+ if (stateOpinions.getString("difference_feature") != null) {
|
|
|
+ stateOpinions.put("difference_feature", stateOpinions.getString("difference_feature").replace("\\n", "").replace(" ", ""));
|
|
|
+ }
|
|
|
+ obj.put("state_opinions", stateOpinions);
|
|
|
+ if (examinationOpinion.getString("issuance") != null) {
|
|
|
+ examinationOpinion.put("issuance", examinationOpinion.getString("issuance").replace(" ", ""));
|
|
|
+ }
|
|
|
+ if (examinationOpinion.getString("reason") != null) {
|
|
|
+ examinationOpinion.put("reason", examinationOpinion.getString("reason").replace(" ", ""));
|
|
|
+ }
|
|
|
+ examinationOpinion.put("publicNos", itemPublicNosStr);
|
|
|
+ obj.put("examination_opinion", examinationOpinion);
|
|
|
+ reviewFileList.add(obj);
|
|
|
+ }
|
|
|
+ map.put("review_files", reviewFileList);
|
|
|
+ JSONObject lastReviewFile = reviewFileList.get(reviewFileList.size() - 1);
|
|
|
+ JSONObject lastExaminationOpinion = lastReviewFile.getJSONObject("examination_opinion");
|
|
|
+ String lastReason = lastExaminationOpinion.getString("reason");
|
|
|
+ rejectionDecision.put("reason", lastReason);
|
|
|
+ map.put("rejection_decision", rejectionDecision);
|
|
|
+ map.put("publicNos", allPublicNos);
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void generateDoc(GenerateRejectionDTO generateRejectionDTO, Integer confessionSessionId, JSONObject object, List<JSONObject> publicNos) {
|
|
|
+ ConfessionSession confessionSession = confessionSessionService.getById(confessionSessionId);
|
|
|
+ String content = confessionSession.getContent();
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+
|
|
|
+ map = this.loadMap(generateRejectionDTO, object, publicNos);
|
|
|
+ ReportTemple reportTemplate = reportTempleService.getById(26);
|
|
|
+ String templateFilePath = fileUtils.getPath(reportTemplate.getTemplatePath());
|
|
|
+ //更新会话
|
|
|
+ String name = DateUtils.dateTimeToStr(new Date(), "yyyyMMdd");
|
|
|
+
|
|
|
+ String finalName = name + "-" + generateRejectionDTO.getCaseVolume() + "-驳回指导函";
|
|
|
+ //生成文档
|
|
|
+ String fileGuid = null;
|
|
|
+ try {
|
|
|
+ fileGuid = this.generateFile(map, templateFilePath, finalName);
|
|
|
+ LambdaUpdateWrapper<AssoConfessionSessionFile> wrapper = new LambdaUpdateWrapper<>();
|
|
|
+ wrapper.eq(AssoConfessionSessionFile::getConfessionSessionId, confessionSessionId).isNull(AssoConfessionSessionFile::getType);
|
|
|
+ assoConfessionSessionFileService.remove(wrapper);
|
|
|
+ AssoConfessionSessionFile assoConfessionSessionFile = new AssoConfessionSessionFile();
|
|
|
+ assoConfessionSessionFile.setGuid(fileGuid);
|
|
|
+ assoConfessionSessionFile.setConfessionSessionId(confessionSessionId);
|
|
|
+ assoConfessionSessionFile.insert();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ throw new XiaoShiException(ExceptionEnum.BUSINESS_ERROR, "生成驳回指导函失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public String generateFile(Map<String, Object> map, String templateFilePath, String name) throws Exception {
|
|
|
+ XWPFTemplate xwpfTemplate = xwpfTemplateService.getHtmlTemplate(map, templateFilePath);
|
|
|
+ String fileName = name + ".docx";
|
|
|
+ String directoryName = fileUtils.createDirectory();
|
|
|
+ String outPath = fileUtils.getSavePath(directoryName) + fileName;
|
|
|
+ File file = new File(outPath);
|
|
|
+ // 生成word保存在指定目录
|
|
|
+ xwpfTemplate.writeToFile(outPath);
|
|
|
+ xwpfTemplate.close();
|
|
|
+ List<String> ids = fileManagerService.uploadFileGetGuid2(Collections.singletonList(file));
|
|
|
+ if (CollectionUtils.isEmpty(ids)) {
|
|
|
+ throw new XiaoShiException("保存记录失败");
|
|
|
+ }
|
|
|
+ return ids.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<JSONObject> getPubilcNos(JSONObject jsonObject) {
|
|
|
+ //去重
|
|
|
+ List<JSONObject> patentLists = new ArrayList<>();
|
|
|
+ List<JSONObject> jsonObjectList = jsonObject.getJSONArray("review_files");
|
|
|
+ for (JSONObject fileObject : jsonObjectList) {
|
|
|
+ JSONObject exObject = fileObject.getJSONObject("examination_opinion");
|
|
|
+ List<JSONObject> publicNoList = exObject.getJSONArray("publicNos");
|
|
|
+ List<String> patentNos = patentLists.stream().map(item -> item.getString("publicNo")).collect(Collectors.toList());
|
|
|
+ List<JSONObject> jsonObjects = publicNoList.stream().filter(item -> !patentNos.contains(item.getString("publicNo"))).collect(Collectors.toList());
|
|
|
+ if (jsonObjects != null && jsonObjects.size() > 0) {
|
|
|
+ patentLists.addAll(jsonObjects);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ //装载
|
|
|
+ this.loadPatentList(patentLists);
|
|
|
+ return patentLists;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void saveContent(ConfessionSession confessionSession, List<JSONObject> patentLists) {
|
|
|
+ Integer confessionSessionId = confessionSession.getId();
|
|
|
+ String content = confessionSession.getContent();
|
|
|
+ JSONObject contentObject = new JSONObject();
|
|
|
+ if (content != null && !content.trim().equals("")) {
|
|
|
+ contentObject = JSON.parseObject(content);
|
|
|
+ }
|
|
|
+ contentObject.put("contrast_files", patentLists);
|
|
|
+ String reJson = JSON.toJSONString(contentObject);
|
|
|
+ confessionSessionMapper.updateSingleField(confessionSessionId, "content", reJson);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void loadPatentList(List<JSONObject> jsonObjects) {
|
|
|
+ for (JSONObject jsonObject : jsonObjects) {
|
|
|
+ String publicNo = jsonObject.getString("publicNo");
|
|
|
+ StarPatentVO starPatentVO = importSinglePatentService.getPatentFromWeb(publicNo);
|
|
|
+ jsonObject.put("title", starPatentVO.getTI());
|
|
|
+ jsonObject.put("type", "pdf");
|
|
|
+ String appNo = starPatentVO.getAN();
|
|
|
+ try {
|
|
|
+ List<String> guids = importSinglePatentService.getPDFFromWeb(starPatentVO);
|
|
|
+ if (guids.size() > 0) {
|
|
|
+ String guid = guids.get(guids.size() - 1);
|
|
|
+ jsonObject.put("guid", guid);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|