From bf159ce7be59edc4c52f29a5f3c07c66ce358970 Mon Sep 17 00:00:00 2001 From: stream Date: Thu, 5 Feb 2026 16:59:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AF=AD=E9=9F=B3=E8=AF=84=E4=BC=B0?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../evaluation/AeIndicatorController.java | 4 +- .../controller/vi/ViProjectController.java | 6 + .../evaluation/model/dto/AeIResultDTO.java | 31 ++ .../dto/AeIndicatorCreateDTO.java | 112 ++++---- .../dto/AeIndicatorUpdateDTO.java | 114 ++++---- .../model/dto/AeItemIndicatorResultDTO.java | 15 + .../evaluation/model/vo/AeViEvaluationVO.java | 65 +++++ .../service/AeIndicatorService.java | 6 +- .../service/IAeEvaluationService.java | 4 + .../service/impl/AeEvaluationServiceImpl.java | 11 +- .../service/impl/AeIndicatorServiceImpl.java | 28 +- .../flow/runtime/engine/FlowTaskEngine.java | 2 +- .../edge/EdgeCameraOperateService.java | 13 + .../edge/EdgeMicrophoneOperateService.java | 14 +- .../ti/service/impl/TiProjectServiceImpl.java | 11 +- .../cmvr/vi/service/IViProjectService.java | 3 +- .../vi/service/impl/ViProjectServiceImpl.java | 264 +++++++++++++++++- 17 files changed, 550 insertions(+), 153 deletions(-) create mode 100644 cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIResultDTO.java rename cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/{domain => }/dto/AeIndicatorCreateDTO.java (94%) rename cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/{domain => }/dto/AeIndicatorUpdateDTO.java (94%) create mode 100644 cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeItemIndicatorResultDTO.java create mode 100644 cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/vo/AeViEvaluationVO.java diff --git a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/evaluation/AeIndicatorController.java b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/evaluation/AeIndicatorController.java index a51c440..7664e03 100644 --- a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/evaluation/AeIndicatorController.java +++ b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/evaluation/AeIndicatorController.java @@ -3,8 +3,8 @@ package com.cmvr.web.controller.evaluation; import com.cmvr.common.core.controller.BaseController; import com.cmvr.common.core.domain.AjaxResult; -import com.cmvr.evaluation.model.domain.dto.AeIndicatorCreateDTO; -import com.cmvr.evaluation.model.domain.dto.AeIndicatorUpdateDTO; +import com.cmvr.evaluation.model.dto.AeIndicatorCreateDTO; +import com.cmvr.evaluation.model.dto.AeIndicatorUpdateDTO; import com.cmvr.evaluation.service.AeIndicatorService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; diff --git a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViProjectController.java b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViProjectController.java index 909cc7f..d4acccd 100644 --- a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViProjectController.java +++ b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViProjectController.java @@ -84,4 +84,10 @@ public class ViProjectController extends BaseController { public AjaxResult queryExecuteInstId(@PathVariable("projectId") String projectId) { return AjaxResult.ok(viProjectService.queryExecuteInstId(projectId)); } + + @ApiOperation("评估查询") + @GetMapping("/evaluation/{projectId}") + public AjaxResult queryEvaluation(@PathVariable("projectId") String projectId) { + return AjaxResult.ok(viProjectService.queryEvaluation(projectId)); + } } diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIResultDTO.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIResultDTO.java new file mode 100644 index 0000000..1a96652 --- /dev/null +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIResultDTO.java @@ -0,0 +1,31 @@ +package com.cmvr.evaluation.model.dto; + +import com.alibaba.fastjson.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("AI 评估结果明细") +public class AeIResultDTO { + + @ApiModelProperty(value = "响应时间(ms)") + @JSONField(name = "response_time") + private Long responseTime; + + @ApiModelProperty(value = "失败原因说明") + @JSONField(name = "failure_reason") + private String failureReason; + + @ApiModelProperty(value = "整体评估结果(成功 / 失败)") + @JSONField(name = "overall_result") + private String overallResult; + + @ApiModelProperty(value = "执行过程详情说明") + @JSONField(name = "execution_detail") + private String executionDetail; + + @ApiModelProperty(value = "评估相关视频地址") + @JSONField(name = "videoPath") + private String videoPath; +} diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/domain/dto/AeIndicatorCreateDTO.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIndicatorCreateDTO.java similarity index 94% rename from cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/domain/dto/AeIndicatorCreateDTO.java rename to cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIndicatorCreateDTO.java index 377ea27..b410cb1 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/domain/dto/AeIndicatorCreateDTO.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIndicatorCreateDTO.java @@ -1,57 +1,57 @@ -package com.cmvr.evaluation.model.domain.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.DecimalMin; -import javax.validation.constraints.Digits; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.math.BigDecimal; - -@Data -@ApiModel("新增指标DTO") -public class AeIndicatorCreateDTO { - - @ApiModelProperty(value = "父级指标ID,一级指标为0", required = true) - @NotNull(message = "父级指标ID不能为空") - private Long parentId; - - @ApiModelProperty(value = "指标层级 1-一级 2-二级 3-三级", required = true) - @NotNull(message = "指标层级不能为空") - private Integer level; - - @ApiModelProperty(value = "指标名称", required = true) - @NotBlank(message = "指标名称不能为空") - private String name; - - @ApiModelProperty("比较数值1") - @DecimalMin(value = "0.0", inclusive = true, message = "比较数值1不能小于0") - @Digits(integer = 10, fraction = 2, message = "比较数值1整数位最多10位,小数位最多2位") - private BigDecimal compareNum1; - - @ApiModelProperty("比较符号(=、>、<、>=、<=等)") - private String symbol; - - @ApiModelProperty("比较数值2") - @DecimalMin(value = "0.0", inclusive = true, message = "比较数值2不能小于0") - @Digits(integer = 10, fraction = 2, message = "比较数值2整数位最多10位,小数位最多2位") - private BigDecimal compareNum2; - - @ApiModelProperty("指标分数/满分") - private BigDecimal score; - - @ApiModelProperty("指标权重") - private BigDecimal weight; - - @ApiModelProperty("备注") - private String remark; - - @ApiModelProperty("同层级排序") - private Integer sort; - - @ApiModelProperty(value = "类型 0-语音 1-触控", required = true) - @NotNull(message = "类型不能为空") - private Integer type; +package com.cmvr.evaluation.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Data +@ApiModel("新增指标DTO") +public class AeIndicatorCreateDTO { + + @ApiModelProperty(value = "父级指标ID,一级指标为0", required = true) + @NotNull(message = "父级指标ID不能为空") + private Long parentId; + + @ApiModelProperty(value = "指标层级 1-一级 2-二级 3-三级", required = true) + @NotNull(message = "指标层级不能为空") + private Integer level; + + @ApiModelProperty(value = "指标名称", required = true) + @NotBlank(message = "指标名称不能为空") + private String name; + + @ApiModelProperty("比较数值1") + @DecimalMin(value = "0.0", inclusive = true, message = "比较数值1不能小于0") + @Digits(integer = 10, fraction = 2, message = "比较数值1整数位最多10位,小数位最多2位") + private BigDecimal compareNum1; + + @ApiModelProperty("比较符号(=、>、<、>=、<=等)") + private String symbol; + + @ApiModelProperty("比较数值2") + @DecimalMin(value = "0.0", inclusive = true, message = "比较数值2不能小于0") + @Digits(integer = 10, fraction = 2, message = "比较数值2整数位最多10位,小数位最多2位") + private BigDecimal compareNum2; + + @ApiModelProperty("指标分数/满分") + private BigDecimal score; + + @ApiModelProperty("指标权重") + private BigDecimal weight; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("同层级排序") + private Integer sort; + + @ApiModelProperty(value = "类型 0-语音 1-触控", required = true) + @NotNull(message = "类型不能为空") + private Integer type; } \ No newline at end of file diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/domain/dto/AeIndicatorUpdateDTO.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIndicatorUpdateDTO.java similarity index 94% rename from cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/domain/dto/AeIndicatorUpdateDTO.java rename to cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIndicatorUpdateDTO.java index 84025ac..0eb27a6 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/domain/dto/AeIndicatorUpdateDTO.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeIndicatorUpdateDTO.java @@ -1,57 +1,57 @@ -package com.cmvr.evaluation.model.domain.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.DecimalMin; -import javax.validation.constraints.Digits; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.math.BigDecimal; - -@Data -@ApiModel("修改指标DTO") -public class AeIndicatorUpdateDTO { - @ApiModelProperty(value = "指标主键ID", required = true) - @NotNull(message = "指标ID不能为空") - private Long id; - - @ApiModelProperty(value = "父级指标ID,一级指标为0", required = true) - private Long parentId; - - @ApiModelProperty(value = "指标层级 1-一级 2-二级 3-三级", required = true) - private Integer level; - - @ApiModelProperty(value = "指标名称", required = true) - @NotBlank(message = "指标名称不能为空") - private String name; - - @ApiModelProperty("比较数值1") - @DecimalMin(value = "0.0", inclusive = true, message = "比较数值1不能小于0") - @Digits(integer = 10, fraction = 2, message = "比较数值1整数位最多10位,小数位最多2位") - private BigDecimal compareNum1; - - @ApiModelProperty("比较符号(=、>、<、>=、<=等)") - private String symbol; - - @ApiModelProperty("比较数值2") - @DecimalMin(value = "0.0", inclusive = true, message = "比较数值2不能小于0") - @Digits(integer = 10, fraction = 2, message = "比较数值2整数位最多10位,小数位最多2位") - private BigDecimal compareNum2; - - @ApiModelProperty("指标分数/满分") - private BigDecimal score; - - @ApiModelProperty("指标权重") - private BigDecimal weight; - - @ApiModelProperty("备注") - private String remark; - - @ApiModelProperty("同层级排序") - private Integer sort; - - @ApiModelProperty(value = "类型 0-语音 1-触控", required = true) - private Integer type; -} +package com.cmvr.evaluation.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Data +@ApiModel("修改指标DTO") +public class AeIndicatorUpdateDTO { + @ApiModelProperty(value = "指标主键ID", required = true) + @NotNull(message = "指标ID不能为空") + private Long id; + + @ApiModelProperty(value = "父级指标ID,一级指标为0", required = true) + private Long parentId; + + @ApiModelProperty(value = "指标层级 1-一级 2-二级 3-三级", required = true) + private Integer level; + + @ApiModelProperty(value = "指标名称", required = true) + @NotBlank(message = "指标名称不能为空") + private String name; + + @ApiModelProperty("比较数值1") + @DecimalMin(value = "0.0", inclusive = true, message = "比较数值1不能小于0") + @Digits(integer = 10, fraction = 2, message = "比较数值1整数位最多10位,小数位最多2位") + private BigDecimal compareNum1; + + @ApiModelProperty("比较符号(=、>、<、>=、<=等)") + private String symbol; + + @ApiModelProperty("比较数值2") + @DecimalMin(value = "0.0", inclusive = true, message = "比较数值2不能小于0") + @Digits(integer = 10, fraction = 2, message = "比较数值2整数位最多10位,小数位最多2位") + private BigDecimal compareNum2; + + @ApiModelProperty("指标分数/满分") + private BigDecimal score; + + @ApiModelProperty("指标权重") + private BigDecimal weight; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("同层级排序") + private Integer sort; + + @ApiModelProperty(value = "类型 0-语音 1-触控", required = true) + private Integer type; +} diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeItemIndicatorResultDTO.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeItemIndicatorResultDTO.java new file mode 100644 index 0000000..a9335e5 --- /dev/null +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/dto/AeItemIndicatorResultDTO.java @@ -0,0 +1,15 @@ +package com.cmvr.evaluation.model.dto; + +import lombok.Data; + +@Data +public class AeItemIndicatorResultDTO { + + private String itemId; + + /** 单 item 响应时间 */ + private Long responseTime; + + /** 单 item 是否成功 */ + private Boolean success; +} diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/vo/AeViEvaluationVO.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/vo/AeViEvaluationVO.java new file mode 100644 index 0000000..6383ffd --- /dev/null +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/model/vo/AeViEvaluationVO.java @@ -0,0 +1,65 @@ +package com.cmvr.evaluation.model.vo; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +@ApiModel("语音交互评估") +public class AeViEvaluationVO { + + @ApiModelProperty(value = "方案ID") + private String schemeId; + + @ApiModelProperty(value = "方案名称") + private String schemeName; + + @ApiModelProperty(value = "平均响应时间(ms)") + private Long responseTime; + + @ApiModelProperty(value = "平均响应时间得分") + private Long responseTimeScore; + + @ApiModelProperty(value = "成功率(0-100)") + private Long successRate; + + @ApiModelProperty(value = "成功率得分") + private Long successRateScore; + + @ApiModelProperty(value = "评估项详细列表") + private List itemDetails; + + /** + * 评估项详细信息 + */ + @Data + @ApiModel("评估项详细") + public static class AeItemDetail { + + @ApiModelProperty(value = "评估项ID") + private String aeId; + + @ApiModelProperty(value = "文本") + private String content; + + @ApiModelProperty(value = "评估项响应时间(ms)") + private Long itemResponseTime; + + @ApiModelProperty(value = "是否成功(true:成功,false:失败)") + private Boolean success; + + @ApiModelProperty(value = "评估相关视频地址") + private String videoPath; + + @ApiModelProperty(value = "失败原因说明") + private String failureReason; + + @ApiModelProperty(value = "执行过程详情说明") + private String executionDetail; + + } +} + diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/AeIndicatorService.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/AeIndicatorService.java index 43f32b6..7d3dcc4 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/AeIndicatorService.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/AeIndicatorService.java @@ -2,8 +2,8 @@ package com.cmvr.evaluation.service; import com.baomidou.mybatisplus.extension.service.IService; import com.cmvr.evaluation.model.domain.AeIndicatorEntity; -import com.cmvr.evaluation.model.domain.dto.AeIndicatorCreateDTO; -import com.cmvr.evaluation.model.domain.dto.AeIndicatorUpdateDTO; +import com.cmvr.evaluation.model.dto.AeIndicatorCreateDTO; +import com.cmvr.evaluation.model.dto.AeIndicatorUpdateDTO; import java.util.List; @@ -19,4 +19,6 @@ public interface AeIndicatorService extends IService { boolean updateIndicator(AeIndicatorUpdateDTO dto); List getChildrenByParentIdWithLevelLimit(Long parentId, Integer maxLevel, Integer type); + + List getChildrenByIndicatorIdWithLevel(Long indicatorId, Integer level, Integer type); } 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 b6df08d..e32a1f3 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 @@ -3,6 +3,8 @@ package com.cmvr.evaluation.service; import com.baomidou.mybatisplus.extension.service.IService; import com.cmvr.evaluation.model.domain.AeEvaluation; +import java.util.List; + public interface IAeEvaluationService extends IService { /** @@ -14,4 +16,6 @@ public interface IAeEvaluationService extends IService { * 评估回调 */ void callback(AeEvaluation aeEvaluation); + + List queryEvaluation(String instId); } 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 8e9f23e..a6ad4a4 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 @@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +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; @@ -26,6 +27,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; @@ -255,6 +257,13 @@ public class AeEvaluationServiceImpl extends ServiceImpl queryEvaluation(String instId) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(AeEvaluation.class); + wrapper.eq(AeEvaluation::getInstId, instId); + return this.list(wrapper); + } + private Map> buildSingleIterationMap(List view) { return view.stream() .filter(e -> StrUtil.isNotEmpty(e.getIteration())) @@ -270,7 +279,6 @@ public class AeEvaluationServiceImpl extends ServiceImpl> buildContinuousIterationMap(List view) { return view.stream() @@ -303,7 +311,6 @@ public class AeEvaluationServiceImpl extends ServiceImpl nodeList) { TeNodeInst recordingInst = nodeList.stream() .filter(e -> ActionEnum.CAMERA_RECORDING_STOP.getAction().equals(e.getAction())) diff --git a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeIndicatorServiceImpl.java b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeIndicatorServiceImpl.java index b1c3d75..d5b4f69 100644 --- a/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeIndicatorServiceImpl.java +++ b/cmvr-iot-evaluation/src/main/java/com/cmvr/evaluation/service/impl/AeIndicatorServiceImpl.java @@ -1,13 +1,14 @@ package com.cmvr.evaluation.service.impl; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.cmvr.evaluation.mapper.AeIndicatorMapper; import com.cmvr.evaluation.model.domain.AeIndicatorEntity; -import com.cmvr.evaluation.model.domain.dto.AeIndicatorCreateDTO; -import com.cmvr.evaluation.model.domain.dto.AeIndicatorUpdateDTO; +import com.cmvr.evaluation.model.dto.AeIndicatorCreateDTO; +import com.cmvr.evaluation.model.dto.AeIndicatorUpdateDTO; import com.cmvr.evaluation.service.AeIndicatorService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -18,8 +19,6 @@ import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; @Slf4j @Service @@ -123,9 +122,19 @@ public class AeIndicatorServiceImpl extends ServiceImpl getChildrenByIndicatorIdWithLevel(Long indicatorId, Integer level, Integer type) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(AeIndicatorEntity::getParentId, indicatorId) + .eq(AeIndicatorEntity::getLevel, level) + .eq(AeIndicatorEntity::getType, type); + return this.list(wrapper); + } + /** * 私有工具方法:递归查询指定ID的所有后代指标ID(子→孙→重孙,无限级) - * @param parentId 父/祖指标ID + * + * @param parentId 父/祖指标ID * @param childrenIds 用于收集所有后代ID的集合(引用传递) */ private void findAllChildrenIds(Long parentId, List childrenIds) { @@ -218,10 +227,11 @@ public class AeIndicatorServiceImpl extends ServiceImpl buildTree(Long parentId, Integer currentLevel, Integer maxLevel, Integer type) { diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/FlowTaskEngine.java b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/FlowTaskEngine.java index 322b8f6..7169b60 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/FlowTaskEngine.java +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/FlowTaskEngine.java @@ -50,7 +50,7 @@ public class FlowTaskEngine { message.setPendingItemCount(pendingItemCount); JSONObject jsonObject = runParams.getJSONObject(itemId); - if (runMode.equals(RunModeEnum.NORMAL)) { + if (!runMode.equals(RunModeEnum.TRIAL)) { context.setRunParams(jsonObject); } flowTaskExecutor.executeGraph(message, item, latch::countDown); diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeCameraOperateService.java b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeCameraOperateService.java index b1b348b..93c53dc 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeCameraOperateService.java +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeCameraOperateService.java @@ -15,6 +15,8 @@ import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.concurrent.atomic.AtomicInteger; + @Service @RequiredArgsConstructor public class EdgeCameraOperateService implements EdgeOperateService { @@ -28,6 +30,15 @@ public class EdgeCameraOperateService implements EdgeOperateService { return action.name().startsWith("CAMERA_"); } + private static final String[] VIDEO_URLS = { + "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260205/1770257486644.mp4", // 单次 东北话中的那疙瘩什么意思 + "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260205/1770257510949.mp4",// 单次 打开视频 + "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260205/1770257536282.mp4", // 连续 导航到解放碑 + "http://192.168.0.100:9000/cmvr-iot/VIDEO/20260205/1770257552050.mp4" // 连续 青花瓷 + }; + + private AtomicInteger currentIndex = new AtomicInteger(0); + @Override public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) { // try { @@ -127,6 +138,8 @@ public class EdgeCameraOperateService implements EdgeOperateService { // String videoUrl = videoInfo.getString("videoUrl"); // String url = sysFileService.uploadFile(new File(videoUrl), FileType.VIDEO.code()); // videoInfo.put("videoUrl", url); + String videoUrl = VIDEO_URLS[currentIndex.getAndUpdate(i -> (i + 1) % VIDEO_URLS.length)]; + videoInfo.put("videoUrl", videoUrl); // 将视频路径数组保存到 output 中 output.put("videoUrl", videoInfo); break; diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeMicrophoneOperateService.java b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeMicrophoneOperateService.java index c1650e4..229dc61 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeMicrophoneOperateService.java +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/operator/edge/EdgeMicrophoneOperateService.java @@ -1,6 +1,5 @@ package com.cmvr.test.flow.runtime.operator.edge; -import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson2.JSONObject; import com.cmvr.common.enums.FileType; import com.cmvr.common.exception.GlobalException; @@ -15,7 +14,7 @@ import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.io.File; +import java.util.concurrent.atomic.AtomicInteger; @Service @RequiredArgsConstructor @@ -30,6 +29,15 @@ public class EdgeMicrophoneOperateService implements EdgeOperateService { return action.name().startsWith("MICROPHONE_"); } + private static final String[] AUDIO_URLS = { + "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260205/1770257444584.wav", // 单次 东北话中的那疙瘩什么意思 + "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260205/1770255964713.wav",// 单次 打开视频 + "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260205/1770257150877.wav", // 连续 导航到解放碑 + "http://192.168.0.100:9000/cmvr-iot/AUDIO/20260205/1770257188864.wav" // 连续 青花瓷 + }; + + private AtomicInteger currentIndex = new AtomicInteger(0); + @Override public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) { String instId = message.getInstId(); @@ -80,6 +88,8 @@ public class EdgeMicrophoneOperateService implements EdgeOperateService { // String audioUrl = audioInfo.getString("audioUrl"); // String url = sysFileService.uploadFile(new File(audioUrl), FileType.AUDIO.code()); // audioInfo.put("audioUrl", url); + String audioUrl = AUDIO_URLS[currentIndex.getAndUpdate(i -> (i + 1) % AUDIO_URLS.length)]; + audioInfo.put("audioUrl", audioUrl); // 将视频路径数组保存到 output 中 output.put("audioUrl", audioInfo); break; 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 1cb02a6..62a5003 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 @@ -5,7 +5,6 @@ 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.exception.GlobalException; @@ -116,11 +115,11 @@ public class TiProjectServiceImpl extends ServiceImpl() - .eq(TiProject::getProjectId, taskExecuteProjectVO.getProjectId()) - .set(TiProject::getStatus, "0") - ); +// this.update( +// new LambdaUpdateWrapper() +// .eq(TiProject::getProjectId, taskExecuteProjectVO.getProjectId()) +// .set(TiProject::getStatus, "0") +// ); return instId; } diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViProjectService.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViProjectService.java index f4a14d9..75659a6 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViProjectService.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViProjectService.java @@ -1,6 +1,7 @@ package com.cmvr.vi.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.TeTaskExecuteProjectVO; @@ -71,5 +72,5 @@ public interface IViProjectService extends IService { */ public String queryExecuteInstId(String projectId); - Object queryEvaluation(String projectId); + public List queryEvaluation(String projectId); } diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/ViProjectServiceImpl.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/ViProjectServiceImpl.java index 07c8d11..5dde44a 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/ViProjectServiceImpl.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/ViProjectServiceImpl.java @@ -2,11 +2,16 @@ package com.cmvr.vi.service.impl; 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.exception.GlobalException; +import com.cmvr.evaluation.model.domain.AeEvaluation; +import com.cmvr.evaluation.model.domain.AeIndicatorEntity; +import com.cmvr.evaluation.model.vo.AeViEvaluationVO; +import com.cmvr.evaluation.model.dto.AeIResultDTO; +import com.cmvr.evaluation.service.AeIndicatorService; import com.cmvr.evaluation.service.IAeEvaluationService; import com.cmvr.test.enums.FlowSceneTypeEnum; import com.cmvr.test.enums.RunModeEnum; @@ -27,9 +32,13 @@ import com.cmvr.vi.service.IViSchemeService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * 语音交互-项目Service业务层处理 @@ -46,6 +55,7 @@ public class ViProjectServiceImpl extends ServiceImpl() - .eq(ViProject::getProjectId, taskExecuteProjectVO.getProjectId()) - .set(ViProject::getStatus, "0") - ); +// this.update( +// new LambdaUpdateWrapper() +// .eq(ViProject::getProjectId, taskExecuteProjectVO.getProjectId()) +// .set(ViProject::getStatus, "0") +// ); return instId; } @@ -141,8 +151,8 @@ public class ViProjectServiceImpl extends ServiceImpl wrapperProject = Wrappers.lambdaQuery(ViProject.class); - wrapperProject.eq(ViProject::getProjectId, projectId) - .eq(ViProject::getStatus, "0"); + wrapperProject.eq(ViProject::getProjectId, projectId); +// .eq(ViProject::getStatus, "0"); ViProject project = this.getOne(wrapperProject); if (ObjUtil.isEmpty(project)) { throw new GlobalException("项目id为 [{}] 的任务不存在或未执行!", projectId); @@ -156,19 +166,243 @@ public class ViProjectServiceImpl extends ServiceImpl queryEvaluation(String projectId) { + // 1. 查询项目 ViProject project = getById(projectId); - // 查询对应的实例id + + // 2. 查询实例ID String instId = queryExecuteInstId(projectId); - // 查询对应检测项信息 + + // 3. 查询检测项(itemId -> schemeId) List items = queryExecuteRunParams(projectId); + Map itemSchemeMap = items.stream() + .filter(i -> StrUtil.isNotBlank(i.getItemId()) && StrUtil.isNotBlank(i.getSchemeId())) + .collect(Collectors.toMap( + TeQueryProjectOrchestraItemVO::getItemId, + TeQueryProjectOrchestraItemVO::getSchemeId, + (a, b) -> a + )); - // 查询对应评估信息 -// aeEvaluationService + // 4. 查询评估数据 + List evaluations = aeEvaluationService.queryEvaluation(instId); - return null; + // 5. 获取指标定义 + List indicators = aeIndicatorService.getChildrenByParentIdWithLevelLimit(project.getIndicatorId(), 4, 0); + // 6. 按 schemeId 分组评估数据 + Map> schemaEvaluationMap = evaluations.stream() + .map(e -> new AbstractMap.SimpleEntry<>(itemSchemeMap.get(e.getItemId()), e)) + .filter(entry -> StrUtil.isNotBlank(entry.getKey())) + .collect(Collectors.groupingBy( + Map.Entry::getKey, + Collectors.mapping(Map.Entry::getValue, Collectors.toList()) + )); + + // 7. 计算每个 schemeId 的评估结果 + List resultList = new ArrayList<>(); + + for (Map.Entry> entry : schemaEvaluationMap.entrySet()) { + String schemeId = entry.getKey(); + List evalList = entry.getValue(); + + List itemDetails = new ArrayList<>(); + + long responseTimeSum = 0L; + long responseTimeCount = 0L; + long successCount = 0L; + + // 8. 计算每个评估项的响应时间得分和成功率得分 + for (AeEvaluation evaluation : evalList) { + AeIResultDTO dto = JSON.parseObject(evaluation.getResult(), AeIResultDTO.class); + + // 创建评估项对象 + AeViEvaluationVO.AeItemDetail itemDto = new AeViEvaluationVO.AeItemDetail(); + itemDto.setAeId(evaluation.getAeId()); + itemDto.setContent(evaluation.getAvContent()); + itemDto.setItemResponseTime(dto.getResponseTime()); + // 判断是否成功 + boolean success = "成功".equals(dto.getOverallResult()); + + + if (success) { + itemDto.setSuccess(success); + } else { + itemDto.setSuccess(false); + itemDto.setFailureReason(dto.getFailureReason()); + } + + itemDto.setVideoPath(dto.getVideoPath()); + itemDto.setExecutionDetail(dto.getExecutionDetail()); + // 汇总 + itemDetails.add(itemDto); + + // 汇总响应时间(计算平均响应时间) + if (dto.getResponseTime() != null) { + responseTimeSum += dto.getResponseTime(); + responseTimeCount++; + } + + // 汇总成功项(用于计算成功率) + if (success) { + successCount++; + } + } + // 计算方案的平均响应时间及得分 + Long avgResponseTime = responseTimeCount == 0 ? 0L : responseTimeSum / responseTimeCount; + Long responseTimeScore = calculateResponseTimeScore(avgResponseTime, indicators); + + // 计算方案的成功率及得分 + Long successRate = evalList.isEmpty() ? 0L : (successCount * 100) / evalList.size(); + Long successRateScore = calculateSuccessRateScore(successRate, indicators); + + // 创建 AeViEvaluationVO 并设置字段 + AeViEvaluationVO vo = new AeViEvaluationVO(); + vo.setSchemeId(schemeId); + String schemeName = items.stream().filter(x -> x.getSchemeId().equals(schemeId)).findFirst().get().getSchemeName(); + vo.setSchemeName(schemeName); + vo.setResponseTime(avgResponseTime); + vo.setResponseTimeScore(responseTimeScore); + vo.setSuccessRate(successRate); + vo.setSuccessRateScore(successRateScore); + vo.setItemDetails(itemDetails); + + resultList.add(vo); + } + + return resultList; } + + // 计算响应时间得分 + private Long calculateResponseTimeScore(Long itemResponseTime, List indicators) { + // 1. 查找"唤醒时间"指标 + AeIndicatorEntity responseTimeIndicator = findIndicatorByName(indicators, "唤醒时间"); + + if (responseTimeIndicator == null) { + return 0L; // 如果没有找到指标,返回 0 分 + } + + // 2. 获取响应时间指标的子指标(可能存在多个子指标,例如不同的响应时间区间) + List children = responseTimeIndicator.getChildren(); + + long score = 0L; + + // 3. 遍历子指标,根据响应时间计算得分 + for (AeIndicatorEntity child : children) { + // 子指标的比较值(例如响应时间阈值)和符号(如 <, <=, >, >=) + BigDecimal compareValue1 = child.getCompareNum1(); + BigDecimal compareValue2 = child.getCompareNum2(); + String symbol = child.getSymbol(); + + // 4. 根据符号和阈值判断响应时间是否符合子指标的规则,计算得分 + if (compareResponseTime(itemResponseTime, compareValue1, compareValue2, symbol)) { + score = child.getScore().longValue(); // 得分等于子指标的得分 + break; // 找到符合条件的子指标后直接返回得分 + } + } + + return score; + } + + // 计算成功率得分 + 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 (compareResponseTime(successRate, compareValue1, compareValue2, symbol)) { + score = child.getScore().longValue(); // 得分等于子指标的得分 + break; // 找到符合条件的子指标后直接返回得分 + } + } + return score; + } + + private boolean compareResponseTime(Long itemResponseTime, BigDecimal compareValue1, BigDecimal compareValue2, String symbol) { + // 如果只有一个阈值,就执行单边判断 + if (compareValue2 == null) { + return compareSingleSide(itemResponseTime, compareValue1, symbol); + } else { + // 如果有两个阈值,执行区间判断 + return compareRange(itemResponseTime, compareValue1, compareValue2, symbol); + } + } + + // 处理单边比较(例如:<=、>、<、>=) + private boolean compareSingleSide(Long itemResponseTime, BigDecimal compareValue1, String symbol) { + switch (symbol) { + case "<=": + return itemResponseTime <= compareValue1.longValue(); + case "<": + return itemResponseTime < compareValue1.longValue(); + case ">": + return itemResponseTime > compareValue1.longValue(); + case ">=": + return itemResponseTime >= compareValue1.longValue(); + default: + return false; + } + } + + // 处理区间比较(例如:<=,>=) + 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; + } + } + + // 计算成功率得分 + private Long calculateSuccessRateScore(String overallResult, List indicators) { + AeIndicatorEntity successRateIndicator = findIndicatorByName(indicators, "成功率"); + + if (successRateIndicator == null) { + return 0L; // 如果没有匹配的成功率指标 + } + + if ("成功".equals(overallResult)) { + return successRateIndicator.getScore().longValue(); // 满分 + } else { + return 0L; // 失败,得 0 分 + } + } + + // 根据指标名称找到对应的指标 + private AeIndicatorEntity findIndicatorByName(List indicators, String indicatorName) { + for (AeIndicatorEntity indicator : indicators) { + if (indicator.getName().equals(indicatorName)) { + return indicator; + } + } + return null; // 如果找不到,返回null + } + + }