package com.fdkankan.scene.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.TimeInterval; import cn.hutool.core.io.FileUtil; import cn.hutool.core.net.multipart.UploadFile; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fdkankan.common.constant.CommonStatus; import com.fdkankan.common.constant.ErrorCode; import com.fdkankan.common.exception.BusinessException; import com.fdkankan.common.util.FileUtils; import com.fdkankan.db.response.PageInfo; import com.fdkankan.fyun.face.FYunFileServiceInterface; import com.fdkankan.model.constants.ConstantFilePath; import com.fdkankan.model.constants.UploadFilePath; import com.fdkankan.redis.constant.RedisKey; import com.fdkankan.scene.bean.IconBean; import com.fdkankan.scene.entity.*; import com.fdkankan.scene.httpclient.ManageHttpClient; import com.fdkankan.scene.mapper.ISceneEvidenceMapper; import com.fdkankan.scene.service.ISceneEditInfoService; import com.fdkankan.scene.service.ISceneEvidenceService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fdkankan.scene.service.ISceneIconService; import com.fdkankan.scene.service.IScenePlusService; import com.fdkankan.scene.vo.*; import com.fdkankan.web.response.ResultData; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** *

* 痕迹物证表 服务实现类 *

* * @author * @since 2025-08-08 */ @Service public class SceneEvidenceServiceImpl extends ServiceImpl implements ISceneEvidenceService { @Autowired private IScenePlusService scenePlusService; @Autowired private ISceneEditInfoService sceneEditInfoService; @Autowired private ISceneIconService sceneIconService; @Resource private ManageHttpClient manageHttpClient; @Autowired private FYunFileServiceInterface fYunFileServiceInterface; @Override public void saveEvidence(SaveEvidenceParamVO param) throws Exception { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum()); if (scenePlus == null) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); this.addOrUpdateData(param.getNum(), param.getDataList()); this.addOrUpdateIcons(param.getNum(), param.getIcons()); //保存数据库 SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId()); this.saveEvidenceToSceneEditInfo(param.getNum(), sceneEditInfo); sceneEditInfoService.updateById(sceneEditInfo); } private void addOrUpdateData(String num, List dataList) throws Exception{ Set sidList = dataList.stream().map(v->v.getSid()).collect(Collectors.toSet()); List sceneEvidences = this.listByNumAndSids(num, sidList); Map dbMap = new HashMap<>(); if(CollUtil.isNotEmpty(sceneEvidences)){ dbMap = sceneEvidences.stream().collect(Collectors.toMap(v -> v.getSid(), v -> v)); } Map finalDbMap = dbMap; List collect = dataList.stream().map(v -> { SceneEvidence sceneEvidence = finalDbMap.get(v.getSid()); if (Objects.isNull(sceneEvidence)) { sceneEvidence = new SceneEvidence(); sceneEvidence.setNum(num); sceneEvidence.setSid(v.getSid()); } sceneEvidence.setUpdateTime(null); sceneEvidence.setEvidenceContent(v.getData()); return sceneEvidence; }).collect(Collectors.toList()); this.saveOrUpdateBatch(collect); } private void addOrUpdateIcons(String num, List icons) throws Exception{ if(CollUtil.isEmpty(icons)){ return; } List sceneIconList = icons.stream().map(v -> { String sid = v.split(".")[0]; SceneIcon sceneIcon = new SceneIcon(); sceneIcon.setNum(num); sceneIcon.setSid(sid); sceneIcon.setFileName(v); sceneIcon.setBizType("evidence"); return sceneIcon; }).collect(Collectors.toList()); sceneIconService.saveBatch(sceneIconList); } @Override public void saveEvidenceToSceneEditInfo(String num, SceneEditInfo sceneEditInfo){ long count = this.count(new LambdaQueryWrapper().eq(SceneEvidence::getNum, num)); sceneEditInfo.setEvidence(count > 0 ? CommonStatus.YES.code() : CommonStatus.NO.code()); sceneEditInfo.setVersion(sceneEditInfo.getVersion() + 1); } @Override public List listByNumAndSids(String num, Set sids) { return this.list(new LambdaQueryWrapper().eq(SceneEvidence::getNum, num).in(SceneEvidence::getSid, sids)); } @Override public List listByNum(String num) { return this.list(new LambdaQueryWrapper().eq(SceneEvidence::getNum, num).orderByDesc(SceneEvidence::getUpdateTime)); } @Override public void deleteEvidence(DeleteSidListParamVO param) { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum()); if (scenePlus == null) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); //处理删除状态数据 // this.deleteHotData(param.getNum(), deleteSidList, bucket); this.remove(new LambdaQueryWrapper().eq(SceneEvidence::getNum, param.getNum()).in(SceneEvidence::getSid, param.getSidList())); // //删除导览中的热点数据 // this.deleteHotDataFromTourJson(param.getNum(), param.getSidList(), bucket); //保存数据库 SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId()); sceneEditInfoService.saveTagsToSceneEditInfo(param.getNum(), sceneEditInfo); sceneEditInfoService.updateById(sceneEditInfo); } @Override public JSONObject listEvidences(String num) { JSONObject result = new JSONObject(); List sceneEvidences = this.listByNum(num); List evidenceContent = sceneEvidences.stream().map(v -> v.getEvidenceContent()).collect(Collectors.toList()); result.put("evidences", evidenceContent); Set sceneIconList = sceneIconService.listByNum(num, "evidence").stream().map(v->v.getFileName()).collect(Collectors.toSet()); result.put("icons", this.sortIcons(evidenceContent, sceneIconList)); return result; } private List sortIcons(List evidences, Set icons){ //统计使用频次 List iconBeans = Lists.newArrayList(); for (String icon : icons) { int count = 0; for (JSONObject tag : evidences) { String sid = tag.getString("icon"); if(StrUtil.isEmpty(sid) || !icon.equals(sid)){ continue; } ++count; } iconBeans.add(IconBean.builder().icon(icon).count(count).build()); } //排序 List iconList = iconBeans.stream().sorted(Comparator.comparing(IconBean::getCount).reversed()) .map(item -> { return item.getIcon(); }).collect(Collectors.toList()); return iconList; } @Override public void deleteIcons(DeleteHotIconParamVO param) { sceneIconService.remove( new LambdaQueryWrapper() .eq(SceneIcon::getBizType, "evidence") .eq(SceneIcon::getNum, param.getNum()) .in(SceneIcon::getFileName, param.getFileNameList())); } @Override public ResultData> traceEvidenceList(JSONObject param) { ResultData> resultData = manageHttpClient.traceEvidenceList(param); return resultData; } @Override public ResultData traceEvidenceInfoList(TraceEvidenceInfoListParamVo param) { if(StrUtil.isEmpty(param.getKno())){ return ResultData.ok(new PageInfo<>()); } return manageHttpClient.traceEvidenceInfoList(param); } @Override public ResultData refreshTraceEvidenceInfoList(String kno) { return manageHttpClient.refreshTraceEvidenceInfoList(kno); } @Override public ResultData syncTraceEvidence(SaveEvidenceParamVO param) throws Exception { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum()); if (scenePlus == null) throw new BusinessException(ErrorCode.FAILURE_CODE_5005); List collect = param.getDataList().stream().map(v -> { JSONObject data = v.getData(); JSONArray medias = data.getJSONArray("media"); if (CollUtil.isNotEmpty(medias)) { medias.stream().forEach(m -> { JSONObject media = (JSONObject) m; String path = media.getString("path"); String fileName = FileUtil.getName(path); String newFileName = UUID.randomUUID().toString() + "." + FileUtil.extName(fileName); String meshKey = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + newFileName; fYunFileServiceInterface.copyFileInBucket(path, meshKey); media.put("src", newFileName); }); } return data; }).collect(Collectors.toList()); this.saveEvidence(param); return ResultData.ok(collect); } @Override public void pushEvidence(BaseJsonArrayParamVO param) { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum()); String kNo = scenePlus.getKNo(); for (JSONObject datum : param.getData()) { manageHttpClient.push(datum); } } @Override public void uploadScreenshot(MultipartFile[] files, String num) throws IOException { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num); if(scenePlus == null){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } if(StrUtil.isEmpty(scenePlus.getKNo())){ return; } List urlList = new ArrayList<>(); for (MultipartFile file : files) { String fileName = file.getOriginalFilename(); // 获取文件后缀 String extName = fileName.substring(fileName.lastIndexOf(".")).toLowerCase(); fileName = UUID.randomUUID().toString().concat(extName); String path = String.format(ConstantFilePath.SCENE_TMP_PATH_V4, num).concat(fileName); FileUtil.mkParentDirs(path); file.transferTo(new File(path)); String ossPath = String.format(UploadFilePath.SCENE_NUM_PATH, num) + "screenshot/" + fileName; fYunFileServiceInterface.uploadFile(path, ossPath); urlList.add(ossPath); FileUtils.delFile(path); } //调用案件系统接口,进行推送 JSONObject param = new JSONObject(); param.put("kno", scenePlus.getKNo()); param.put("fileList", urlList); manageHttpClient.pushScreenshot(param); } }