package com.supervision.police.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.supervision.chat.UploadParamEnum; import com.supervision.chat.client.LangChainChatService; import com.supervision.chat.client.dto.CreateBaseDTO; import com.supervision.chat.client.dto.LangChainChatRes; import com.supervision.common.domain.R; import com.supervision.common.enums.ResultStatusEnum; import com.supervision.common.exception.CustomException; import com.supervision.common.utils.ExcelReader; import com.supervision.common.utils.IPages; import com.supervision.common.utils.StringUtils; import com.supervision.config.BusinessException; import com.supervision.constant.DataStatus; import com.supervision.police.domain.CasePerson; import com.supervision.police.domain.ComDictionary; import com.supervision.police.dto.*; import com.supervision.police.mapper.ModelCaseMapper; import com.supervision.police.domain.ModelCase; import com.supervision.police.service.CasePersonService; import com.supervision.police.service.CaseStatusManageService; import com.supervision.police.service.ComDictionaryService; import com.supervision.police.service.ModelCaseService; import com.supervision.police.vo.ModelCaseVO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * 案件表(ModelCase)表服务实现类 * * @author qmy * @since 2024-07-02 14:51:27 */ @Slf4j @Service @RequiredArgsConstructor public class ModelCaseServiceImpl extends ServiceImpl implements ModelCaseService { private final ComDictionaryService comDictionaryService; private final ModelCaseMapper modelCaseMapper; private final CasePersonService casePersonService; private final CaseStatusManageService caseStatusManageService; private final LangChainChatService langChainChatService; /** * 查询列表 * * @param modelCase * @param page * @param size * @return */ @Override public IPage queryList(ModelCaseVO modelCase, Integer page, Integer size) { IPage modelCaseIPage = modelCaseMapper.selectAll(Page.of(page, size), modelCase); if (CollUtil.isEmpty(modelCaseIPage.getRecords())) { return Page.of(page, size); } List caseIdList = modelCaseIPage.getRecords().stream().map(ModelCase::getId).toList(); List casePersonList = casePersonService.list( Wrappers.lambdaQuery(CasePerson.class).in(CasePerson::getCaseId, caseIdList)); // 多级分组 Map>> persionMap = casePersonList.stream().collect(Collectors.groupingBy(CasePerson::getCaseId, Collectors.groupingBy(person -> NumberUtil.equals(person.getCaseActorFlag(), 1) ? "1" : "2"))); List dicts = comDictionaryService.list(); return modelCaseIPage.convert(modelCaseInfo -> { ModelCaseDTO modelCaseDTO = BeanUtil.toBean(modelCaseInfo, ModelCaseDTO.class, CopyOptions.create().setIgnoreProperties("lawActor")); String[] caseTypes = modelCaseDTO.getCaseType().split(","); List caseType = new ArrayList<>(); for (String type : caseTypes) { caseType.add(comDictionaryService.getName(dicts, "case_type", type)); } if (StrUtil.isEmpty(modelCaseDTO.getCaseStatus())) { modelCaseDTO.setCaseStatus("1"); } modelCaseDTO.setCaseTypeName(StringUtils.join(caseType, ",")); modelCaseDTO.setCaseStatusName(comDictionaryService.getName(dicts, "case_status", modelCaseDTO.getCaseStatus())); modelCaseDTO.setCrimeModeName(comDictionaryService.getName(dicts, "crime_mode", modelCaseDTO.getCrimeMode())); modelCaseDTO.setIdentifyResultName(comDictionaryService.getName(dicts, "identify_result", modelCaseDTO.getIdentifyResult())); Map> casePersonMap = persionMap.get(modelCaseDTO.getId()); if (CollUtil.isNotEmpty(casePersonMap)) { Optional optionalCasePerson = casePersonMap.getOrDefault("1", new ArrayList<>()) .stream().filter(person -> Integer.valueOf(1).equals(person.getCaseActorFlag())).findAny(); if (optionalCasePerson.isPresent()){ modelCaseDTO.setLawActor(optionalCasePerson.get()); modelCaseDTO.floatLawActorInfo(); } modelCaseDTO.setLawPartyList(casePersonMap.getOrDefault("2", new ArrayList<>())); } if (Objects.isNull(modelCaseDTO.getLawPartyList())) { modelCaseDTO.setLawPartyList(new ArrayList<>()); } return modelCaseDTO; }); } @Override public R checkCaseNo(String caseNo, String caseId) { Long count = modelCaseMapper.selectCount(new LambdaQueryWrapper() .eq(ModelCase::getCaseNo, caseNo) .eq(ModelCase::getDataStatus, "1") .ne(StrUtil.isNotEmpty(caseId), ModelCase::getId, caseId)); if (count == 0) { return R.ok(caseNo); } else { return R.okMsg("案件编号已存在,请勿重复添加"); } } @Override @Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class) public R addOrUpd(ModelCaseBase modelCaseBase) { int i = 0; if (StrUtil.isBlank(modelCaseBase.getCaseNo())) { throw new BusinessException("案件编号不能为空"); } ModelCase modelCase = modelCaseBase.toModelCase(); if (modelCase.getId() != null) { // 如果更新,则校验案件编码,案件编码不允许修改(案件编码作为和知识库交互的主键,是唯一的) ModelCase exist = modelCaseMapper.selectById(modelCase.getId()); if (!StrUtil.equals(exist.getCaseNo(), modelCase.getCaseNo())) { throw new BusinessException("案件编号不允许修改"); } i = modelCaseMapper.updateById(modelCase); } else { Long num = modelCaseMapper.selectCount(null); modelCase.setIndexNum(Integer.parseInt(num.toString()) + 1); i = modelCaseMapper.insert(modelCase); // 保存案件行为人 casePersonService.saveCaseActor(modelCase.getId(), modelCaseBase.getCaseActorName(), modelCaseBase.getCaseActorIdCard()); // 这里需要调用知识库的接口,去保存知识库 CreateBaseDTO createBaseDTO = new CreateBaseDTO(); createBaseDTO.setKnowledge_base_name(modelCase.getCaseNo()); LangChainChatRes chat = langChainChatService.createBase(createBaseDTO); log.info("创建知识库:{}", chat); if (200 != chat.getCode()) { throw new BusinessException("保存知识库失败"); } } if (i > 0) { return R.okMsg("保存成功"); } else { return R.fail("保存失败"); } } @Override public R del(String id) { ModelCase modelCase = modelCaseMapper.selectById(id); LangChainChatRes langChainChatRes = langChainChatService.deleteBase(modelCase.getCaseNo()); if (200 != langChainChatRes.getCode()){ log.info("删除知识库失败"); } modelCase.setDataStatus(DataStatus.NOT_AVAILABLE.getCode()); int i = modelCaseMapper.updateById(modelCase); if (i > 0) { return R.okMsg("删除成功"); } else { return R.fail("删除失败"); } } @Override public R> getPerson(String caseId, String name) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(CasePerson::getCaseId, caseId) .like(StrUtil.isNotEmpty(name), CasePerson::getName, name); List casePeople = casePersonService.list(wrapper); List dicts = comDictionaryService.list(); for (CasePerson cp : casePeople) { cp.setRoleName(comDictionaryService.getName(dicts, "case_role", cp.getRoleCode())); } return R.ok(casePeople); } @Override @Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class) public R addPerson(CasePerson person) { Assert.notEmpty(person.getCaseId(), "案件id不能为空"); Assert.notEmpty(person.getIdCard(), "身份证号不能为空"); Assert.notEmpty(person.getName(), "姓名不能为空"); Assert.notEmpty(person.getRoleCode(), "角色不能为空"); long count = casePersonService.count(new LambdaQueryWrapper() .eq(CasePerson::getCaseId, person.getCaseId()).eq(CasePerson::getIdCard, person.getIdCard())); Assert.isTrue(count == 0, "该身份证号已存在"); boolean success = casePersonService.save(person); if (success) { caseStatusManageService.whenSaveCasePeople(person.getCaseId(), person); return R.okMsg("新增成功"); } else { return R.fail("新增失败"); } } @Override @Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class) public boolean updatePerson(CasePerson person) { Assert.notEmpty(person.getId(), "id不能为空"); Assert.notEmpty(person.getCaseId(), "案件id不能为空"); Assert.notEmpty(person.getIdCard(), "身份证号不能为空"); Assert.notEmpty(person.getName(), "姓名不能为空"); Assert.notEmpty(person.getRoleCode(), "角色不能为空"); CasePerson casePerson = casePersonService.getById(person.getId()); Assert.notNull(casePerson, "该人员不存在"); Assert.isFalse(Integer.valueOf(1).equals(casePerson.getCaseActorFlag()), "该人员为案件行为人,不能修改"); boolean update = casePersonService.lambdaUpdate().eq(CasePerson::getId, person.getId()) .set(CasePerson::getIdCard, person.getIdCard()) .set(CasePerson::getName, person.getName()) .set(CasePerson::getRoleCode, person.getRoleCode()) .update(); if (update){ caseStatusManageService.whenSaveCasePeople(person.getCaseId(), person); } return update; } @Override public R uploadCase(MultipartFile file) { /** * 检查文件格式 */ String fileName = file.getOriginalFilename(); assert fileName != null; // 截取文件的类型符 String substring = fileName.substring(fileName.lastIndexOf(".") + 1); if (!("xls".equals(substring) || "xlsx".equals(substring))) { throw new CustomException(ResultStatusEnum.INCORRECT_FILE_FORMAT);// 响应“文件格式不正确”异常 } List putList = new ArrayList<>(); try { putList = ExcelReader.getCaseList(file.getInputStream(), substring, null); } catch (IOException e) { e.printStackTrace(); throw new CustomException(ResultStatusEnum.UPLOAD_EXCEPTION);// 响应“文件上传异常”错误 } List dicts = comDictionaryService.list(); /** * 读取bean列表,导入到数据库中 */ List> errorList = new ArrayList<>(); int index = modelCaseMapper.selectMaxIndex() + 1; int add = 0; for (ModelCase modelCase : putList) { if (StringUtils.isEmpty(modelCase.getCaseNo()) || StringUtils.isEmpty(modelCase.getCaseName()) || StringUtils.isEmpty(modelCase.getCaseTypeName()) || StringUtils.isEmpty(modelCase.getCaseStatusName()) || StringUtils.isEmpty(modelCase.getCrimeModeName())) { errorList.add(errorMapBuilder(modelCase, "必填项为空")); continue; } //替换字典项 String[] split = modelCase.getCaseTypeName().split(","); List caseTypes = new ArrayList<>(); for (String type : split) { caseTypes.add(comDictionaryService.getValue(dicts, "case_type", type)); } modelCase.setCaseType(StringUtils.join(caseTypes, ",")); modelCase.setCaseStatus(comDictionaryService.getValue(dicts, "case_status", modelCase.getCaseStatusName())); modelCase.setCrimeMode(comDictionaryService.getValue(dicts, "crime_mode", modelCase.getCrimeModeName())); modelCase.setIndexNum(index); modelCaseMapper.insert(modelCase); add++; index++; } Map returnMap = new HashMap<>(); returnMap.put("errorList", errorList); returnMap.put("add", add); return R.ok(returnMap); } private Map errorMapBuilder(ModelCase modelCase, String errorText) { return new HashMap(2) {{ put("caseNo", modelCase.getCaseNo()); put("caseName", modelCase.getCaseName()); put("errorText", errorText); }}; } @Override public R getIndexDetail(String caseId, String indexType, Integer page, Integer size) { IPage iPage = new Page<>(page, size); iPage = modelCaseMapper.getIndexDetail(iPage, caseId, indexType); List records = iPage.getRecords(); for (IndexDetail record : records) { if (StringUtils.isEmpty(record.getAtomicIds())) { continue; } // 是否是新的结果 record.setNewFlag(!StrUtil.equals(record.getIndexResult(), record.getPreResult())); String judgeLogic = record.getJudgeLogic(); Map indexJundgeLogicMap = parseLogicMap(judgeLogic); String[] array = record.getAtomicIds().split(","); List atomicIds = Arrays.asList(array); List atomics = modelCaseMapper.getAtomicDetail(caseId, atomicIds); for (AtomicIndexDTO atomic : atomics) { // 需要和原子指标的规则判断是否一致(解决出罪和入罪冲突的问题) String s = indexJundgeLogicMap.get(atomic.getAtomicIndexId()); atomic.judgeWithIndexResult(s); if (StrUtil.isBlank(atomic.getRecord())) { atomic.setRecord("无"); } } record.setRecord("无"); // 遍历,atomic的record字段存在不为空,且不是无的,如果有,就是有 if (atomics.stream().anyMatch(atomic -> StrUtil.isNotBlank(atomic.getRecord()) && !StrUtil.equals("无", atomic.getRecord()))) { record.setRecord("有"); } record.setChildren(atomics); } iPage.setRecords(records); return R.ok(IPages.buildDataMap(iPage)); } private Map parseLogicMap(String judgeLogic) { List judgeLogics = JSONUtil.toList(judgeLogic, JudgeLogic.class); Map resultMap = new HashMap<>(); for (JudgeLogic logic : judgeLogics) { for (AtomicData atomicDatum : logic.getAtomicData()) { // 原子指标结果 -1:未知, 0:不存在, 1存在 if (atomicDatum.getRelationalSymbol().equals("1") || atomicDatum.getRelationalSymbol().equals("3")) { resultMap.put(atomicDatum.getAtomicIndex(), "1"); } else if (atomicDatum.getRelationalSymbol().equals("2") || atomicDatum.getRelationalSymbol().equals("4")) { resultMap.put(atomicDatum.getAtomicIndex(), "0"); } else { resultMap.put(atomicDatum.getAtomicIndex(), "-1"); } } } return resultMap; } }