package com.fdkankan.scene.service.impl; import cn.hutool.core.bean.BeanUtil; 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.JSONException; 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.EvidenceBean; import com.fdkankan.scene.bean.IconBean; import com.fdkankan.scene.bean.JMErrorCode; import com.fdkankan.scene.entity.*; import com.fdkankan.scene.httpclient.ManageHttpClient; import com.fdkankan.scene.mapper.ISceneEvidenceMapper; import com.fdkankan.scene.service.*; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fdkankan.scene.util.JmgaSSOLoginHelper; import com.fdkankan.scene.vo.*; import com.fdkankan.web.response.ResultData; import com.fdkankan.web.user.SSOUser; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; 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 */ @Slf4j @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; @Value("${4dkk.fdService.basePath}") private String basePath; @Autowired private JmgaSSOLoginHelper jmgaSSOLoginHelper; @Autowired private ISceneMidService sceneMidService; @Override public void saveEvidence(SaveEvidenceParamVO param, String token) 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.generalConfig(param.getNum(), param.getGeneralConfig()); this.addOrUpdateIcons(param.getNum(), param.getIcons()); //保存数据库 SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId()); this.saveEvidenceToSceneEditInfo(param.getNum(), sceneEditInfo); sceneEditInfoService.updateById(sceneEditInfo); //推送媒体库 Set newMids = this.batchPushMedia(param, token, scenePlus); Set dbMids = param.getDataList().stream() .filter(v -> v.getData().containsKey("mid") && v.getData().getLong("mid") != null) .map(v -> v.getData().getLong("mid")).collect(Collectors.toSet()); Set mids = new HashSet<>(); if(CollUtil.isNotEmpty(newMids)){ mids.addAll(newMids); } if(CollUtil.isNotEmpty(dbMids)){ mids.addAll(dbMids); } if(CollUtil.isNotEmpty(mids)){ //保存场景码与媒体库id关系 List sms = mids.stream().map(v -> { SceneMid sm = new SceneMid(); sm.setNum(param.getNum()); sm.setMid(v); return sm; }).collect(Collectors.toList()); sceneMidService.saveBatch(sms); } } private void generalConfig(String num, JSONObject generalConfig){ if(CollUtil.isEmpty(generalConfig)){ return; } List sceneEvidences = this.listByNum(num); if(CollUtil.isEmpty(sceneEvidences)){ return; } sceneEvidences.stream().forEach(v->{ JSONObject visiSetting = v.getEvidenceContent().getJSONObject("visiSetting"); for (String settingKey : generalConfig.keySet()) { visiSetting.put(settingKey, generalConfig.get(settingKey)); } }); this.updateBatchById(sceneEvidences); } private Set batchPushMedia(SaveEvidenceParamVO param, String token, ScenePlus scenePlus){ log.info("--------------SaveEvidenceParamVO:{}", JSON.toJSONString(param)); SSOUser ssoUser = jmgaSSOLoginHelper.getSsoUser(token); List params = new ArrayList<>(); for (EvidenceParamVO evidenceParamVO : param.getDataList()) { //media JSONArray medias = evidenceParamVO.getData().getJSONArray("media"); if(CollUtil.isNotEmpty(medias)){ for (Object o : medias) { JSONObject media = JSON.parseObject(JSON.toJSONString(o)); if(media.getIntValue("isAddMedia") != 1){ continue; } String ossPath = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + media.getString("src"); JSONObject item = new JSONObject(); params.add(item); item.put("num", param.getNum()); item.put("kno", scenePlus.getKNo()); item.put("filePath", ossPath); item.put("fileName", media.getString("name")); item.put("fileSize", fYunFileServiceInterface.getSpace("4dkankan", ossPath)); item.put("delSource", 0); item.put("toHaixin", 0); item.put("dictId", evidenceParamVO.getData().getInteger("dictId")); item.put("content", EvidenceBean.builder(). title(evidenceParamVO.getData().getString("title")) .collectedTime(evidenceParamVO.getData().getString("collectedTime")) .collectionModeName(evidenceParamVO.getData().getString("collectionModeName")) .createAccount(evidenceParamVO.getData().getString("createAccount")) .feature(evidenceParamVO.getData().getString("feature")) .leftPosition(evidenceParamVO.getData().getString("leftPosition")) .status(evidenceParamVO.getData().getInteger("status")).build()); } } //bgm JSONObject bgm = evidenceParamVO.getData().getJSONObject("bgm"); if(bgm != null && bgm.getIntValue("isAddMedia") == 1){ String ossPath = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + bgm.getString("src"); JSONObject item = new JSONObject(); params.add(item); item.put("dictId", evidenceParamVO.getData().getInteger("dictId")); item.put("num", param.getNum()); item.put("kno", scenePlus.getKNo()); item.put("filePath", ossPath); item.put("fileName", bgm.getString("name")); item.put("fileSize", fYunFileServiceInterface.getSpace("4dkankan", ossPath)); item.put("delSource", 0); item.put("toHaixin", 0); item.put("content", EvidenceBean.builder(). title(evidenceParamVO.getData().getString("title")) .collectedTime(evidenceParamVO.getData().getString("collectedTime")) .collectionModeName(evidenceParamVO.getData().getString("collectionModeName")) .createAccount(evidenceParamVO.getData().getString("createAccount")) .feature(evidenceParamVO.getData().getString("feature")) .leftPosition(evidenceParamVO.getData().getString("leftPosition")) .status(evidenceParamVO.getData().getInteger("status")).build()); } } //调用案件系统接口,进行推送 if(CollUtil.isEmpty(params)){ return null; } JSONObject playLoad = new JSONObject(); playLoad.put("params", params); ResultData> resultData = manageHttpClient.addMediaLibrarys(basePath, token, playLoad); return resultData.getData().stream().map(v -> v.getLong("id")).collect(Collectors.toSet()); } 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()); Long mid = v.getData().getLong("mid"); if (Objects.isNull(sceneEvidence)) { sceneEvidence = new SceneEvidence(); sceneEvidence.setNum(num); sceneEvidence.setSid(v.getSid()); sceneEvidence.setMid(mid); } sceneEvidence.setUpdateTime(null); JSONObject evidenceContent = JSON.parseObject(v.getData().toString()); JSONArray medias = evidenceContent.getJSONArray("media"); if(CollUtil.isNotEmpty(medias)){ for (Object o : medias) { JSONObject media = (JSONObject) o; media.remove("isAddMedia"); } } JSONObject bgm = evidenceContent.getJSONObject("bgm"); if(bgm != null){ bgm.remove("isAddMedia"); } sceneEvidence.setEvidenceContent(evidenceContent); 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 = FileUtil.getPrefix(v); 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) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().eq(SceneEvidence::getNum, num); if(CollUtil.isNotEmpty(sids)){ queryWrapper.in(SceneEvidence::getSid, sids); } return this.list(queryWrapper); } @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(String token, TraceEvidenceListParamVO param) { ResultData> resultData = manageHttpClient.traceEvidenceList(basePath, token, param); return resultData; } @Override public ResultData traceEvidenceInfoList(String token, TraceEvidenceInfoListParamVo param) { return manageHttpClient.traceEvidenceInfoList(basePath, token, param); } @Override public ResultData refreshTraceEvidenceInfoList(String token, BaseSceneParamVO param) { ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum()); if(StrUtil.isEmpty(scenePlus.getKNo())){ return ResultData.ok(); } return manageHttpClient.refreshTraceEvidenceInfoList(basePath, token, scenePlus.getKNo()); } @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 midList = param.getDataList().stream().map(v -> v.getData().getLong("mid")).collect(Collectors.toList()); long count = this.count(new LambdaQueryWrapper().eq(SceneEvidence::getNum, param.getNum()).in(SceneEvidence::getMid, midList)); if(count > 0) throw new BusinessException(JMErrorCode.FAILURE_CODE_20000.code(), JMErrorCode.FAILURE_CODE_20000.message()); List collect = param.getDataList().stream().map(v -> { JSONObject data = v.getData(); JSONArray medias = data.getJSONArray("media"); if (CollUtil.isNotEmpty(medias)) { medias.stream().forEach(m -> { LinkedHashMap media = (LinkedHashMap) m; String sid = (String) media.get("sid"); String path = (String)media.get("src"); String fileName = FileUtil.getName(path); String newFileName = sid + "." + FileUtil.extName(fileName); String meshKey = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + newFileName; if(path.startsWith("/oss/")){ path = path.replace("/oss/", ""); } fYunFileServiceInterface.copyFileInBucket(path, meshKey); media.put("src", newFileName); }); } return data; }).collect(Collectors.toList()); this.saveEvidence(param, null); 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()) { // String fileName = datum.getString("fileName"); // String filePath = String.format(UploadFilePath.USER_EDIT_PATH, param.getNum()) + fileName; // datum.put("kno", kNo); // datum.put("filePath", filePath); // datum.put("fileSize", fYunFileServiceInterface.getSpace("4dkankan", filePath)); // datum.put("delSource", 0); // datum.put("toHaixin", 1); // manageHttpClient.addMediaLibrary(basePath, datum); // } // } @Override public void uploadScreenshot(String token, MultipartFile[] files, BaseJsonArrayParamVO data) throws IOException { String num = data.getNum(); Map fileDataMap = data.getData().stream().collect(Collectors.toMap(v -> v.getString("fileName"), v -> v)); ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num); if(scenePlus == null){ throw new BusinessException(ErrorCode.FAILURE_CODE_5005); } //这里注释调,因为燕海说没有KNO也可以通过此接口进行推送 // if(StrUtil.isEmpty(scenePlus.getKNo())){ // return; // } List params = 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); FileUtils.delFile(path); JSONObject param = new JSONObject(); params.add(param); param.put("kno", scenePlus.getKNo()); param.put("filePath", ossPath); param.put("fileSize", fYunFileServiceInterface.getSpace("4dkankan", ossPath)); param.put("delSource", 1); param.put("toHaixin", 1); param.put("num", num); param.put("fileName", file.getOriginalFilename()); param.put("category", fileDataMap.get(file.getOriginalFilename()).getString("category")); } //调用案件系统接口,进行推送 JSONObject playLoad = new JSONObject(); playLoad.put("params", params); manageHttpClient.addMediaLibrarys(basePath, token, playLoad); } public static void main(String[] args) { String jsonStr = "{\"users\":[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]}"; JSONObject jsonObj = JSON.parseObject(jsonStr); try { JSONArray usersArray = jsonObj.getJSONArray("users"); for (Object o : usersArray) { JSONObject userObj = (JSONObject) o; System.out.println("Name: " + userObj.getString("name") + ", Age: " + userObj.getIntValue("age")); } for (int i = 0; i < usersArray.size(); i++) { JSONObject userObj = usersArray.getJSONObject(i); System.out.println("Name: " + userObj.getString("name") + ", Age: " + userObj.getIntValue("age")); } } catch (JSONException e) { e.printStackTrace(); } } @Override public ResultData getCaseByNum(String num) { return manageHttpClient.getCaseByNum(basePath, num); } }