diff --git a/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/BaseEntity.java b/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/BaseEntity.java index 7599067..ee06996 100644 --- a/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/BaseEntity.java +++ b/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/BaseEntity.java @@ -4,6 +4,8 @@ import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Map; + +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -24,16 +26,20 @@ public class BaseEntity implements Serializable private String searchValue; /** 创建者 */ + @TableField(fill = FieldFill.INSERT) private String createBy; /** 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT) private Date createTime; /** 更新者 */ + @TableField(fill = FieldFill.UPDATE) private String updateBy; /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date updateTime; diff --git a/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/entity/SysFileInfo.java b/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/entity/SysFileInfo.java index 5689814..1012d5c 100644 --- a/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/entity/SysFileInfo.java +++ b/cmvr-iot-common/src/main/java/com/cmvr/common/core/domain/entity/SysFileInfo.java @@ -1,6 +1,8 @@ package com.cmvr.common.core.domain.entity; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -32,11 +34,11 @@ public class SysFileInfo implements Serializable { private Integer fileType; @ApiModelProperty("上传人") -// @TableField(fill = FieldFill.INSERT) // todo 暂时不要 没有token + @TableField(fill = FieldFill.INSERT) private String createBy; @ApiModelProperty("上传时间") -// @TableField(fill = FieldFill.INSERT) + @TableField(fill = FieldFill.INSERT) private Date createTime; @ApiModelProperty("文件MD5值") 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 836ffea..e97d595 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 @@ -33,9 +33,9 @@ public class MyMetaObjectHandler implements MetaObjectHandler { } // 起始版本 3.3.0(推荐使用) this.setFieldValByName(CREATE_BY, username, metaObject); - this.setFieldValByName(CREATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject); + this.setFieldValByName(CREATE_TIME, currentTime(metaObject, CREATE_TIME), metaObject); this.setFieldValByName(UPDATE_BY, username, metaObject); - this.setFieldValByName(UPDATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject); + this.setFieldValByName(UPDATE_TIME, currentTime(metaObject, UPDATE_TIME), metaObject); this.setFieldValByName(DELETED, "0", metaObject); // this.setFieldValByName(STATUS, "1", metaObject); if (getFieldValByName(STATUS, metaObject) == null) { @@ -56,9 +56,14 @@ public class MyMetaObjectHandler implements MetaObjectHandler { username = "anonymous"; // 匿名接口默认值 } this.setFieldValByName(UPDATE_BY, username, metaObject); - this.setFieldValByName(UPDATE_TIME, formatDate(metaObject.getSetterType(CREATE_TIME)), metaObject); + this.setFieldValByName(UPDATE_TIME, currentTime(metaObject, UPDATE_TIME), metaObject); } + private Object currentTime(MetaObject metaObject, String fieldName) { + return metaObject.hasSetter(fieldName) + ? formatDate(metaObject.getSetterType(fieldName)) + : null; + } /** * 处理特殊日期 diff --git a/cmvr-iot-test/pom.xml b/cmvr-iot-test/pom.xml index d93ed04..5565495 100644 --- a/cmvr-iot-test/pom.xml +++ b/cmvr-iot-test/pom.xml @@ -47,5 +47,12 @@ nashorn-core ${nashorn.version} + + + junit + junit + 4.13.2 + test + diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/dispatcher/FlowGetCurrentObjNodeHandler.java b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/dispatcher/FlowGetCurrentObjNodeHandler.java index 09ff6f8..5d1c1e1 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/dispatcher/FlowGetCurrentObjNodeHandler.java +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/dispatcher/FlowGetCurrentObjNodeHandler.java @@ -1,16 +1,12 @@ package com.cmvr.test.flow.runtime.dispatcher; -import cn.hutool.core.collection.CollUtil; -import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.cmvr.test.flow.runtime.engine.support.FlowLoopValueResolver; import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage; import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.util.Collections; -import java.util.List; - @Slf4j @Component("GET_CURRENT_OBJECT") public class FlowGetCurrentObjNodeHandler implements FlowNodeTypeHandler { @@ -19,18 +15,11 @@ public class FlowGetCurrentObjNodeHandler implements FlowNodeTypeHandler { @Override public TaskNodeExecuteResult handle(TaskNodeExecuteMessage message) { try { -// JSONObject inputParams = message.getInputParams(); -// JSONArray jsonArray = inputParams.getJSONArray("array"); -// -// List iterations = message.getIterations(); -// int last = CollUtil.getLast(iterations) - 1; - int index = message.getLoopNum() - 1; + int iteration = message.getLoopNum(); + int index = iteration - 1; JSONObject output = new JSONObject(); output.put("index", index); - JSONArray objects = (JSONArray)message.getLoopArray(); - if (CollUtil.isNotEmpty(objects) && index >= 0) { - output.put("object", objects.get(index)); - } + output.put("object", FlowLoopValueResolver.current(message.getLoopArray(), iteration)); return TaskNodeExecuteResult.success(output); diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowLoopValueResolver.java b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowLoopValueResolver.java new file mode 100644 index 0000000..f0477de --- /dev/null +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowLoopValueResolver.java @@ -0,0 +1,91 @@ +package com.cmvr.test.flow.runtime.engine.support; + +import com.alibaba.fastjson2.JSON; +import com.cmvr.common.exception.GlobalException; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; + +/** Resolves the two supported loop sources: arrays and iteration counts. */ +public final class FlowLoopValueResolver { + + private FlowLoopValueResolver() { + } + + public static int count(Object value) { + Object normalized = normalize(value); + if (normalized == null) { + return 0; + } + if (normalized instanceof Collection) { + return ((Collection) normalized).size(); + } + if (normalized != null && normalized.getClass().isArray()) { + return Array.getLength(normalized); + } + if (normalized instanceof Number) { + return ((Number) normalized).intValue(); + } + throw unsupported(value); + } + + public static Object current(Object value, int iteration) { + if (iteration < 1) { + throw new GlobalException("当前循环次数必须从 1 开始: " + iteration); + } + + Object normalized = normalize(value); + int index = iteration - 1; + if (normalized instanceof Collection) { + Collection collection = (Collection) normalized; + if (index >= collection.size()) { + throw outOfBounds(iteration, collection.size()); + } + return new ArrayList<>(collection).get(index); + } + if (normalized != null && normalized.getClass().isArray()) { + int length = Array.getLength(normalized); + if (index >= length) { + throw outOfBounds(iteration, length); + } + return Array.get(normalized, index); + } + if (normalized instanceof Number) { + int loopCount = ((Number) normalized).intValue(); + if (iteration > loopCount) { + throw outOfBounds(iteration, loopCount); + } + return iteration; + } + throw unsupported(value); + } + + private static Object normalize(Object value) { + if (!(value instanceof String)) { + return value; + } + + String text = ((String) value).trim(); + if (text.startsWith("[")) { + try { + return JSON.parseArray(text); + } catch (Exception e) { + throw new GlobalException("循环数组参数格式错误: " + value); + } + } + try { + return Integer.parseInt(text); + } catch (NumberFormatException e) { + throw unsupported(value); + } + } + + private static GlobalException unsupported(Object value) { + return new GlobalException("循环参数仅支持数组或数字: " + value); + } + + private static GlobalException outOfBounds(int iteration, int count) { + return new GlobalException("当前循环次数超出范围: " + iteration + "/" + count); + } +} diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowNodeParamPreparer.java b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowNodeParamPreparer.java index 14ed92b..f5a3f87 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowNodeParamPreparer.java +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/flow/runtime/engine/support/FlowNodeParamPreparer.java @@ -2,7 +2,6 @@ package com.cmvr.test.flow.runtime.engine.support; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; -import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.cmvr.common.exception.GlobalException; @@ -17,8 +16,6 @@ import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import java.lang.reflect.Array; -import java.util.Collection; import java.util.List; @Component @@ -51,32 +48,7 @@ public class FlowNodeParamPreparer { if (node.getNodeType() == NodeTypeEnum.LOOP) { Object loopNumVal = input.get("loopNum"); input.put("loopArray", loopNumVal); - int loopCount = 0; - - // 根据迭代路径找到当前层的集合对象 -// Object target = resolveLoopTarget(loopNumVal, rootMessage.getIterations(), 0); - Object target = loopNumVal; - if (target instanceof JSONArray) { - loopCount = ((JSONArray) target).size(); - } else if (target instanceof Collection) { - loopCount = ((Collection) target).size(); - } else if (target != null && target.getClass().isArray()) { - loopCount = Array.getLength(target); - } else if (target instanceof Number) { - loopCount = ((Number) target).intValue(); - } else if (target != null) { - try { - String string = target.toString(); - if (string.startsWith("[")) { - JSONArray array = JSON.parseArray(string); - loopCount = array.size(); - }else { - loopCount = Integer.parseInt(string); - } - } catch (NumberFormatException e) { - throw new GlobalException("loopNum 参数格式错误: " + loopNumVal); - } - } + int loopCount = FlowLoopValueResolver.count(loopNumVal); // 写回 inputParams,供 LoopHandler 使用 input.put("loopNum", loopCount); @@ -177,40 +149,4 @@ public class FlowNodeParamPreparer { return curr; } - /** - * 根据迭代路径(iterations)逐层解析嵌套集合 - * - iterations = [] → 返回最外层对象 - * - iterations = [2] → 返回 list[1] - * - iterations = [2,3] → 返回 list[1][2] - */ - private Object resolveLoopTarget(Object obj, List iterations, int depth) { - if (obj == null) return null; - - // 已经走到当前循环层,返回目标 - if (depth >= iterations.size()) { - return obj; - } - - int idx = iterations.get(depth) - 1; - - if (obj instanceof List) { - List list = (List) obj; - if (idx >= 0 && idx < list.size()) { - return resolveLoopTarget(list.get(idx), iterations, depth + 1); - } - } else if (obj instanceof JSONArray) { - JSONArray arr = (JSONArray) obj; - if (idx >= 0 && idx < arr.size()) { - return resolveLoopTarget(arr.get(idx), iterations, depth + 1); - } - } else if (obj != null && obj.getClass().isArray()) { - int length = Array.getLength(obj); - if (idx >= 0 && idx < length) { - return resolveLoopTarget(Array.get(obj, idx), iterations, depth + 1); - } - } - - // 如果不是集合类型,直接返回 - return obj; - } } diff --git a/cmvr-iot-test/src/main/java/com/cmvr/test/service/impl/TeTaskInstServiceImpl.java b/cmvr-iot-test/src/main/java/com/cmvr/test/service/impl/TeTaskInstServiceImpl.java index 9d3f579..e42e158 100644 --- a/cmvr-iot-test/src/main/java/com/cmvr/test/service/impl/TeTaskInstServiceImpl.java +++ b/cmvr-iot-test/src/main/java/com/cmvr/test/service/impl/TeTaskInstServiceImpl.java @@ -59,6 +59,7 @@ public class TeTaskInstServiceImpl extends ServiceImpl() .eq(TeTaskInst::getId, instId) .set(TeTaskInst::getStatus, taskStatusEnum.getCode()) diff --git a/cmvr-iot-test/src/test/java/com/cmvr/test/flow/runtime/engine/support/FlowLoopValueResolverTest.java b/cmvr-iot-test/src/test/java/com/cmvr/test/flow/runtime/engine/support/FlowLoopValueResolverTest.java new file mode 100644 index 0000000..517d6d2 --- /dev/null +++ b/cmvr-iot-test/src/test/java/com/cmvr/test/flow/runtime/engine/support/FlowLoopValueResolverTest.java @@ -0,0 +1,64 @@ +package com.cmvr.test.flow.runtime.engine.support; + +import com.alibaba.fastjson2.JSON; +import com.cmvr.common.exception.GlobalException; +import com.cmvr.test.flow.runtime.dispatcher.FlowGetCurrentObjNodeHandler; +import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage; +import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +public class FlowLoopValueResolverTest { + + @Test + public void resolvesCurrentArrayElement() { + assertEquals(3, FlowLoopValueResolver.count(JSON.parseArray("[\"a\",\"b\",\"c\"]"))); + assertEquals("b", FlowLoopValueResolver.current(Arrays.asList("a", "b", "c"), 2)); + assertEquals(20, FlowLoopValueResolver.current(new Integer[]{10, 20, 30}, 2)); + assertEquals("b", FlowLoopValueResolver.current("[\"a\",\"b\",\"c\"]", 2)); + } + + @Test + public void resolvesCurrentNumericIteration() { + assertEquals(3, FlowLoopValueResolver.count(3)); + assertEquals(2, FlowLoopValueResolver.current(3, 2)); + assertEquals(3, FlowLoopValueResolver.count("3")); + assertEquals(2, FlowLoopValueResolver.current("3", 2)); + } + + @Test + public void currentObjectNodeKeepsOutputContractForArrayLoop() { + TaskNodeExecuteResult result = executeCurrentObjectNode(Arrays.asList("a", "b", "c"), 2); + + assertEquals(1, result.getOutputParams().getIntValue("index")); + assertEquals("b", result.getOutputParams().get("object")); + } + + @Test + public void currentObjectNodeReturnsIterationForNumericLoop() { + TaskNodeExecuteResult result = executeCurrentObjectNode(3, 2); + + assertEquals(1, result.getOutputParams().getIntValue("index")); + assertEquals(2, result.getOutputParams().getIntValue("object")); + } + + @Test(expected = GlobalException.class) + public void rejectsUnsupportedLoopValue() { + FlowLoopValueResolver.count("not-a-loop"); + } + + @Test(expected = GlobalException.class) + public void rejectsIterationOutsideLoopRange() { + FlowLoopValueResolver.current(Arrays.asList("a"), 2); + } + + private TaskNodeExecuteResult executeCurrentObjectNode(Object loopValue, int iteration) { + TaskNodeExecuteMessage message = new TaskNodeExecuteMessage(); + message.setLoopArray(loopValue); + message.setLoopNum(iteration); + return new FlowGetCurrentObjNodeHandler().handle(message); + } +} 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 fd02cea..b039238 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 @@ -163,7 +163,7 @@ public class TiProjectServiceImpl extends ServiceImpl wrapper = Wrappers.lambdaUpdate(); wrapper.eq(TiProject::getProjectId, projectId) .set(TiProject::getStatus, status); - return this.update(null, wrapper); + return this.update(new TiProject(), wrapper); } // 功能ID -> 音频地址 diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/ex/ExViProjectServiceImpl.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/ex/ExViProjectServiceImpl.java index 9145034..ae50c09 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/ex/ExViProjectServiceImpl.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/ex/ExViProjectServiceImpl.java @@ -27,6 +27,6 @@ public class ExViProjectServiceImpl implements ExViProjectService { wrapper.eq(ViProject::getProjectId, id) .eq(ViProject::getStatus, 1) // 运行中 .set(ViProject::getStatus, 2); // 完成 - return viProjectService.update(null, wrapper); + return viProjectService.update(new ViProject(), wrapper); } } 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 390c326..6fe7692 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 @@ -138,6 +138,7 @@ public class ViProjectServiceImpl extends ServiceImpl() .eq(ViProject::getProjectId, taskExecuteProjectVO.getProjectId()) .set(ViProject::getStatus, "1") //执行中