From 69f74f62275c18c7807b40d89769f6e84dd2bd02 Mon Sep 17 00:00:00 2001 From: stream Date: Thu, 12 Mar 2026 09:47:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=A6=E6=8E=A7=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E8=AF=84=E4=BC=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmvr-iot-admin/pom.xml | 6 + .../controller/ti/TiProjectController.java | 13 ++ .../src/main/resources/application-dev.yml | 2 +- .../service}/ExTiProjectService.java | 4 +- .../service/IAeEvaluationService.java | 2 + .../service/impl/AeCallbackServiceImpl.java | 11 +- .../service/impl/AeEvaluationServiceImpl.java | 10 +- .../mybatisPlus/MyMetaObjectHandler.java | 5 +- cmvr-iot-ti/pom.xml | 5 + .../com/cmvr/ti/model/domain/TiProject.java | 2 +- .../cmvr/ti/service/ITiProjectService.java | 8 +- .../ti/service/ex/ExTiProjectServiceImpl.java | 7 +- .../ti/service/impl/TiProjectServiceImpl.java | 215 ++++++++++++++++++ 13 files changed, 282 insertions(+), 8 deletions(-) rename {cmvr-iot-test/src/main/java/com/cmvr/test/service/ex => cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service}/ExTiProjectService.java (53%) diff --git a/cmvr-iot-admin/pom.xml b/cmvr-iot-admin/pom.xml index 540366b..9b66bc1 100644 --- a/cmvr-iot-admin/pom.xml +++ b/cmvr-iot-admin/pom.xml @@ -71,6 +71,12 @@ com.cmvr cmvr-iot-ti + + + + com.cmvr + cmvr-iot-evaluation + dev diff --git a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/ti/TiProjectController.java b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/ti/TiProjectController.java index 937313f..1383675 100644 --- a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/ti/TiProjectController.java +++ b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/ti/TiProjectController.java @@ -84,4 +84,17 @@ public class TiProjectController extends BaseController { public AjaxResult queryExecuteInstId(@PathVariable("projectId") String projectId) { return AjaxResult.ok(tiProjectService.queryExecuteInstId(projectId)); } + + @ApiOperation("临时执行项目评估") + @PostMapping("/evaluation") + public AjaxResult evaluation(@RequestBody List funcIds) { + tiProjectService.executeTiEvaluation(funcIds); + return AjaxResult.ok(); + } + + @ApiOperation("评估查询") + @GetMapping("/evaluation/{projectId}") + public AjaxResult queryEvaluation(@PathVariable("projectId") String projectId) { + return AjaxResult.ok(tiProjectService.queryEvaluation(projectId)); + } } diff --git a/cmvr-iot-admin/src/main/resources/application-dev.yml b/cmvr-iot-admin/src/main/resources/application-dev.yml index 25ec2cd..7e3f327 100644 --- a/cmvr-iot-admin/src/main/resources/application-dev.yml +++ b/cmvr-iot-admin/src/main/resources/application-dev.yml @@ -123,7 +123,7 @@ api: TOUCH_COORDINATES: # 意图识别 app-id: d5thge2cktmipk78h82g app-key: d1ebtabnjkflk4gmhikg - evaluation: http://192.168.0.18:8000/analyze + evaluation: http://192.168.0.8:8000/analyze flowise: tts: 192.168.0.222:8080/tts/ diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/service/ex/ExTiProjectService.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/ExTiProjectService.java similarity index 53% rename from cmvr-iot-test/src/main/java/com/cmvr/test/service/ex/ExTiProjectService.java rename to cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/ExTiProjectService.java index 7e78c08..a2703b8 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/service/ex/ExTiProjectService.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/ExTiProjectService.java @@ -1,4 +1,4 @@ -package com.cmvr.test.service.ex; +package com.cmvr.evaluation.service; import com.alibaba.fastjson2.JSONObject; @@ -6,4 +6,6 @@ public interface ExTiProjectService { public JSONObject queryById(String id); + public boolean updateProjectStatus(String projectId, Integer status); + } diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/IAeEvaluationService.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/IAeEvaluationService.java index 1736dcd..e6fe87d 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/IAeEvaluationService.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/IAeEvaluationService.java @@ -16,6 +16,8 @@ public interface IAeEvaluationService extends IService { List queryEvaluation(String instId); + public List queryEvaluationByProjectId(String projectId); + /** * 判断当前项目是否已完成全部评估 */ diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeCallbackServiceImpl.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeCallbackServiceImpl.java index 2024bc0..ad6de14 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeCallbackServiceImpl.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeCallbackServiceImpl.java @@ -8,8 +8,10 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cmvr.common.exception.GlobalException; import com.cmvr.evaluation.model.domain.AeEvaluation; import com.cmvr.evaluation.service.AeCallbackService; +import com.cmvr.evaluation.service.ExTiProjectService; import com.cmvr.evaluation.service.ExViProjectService; import com.cmvr.evaluation.service.IAeEvaluationService; +import com.cmvr.test.enums.RunModeEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -25,6 +27,7 @@ public class AeCallbackServiceImpl implements AeCallbackService { private final IAeEvaluationService aeEvaluationService; private final ExViProjectService exViProjectService; + private final ExTiProjectService exTiProjectService; @Override public void callback(AeEvaluation aeEvaluation) { @@ -59,7 +62,13 @@ public class AeCallbackServiceImpl implements AeCallbackService { // 判断是否是最后一次评估 更改项目状态 boolean finished = aeEvaluationService.isAllEvaluationsFinished(byId.getInstId()); - if (finished) { + if (!finished) { + return; + } + String aeType = aeEvaluation.getAeType(); + if (RunModeEnum.TI_PROJECT.name().equals(aeType)) { + exTiProjectService.updateProjectStatus(byId.getTaskId(), 2); + } else { exViProjectService.updateStatus(byId.getTaskId()); } } diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeEvaluationServiceImpl.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeEvaluationServiceImpl.java index c378fd2..962c1d0 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeEvaluationServiceImpl.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeEvaluationServiceImpl.java @@ -194,7 +194,8 @@ public class AeEvaluationServiceImpl extends ServiceImpl queryEvaluationByProjectId(String projectId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(AeEvaluation.class); + wrapper.eq(AeEvaluation::getTaskId, projectId); + return this.list(wrapper); + } + @Override public boolean isAllEvaluationsFinished(String instId) { long total = this.count( diff --git a/cmvr-iot-framework/src/main/java/com/cmvr/framework/mybatisPlus/MyMetaObjectHandler.java b/cmvr-iot-framework/src/main/java/com/cmvr/framework/mybatisPlus/MyMetaObjectHandler.java index cd77510..d53d4e0 100644 --- a/cmvr-iot-framework/src/main/java/com/cmvr/framework/mybatisPlus/MyMetaObjectHandler.java +++ b/cmvr-iot-framework/src/main/java/com/cmvr/framework/mybatisPlus/MyMetaObjectHandler.java @@ -30,7 +30,10 @@ public class MyMetaObjectHandler implements MetaObjectHandler { this.setFieldValByName(UPDATE_BY, SecurityUtils.getUsername(), metaObject); this.setFieldValByName(UPDATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject); this.setFieldValByName(DELETED, "0", metaObject); - this.setFieldValByName(STATUS, "1", metaObject); +// this.setFieldValByName(STATUS, "1", metaObject); + if (getFieldValByName(STATUS, metaObject) == null) { + this.setFieldValByName(STATUS, "1", metaObject); + } } /** diff --git a/cmvr-iot-ti/pom.xml b/cmvr-iot-ti/pom.xml index df5344e..46b21fa 100644 --- a/cmvr-iot-ti/pom.xml +++ b/cmvr-iot-ti/pom.xml @@ -28,6 +28,11 @@ cmvr-iot-test + + + com.cmvr + cmvr-iot-evaluation + \ No newline at end of file diff --git a/cmvr-iot-ti/src/main/java/com/cmvr/ti/model/domain/TiProject.java b/cmvr-iot-ti/src/main/java/com/cmvr/ti/model/domain/TiProject.java index b197964..a9661b2 100644 --- a/cmvr-iot-ti/src/main/java/com/cmvr/ti/model/domain/TiProject.java +++ b/cmvr-iot-ti/src/main/java/com/cmvr/ti/model/domain/TiProject.java @@ -74,7 +74,7 @@ public class TiProject extends BaseEntity { @ApiModelProperty("送样日期") private Date sampleDate; - @ApiModelProperty(value = "状态", notes = "状态(0已执行 1未执行)") + @ApiModelProperty(value = "状态", notes = "状态(0未执行 1执行中 2执行完成(评估))") private String status; @ApiModelProperty(value = "评价id") diff --git a/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ITiProjectService.java b/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ITiProjectService.java index b57a88c..fbb5f8c 100644 --- a/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ITiProjectService.java +++ b/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ITiProjectService.java @@ -1,8 +1,8 @@ package com.cmvr.ti.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.cmvr.evaluation.model.vo.AeViEvaluationVO; import com.cmvr.test.model.domain.TeTaskInst; -import com.cmvr.test.model.vo.TeQueryProjectOrchestraItemVO; import com.cmvr.test.model.vo.TeQueryTaskOrchestraItemVO; import com.cmvr.test.model.vo.TeTaskExecuteProjectVO; import com.cmvr.ti.model.domain.TiProject; @@ -27,4 +27,10 @@ public interface ITiProjectService extends IService { public TeTaskInst getTeTaskInst(String projectId); public String queryExecuteInstId(String projectId); + + public boolean updateProjectStatus(String projectId, Integer status); + + public void executeTiEvaluation(List funcIds); + + public AeViEvaluationVO queryEvaluation(String projectId); } diff --git a/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ex/ExTiProjectServiceImpl.java b/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ex/ExTiProjectServiceImpl.java index 0482e29..43a71c2 100644 --- a/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ex/ExTiProjectServiceImpl.java +++ b/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/ex/ExTiProjectServiceImpl.java @@ -1,7 +1,7 @@ package com.cmvr.ti.service.ex; import com.alibaba.fastjson2.JSONObject; -import com.cmvr.test.service.ex.ExTiProjectService; +import com.cmvr.evaluation.service.ExTiProjectService; import com.cmvr.ti.service.ITiProjectService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,4 +16,9 @@ public class ExTiProjectServiceImpl implements ExTiProjectService { public JSONObject queryById(String id) { return JSONObject.from(tiProjectService.getById(id)); } + + @Override + public boolean updateProjectStatus(String projectId, Integer status) { + return tiProjectService.updateProjectStatus(projectId, status); + } } diff --git a/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/impl/TiProjectServiceImpl.java b/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/impl/TiProjectServiceImpl.java index 62a5003..f1bbd88 100644 --- a/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/impl/TiProjectServiceImpl.java +++ b/cmvr-iot-ti/src/main/java/com/cmvr/ti/service/impl/TiProjectServiceImpl.java @@ -1,13 +1,25 @@ package com.cmvr.ti.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.cmvr.common.core.domain.entity.SysDictData; import com.cmvr.common.exception.GlobalException; +import com.cmvr.evaluation.model.domain.AeEvaluation; +import com.cmvr.evaluation.model.domain.AeIndicatorEntity; +import com.cmvr.evaluation.model.dto.AeIResultDTO; +import com.cmvr.evaluation.model.vo.AeViEvaluationVO; +import com.cmvr.evaluation.service.AeIndicatorService; +import com.cmvr.evaluation.service.IAeEvaluationService; +import com.cmvr.system.service.ISysDictTypeService; import com.cmvr.test.enums.FlowSceneTypeEnum; import com.cmvr.test.enums.RunModeEnum; import com.cmvr.test.flow.runtime.engine.FlowTaskRuntimeService; @@ -26,12 +38,19 @@ import com.cmvr.ti.model.domain.TiVehicleFunction; import com.cmvr.ti.service.ITiProjectService; import com.cmvr.ti.service.ITiVehicleFunctionService; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -42,6 +61,11 @@ public class TiProjectServiceImpl extends ServiceImpl wrapper = Wrappers.lambdaUpdate(); + wrapper.eq(TiProject::getProjectId, projectId) + .set(TiProject::getStatus, status); + return this.update(null, wrapper); + } + + // 功能ID -> 音频地址 + private final Map AUDIO_PATH_MAP = new HashMap() {{ + put("8", "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260310/1773108837127.wav"); // 播放音乐 + put("12", "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260310/1773108916488.wav"); // 打开导航 + put("9", "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260310/1773108933968.wav"); // 能量回收 + }}; + + // 功能ID -> 视频地址 + private final Map VIDEO_PATH_MAP = new HashMap() {{ + put("8", "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260310/1773108955700.mp4"); // 播放音乐 + put("12", "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260310/1773108967164.mp4"); // 打开导航 + put("9", "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260310/1773108978124.mp4"); // 能量回收 + }}; + + @Override + public void executeTiEvaluation(List funcIds) { + AeEvaluation aeEvaluation = new AeEvaluation(); + aeEvaluation.setAeType(RunModeEnum.TI_PROJECT.name()); + aeEvaluation.setInstId(IdUtil.fastSimpleUUID()); + aeEvaluation.setTaskId("aadb21a32e7990456b866e844a7d4a54"); + aeEvaluation.setItemId(IdUtil.fastSimpleUUID()); + + // todo 触控交互评估 + String taskId = aeEvaluation.getTaskId(); + updateProjectStatus(taskId, 1); // 执行中 + // 模拟流程运行 +// try { +// Thread.sleep(30000); +// } catch (InterruptedException e) { +// throw new RuntimeException(e); +// } + + + // 查字典 + List tiFunctionConfig = dictTypeService.selectDictDataByType("ti_function_config"); + Map functionMap = tiFunctionConfig.stream() + .collect(Collectors.toMap( + SysDictData::getDictValue, + SysDictData::getDictLabel + )); + + // 构建评估任务列表 + List evaluations = new LinkedList<>(); + for (Long funcId : funcIds) { + TiVehicleFunction byId = vehicleFunctionService.getById(funcId); + String funcName = functionMap.get(byId.getFuncKey()); + AeEvaluation eval = new AeEvaluation(); + BeanUtil.copyProperties(aeEvaluation, eval); + eval.setAeId(IdUtil.fastSimpleUUID()); + eval.setStatus(0); // 待评估 + eval.setAvContent(funcName); + eval.setAudioPath(AUDIO_PATH_MAP.get(byId.getFuncKey())); + eval.setVideoPath(VIDEO_PATH_MAP.get(byId.getFuncKey())); + evaluations.add(eval); + } + + try { + // 入库 + aeEvaluationService.saveBatch(evaluations); + + // 提交评估 + for (AeEvaluation e : evaluations) { + redisTemplate.opsForList() + .rightPush("ae:evaluation:queue", JSON.toJSONString(e)); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public AeViEvaluationVO queryEvaluation(String projectId) { + // 1. 查询项目 + TiProject project = getById(projectId); + + // 2. 查询评估数据(允许不完整) + List evaluations = aeEvaluationService.queryEvaluationByProjectId(projectId); + if (CollUtil.isEmpty(evaluations)) { + throw new GlobalException(StrUtil.format("暂无项目id为{}的数据", projectId)); + } + + // 3. 获取指标定义 + List indicators = + aeIndicatorService.getChildrenByParentIdWithLevelLimit( + project.getIndicatorId(), 4, 1 + ); + + List itemDetails = new ArrayList<>(); + + int failureCount = 0; + for (AeEvaluation evaluation : evaluations) { + AeViEvaluationVO.AeItemDetail itemDto = new AeViEvaluationVO.AeItemDetail(); + itemDto.setAeId(evaluation.getAeId()); + itemDto.setContent(evaluation.getAvContent()); + AeIResultDTO dto = JSON.parseObject(evaluation.getResult(), AeIResultDTO.class); + itemDto.setItemResponseTime(dto.getResponseTime()); + itemDto.setStatus(evaluation.getStatus()); + + boolean success = "成功".equals(dto.getOverallResult()); + + if (!success) { + itemDto.setFailureReason(dto.getFailureReason()); + failureCount++; + } + + itemDto.setVideoPath(dto.getVideoPath()); + itemDto.setExecutionDetail(dto.getExecutionDetail()); + + itemDetails.add(itemDto); + } + + // 计算成功率 + Long successRate = (long) (((evaluations.size() - failureCount) * 100.0) / evaluations.size()); + + //成功率得分 + Long score = calculateSuccessRateScore(successRate, indicators); + + + AeViEvaluationVO vo = new AeViEvaluationVO(); + vo.setItemDetails(itemDetails); + vo.setSuccessRate(successRate); + vo.setSuccessRateScore(score); + return vo; + } + + private Long calculateSuccessRateScore(Long successRate, List indicators) { + // 查找成功率指标 + AeIndicatorEntity successRateIndicator = findIndicatorByName(indicators, "成功率"); + + if (successRateIndicator == null) { + return 0L; // 如果没有匹配的成功率指标,返回 0 分 + } + List children = successRateIndicator.getChildren(); + + long score = 0L; + for (AeIndicatorEntity child : children) { + // 子指标的比较值(例如响应时间阈值)和符号(如 <, <=, >, >=) + BigDecimal compareValue1 = child.getCompareNum1(); + BigDecimal compareValue2 = child.getCompareNum2(); + String symbol = child.getSymbol(); + + // 4. 根据符号和阈值判断响应时间是否符合子指标的规则,计算得分 + if (compareRange(successRate, compareValue1, compareValue2, symbol)) { + score = child.getScore().longValue(); // 得分等于子指标的得分 + break; // 找到符合条件的子指标后直接返回得分 + } + } + return score; + } + + private AeIndicatorEntity findIndicatorByName(List indicators, String indicatorName) { + for (AeIndicatorEntity indicator : indicators) { + if (indicator.getName().equals(indicatorName)) { + return indicator; + } + } + return null; // 如果找不到,返回null + } + + // 处理区间比较(例如:<=,>=) + private boolean compareRange(Long itemResponseTime, BigDecimal compareValue1, BigDecimal compareValue2, String symbol) { + // 如果 compareValue1 > compareValue2,交换两者 + if (compareValue1.compareTo(compareValue2) > 0) { + BigDecimal temp = compareValue1; + compareValue1 = compareValue2; + compareValue2 = temp; + } + + switch (symbol) { + case "≤": + return itemResponseTime <= compareValue2.longValue() && itemResponseTime >= compareValue1.longValue(); + case "<": + return itemResponseTime < compareValue2.longValue() && itemResponseTime >= compareValue1.longValue(); + case ">": + return itemResponseTime > compareValue1.longValue() && itemResponseTime <= compareValue2.longValue(); + case "≥": + return itemResponseTime >= compareValue1.longValue() && itemResponseTime <= compareValue2.longValue(); + default: + return false; + } + } }