mirror of
https://gitee.com/iteaj/iboot.git
synced 2026-08-30 17:20:20 +08:00
完善iotview功能
This commit is contained in:
@@ -14,6 +14,11 @@ public class ListFetchResult extends ViewFetchResult {
|
||||
super(item, values);
|
||||
}
|
||||
|
||||
public ListFetchResult addValue(BaseEchartsCount value) {
|
||||
getValue().add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseEchartsCount> getValue() {
|
||||
return (List<BaseEchartsCount>) super.getValue();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.iteaj.framework.spi.iot.view;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 自定义对象获取
|
||||
*/
|
||||
@Getter
|
||||
public abstract class OriginFetchResult extends ViewFetchResult{
|
||||
|
||||
/**
|
||||
* 是否是原始数据
|
||||
* 原始数据全段不做处理, 直接渲染
|
||||
*/
|
||||
private boolean origin;
|
||||
|
||||
public OriginFetchResult(Object value) {
|
||||
super(null, value);
|
||||
this.origin = true;
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,8 @@ public class ViewApiParams {
|
||||
|
||||
/**
|
||||
* 时间范围(格式 yyyy-MM-dd HH:mm)
|
||||
* 1. 支持具体的时间 如:2024-01-10 15:00 - 2024-01-16 15:00
|
||||
* 2. 支持now关键字 如:now-6 - now
|
||||
* 1. 支持具体的时间 如:2024-01-10 15:00,2024-01-16 15:00
|
||||
* 2. 支持now关键字 如:now-6,now
|
||||
* @see #timeType
|
||||
*/
|
||||
private List<String> timeRange;
|
||||
@@ -37,6 +37,41 @@ public class ViewApiParams {
|
||||
*/
|
||||
private List<Value> values;
|
||||
|
||||
/**
|
||||
* 范围值
|
||||
*/
|
||||
private String rangeValue;
|
||||
|
||||
/**
|
||||
* 产品轴类型(time, range)
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 范围类型(all、product、device、group...)
|
||||
*/
|
||||
private String range;
|
||||
|
||||
/**
|
||||
* 范围值(产品列表, 设备列表, 分组列表, ...)
|
||||
*/
|
||||
private List<String> ranges;
|
||||
|
||||
public void setRangeValue(String rangeValue) {
|
||||
this.rangeValue = rangeValue;
|
||||
if(StrUtil.isNotBlank(rangeValue)) {
|
||||
final String[] split = rangeValue.split(DataItemOption.SPLIT);
|
||||
if(split.length == 1) {
|
||||
this.range = split[0];
|
||||
} else if(split.length > 1) {
|
||||
this.range = split[0];
|
||||
this.ranges = Arrays.asList(split[1].split(","));
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Value {
|
||||
@@ -61,20 +96,16 @@ public class ViewApiParams {
|
||||
*/
|
||||
private String calcType;
|
||||
|
||||
/**
|
||||
*/
|
||||
private String range;
|
||||
|
||||
/**
|
||||
* 范围值
|
||||
*/
|
||||
private String rangeValue;
|
||||
|
||||
private List<String> values;
|
||||
|
||||
public Value build() {
|
||||
if(values != null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if(StrUtil.isNotBlank(this.getValue())) {
|
||||
this.values = Arrays.asList(this.getValue().split(DataItemOption.SPLIT));
|
||||
this.calcType = this.values.get(this.values.size() - 1);
|
||||
} else {
|
||||
throw new ServiceException("项格式错误");
|
||||
}
|
||||
@@ -86,6 +117,9 @@ public class ViewApiParams {
|
||||
if(values == null) {
|
||||
build();
|
||||
}
|
||||
if(index > (this.values.size() - 1)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return this.values.get(index);
|
||||
}
|
||||
|
||||
+61
-27
@@ -1,16 +1,16 @@
|
||||
package com.iteaj.iboot.plugin.iotview.api;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.iteaj.framework.exception.ServiceException;
|
||||
import com.iteaj.framework.spi.iot.data.BaseEchartsCount;
|
||||
import com.iteaj.framework.spi.iot.view.*;
|
||||
import com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto;
|
||||
import com.iteaj.iboot.plugin.iotview.service.ISVDataService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class DeviceStatusApiItem implements ViewApiItem {
|
||||
@@ -19,8 +19,9 @@ public class DeviceStatusApiItem implements ViewApiItem {
|
||||
private static final String NAME = "设备状态";
|
||||
private final ISVDataService isvDataService;
|
||||
|
||||
private List<DataItemOption> options = Arrays.asList(new DataItemOption("设备状态", KEY)
|
||||
.asName().builder()
|
||||
private List<DataItemOption> options = Arrays.asList(new DataItemOption("设备状态", KEY).asName().builder()
|
||||
.addNameChild("总设备数", "all", true)
|
||||
.toParent()
|
||||
.addNameChild("在线", "online")
|
||||
.addNameChild("统计", "count", true)
|
||||
.toParent()
|
||||
@@ -55,33 +56,66 @@ public class DeviceStatusApiItem implements ViewApiItem {
|
||||
|
||||
@Override
|
||||
public List<ViewFetchResult> fetch(List<ViewApiParams.Value> values, ViewApiParams params) {
|
||||
|
||||
if(StrUtil.isBlank(params.getRange())) {
|
||||
throw new ServiceException("未指定统计范围配置");
|
||||
}
|
||||
if(StrUtil.isBlank(params.getCategory())) {
|
||||
throw new ServiceException("未指定产品轴配置");
|
||||
}
|
||||
|
||||
List<ViewFetchResult> results = new ArrayList<>(values.size());
|
||||
values.stream().forEach(item -> {
|
||||
if(Objects.equals("range", params.getCategory())) {
|
||||
Map<String, ListFetchResult> maps = new LinkedHashMap<>();
|
||||
values.stream().forEach(item -> {
|
||||
final String status = item.getValueItem(1);
|
||||
final String countType = item.getValueItem(2);
|
||||
|
||||
final String rangeConfig = item.getRangeValue();
|
||||
if(StrUtil.isBlank(rangeConfig)) {
|
||||
throw new ServiceException("未指定统计范围");
|
||||
}
|
||||
final String[] split = rangeConfig.split(DataItemOption.SPLIT);
|
||||
String range = split[0]; String rangeValue = null;
|
||||
if(split.length > 1) {
|
||||
rangeValue = split[1];
|
||||
}
|
||||
final String status = item.getValueItem(1);
|
||||
final String countType = item.getValueItem(2);
|
||||
List<DeviceStatusCountDto> countDtos = isvDataService.countDeviceStatus(status
|
||||
, params.getCategory(), params.getRange(), params.getRanges());
|
||||
if(CollectionUtil.isNotEmpty(countDtos)) {
|
||||
countDtos.forEach(countDto -> {
|
||||
ListFetchResult listFetchResult = maps.get(item.getItem());
|
||||
if(listFetchResult == null) {
|
||||
maps.put(item.getItem(), listFetchResult = new ListFetchResult(item.getItem(), new ArrayList<>()));
|
||||
}
|
||||
|
||||
DeviceStatusCountDto num = isvDataService.countDeviceStatus(status, range, rangeValue);
|
||||
if("count".equals(countType)) {
|
||||
results.add(new NumberFetchResult(item.getItem(), num.getTotal()));
|
||||
} else if("ratio".equals(countType)) {
|
||||
results.add(new NumberFetchResult(item.getItem()
|
||||
, new BigDecimal(num.getValue() / (num.getTotal() * 1.0))
|
||||
.setScale(2, BigDecimal.ROUND_DOWN)));
|
||||
} else {
|
||||
if("count".equals(countType)) {
|
||||
listFetchResult.addValue(new BaseEchartsCount(countDto.getName(), countDto.getValue()));
|
||||
} else if("ratio".equals(countType)) {
|
||||
listFetchResult.addValue(new BaseEchartsCount(countDto.getName()
|
||||
, new BigDecimal(countDto.getValue() / (countDto.getTotal() * 1.0))
|
||||
.setScale(2, BigDecimal.ROUND_DOWN)));
|
||||
} else {
|
||||
listFetchResult.addValue(new BaseEchartsCount(countDto.getName(), countDto.getTotal()));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
results.addAll(maps.values());
|
||||
} else if(Objects.equals("time", params.getCategory())) {
|
||||
throw new ServiceException("不支持按时间统计");
|
||||
} else {
|
||||
values.stream().forEach(item -> {
|
||||
final String status = item.getValueItem(1);
|
||||
final String countType = item.getValueItem(2);
|
||||
|
||||
List<DeviceStatusCountDto> countDtos = isvDataService.countDeviceStatus(status
|
||||
, params.getCategory(), params.getRange(), params.getRanges());
|
||||
final DeviceStatusCountDto countDto = countDtos.get(0);
|
||||
if ("count".equals(countType)) {
|
||||
results.add(new NumberFetchResult(item.getItem(), countDto.getValue()));
|
||||
} else if ("ratio".equals(countType)) {
|
||||
results.add(new NumberFetchResult(item.getItem()
|
||||
, new BigDecimal(countDto.getValue() / (countDto.getTotal() * 1.0))
|
||||
.setScale(2, BigDecimal.ROUND_DOWN)));
|
||||
} else {
|
||||
results.add(new NumberFetchResult(item.getItem(), countDto.getTotal()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
+17
-5
@@ -1,10 +1,8 @@
|
||||
package com.iteaj.iboot.plugin.iotview.api;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.iteaj.framework.spi.iot.view.DataItemOption;
|
||||
import com.iteaj.framework.spi.iot.view.ViewApiItem;
|
||||
import com.iteaj.framework.spi.iot.view.ViewApiParams;
|
||||
import com.iteaj.framework.spi.iot.view.ViewFetchResult;
|
||||
import com.iteaj.framework.spi.iot.data.BaseEchartsCount;
|
||||
import com.iteaj.framework.spi.iot.view.*;
|
||||
import com.iteaj.iboot.plugin.iotview.service.ISVDataService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -48,7 +46,21 @@ public class ModelAttrApiItem implements ViewApiItem {
|
||||
|
||||
@Override
|
||||
public List<ViewFetchResult> fetch(List<ViewApiParams.Value> values, ViewApiParams params) {
|
||||
return null;
|
||||
return Arrays.asList(new ListFetchResult("温度", Arrays.asList(
|
||||
new BaseEchartsCount("2025-01", 30),
|
||||
new BaseEchartsCount("2025-02", 50),
|
||||
new BaseEchartsCount("2025-03", 70),
|
||||
new BaseEchartsCount("2025-04", 90),
|
||||
new BaseEchartsCount("2025-05", 88)
|
||||
)
|
||||
)
|
||||
, new ListFetchResult("湿度", Arrays.asList(
|
||||
new BaseEchartsCount("2025-01", 28),
|
||||
new BaseEchartsCount("2025-02", 54),
|
||||
new BaseEchartsCount("2025-03", 42),
|
||||
new BaseEchartsCount("2025-04", 19),
|
||||
new BaseEchartsCount("2025-05", 38)
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
@@ -98,7 +98,11 @@ public class ISVDataController {
|
||||
if(Objects.equals(args[0], "device")) {
|
||||
List<DataItemOption> devices = isvDataService.listDeviceOptions(args[1]);
|
||||
if(CollectionUtil.isNotEmpty(devices)) {
|
||||
devices.forEach(item -> {
|
||||
item.setValue(key + DataItemOption.SPLIT + item.getValue()).setLeaf(true);
|
||||
});
|
||||
|
||||
return IotViewResult.Success(devices);
|
||||
}
|
||||
}
|
||||
return IotViewResult.Success(Collections.EMPTY_LIST);
|
||||
|
||||
+5
@@ -16,4 +16,9 @@ public class DeviceStatusCountDto {
|
||||
* 总值
|
||||
*/
|
||||
private int total;
|
||||
|
||||
/**
|
||||
* 类别名称
|
||||
*/
|
||||
private String name;
|
||||
}
|
||||
|
||||
+7
-1
@@ -14,5 +14,11 @@ public interface ISVDataMapper extends Mapper {
|
||||
|
||||
List<DataItemOption> listGroupOption();
|
||||
|
||||
DeviceStatusCountDto countDeviceStatus(String status, String range, String rangeValue);
|
||||
List<DeviceStatusCountDto> countDeviceStatus(String status, String range, List<String> values);
|
||||
|
||||
List<DataItemOption> listDeviceOptions(String productCode);
|
||||
|
||||
List<DeviceStatusCountDto> countDeviceStatusByTime(String status, String range, List<String> values);
|
||||
|
||||
List<DeviceStatusCountDto> countDeviceStatusByRange(String status, String range, List<String> values);
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,5 +15,5 @@ public interface ISVDataService {
|
||||
|
||||
List<DataItemOption> listDeviceOptions(String productCode);
|
||||
|
||||
DeviceStatusCountDto countDeviceStatus(String status, String range, String rangeValue);
|
||||
List<DeviceStatusCountDto> countDeviceStatus(String status, String category, String range, List<String> values);
|
||||
}
|
||||
|
||||
+10
-3
@@ -7,6 +7,7 @@ import com.iteaj.iboot.plugin.iotview.service.ISVDataService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class ISVDataServiceImpl implements ISVDataService {
|
||||
@@ -34,11 +35,17 @@ public class ISVDataServiceImpl implements ISVDataService {
|
||||
|
||||
@Override
|
||||
public List<DataItemOption> listDeviceOptions(String productCode) {
|
||||
return null;
|
||||
return isvDataMapper.listDeviceOptions(productCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceStatusCountDto countDeviceStatus(String status, String range, String rangeValue) {
|
||||
return isvDataMapper.countDeviceStatus(status, range, rangeValue);
|
||||
public List<DeviceStatusCountDto> countDeviceStatus(String status, String category, String range, List<String> values) {
|
||||
if(Objects.equals(category, "time")) {
|
||||
return isvDataMapper.countDeviceStatusByTime(status, range, values);
|
||||
} else if(Objects.equals(category, "range")) {
|
||||
return isvDataMapper.countDeviceStatusByRange(status, range, values);
|
||||
} else { // void
|
||||
return isvDataMapper.countDeviceStatus(status, range, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,68 @@
|
||||
</select>
|
||||
|
||||
<select id="countDeviceStatus" resultType="com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto">
|
||||
select count(if(status=#{status}, 1, null)) value, count(1) total from iot_device
|
||||
<where>
|
||||
|
||||
</where>
|
||||
select count(if(a.status=#{status}, 1, null)) value, count(1) total, b.name from iot_device a
|
||||
<if test="range == 'device'">
|
||||
left join iot_device b on a.id=b.id
|
||||
where uid in (
|
||||
<foreach collection="values" separator="," item="uid">
|
||||
#{uid}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
<if test="range == 'product'">
|
||||
right join iot_product b on a.product_id=b.id
|
||||
where b.code in (
|
||||
<foreach collection="values" separator="," item="productCode">
|
||||
#{productCode}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
<if test="range == 'group'">
|
||||
right join iot_device_group b on a.device_group_id=b.id
|
||||
where b.id in (
|
||||
<foreach collection="values" separator="," item="groupId">
|
||||
#{groupId}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
</select>
|
||||
<select id="listDeviceOptions" resultMap="BaseResultMap">
|
||||
select a.name label, a.uid code from iot_device a
|
||||
right join iot_product p on a.product_id = p.id
|
||||
where p.code = #{productCode}
|
||||
</select>
|
||||
<select id="countDeviceStatusByTime" resultType="com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto">
|
||||
select count(if(a.status=#{status}, 1, null)) value, count(1) total from iot_device a
|
||||
</select>
|
||||
<select id="countDeviceStatusByRange" resultType="com.iteaj.iboot.plugin.iotview.dto.DeviceStatusCountDto">
|
||||
select count(if(a.status=#{status}, 1, null)) value, count(1) total, b.name from iot_device a
|
||||
<if test="range == 'device'">
|
||||
left join iot_device b on a.id=b.id
|
||||
where uid in (
|
||||
<foreach collection="values" separator="," item="uid">
|
||||
#{uid}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
<if test="range == 'product'">
|
||||
right join iot_product b on a.product_id=b.id
|
||||
where b.code in (
|
||||
<foreach collection="values" separator="," item="productCode">
|
||||
#{productCode}
|
||||
</foreach>
|
||||
)
|
||||
group by b.id
|
||||
</if>
|
||||
<if test="range == 'group'">
|
||||
right join iot_device_group b on a.device_group_id=b.id
|
||||
where b.id in (
|
||||
<foreach collection="values" separator="," item="groupId">
|
||||
#{groupId}
|
||||
</foreach>
|
||||
)
|
||||
group by b.id
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user