场景化配置:动态获取设备数据接口
master
xs 2 weeks ago
parent db180ca6de
commit fc919b0241

@ -67,4 +67,7 @@ public interface RemoteTdEngineService {
R<Map<String,Object>> getDeviceLocation(@Validated @RequestBody TdSelectDto tdSelectDto, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("/tdengine/dropTable")
R<?> dropTable(@Validated @RequestBody TdTableDropVo tdTableDropVo, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("/tdengine/getGroupDeviceData")
R<TdReturnDataVo> getGroupDeviceData(@Validated @RequestBody TdGroupSelectDto tdGroupSelectDto, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

@ -0,0 +1,48 @@
package com.ruoyi.tdengine.api.domain;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class TdGroupSelectDto {
//数据库名称
@NotBlank(message="databaseName cannot be empty")
private String databaseName;
//子表名称
@NotBlank(message="tableName cannot be empty")
private String tableName;
//控制输出条数
private int limit;
//指定从第几条之后输出例如limit 2,5输出第3行到第7行的数据
private int offset;
/**
* timestamp
*/
//子表名称
@NotBlank(message="firstFieldName cannot be empty")
private String firstFieldName;
//过滤条件:开始时间
//子表名称
@NotNull(message="startTime cannot be empty")
private long startTime;
//过滤条件:结束时间
//子表名称
@NotNull(message="endTime cannot be empty")
private long endTime;
@NotBlank(message="functionIdentifier cannot be empty")
private String functionIdentifier;
@NotBlank(message="interval cannot be empty")
private String interval;
}

@ -37,4 +37,5 @@ public class TdHistorySelectDto {
//排序方式
private String sort;
}

@ -112,6 +112,11 @@ public class RemoteTdEngineFallbackFactory implements FallbackFactory<RemoteTdEn
return R.fail("drop子表失败:" + throwable.getMessage());
}
@Override
public R<TdReturnDataVo> getGroupDeviceData(TdGroupSelectDto tdGroupSelectDto, String source) {
return R.fail("按日期分组获取数据失败:" + throwable.getMessage());
}
};
}
}

@ -182,4 +182,27 @@ public class HwDictConstants {
public static final String OFFLINE_RULE_TYPE_DEVICE = "1";//离线报警规则类型:设备
public static final String OFFLINE_RULE_TYPE_SCENE = "3";//离线报警规则类型:场景
public static final String INTERVAL_HOUR = "1";//小时
public static final String INTERVAL_DAY = "2";//日
public static final String INTERVAL_WEEK = "3";//周
public static final String INTERVAL_MONTH="4";//月
public static final String INTERVAL_YEAR="5";//年
public static final Map<String, String> intervalMap = new HashMap<String, String>();
static {
intervalMap.put(INTERVAL_HOUR, "1m");
intervalMap.put(INTERVAL_DAY, "1h");
intervalMap.put(INTERVAL_WEEK, "1d");
intervalMap.put(INTERVAL_MONTH, "1w");
intervalMap.put(INTERVAL_YEAR, "30d");
}
public static final String INTERVAL_TYPE_AVG="1";//平均值
public static final String INTERVAL_TYPE_SUM = "2";//累计值
public static final String INTERVAL_TYPE_MAX="3";//最大值
public static final String INTERVAL_TYPE_MIN = "4";//最小值
}

@ -554,8 +554,29 @@ public class HwMonitorPlatformController extends BaseController {
return error(String.format("获取设备信息异常:%e",ex.getMessage()));
}
}
/**
* @return AjaxResult
* @param: deviceHistoryData
* @description
* @author xins
* @date 2024-12-31 16:24
*/
// @RequiresPermissions("business:monitor:deviceInfo")
@PostMapping("/getGroupDeviceData")
public AjaxResult getGroupDeviceData(@Validated @RequestBody DeviceHistoryGroupDataVo deviceHistoryGroupDataVo) {
JSONObject returnObj = new JSONObject();
TdReturnDataVo returnDataVo = hwMonitorPlatformService.getGroupDeviceData(deviceHistoryGroupDataVo);
if (returnDataVo != null) {
List<DeviceDataColumnVo> deviceDataColumnVos = hwMonitorPlatformService.
getDeviceDataColumns(deviceHistoryGroupDataVo.getDeviceModeId());
returnObj.put("deviceDataColumns", deviceDataColumnVos);
returnObj.put("groupDeviceData", returnDataVo);
}
return success(returnObj);
}
}

@ -0,0 +1,50 @@
package com.ruoyi.business.domain.VO;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @Description:
* @ClassName: DeviceHistoryGroupDataVo
* @Author : xins
* @Date :2024-12-31 16:30
* @Version :1.0
*/
@Data
public class DeviceHistoryGroupDataVo {
@NotNull(message = "deviceId cannot be null")
private Long deviceId;
@NotNull(message = "deviceModeId cannot be null")
private Long deviceModeId;
private int limit;
//指定从第几条之后输出例如limit 2,5输出第3行到第7行的数据
private int offset;
//过滤条件:开始时间
@NotNull(message = "startTime cannot be null")
private long startTime;
//过滤条件:结束时间
@NotNull(message = "endTime cannot be null")
private long endTime;
@NotNull(message = "interval cannot be null")
private String interval;//1小时2日3周4月5年
//此字段暂时不用
private int intervalValue;//小时默认1按照分钟展示2日按照24小时展示周按照7天展示月按照30天展示年按照12个月展示
@NotNull(message = "intervalType cannot be null")
private String intervalType;//1agv平均值2sum累计值3max最大值4min最小值
@NotNull(message = "functionIdentifier cannot be null")
private String functionIdentifier;
}

@ -3,6 +3,7 @@ package com.ruoyi.business.service;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.business.domain.VO.DeviceDataColumnVo;
import com.ruoyi.business.domain.VO.DeviceHistoryDataVo;
import com.ruoyi.business.domain.VO.DeviceHistoryGroupDataVo;
import com.ruoyi.business.domain.VO.DeviceLatestDataVo;
import com.ruoyi.tdengine.api.domain.TdReturnDataVo;
@ -45,4 +46,13 @@ public interface IHwMonitorPlatformService {
* @date 2023-09-25 15:40
*/
public List<DeviceDataColumnVo> getDeviceDataColumns(Long deviceModeId);
/**
* @return TdReturnDataVo
* @param: deviceHistoryGroupDataVo
* @description
* @author xins
* @date 2024-12-31 16:23
*/
public TdReturnDataVo getGroupDeviceData(DeviceHistoryGroupDataVo deviceHistoryGroupDataVo);
}

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.ruoyi.business.domain.HwDeviceModeFunction;
import com.ruoyi.business.domain.VO.DeviceDataColumnVo;
import com.ruoyi.business.domain.VO.DeviceHistoryDataVo;
import com.ruoyi.business.domain.VO.DeviceHistoryGroupDataVo;
import com.ruoyi.business.domain.VO.DeviceLatestDataVo;
import com.ruoyi.business.mapper.HwDeviceModeFunctionMapper;
import com.ruoyi.business.service.IHwMonitorPlatformService;
@ -11,20 +12,18 @@ import com.ruoyi.common.core.constant.HwDictConstants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TdEngineConstants;
import com.ruoyi.tdengine.api.RemoteTdEngineService;
import com.ruoyi.tdengine.api.domain.TdField;
import com.ruoyi.tdengine.api.domain.TdHistorySelectDto;
import com.ruoyi.tdengine.api.domain.TdReturnDataVo;
import com.ruoyi.tdengine.api.domain.TdSuperTableSelectVo;
import com.ruoyi.tdengine.api.domain.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.time.*;
import java.time.format.DateTimeFormatter;
/**
* @Description:
@ -205,4 +204,284 @@ public class HwMonitorPlatformServiceImpl implements IHwMonitorPlatformService {
return deviceDataColumnVos;
}
/**
* @return TdReturnDataVo
* @param: deviceHistoryGroupDataVo
* @description
* @author xins
* @date 2024-12-31 16:23
*/
@Override
public TdReturnDataVo getGroupDeviceData(DeviceHistoryGroupDataVo deviceHistoryGroupDataVo) {
TdGroupSelectDto tdGroupSelectDto = new TdGroupSelectDto();
tdGroupSelectDto.setDatabaseName(TdEngineConstants.getDatabaseName());
tdGroupSelectDto.setTableName(TdEngineConstants.getDeviceDataTableName(deviceHistoryGroupDataVo.getDeviceId()));
tdGroupSelectDto.setFirstFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME);
String functionIdentifier = deviceHistoryGroupDataVo.getFunctionIdentifier().equalsIgnoreCase("value") ?
"value1" : deviceHistoryGroupDataVo.getFunctionIdentifier();
tdGroupSelectDto.setStartTime(deviceHistoryGroupDataVo.getStartTime());
tdGroupSelectDto.setEndTime(deviceHistoryGroupDataVo.getEndTime());
tdGroupSelectDto.setFunctionIdentifier(functionIdentifier);
tdGroupSelectDto.setInterval(HwDictConstants.intervalMap.get(deviceHistoryGroupDataVo.getInterval()));
tdGroupSelectDto.setOffset(deviceHistoryGroupDataVo.getOffset() * deviceHistoryGroupDataVo.getLimit());
tdGroupSelectDto.setLimit(deviceHistoryGroupDataVo.getLimit());
return this.remoteTdEngineService.getGroupDeviceData(tdGroupSelectDto, SecurityConstants.INNER).getData();
}
// private static Map<String, Object> createEvent(String timestamp, double value) {
// Map<String, Object> event = new HashMap<>();
// event.put("timestamp", Instant.parse(timestamp));
// event.put("value", value);
// return event;
// }
//
// public List<Map<LocalDate, Double>> groupDeviceData(List<Map<String, Object>> historyData, DeviceHistoryDataVo historyDataVo) {
// // 创建一个包含多个 Map 对象的列表
// List<String> functionIdentifiers = historyDataVo.getFunctionIdentifiers();
// String functionIdentifer = functionIdentifiers.get(0);
//
// // 设置时间戳的格式
// DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// DateTimeFormatter hourFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");
//
// Map<LocalDateTime, Double> deviceDataGroup = new HashMap<>();
// // 按INTERVAL分组
// String interval = historyDataVo.getInterval();
// String intervalType = historyDataVo.getIntervalType();
// switch (interval) {
// case HwDictConstants.INTERVAL_HOUR:
// switch (intervalType) {
// case HwDictConstants.INTERVAL_TYPE_AVG:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.HOURS),
// Collectors.averagingDouble(e -> (double) e.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_SUM:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get("ts"), DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.HOURS),
// Collectors.summingDouble(event -> (double) event.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MAX:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.HOURS),
// Collectors.collectingAndThen(
// Collectors.maxBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MIN:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME).truncatedTo(ChronoUnit.HOURS),
// Collectors.collectingAndThen(
// Collectors.minBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// }
//
//
// break;
// case HwDictConstants.INTERVAL_DAY:
// switch (intervalType) {
// case HwDictConstants.INTERVAL_TYPE_AVG:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.DAYS),
// Collectors.averagingDouble(e -> (double) e.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_SUM:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get("ts"), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.DAYS),
// Collectors.summingDouble(event -> (double) event.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MAX:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.DAYS),
// Collectors.collectingAndThen(
// Collectors.maxBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MIN:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.DAYS),
// Collectors.collectingAndThen(
// Collectors.minBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// }
// break;
// case HwDictConstants.INTERVAL_WEEK:
// switch (intervalType) {
// case HwDictConstants.INTERVAL_TYPE_AVG:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.WEEKS),
// Collectors.averagingDouble(e -> (double) e.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_SUM:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get("ts"), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.WEEKS),
// Collectors.summingDouble(event -> (double) event.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MAX:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.WEEKS),
// Collectors.collectingAndThen(
// Collectors.maxBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MIN:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.WEEKS),
// Collectors.collectingAndThen(
// Collectors.minBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// }
// break;
// case HwDictConstants.INTERVAL_MONTH:
// switch (intervalType) {
// case HwDictConstants.INTERVAL_TYPE_AVG:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.MONTHS),
// Collectors.averagingDouble(e -> (double) e.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_SUM:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get("ts"), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.MONTHS),
// Collectors.summingDouble(event -> (double) event.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MAX:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.MONTHS),
// Collectors.collectingAndThen(
// Collectors.maxBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MIN:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.MONTHS),
// Collectors.collectingAndThen(
// Collectors.minBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// }
// break;
// case HwDictConstants.INTERVAL_YEAR:
// switch (intervalType) {
// case HwDictConstants.INTERVAL_TYPE_AVG:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.YEARS),
// Collectors.averagingDouble(e -> (double) e.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_SUM:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get("ts"), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.YEARS),
// Collectors.summingDouble(event -> (double) event.get(functionIdentifer))
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MAX:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.YEARS),
// Collectors.collectingAndThen(
// Collectors.maxBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// case HwDictConstants.INTERVAL_TYPE_MIN:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.YEARS),
// Collectors.collectingAndThen(
// Collectors.minBy(Comparator.comparingDouble(e -> (double) e.get(functionIdentifer))),
// opt -> opt.map(e -> (double) e.get(functionIdentifer)).orElse(Double.NaN)
// )
// ));
// break;
// }
// break;
// default:
// deviceDataGroup = historyData.stream()
// .collect(Collectors.groupingBy(
// event -> LocalDateTime.parse((String) event.get(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME), DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// .truncatedTo(ChronoUnit.SECONDS),
// e -> (double) e.get(functionIdentifer)
// ));
// break;
// }
//
//
// // 分组的结果
// System.out.println("Max Values by:"+interval);
// deviceDataGroup.forEach((day, maxValue) -> {
// String formattedDay = dayFormatter.format(day);
// System.out.println("Day: " + formattedDay + ", Max Value: " + maxValue);
// });
//
//
// return deviceDataGroup;
//
// }
}

@ -194,7 +194,7 @@ select a.device_mode_name,sum(a.sum) sum from (select
<if test="currentModuleVersion != null and currentModuleVersion != ''"> and current_module_version = #{currentModuleVersion}</if>
<if test="currentSinglechipVersion != null and currentSinglechipVersion != ''"> and current_singlechip_version = #{currentSinglechipVersion}</if>
<if test="deviceField != null and deviceField != ''"> and device_field = #{deviceField}</if>
<if test="tenantId != null "> and tenant_id = #{tenantId}</if>
<if test="tenantId != null "> and hd.tenant_id = #{tenantId}</if>
<if test="onlineStatus != null and onlineStatus != ''"> and online_status = #{onlineStatus}</if>
<if test="deviceTypeStr != null and deviceTypeStr != ''"> and device_type in (${deviceTypeStr})</if>
<!-- 租户数据范围过滤 -->

Loading…
Cancel
Save