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") //执行中