diff --git a/app.db b/app.db
index a99e382..2b34b99 100644
Binary files a/app.db and b/app.db differ
diff --git a/src/main/java/com/iflytop/digester/StartResetTaskThread.java b/src/main/java/com/iflytop/digester/StartResetTaskThread.java
new file mode 100644
index 0000000..5810e11
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/StartResetTaskThread.java
@@ -0,0 +1,248 @@
+package com.iflytop.digester;
+import com.iflytop.digester.deviceinstance.Device;
+import com.iflytop.digester.underframework.dao.model.UfMdbRuntimeVariable;
+public class StartResetTaskThread extends Thread {
+ // 是否需要放置异常处理试管架
+ private Boolean isErrorTubeRackRequired = true;
+
+ @Override
+ public void run() {
+ var device = Device.getInstance();
+ device.setStatus("preparing");
+ this.setProgressMessage("设备初始化...");
+
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+// this.getDevice().getIO().setValue("LightRed", 1);
+//
+// this.setProgressMessage("设备初始化 : 关闭设备门");
+// DiActMotor doorMotor = this.getActuator(MyDevice.ACT_DOOR_MOTOR, DiActMotor.class);
+// doorMotor.setEnable(true);
+// MoveDoorClose.execute(this.getDevice());
+//
+// this.setProgressMessage("设备初始化 : 加液臂复位");
+// DiActMotor liquidMotor = this.getActuator(MyDevice.ACT_LIQUID_MOTOR, DiActMotor.class);
+// liquidMotor.setEnable(true);
+// liquidMotor.reset();
+// liquidMotor.moveTo("LiquidArmStandby");
+//
+// this.setProgressMessage("设备初始化 : 关闭夹爪");
+// DiActServo transferClipServo = this.getActuator(MyDevice.ACT_TRANSFER_CLIP_SERVO, DiActServo.class);
+// transferClipServo.setEnable(true);
+// transferClipServo.moveTo("TransClipServoClose");
+//
+// this.setProgressMessage("设备初始化 : 搬运机械臂上下移动复位");
+// DiActMotor transUdMotor = this.getActuator(MyDevice.ACT_TRANSFER_UD_MOTOR, DiActMotor.class);
+// transUdMotor.setEnable(true);
+// transUdMotor.reset();
+// transUdMotor.moveTo("TransUdMotorStandby");
+//
+// this.setProgressMessage("设备初始化 : 搬运机械臂左右移动复位");
+// DiActMotor transLrMotor = this.getActuator(MyDevice.ACT_TRANSFER_LR_MOTOR, DiActMotor.class);
+// transLrMotor.setEnable(true);
+// transLrMotor.reset();
+// transLrMotor.setMoveOffset("TransLrMotorGlobalOffset");
+// transLrMotor.moveTo("TransLrMotorStandby");
+//
+// // @TODO : http://127.0.0.1:5566/issues/39
+// this.setProgressMessage("设备初始化 : 加液转盘复位");
+// DiActMotor liquidPlateMotor = this.getActuator(MyDevice.ACT_LIQUID_PLATE_MOTOR, DiActMotor.class);
+// liquidPlateMotor.setEnable(true);
+// liquidPlateMotor.reset();
+//
+// // @TODO : http://127.0.0.1:5566/issues/40
+// this.setProgressMessage("设备初始化 : 加热盘转盘复位");
+// DiActMotor heatPlateMotor = this.getActuator(MyDevice.ACT_HEAT_PLATE_MOTOR, DiActMotor.class);
+// heatPlateMotor.setEnable(true);
+// heatPlateMotor.reset();
+// heatPlateMotor.moveTo("HeatPlateStandby");
+//
+// this.setupHeatingSlotCover();
+// this.setupPeristalticPump();
+//
+// this.setProgressMessage("设备初始化 : 相机");
+// DiActCameraBasler camera = this.getActuator(MyDevice.ACT_CAMERA, DiActCameraBasler.class);
+// camera.setEnable(true);
+//
+// this.setProgressMessage("设备初始化 : 定时刷新加热盘温度");
+// var slotMan = this.getResourceManager(ResHeatingTubeRackSlotManager.class);
+// slotMan.startTemperatureRefresh();
+//
+// if ( this.isErrorTubeRackRequired ) {
+// this.setProgressMessage("设备初始化 : 放入异常处理试管架");
+// doorMotor.reset(); // 打开设备门
+// DiMdbNotification.taskAction(this, "TaskStartResetErrorTubeRackPutIn");
+// this.waitAction("TaskStartResetErrorTubeRackPutIn");
+// }
+//
+// this.getDevice().getIO().setValue("LightRed", 0);
+// this.getDevice().getIO().setValue("LightGreen", 1);
+
+ this.setProgressMessage("设备初始化 : 完成");
+ device.setStatus("ready");
+ UfMdbRuntimeVariable.setString("设备已就绪","device.message");
+ }
+//
+// // 设置蠕动泵
+// private void setupPeristalticPump() {
+// int peristalticPumpCount = 1;
+// var actuators = this.getDevice().getActuators().getAll();
+// for ( var actuator : actuators ) {
+// if (actuator instanceof DiActPeristalticPump pump) {
+// this.setProgressMessage("设备初始化 : 蠕动泵复位 " + peristalticPumpCount + "/16");
+// pump.setEnable(true);
+// peristalticPumpCount++;
+// }
+// }
+//
+// Boolean enableSetup = this.getDevice().getEnv().getProperty("app.liquidPeristalticPumpPipeSetupEnable",Boolean.class);
+// assert enableSetup != null;
+// if ( !enableSetup ) {
+// return ;
+// }
+//
+// DiActMotor liquidPlateMotor = this.getActuator(MyDevice.ACT_LIQUID_PLATE_MOTOR, DiActMotor.class);
+// DiActMotor liquidMotor = this.getActuator(MyDevice.ACT_LIQUID_MOTOR, DiActMotor.class);
+//
+// this.setProgressMessage("设备初始化 : 初始化加液管路");
+// MoveDoorOpen.execute(this.getDevice());
+// DiMdbNotification.taskAction(this, "TaskStartResetPumpPipeSetupTubeRankPutIn");
+// this.waitAction("TaskStartResetPumpPipeSetupTubeRankPutIn");
+// MoveDoorClose.execute(this.getDevice());
+//
+// // 加液管充满
+// for ( int i=0; i<8; i++ ) {
+// this.setProgressMessage("设备初始化 : 初始化加液管路 " + (i+1) + "/8");
+// if ( 0 == i%2 ) {
+// liquidMotor.moveTo("LiquidArmPumpGroupOut");
+// liquidPlateMotor.moveTo("LiquidPlateSlotPumpOutGroup",i/2);
+// } else {
+// liquidMotor.moveTo("LiquidArmPumpGroupIn");
+// liquidPlateMotor.moveTo("LiquidPlateSlotPumpInGroup", i/2);
+// }
+//
+// var pump0 = this.getActuator("LiquidPeristalticPump_"+i+"_0", DiActPeristalticPump.class);
+// var pump1 = this.getActuator("LiquidPeristalticPump_"+i+"_1", DiActPeristalticPump.class);
+// var pipeVolumeCircle0 = pump1.getLocationValue("LiquidPeristalticPumpPipeVolumeCircle",i, 0);
+// var pipeVolumeCircle1 = pump1.getLocationValue("LiquidPeristalticPumpPipeVolumeCircle",i, 1);
+// this.batchExecute(List.of(
+// () -> pump0.moveBy(pipeVolumeCircle0),
+// () -> pump1.moveBy(pipeVolumeCircle1)
+// ));
+// pump0.retract();
+// pump1.retract();
+// }
+//
+// liquidMotor.moveTo("LiquidArmStandby");
+//
+// // 加液管充满, 需要取出试管架
+// MoveDoorOpen.execute(this.getDevice());
+// DiMdbNotification.taskAction(this, "TaskStartResetPumpPipeSetupTubeRankTakeOut");
+// this.waitAction("TaskStartResetPumpPipeSetupTubeRankTakeOut");
+// MoveDoorClose.execute(this.getDevice());
+// }
+//
+// /**
+// * 清理试管架
+// * @issue : 无法获取加液位置是否存在试管架
+// */
+// private void setupHeatingSlotCover() {
+// boolean isDoorOpen = false;
+// Integer errorSlotIndex = this.getDevice().getEnv().getProperty("app.errorSlotIndex",Integer.class);
+//
+// for ( int i=0; i<5; i++ ) {
+// this.setProgressMessage("设备初始化 : 检查试管架 " + (i+1) + "/5");
+// String key = "HeatingPlateMotorSlotCover_" + i;
+// DiActServo heatSlotCoverServo = this.getActuator(key, DiActServo.class);
+// heatSlotCoverServo.setEnable(true);
+// var currentPos = heatSlotCoverServo.getCurrentPos();
+// LOG.info("HeatingPlateMotorSlotCover #{} : current pos = {}", i, currentPos);
+//
+// // 如果是空的,则初始化位置后继续下一步
+// var rackExistsPos = heatSlotCoverServo.getLocationValue("HeatingPlateMotorSlotCoverRackExists");
+// if ( currentPos > rackExistsPos ) {
+// heatSlotCoverServo.setCurrentPosAsMiddle();
+// continue;
+// }
+//
+// // 如果是空试管架, 又是异常区域则不处理, 因为异常区域始终要有个试管架
+// var emptyRackExistsPos = heatSlotCoverServo.getLocationValue("HeatingPlateMotorSlotCoverEmptyRackExists");
+// if ( currentPos > emptyRackExistsPos && null != errorSlotIndex && errorSlotIndex == i ) { // 异常区域存在空试管架
+// this.isErrorTubeRackRequired = false;
+// continue;
+// }
+//
+// var moveToLiquidPlate = new MoveMoveTubeRackFromHeatPlateToLiquidPlate();
+// moveToLiquidPlate.setDevice(this.getDevice());
+// moveToLiquidPlate.slotIndex = i;
+// moveToLiquidPlate.updateSlotStatus = false;
+// moveToLiquidPlate.run();
+//
+// if ( !isDoorOpen ) {
+// MoveDoorOpen.execute(this.getDevice());
+// isDoorOpen = true;
+// }
+//
+// heatSlotCoverServo.moveTo("HeatingPlateMotorSlotCoverEmpty");
+// heatSlotCoverServo.setEnable(false);
+//
+// // 等待取出试管架
+// DiMdbNotification.taskAction(this, "TaskStartResetErrorTubeRackTakeOut");
+// this.waitAction("TaskStartResetErrorTubeRackTakeOut");
+// LOG.info("HeatingPlateMotorSlotCover #{} : take out", i);
+//
+// heatSlotCoverServo.setEnable(true);
+// heatSlotCoverServo.setCurrentPosAsMiddle();
+// }
+//
+// if ( isDoorOpen ) {
+// MoveDoorClose.execute(this.getDevice());
+// }
+// }
+//
+// // 异常处理位试管架取出
+// public void actionErrorTubeRackTakeOut() {
+// var action = this.getAction("TaskStartResetErrorTubeRackTakeOut");
+// action.finish();
+// }
+//
+// // 放入异常处理位试管架
+// public void actionErrorTubeRackPutIn() {
+// var slotMan = this.getResourceManager(ResHeatingTubeRackSlotManager.class);
+// var slot = slotMan.getErrorSlot();
+//
+// // 关闭设备门
+// DiActMotor doorMotor = this.getActuator(MyDevice.ACT_DOOR_MOTOR, DiActMotor.class);
+// doorMotor.moveToIO(1, 1);
+//
+// var move = new MoveMoveTubeRackFromLiquidPlateToHeatPlate();
+// move.slotIndex = slot.index;
+// move.setDevice(this.getDevice());
+// move.run();
+// slot.lock();
+//
+// var action = this.getAction("TaskStartResetErrorTubeRackPutIn");
+// action.finish();
+// }
+//
+// // 蠕动泵管路初始化
+// public void actionPumpPipeSetupTubeRankPutIn() {
+// var action = this.getAction("TaskStartResetPumpPipeSetupTubeRankPutIn");
+// action.finish();
+// }
+//
+// // 蠕动泵管路初始化
+// public void actionPumpPipeSetupTubeRankTakeOut() {
+// var action = this.getAction("TaskStartResetPumpPipeSetupTubeRankTakeOut");
+// action.finish();
+// }
+
+ // set progress message
+ private void setProgressMessage(String message) {
+ UfMdbRuntimeVariable.setString(message, "device.start.message");
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/controller/DeviceController.java b/src/main/java/com/iflytop/digester/controller/DeviceController.java
new file mode 100644
index 0000000..beeeb2d
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/controller/DeviceController.java
@@ -0,0 +1,31 @@
+package com.iflytop.digester.controller;
+import com.iflytop.digester.StartResetTaskThread;
+import com.iflytop.digester.deviceinstance.Device;
+import com.iflytop.digester.underframework.controller.UfApiControllerBase;
+import com.iflytop.digester.underframework.controller.UfApiResponse;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+@Controller
+public class DeviceController extends UfApiControllerBase {
+ @Resource
+ private Device device;
+
+ @ResponseBody
+ @PostMapping("/api/device/start")
+ public UfApiResponse start() {
+ if (!"new".equals(this.device.getStatus())) {
+ return this.error("当前设备无法执行启动操作");
+ }
+ var startReset = new StartResetTaskThread();
+ startReset.start();
+ return this.success();
+ }
+
+ @ResponseBody
+ @PostMapping("/api/device/status-get")
+ public UfApiResponse statusGet() {
+ return this.success(this.device.getStatus());
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/controller/HeatSlotController.java b/src/main/java/com/iflytop/digester/controller/HeatSlotController.java
new file mode 100644
index 0000000..fe8cec2
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/controller/HeatSlotController.java
@@ -0,0 +1,21 @@
+package com.iflytop.digester.controller;
+import com.iflytop.digester.deviceinstance.Device;
+import com.iflytop.digester.underframework.controller.UfApiControllerBase;
+import com.iflytop.digester.underframework.controller.UfApiResponse;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import java.util.Map;
+@Controller
+public class HeatSlotController extends UfApiControllerBase {
+ @Resource
+ private Device device;
+
+ @ResponseBody
+ @PostMapping("/api/heat-slot/list")
+ public UfApiResponse list() {
+ var heatSlots = this.device.heatingTurntable.getSlots();
+ return this.success(Map.of("slots", heatSlots));
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/controller/LiquidController.java b/src/main/java/com/iflytop/digester/controller/LiquidController.java
new file mode 100644
index 0000000..52a86de
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/controller/LiquidController.java
@@ -0,0 +1,21 @@
+package com.iflytop.digester.controller;
+import com.iflytop.digester.deviceinstance.Device;
+import com.iflytop.digester.underframework.controller.UfApiControllerBase;
+import com.iflytop.digester.underframework.controller.UfApiResponse;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import java.util.Map;
+@Controller
+public class LiquidController extends UfApiControllerBase {
+ @Resource
+ private Device device;
+
+ @ResponseBody
+ @PostMapping("/api/liquid/list")
+ public UfApiResponse list() {
+ var liquids = this.device.liquidAddition.getLiquids();
+ return this.success(Map.of("liquids", liquids));
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/deviceinstance/Device.java b/src/main/java/com/iflytop/digester/deviceinstance/Device.java
index e4f37b6..02eb416 100644
--- a/src/main/java/com/iflytop/digester/deviceinstance/Device.java
+++ b/src/main/java/com/iflytop/digester/deviceinstance/Device.java
@@ -1,9 +1,14 @@
package com.iflytop.digester.deviceinstance;
+import com.iflytop.digester.DigestionTaskThread;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class Device {
+ // logger
+ public static final Logger LOG = LoggerFactory.getLogger(Device.class);
// device instance
private static Device instance = null;
@@ -22,6 +27,9 @@ public class Device {
@Resource
public Camera camera;
+ // device status
+ private String status = "new"; // new, preparing, ready, running, stopping, stopped
+
// get device instance
public static Device getInstance() {
return instance;
@@ -31,4 +39,15 @@ public class Device {
public void init() {
instance = this;
}
+
+ // start device
+ public String getStatus() {
+ return status;
+ }
+
+ // set device status
+ public void setStatus(String status) {
+ LOG.info("[Device Status] {} => {}", this.status, status);
+ this.status = status;
+ }
}
diff --git a/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java b/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java
index 8ea72a5..d5311ca 100644
--- a/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java
+++ b/src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java
@@ -17,6 +17,11 @@ public class HeatingTurntableInstance {
}
}
+ // 获取槽位列表
+ public List getSlots() {
+ return slots;
+ }
+
// 分配加热位
synchronized public HeatingTurntableSlot allocSlot( String tubeRackNo ) {
for (HeatingTurntableSlot slot : slots) {
diff --git a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java
index cdfe016..e52132e 100644
--- a/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java
+++ b/src/main/java/com/iflytop/digester/deviceinstance/LiquidAdditionInstance.java
@@ -17,13 +17,19 @@ public class LiquidAdditionInstance {
LiquidAdditionLiquid liquid = new LiquidAdditionLiquid();
// @TODO : 测试用,要删除
- liquid.type = "盐酸";
+ liquid.type = "hydrochloric";
liquid.volume = 100;
liquids.add(liquid);
}
}
+ // get liquids
+ public List getLiquids() {
+ return this.liquids;
+ }
+
+
// 针对试管加液
public void addLiquidToTubes(List tubes, String type, int volume ) {
var pumpIndexes = this.getPumpIndexForGroupOutAndIn(type);
diff --git a/src/main/java/com/iflytop/digester/underframework/controller/UfApiDictionary.java b/src/main/java/com/iflytop/digester/underframework/controller/UfApiDictionary.java
new file mode 100644
index 0000000..eb7892d
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/underframework/controller/UfApiDictionary.java
@@ -0,0 +1,17 @@
+package com.iflytop.digester.underframework.controller;
+import com.iflytop.digester.underframework.dao.model.UfMdbDictItem;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.ResponseBody;
+import java.util.Map;
+@Controller
+public class UfApiDictionary extends UfApiControllerBase {
+ @ResponseBody
+ @PostMapping("/api/dictionary/list-by-group")
+ public UfApiResponse listByGroup(@RequestBody Map params ) {
+ var group = (String)params.get("group");
+ var items = UfMdbDictItem.getItems(group);
+ return success(items);
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/underframework/controller/UfApiRuntimeVariable.java b/src/main/java/com/iflytop/digester/underframework/controller/UfApiRuntimeVariable.java
new file mode 100644
index 0000000..0040cd2
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/underframework/controller/UfApiRuntimeVariable.java
@@ -0,0 +1,18 @@
+package com.iflytop.digester.underframework.controller;
+import com.iflytop.digester.underframework.dao.model.UfMdbRuntimeVariable;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.ResponseBody;
+import java.util.Map;
+@Controller
+public class UfApiRuntimeVariable extends UfApiControllerBase {
+ @ResponseBody
+ @PostMapping("/api/runtime-variable/get")
+ public UfApiResponse get(@RequestBody Map params ) {
+ String key = (String)params.get("key");
+ var value = UfMdbRuntimeVariable.getString(key);
+ assert value != null;
+ return success(Map.of("value", value));
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbDictItem.java b/src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbDictItem.java
new file mode 100644
index 0000000..fb362f5
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbDictItem.java
@@ -0,0 +1,33 @@
+package com.iflytop.digester.underframework.dao.model;
+import com.iflytop.digester.underframework.dao.record.UfActiveRecord;
+import com.iflytop.digester.underframework.dao.record.UfActiveRecordField;
+
+import java.util.List;
+import java.util.Map;
+
+public class UfMdbDictItem extends UfActiveRecord {
+ @UfActiveRecordField
+ public String groupKey;
+
+ @UfActiveRecordField
+ public String groupName;
+
+ @UfActiveRecordField
+ public String itemKey;
+
+ @UfActiveRecordField
+ public String itemName;
+
+ @UfActiveRecordField
+ public String itemValue;
+
+ // get table name
+ public static String getTableName() {
+ return "app_dict_items";
+ }
+
+ // get items
+ public static List getItems(String groupKey) {
+ return UfActiveRecord.find(UfMdbDictItem.class, Map.of("groupKey", groupKey));
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbRuntimeVariable.java b/src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbRuntimeVariable.java
new file mode 100644
index 0000000..5488f35
--- /dev/null
+++ b/src/main/java/com/iflytop/digester/underframework/dao/model/UfMdbRuntimeVariable.java
@@ -0,0 +1,67 @@
+package com.iflytop.digester.underframework.dao.model;
+import com.iflytop.digester.underframework.dao.record.UfActiveRecord;
+import com.iflytop.digester.underframework.dao.record.UfActiveRecordField;
+import java.util.Map;
+public class UfMdbRuntimeVariable extends UfActiveRecord {
+ @UfActiveRecordField
+ public String key;
+
+ @UfActiveRecordField
+ public String value;
+
+ // get table name
+ public static String getTableName() {
+ return "app_runtime_variables";
+ }
+
+ // build key
+ private static String buildKey(String key, Object ... args) {
+ StringBuilder keyBuilder = new StringBuilder(key);
+ for (Object arg : args) {
+ keyBuilder.append(".").append(arg.toString());
+ }
+ return keyBuilder.toString();
+ }
+
+ // get location value
+ public static UfMdbRuntimeVariable getVariable(String key, Object ... args ) {
+ key = UfMdbRuntimeVariable.buildKey(key, args);
+ return UfActiveRecord.findOne(UfMdbRuntimeVariable.class, Map.of("key", key));
+ }
+
+ // get string
+ public static String getString(String name, Object ... args ) {
+ var variable = UfMdbRuntimeVariable.getVariable(name, args);
+ return null == variable ? null : variable.value;
+ }
+
+ // get integer
+ public static Integer getInteger(String name, Object ... args ) {
+ var variable = UfMdbRuntimeVariable.getVariable(name, args);
+ return null == variable ? null : Integer.parseInt(variable.value);
+ }
+
+ // set string
+ public static void setString(String value, String name, Object ... args ) {
+ var variable = UfMdbRuntimeVariable.getVariable(name, args);
+ if ( null == variable ) {
+ variable = new UfMdbRuntimeVariable();
+ variable.key = UfMdbRuntimeVariable.buildKey(name, args);
+ }
+ variable.value = value;
+ variable.save();
+ }
+
+ // set integer
+ public static void setInteger(Integer value, String name, Object ... args ) {
+ UfMdbRuntimeVariable.setString(value.toString(), name, args);
+ }
+
+ // remove
+ public static void remove(String name, Object ... args ) {
+ var variable = UfMdbRuntimeVariable.getVariable(name);
+ if ( null != variable ) {
+ variable.delete();
+ }
+ }
+}
diff --git a/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java b/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java
index c87e991..ae51de4 100644
--- a/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java
+++ b/src/main/java/com/iflytop/digester/underframework/dao/record/UfActiveRecord.java
@@ -103,6 +103,13 @@ public class UfActiveRecord {
return mapper.count(criteria);
}
+ // find by conditions
+ public static List find(Class modelClass, Map conditions) {
+ var criteria = new UfActiveRecordCriteria();
+ criteria.conditions = conditions;
+ return UfActiveRecord.find(modelClass, criteria);
+ }
+
// find all by criteria
public static List find(Class modelClass, UfActiveRecordCriteria criteria ) {
criteria.tableName = UfActiveRecord.getTableNameFromModelClass(modelClass);
diff --git a/web b/web
index 1281f43..7f4d0b8 160000
--- a/web
+++ b/web
@@ -1 +1 @@
-Subproject commit 1281f43be8a5de2f98d83c2a32506bb878eb5495
+Subproject commit 7f4d0b8bfe683b41e75233368ed1ec1e98c8c350