You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fu-hsi-service/src/main/java/com/supervision/police/service/impl/ModelCaseServiceImpl.java

523 lines
24 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.conditions.query.QueryWrapper;
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.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.StringUtils;
import com.supervision.config.BusinessException;
import com.supervision.constant.DataStatus;
import com.supervision.police.domain.*;
import com.supervision.police.dto.*;
import com.supervision.police.mapper.ModelCaseMapper;
import com.supervision.police.service.*;
import com.supervision.police.vo.ModelCaseVO;
import com.supervision.utils.IndexRuleUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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<ModelCaseMapper, ModelCase> implements ModelCaseService {
private static final String DATA_STATUS_DEFAULT = "1";
private final ComDictionaryService comDictionaryService;
private final ModelCaseMapper modelCaseMapper;
private final CaseStatusManageService caseStatusManageService;
private final LangChainChatService langChainChatService;
private final ModelAtomicResultService modelAtomicResultService;
@Autowired
private NoteRecordSplitService noteRecordSplitService;
@Autowired
private NoteRecordService noteRecordService;
@Autowired
private CasePersonService casePersonService;
@Autowired
private CaseEvidenceService caseEvidenceService;
private final EvidenceDirectoryService directoryService;
/**
* 查询列表
*
* @param modelCase
* @param page
* @param size
* @return
*/
@Override
public IPage<ModelCaseDTO> queryList(ModelCaseVO modelCase, Integer page, Integer size) {
IPage<ModelCase> modelCaseIPage = modelCaseMapper.selectAll(Page.of(page, size), modelCase);
if (CollUtil.isEmpty(modelCaseIPage.getRecords())) {
return Page.of(page, size);
}
List<String> caseIdList = modelCaseIPage.getRecords().stream().map(ModelCase::getId).toList();
List<CasePerson> casePersonList = casePersonService.list(
Wrappers.lambdaQuery(CasePerson.class).in(CasePerson::getCaseId, caseIdList));
// 多级分组
Map<String, Map<String, List<CasePerson>>> persionMap = casePersonList.stream().collect(Collectors.groupingBy(CasePerson::getCaseId,
Collectors.groupingBy(person -> NumberUtil.equals(person.getCaseActorFlag(), 1) ? "1" : "2")));
List<ComDictionary> dicts = comDictionaryService.list();
return modelCaseIPage.convert(modelCaseInfo -> {
ModelCaseDTO modelCaseDTO = BeanUtil.toBean(modelCaseInfo, ModelCaseDTO.class, CopyOptions.create().setIgnoreProperties("lawActor"));
String[] caseTypes = modelCaseDTO.getCaseType().split(",");
List<String> 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<String, List<CasePerson>> casePersonMap = persionMap.get(modelCaseDTO.getId());
if (CollUtil.isNotEmpty(casePersonMap)) {
Optional<CasePerson> 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<ModelCase>()
.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());
caseEvidenceService.initCaseEvidenceDirectory(modelCase.getId(), modelCase.getCaseType());
// 这里需要调用知识库的接口,去保存知识库
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);
modelCase.setDataStatus(DataStatus.NOT_AVAILABLE.getCode());
int i = modelCaseMapper.updateById(modelCase);
if (i > 0) {
return R.okMsg("删除成功");
} else {
return R.fail("删除失败");
}
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public R<?> realDeleteByIds(List<String> ids) {
List<ModelCase> modelCases = modelCaseMapper.selectBatchIds(ids);
if (modelCases != null && !modelCases.isEmpty()) {
modelCases.forEach(modelCase -> {
LangChainChatRes<Object> langChainChatRes = langChainChatService.deleteBase(modelCase.getCaseNo());
if (200 != langChainChatRes.getCode()) {
log.error("删除知识库失败:{}, caseNo:{}", langChainChatRes.getMsg(), modelCase.getCaseNo());
// throw new BusinessException("删除知识库失败");
}
});
}
noteRecordService.list(new QueryWrapper<NoteRecord>().in("case_id", ids)).forEach(noteRecord -> noteRecordSplitService.delRecords(noteRecord.getId()));
List<String> personIds = casePersonService.list(new QueryWrapper<CasePerson>().in("case_id", ids)).stream().map(CasePerson::getId).collect(Collectors.toList());
personIds.forEach(personId -> casePersonService.removeById(personId));
int i = modelCaseMapper.deleteBatchIds(ids);
if (i > 0) {
return R.okMsg("删除成功");
} else {
return R.fail("删除失败");
}
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = Exception.class)
public R<?> resetDataStatusByIds(List<String> ids) {
boolean result = false;
//批量查出案件,并更新案件状态
List<ModelCase> modelCases = modelCaseMapper.selectBatchIds(ids);
if (modelCases != null && !modelCases.isEmpty()) {
modelCases.forEach(modelCase -> {
modelCase.setDataStatus(DATA_STATUS_DEFAULT);
});
result = updateBatchById(modelCases);
}
if (result) {
return R.okMsg("恢复成功");
} else {
return R.fail("恢复失败");
}
}
@Override
public R<List<CasePerson>> getPerson(String caseId, String name) {
LambdaQueryWrapper<CasePerson> wrapper = Wrappers.lambdaQuery();
wrapper.eq(CasePerson::getCaseId, caseId)
.like(StrUtil.isNotEmpty(name), CasePerson::getName, name);
List<CasePerson> casePeople = casePersonService.list(wrapper);
List<ComDictionary> 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<CasePerson>()
.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<ModelCase> putList = new ArrayList<>();
try {
putList = ExcelReader.getCaseList(file.getInputStream(), substring, null);
} catch (IOException e) {
e.printStackTrace();
throw new CustomException(ResultStatusEnum.UPLOAD_EXCEPTION);// 响应“文件上传异常”错误
}
List<ComDictionary> dicts = comDictionaryService.list();
/**
* 读取bean列表导入到数据库中
*/
List<Map<String, Object>> 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<String> 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<String, Object> returnMap = new HashMap<>();
returnMap.put("errorList", errorList);
returnMap.put("add", add);
return R.ok(returnMap);
}
private Map<String, Object> errorMapBuilder(ModelCase modelCase, String errorText) {
return new HashMap<String, Object>(2) {{
put("caseNo", modelCase.getCaseNo());
put("caseName", modelCase.getCaseName());
put("errorText", errorText);
}};
}
@Override
public IPage<IndexDetail> getIndexDetail(IndexResultQuery query, Integer pageNum, Integer pageSize) {
Assert.notEmpty(query.getCaseId(), "案件id不能为空");
Assert.notEmpty(query.getIndexType(), "指标类型不能为空");
IPage<IndexDetail> iPage = modelCaseMapper.pageListIndexResult(query, Page.of(pageNum, pageSize));
List<IndexDetail> records = iPage.getRecords();
// 添加 附属内容
attachRecord(query.getCaseId(), records);
return iPage;
}
/**
* 添加 指标结果附属内容
*
* @param caseId 案件id
* @param indexDetails 指标结果
*/
private void attachRecord(String caseId, List<IndexDetail> indexDetails) {
if (CollUtil.isEmpty(indexDetails)) {
return;
}
// indexDetails中涉及到的原子指标结果数据
List<String> indexIdList = indexDetails.stream().map(IndexDetail::getIndexId).toList();
List<ModelAtomicResult> modelAtomicResultList = modelAtomicResultService.lambdaQuery()
.eq(ModelAtomicResult::getCaseId, caseId)
.in(CollUtil.isNotEmpty(indexIdList), ModelAtomicResult::getIndexId, indexIdList).list();
// records中涉及到的笔录片段id
Set<String> recordSegmentList = modelAtomicResultList.stream()
.filter(atomic -> StrUtil.isNotEmpty(atomic.getRecordSplitId()))
.flatMap(atomic -> Arrays.stream(atomic.getRecordSplitId().split(","))).collect(Collectors.toSet());
List<NoteRecordSplit> nodeRecordSpliteList =
CollUtil.isEmpty(recordSegmentList) ? new ArrayList<>() :
noteRecordSplitService.lambdaQuery().in(NoteRecordSplit::getId, recordSegmentList).list();
Map<String, NoteRecordSplit> nodeRecordSpliteMap = nodeRecordSpliteList.stream().collect(Collectors.toMap(NoteRecordSplit::getId, v -> v));
// 获取证据目录
List<EvidenceDirectoryDTO> evidenceDirectoryDTOS = directoryService.listDirectoryTree(caseId);
EvidenceDirectoryDTO rootDirectory = new EvidenceDirectoryDTO(evidenceDirectoryDTOS);
List<ModelAtomicResult> atomicResultList = modelAtomicResultService.lambdaQuery().eq(ModelAtomicResult::getCaseId, caseId).list();
List<String> list = atomicResultList.stream().map(ModelAtomicResult::getEvidenceId).filter(Objects::nonNull).map(v -> v.split(",")).flatMap(Arrays::stream).toList();
List<CaseEvidence> caseEvidenceList = CollUtil.isEmpty(list) ? new ArrayList<>() : caseEvidenceService.listByIds(list);
for (IndexDetail record : indexDetails) {
if (StringUtils.isEmpty(record.getIndexResult())) {
continue;
}
// 是否是新的结果
record.setNewFlagValue();
List<String> atomicIndexIds = IndexRuleUtil.getAtomicIndexIds(record.getIndexRule());
List<AtomicIndexDTO> atomics = modelCaseMapper.getAtomicDetail(caseId, record.getIndexId(), atomicIndexIds);
for (AtomicIndexDTO atomic : atomics) {
// 获取原子指标的判断规则
// 配置的指标的逻辑
Map<String, String> indexJudgeLogicMap = IndexRuleUtil.getIndexJudgeLogicMap(record.getIndexRule());
// 需要和原子指标的规则判断是否一致(解决出罪和入罪冲突的问题)
String relationalSymbol = indexJudgeLogicMap.get(atomic.getAtomicIndexId());
atomic.judgeWithIndexResult(relationalSymbol);
atomic.setSegmentation(nodeRecordSpliteMap);
atomic.setRecordIfSegmentationAbsent("无");
List<ModelAtomicResult> filterAtomicResultList = atomicResultList.stream().filter(v -> StrUtil.equals(atomic.getAtomicIndexId(), v.getAtomicId()) && StrUtil.equals(record.getIndexId(), v.getIndexId())).toList();
List<EvidentIndexResultDTO> evidentResult = getEvidentResult(filterAtomicResultList, caseEvidenceList, rootDirectory);
atomic.setEvidentResultList(evidentResult);
atomic.setParentIndexName(record.getIndexName());
}
// ===================================↑新方法=====================================
// ===================================↓老方法=====================================
// if (StringUtils.isEmpty(record.getJudgeLogic())) {
// continue;
// }
// // 是否是新的结果
// record.setNewFlagValue();
//
// List<String> atomicIds = JudgeLogicUtil.pickAtomicIndexIds(record.getJudgeLogic());
// List<AtomicIndexDTO> atomics = modelCaseMapper.getAtomicDetail(caseId, record.getIndexId(), atomicIds);
// for (AtomicIndexDTO atomic : atomics) {
// // 获取原子指标的判断规则
// // 配置的指标的逻辑
// Map<String, String> indexJundgeLogicMap = parseLogicMap(record.getJudgeLogic());
// // 需要和原子指标的规则判断是否一致(解决出罪和入罪冲突的问题)
// String relationalSymbol = indexJundgeLogicMap.get(atomic.getAtomicIndexId());
//
// atomic.judgeWithIndexResult(relationalSymbol);
// atomic.setSegmentation(nodeRecordSpliteMap);
// atomic.setRecordIfSegmentationAbsent("无");
// List<ModelAtomicResult> filterAtomicResultList = atomicResultList.stream().filter(v -> StrUtil.equals(record.getIndexId(), v.getIndexId())).toList();
// List<EvidentIndexResultDTO> evidentResult = getEvidentResult(filterAtomicResultList, caseEvidenceList, rootDirectory);
// atomic.setEvidentResultList(evidentResult);
// }
record.setChildren(atomics);
record.setRecordValue();
}
}
private List<EvidentIndexResultDTO> getEvidentResult(List<ModelAtomicResult> atomicResultList, List<CaseEvidence> caseEvidenceList, EvidenceDirectoryDTO rootDirectory) {
ArrayList<EvidentIndexResultDTO> evidentIndexResultDTOS = new ArrayList<>();
for (ModelAtomicResult modelAtomicResult : atomicResultList) {
String evidenceId = modelAtomicResult.getEvidenceId();
if (StrUtil.isEmpty(evidenceId)) {
continue;
}
List<String> evidenceIdList = Arrays.asList(evidenceId.split(","));
for (CaseEvidence caseEvidence : caseEvidenceList) {
if (evidenceIdList.contains(caseEvidence.getId())) {
EvidentIndexResultDTO evidentIndexResultDTO = new EvidentIndexResultDTO();
evidentIndexResultDTO.setEvidenceId(caseEvidence.getId());
evidentIndexResultDTO.setEvidenceName(caseEvidence.getEvidenceName());
evidentIndexResultDTO.setDirectoryId(caseEvidence.getDirectoryId());
evidentIndexResultDTO.setDetails(modelAtomicResult.getRemark());
evidentIndexResultDTO.setIndexId(modelAtomicResult.getIndexId());
evidentIndexResultDTO.setProvider(caseEvidence.getProvider());
EvidenceDirectoryDTO directory = rootDirectory.findDirectory(caseEvidence.getDirectoryId());
if (directory != null) {
evidentIndexResultDTO.setDirectoryName(directory.getDirectoryName());
List<String> directoryPath = rootDirectory.getDirectoryPath(evidentIndexResultDTO.getDirectoryId());
evidentIndexResultDTO.setDirectoryPath(StrUtil.join(">", directoryPath));
}
evidentIndexResultDTOS.add(evidentIndexResultDTO);
}
}
}
return evidentIndexResultDTOS;
}
private Map<String, String> parseLogicMap(String judgeLogic) {
List<JudgeLogic> judgeLogics = JSONUtil.toList(judgeLogic, JudgeLogic.class);
Map<String, String> resultMap = new HashMap<>();
for (JudgeLogic logic : judgeLogics) {
for (AtomicData atomicDatum : logic.getAtomicData()) {
resultMap.put(atomicDatum.getAtomicIndex(), atomicDatum.getRelationalSymbol());
}
}
return resultMap;
}
}